大量数据+同步+多线程_Vulkan 多线程渲染

db60bec931e093d60fcec4d16329f294.png

1. Overview of Vulkan

1.1 计算机图形软件

图形软件有两个大类:专用软件包(special-purpose packages)和通用编程软件包(general programming packages)。

专用软件包通常提供一种UI设计语言,让用户直接生成想要的图形,不用关心内部实现。这类软件例子是PS、CAD等等。

相反,通用编程软件包提供一个可使用C、C++或Java等高级语言编程的图形函数库。图形函数库中提供几何图元、矩阵变换等操作,提供了间接操作硬件的软件接口,所以这组图形函数又被称为计算机图形应用编程接口(computer-graphics application programming interface,CG API)。OpenGL、Vulkan、DirectX、Metal皆在此列。

1.2 Vulkan多线程的设计理念

Vulkan不仅仅是图形(graphics)API,而是一个面向图形和计算的编程接口(graphics and compute)。支持Vulkan的设备可以是GPU,也可以是DSP或者固定功能的硬件。

Vulkan中的计算模型主要基于并行计算,因此支持多线程是Vulkan设计的核心理念之一。

为了较少Vulkan内部因为互斥同步等操作造成的卡顿问题,Vulkan内部默认认为对任何资源的访问不存在多线程竞争,所有的资源同步操作由应用开发者去负责,因为对资源的访问和使用没有人比应用开发者自己更加清楚。Vulkan称之为外部同步(external synchronization)。

因为这个原因,资源管理和线程同步工作成为编写Vulkan程序的最大难点之一。想要让Vulkan多线程正常运行,你需要做大量的工作。当然,换来的是Vulkan有了更加干净的线程模型以及比其它CG API高得多的性能。

5e679ceb9862ea3af2c36fa349075881.png
image-20200730105359314.png

1.3. Instances, Devices, and Queues

在正式研究Vulkan多线程之前,有三个重要的基础概念需要了解—Instances, Devices, and Queues。

Instances可以看做是应用的子系统,从逻辑上把Vulkan与应用程序上下文中的其他逻辑隔开。Instances可以看做是Vulkan的上下文,它会跟踪所有状态,从逻辑上把所有支持Vulkan的设备整合在一起。

Devices有两个概念:Physical devices和Logical device。

Physical devices通常代表一个或者多个支持Vulkan的硬件设备,这些设备具有特定功能,可以提供一系列Queues。图形显卡、加速器、DSP等都可以是Vulkan的Physical devices。

Logical device是Physical devices的软件抽象,用于预订一些硬件资源。

Queues可以理解为一个“GPU线程”,它是实现Vulkan多线程的关键元素之一,用于响应应用的请求,大部分时间,应用都在与其交互。

Vulkan功能的层次结构图如下:

d6c879b05ad44fe651634d5c6e89cdcb.png
image-20200730105801733.png

2. Queues and Command Buffer

2.1 Queues

Queue代表一个GPU线程,Vulkan设备执行的就是提交到Queues中的工作。物理设备中Queue可能不止一个,每一个Queue都被包含在Queue Families中。

Queue Families是一个有相同功能的Queues的集合,它们的性能水平和对系统资源的访问是相同的,并且在它们之间数据传输工作没有任何成本(同步之外)。

一个物理设备中可以存在多个Queue Families,不同的Queue Families有不同的特性。相同Queue Families中的Queues的功能相同,并且可以并行运行。

按照Queue的能力,可以将其划分为:

  • Graphics(图形)
    • 该系列中的Queues支持图形操作,例如绘制点,线和三角形。
  • Compute(计算)
    • 该系列中的Queues支持诸如computer shader之类的计算操作。
  • Transfer(传输,拷贝)
    • 该系列中的Queues支持传输操作,例如复制缓冲区和图像内容。
  • Sparse binding(稀疏绑定)
    • 该系列中的队列支持用于更新稀疏资源(sparse resource)的内存绑定操作。

ab77721e7ff093fbfc201dbaae84da64.png
image-20200730112126405.png

2.2 Command Buffer

2.2.1 单线程的性能瓶颈

传统CG API是单线程的,性能的提升只能依赖于CPU主频的提高。能有的优化方案也不外乎主线程和渲染线程分开,或者某些资源的异步加载、离线处理。

a1ce1e5b3af62a42b7e0766fe983bb05.png
image-20200730114946379.png

但是在实际应用中我们还是经常遇到传统CG API导致的性能瓶颈。

以手机终端为例,CPU主频提升有限,各大芯片厂商开始向多核多线程发展,考虑到功耗温控问题,又不能把CPU频率升的太高,越来越高的刷新率对实时渲染的速度要求越来越苛刻。

cfe7723f6ae73c61cfded18cd7241c06.png
image-20200730115516772.png

Vulkan为了充分发挥CPU多核多线程的作用,引入了command buffer的概念。多个线程可以同时协作,每个CPU线程都可以往自己的command buffer中提交渲染命令,然后统一提交到对应的Queue中,大大提高了CPU的利用率。

2b65b4e90e128cfb0c6d503df3eb37a0.png
image-20200730115609709.png

2.2.2 Command Buffer的作用

应用在绘制时会提交一系列绘制命令给GPU驱动,但是这些绘制命令不会立刻被执行,而是被简单的添加到Command Buffer的末尾。

在其他CG APIs中,驱动程序在应用不感知的情况下,把API调用翻译成GPU command并储存在command buffer中,最终提交给GPU处理。command buffer的创建和销毁都由驱动负责。

在Vulkan中,你需要自己从Command Buffer Pool中申请command buffer,将想要记录的命令放入command buffer中。

Command Buffer Pool:

da156a37f32a7a6c0b99b870bb6cde23.png
image-20200730142932026.png

2.2.3 Recording command

Command Buffer可以记录(Record)很多命令,比如:设置状态、绘制操作、数据拷贝...

82a2e61d08ceb074909f5e19b4788cce.png
image-20200730142958943.png

f64cb94d69ff77c940b889a979262f23.png
image-20200730142302468.png

理论上,一个线程可以把Command记录到多个Command Buffer中,多个线程也可以共享同一个Command Buffer,但是一般不鼓励多个线程共享一个Command Buffer。

Vulkan的关键设计原则之一就是做到高效的多线程。想实现这一点,应用程序要注意因为资源竞争导致的多线程彼此阻塞。因此,每个线程最好有一个或者对个Command Buffer,不要尝试共享一个。另外,Command Buffer由Command Buffer Pool分配,应用可以为每一个线程创建一个Command Buffer Pool,让各个工作线程从Command Buffer Pool中分配Command Buffer,无需参与竞争。

cd2831cfeede916a0736a081031404ea.png
image-20200730144149412.png

2.2.4 Submitting Command Buffers

提交过程使用示意图更加好理解一点。

单线程Command Buffer提交过程:

7a2a9348c334a51738a38e71a815dfab.png
submit cb1.PNG

b060f7f6f4f79674d2607e5386ad3a10.png
submit cb5.PNG

79a28aaa8e3f1b8924bb2330ba452fb4.png
submit cb2.PNG

多线程Command Buffer提交过程:

e852158ae1ef6115828cfbcf792940b7.png
submit cb3.PNG

91e33166a056dce1b367cc9d57f04233.png
submit cb4.PNG

整体流程如下:

0e591a910f2e551d478d1bbadb755955.png
image-20200730144906368.png

3. Synchronization

3.1 显示同步操作

Vulkan把同步的操作交给了应用(external synchronization),绝大多数的Vulkan命令根本不提供同步,需要应用自己负责。Vulkan给应用提供了同步原语,帮助应用进行同步操作。

Vulkan中主要有四种同步原语(synchronization primitives):

  • Fences
    • 最大颗粒度的同步原语,目的是给CPU端提供一种方法,可以知道GPU或者其他Vulkan Device什么时候把提交的工作全部做完。
    • 如果你熟悉Android显示机制的话,acquire fence或者retire fence就是类似的作用
  • Semaphores
    • 颗粒度比Fences更小一点,通常用于不同Queue之间的数据同步操作
  • Events
    • 颗粒度更小,可以用于Command Buffer之间的同步工作
  • Barriers
    • Vulkan流水线(Pipeline)阶段内用于内存访问管理和资源状态移动的同步机制

下面这张图取自NVIDIA公司Vulkan 多线程讲解的PPT:

71b932808bab26258a41d2d7e892cb64.png
image-20200730145823767.png

3.2 隐藏的执行顺序

Vulkan是显式的API没错,号称是“没有秘密的API”。但是在多线程同步时,还是存在一些潜规则。

以下面这张图为例,同一个Queue中,Command Buffer1 和Command Buffer2 谁先执行?Command Buffer中记录的一堆命令是如何执行的?

0e591a910f2e551d478d1bbadb755955.png
image-20200730144906368.png

Vulkan的执行顺序其实是有一定的潜规则的,在没有同步原语的情况下:

  • Command Buffer中的Command,先记录的先执行
  • 先提交的Command Buffer先执行
  • 同一个Queue中,一起提交的Command Buffer1 和Command Buffer2 按照下标的顺序执行,Command Buffer1 先执行

3.3 Barriers

所有的同步原语中,Barriers使用起来最为困难。Barriers用于显式的控制buffer或者image的访问范围,避免hazards(RaW,WaR,and WaW),保证数据一致性。

Barriers需要开发者了解渲染管线的各个阶段,能清晰的把握管线中每个步骤对资源的读写顺序。

Vulkan中将Pipeline的各个阶段定义为:

  • TOP_OF_PIPE_BIT
  • DRAW_INDIRECT_BIT
  • VERTEX_INPUT_BIT
  • VERTEX_SHADER_BIT
  • TESSELLATION_CONTROL_SHADER_BIT
  • TESSELLATION_EVALUATION_SHADER_BIT
  • GEOMETRY_SHADER_BIT
  • FRAGMENT_SHADER_BIT
  • EARLY_FRAGMENT_TESTS_BIT
  • LATE_FRAGMENT_TESTS_BIT
  • COLOR_ATTACHMENT_OUTPUT_BIT
  • TRANSFER_BIT
  • COMPUTE_SHADER_BIT
  • BOTTOM_OF_PIPE_BIT

对应:

ac1aa4752cffd80b2c747ac3ff7f0064.png
image-20200730152820973.png

假设我们有个两个渲染管线P1 和 P2,P1会通过Vertex Shader往buffer写入顶点数据,P2需要在Compute Shader中使用这些数据。

如果使用fence去同步,你的流程应该是这样:P1的Command提交后,P2通过fence确保P1的操作已经被全部执行完,再开始工作。

cfd35803fcdad7eb088d274d1503542e.png
image-20200730153109052.png

但是这种大颗粒度的同步操作无疑造成了耗时操作:P1的数据在Vertex Shader阶段就已经准备好了,我们为什么要等到它所有操作执行完再开始?P2平白多等待了很长时间,而且在这个期间P2的其他阶段并没有使用到P1的数据,也是可以执行的啊。

Barriers的引入完全解决了这个问题,我们只需要告诉Vulkan,我们在P2的Compute Shader阶段才会等待P1 Vertex Shader里面的数据,其他阶段并不关心,可以同步进行。

71244dca8322a9e45ad93d3e5bd8c6ec.png
image-20200730152521195.png

使用方法:

ed769e91d1f27690205f2c98c5bef611.png
image-20200730153743130.png

参考文档:

  1. Vulkan Overview
  2. Android and Vulkan - GDD China.pdf
  3. Vulkan Programming Guide
  4. Vulkan Cookbook
  5. Learning Vulkan
  6. Vulkan Multi-Threading
  7. Vulkan中的同步机制
  8. Vulkan® 1.1.148 - A Specification
  9. VULKAN BARRIERS EXPLAINED
  10. vulkan中的同步和缓存控制之二,barrier和event
  11. Xinzhao:vulkan中的同步和缓存控制之一,fence和semaphore

本系列文章汇总:

  • Vulkan 简介
  • Vulkan 多线程渲染
  • Vulkan 内存管理
  • Vulkan 绘制与显示
  • Vulkan 资源绑定和状态管理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/455430.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

飞康任命Gartner前分析师担任亚洲区市场总监

在虚拟化、数据保护和数据迁移领域具备15年创新经验的美国飞康软件公司(FalconStor Software, Inc.,NASDAQ:FALC)近日宣布任命张瑾(Jimmie Chang)先生担任该公司亚洲区市场部门负责人。 飞康公司近日面向全…

12_登陆案例

13131转载于:https://www.cnblogs.com/ZHONGZHENHUA/p/7044846.html

如何基于FFMPEG和SDL写一个少于1000行代码的视频播放器

http://blog.csdn.net/eplaylity/archive/2008/12/05/3454431.aspx http://www.cnblogs.com/konyel/tag/SDLGuide%E4%B8%AD%E6%96%87%E8%AF%91%E7%89%88/ ffmpeg文档http://blog.sina.com.cn/s/blog_46dc65a90100a91b.html http://dranger.com/ffmpeg/ffmpeg.html VLC核心功能部…

Flask 概述

什么是Web Framework? Web Application Framework(Web应用程序框架)或简单的Web Framework(Web框架)表示一个库和模块的集合,使Web应用程序开发人员能够编写应用程序,而不必担心协议&#xff0…

(五)Maven中的聚合和继承

一、为什么要聚合? 定义:我们在开发过程中,创建了2个以上的模块,每个模块都是一个独立的maven project,在开始的时候我们可以独立的编译和测试运行每个模块,但是随着项目的不断变大和复杂化,我们…

python堆栈反向输出列表_python - IPython:将Python脚本的输出重定向到文件(如bash) - 堆栈内存溢出...

IPython有自己的上下文管理器来捕获stdout / err ,但它没有重定向到文件,它重定向到一个对象:from IPython.utils import iowith io.capture_output() as captured:%run my_script.pyprint captured.stdout # prints stdout from your script…

关于datagrid

基本在公司使用的datagrid不需要自己写前台代码,只需要自己给grid明确id,url以及列属性即可。 后台需要返回一个数据类型:{recordsFiltered2, data[], drawnull, recordsTotal2},通常返回这个数据类型的话,只需要调用d…

M-JPEG、MPEG4、H.264都有何区别 依维安防论坛

压缩方式是网络视频服务器和网络摄像机的核心技术,压缩方式很大程度上决定着图像的质量、压缩比、传输效率、传输速度等性能,它是评价网络视频服务器和网络摄像机性能优劣的重要一环。 随着多媒体技术的发展,相继推出了许多压缩编码标准&…

Django/Flask/Tornado三大web框架性能分析

写在前面:本文的数据涉及到之前遇到过的问题,大概一次 http 请求到收到响应需要多少时间。这个问题在实际工作中与框架有比较大的关系,因此特别就框架的性能做了一次分析。这里使用之前的一个报告数据: Pythons Web Framework Ben…

python urllib模块学习笔记

这个模块是最基本最常用的,以前看过,总结一下 #coding : utf-8import urlliburl http://cnblogs.com#代理服务器proxies {http:http://127.0.0.1:8087}#使用代理服务器打开r urllib.urlopen(url,proxies proxies)print r.info()print r.getcode()pri…

hibernate基础工具findBySQL学习

public List<Map<String,Object>> findBySQL(String sql,Map<String,Object> param,int start,int max) {log.debug("finding List by hql");try {       //最后返回map map的key可为别名和数据库字段SQLQuery querysessionFactory.getCurr…

python处理ini文件_python对ini配置文件处理

>>> cf.read("test.ini") #读取配置文件[test.ini]>>> cf.sections() #片段名[base, callback]>>> cf.options("callback") #配置…

Python实现自动推本地github博客到远程仓库

Python实现自动推本地github博客到远程仓库 以前的简单版本 通过python中的os模块操作系统命令 详情可参考:Python实现一行代码推本地git到远程仓库 升级版本 本次加入了监听文件修改功能 这样脚本只需在后台运行,即可检测到对应的文件夹中的内容是否变化 如果变化,则调用…

H.264/MPEG-4 AVC

维基百科&#xff0c;自由的百科全书跳转到&#xff1a; 导航, 搜索 跳过字词转换说明 汉漢▼▲为了阅读方便&#xff0c;本文使用全文手工轉換。转换内容&#xff1a;本文采用电脑和信息技术组全文转换 [查看] • [编辑] • [强制刷新] 以下為本條目單獨的全文轉換&#xff0c…

JavaScript 专题之函数柯里化

JavaScript 专题系列第十三篇&#xff0c;讲解函数柯里化以及如何实现一个 curry 函数 定义 维基百科中对柯里化 (Currying) 的定义为&#xff1a; In mathematics and computer science, currying is the technique of translating the evaluation of a function that takes m…

机器学习模板

根据心情补充&#xff0c;语言都是Python hash&#xff0c;把所有的文本转化成数字 from sklearn.preprocessing import LabelEncoder for c in train.columns:if train[c].dtype object:lbl LabelEncoder()lbl.fit(list(train[c].values) list(test[c].values))train[c] l…

漂亮特殊字体可复制_12个创意字体免费下载网站

今天为大家介绍12个创意字体的网站&#xff0c;这些网站都有提供免费下载的字体哦&#xff0c;希望对大家在创作上面有所帮助。FontSpace在Fontspace上有超过42000种免费字体。在这里字体被整齐的分门归类&#xff0c;帮助你找到想要的字体。除了典型的“serif” “script”等&…

使用postman测试接口

Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件。在java web开发中使用非常多&#xff0c;经常用来测试接口。 使用postman模拟json数据的发送 第一步:在header里边设置发送数据的类型 Paste_Image.png设置发送数据类型为json&#xff0c;也就是key为Content-…

删除github上的commit历史记录

删除github上的commit历史记录 起步 今天小编发现了git克隆下来的远程库特别大: 经过查询之后发现是每次推送之后都会留下记录缓存&#xff0c;这样很多没用的记录就会占用多余的空间&#xff0c;别人克隆的时候也会多耗费时间&#xff0c;今天我查到了一个清除无用记录的方…

DirectShow组件原理分析及应用

1 DirectX简介  DirectX是Microsoft公司为游戏和其他高性能多媒体应用所提供的一套底层应用程序编程接口。这些接口包括对二维和三维图形&#xff0c;声效和音乐&#xff0c;输入设备以及多玩家网络游戏等的支持。目前DirectX的最高版本是DirectX 9.0。  1.1 DirectX的组成…