新图形API为Unity 5 带来了什么&下一代新图形API的好处

发表于2015-09-10
评论0 1.5k浏览

西瓜的演讲
ppt翻译+解释+其他: wolf96
 http://img.blog.csdn.net/20150831093624991

 

在最基本的层面上,这些新api是为了改进CPU性能和效率,通过:

减少CPU渲染瓶颈的情况,

提供更多可预测和稳定的驱动的行为,

给应用程序更多控制,就像在控制台开发一样

 http://img.blog.csdn.net/20150831093635446

 

在传统的api,通常只有单个CPU线程提交GPU的工作。当试图渲染一个极其复杂的场景时,可能成为一个瓶颈。

因此,大多数应用程序尝试在“渲染线程”做尽可能少的事情,和驱动多线程也可以分担一点,但可伸缩性当然是有限的。

相比之下,我们会发现这些新的api,而不是处理这个问题而是更直接通过支持GPU创建很多线程来解决问题。

 http://img.blog.csdn.net/20150831093644613

 

在谈到一个驱动的可预见性和稳定性,当你的应用程序提交一个draw call,或者映射一个缓冲区来写入,你的驱动可能通过即时编译着色器代码来应对,插入栅栏或刷新缓存来避免冲突,甚至可能去分配内存。所有这些意味着两次调用相同API函数可能会在非常不同的时间里(甚至跨帧),这使得它很难获得一致的帧时间。

 http://img.blog.csdn.net/20150831093654849

 

与在PC上的这种驱动行为相比,现代控制台图形api给应用程序更大控制,在这些操作中:当发生编译时,当发生同步时,当分配内存时。

 http://img.blog.csdn.net/20150831093708128

 

 

命令缓冲区

 http://img.blog.csdn.net/20150831093720988

 

CPU创建线程调用对GPU发出命令,驱动交给了GPU的前端进行处理

 http://img.blog.csdn.net/20150831093729354

 

更好的模型就是认为cpu线程把这些命令写入内存。这段内存就是我们说的“命令缓冲区”。

命令缓冲区的格式通常是GPU特定的,所以只有驱动知道的确切格式。

 http://img.blog.csdn.net/20150831093735738

 

当命令缓冲区的命令已满,或者当应用程序请求刷新,缓冲就会被提交到GPU上执行

 

 http://img.blog.csdn.net/20150831093821116

 

驱动将添加完整的缓冲队列到GPU前端进行处理。

 

 http://img.blog.csdn.net/20150831093849963

 

通过这种方式,CPU和GPU可以异步运行。

前一代图形API的用户如D3D11或OpenGL通常不知道这些命令缓冲区的存在,因此,更简单的模型是可行的。

但是,GPU处理命令的速度比CPU产生的要快。如果我们要提高渲染性能,就需要扩展多个CPU线程。

但是当这样的命令缓冲区是隐藏的,并不可能扩展多个CPU线程来创建GPU命令。

 

 http://img.blog.csdn.net/20150831093832805

 

所以为了解决这些问题,所有新的API包括一个更明确的具体的概念关于命令缓冲区或“命令列表”。

 http://img.blog.csdn.net/20150831093907865http://img.blog.csdn.net/20150831093912150

 

像图示:4个CPU线程都在写命令到另一个命令缓冲区…

 http://img.blog.csdn.net/20150831093955783

 

当其中一个线程完成命令,它将提交执行的缓冲队列。

 http://img.blog.csdn.net/20150831094022706

 

如果想要产生更多的GPU命令,线程将要开始填写一个新命令缓冲区。

所有这些api还支持多个队列,所以GPU可以使用多个异步流的命令。

大多数这些api使用方法,常常被称为“free threading

可以调用任何API函数在任何线程上,并不需要渲染线程,但应用程序的任何操作必须确保正确地同步读写相同的对象

命令缓冲区的内容是不透明的,不能像在控制台一样预建立缓冲传输。

Metal只有一次命令缓冲,一旦提交,就会隐式删除

Vulkan, D3D12允许更多缓冲区重用,可以重提交相同的缓冲通过帧/框架
 

 

Unity5中的情况

 http://img.blog.csdn.net/20150831094042118

 

Unity5.2是使用双线程渲染,一个主线程负责高级逻辑渲染。一个渲染线程负责调用API和其他工作。

Unity有自己的命令缓冲区和环形缓冲。

可以在任何平台中使用,除了webGL,因为webGL没有线程    

环形缓冲是一个环形缓冲区,是首尾相连的队列数据结构,在一个线程上下文与另一个线程上下文之间传递数据

Ring Buffer 比链表要快,因为它是数组,而且有一个容易预测的访问模式。

详细请看http://www.cnblogs.com/shanyou/archive/2013/02/04/2891300.html和http://my.oschina.net/alphajay/blog/36602 我觉得讲得很明白


 

 

管线状态对象PSO

 http://img.blog.csdn.net/20150831094145940

 

 

OpenGL是一个状态机,通过启用/禁用来改变状态,D3D9也有类似的“SetRenderState”来改变状态。但随着10和11,转向较粗粒度的状态对象。所以单个对象表现blend-related状态。  

http://img.blog.csdn.net/20150831094056271

这些新的API,有一个状态对象,该对象封装了几乎全部GPU状态向量。

所以改变个体的状态,要切换到管道状态,绘制,然后切换到状态B,绘制,等等。

这些非常粗粒度,整体状态对象允许驱动程序在可预见的时期编译和验证状态,。当你刚开始在新的状态下渲染时,避免驱动暂停。

 http://img.blog.csdn.net/20150831094202274

 

什么进入了PSO?最重要的部分是不同编程阶段的shader。所以你需要一个独特的PSO把每一个你将会用到的着色器组合起来。一些引擎的工作方式,但是如果你依赖于混搭的能力,这可能是棘手的。

同时,PSO也包含大部分的固定功能状态,如混合相关的、光栅化等。

它还包含所有顶点属性的格式信息和颜色/深度targets。

 http://img.blog.csdn.net/20150831094238790?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

 

什么不能进入PSO?最重要的是你的资源绑定:实际的顶点/索引/持续的缓冲,纹理,取样器等等。

此外,每个APIs的一些固定功能状态也是与PSO分开的。每个API都有点不同,但就是一个例子,但是都允许动态设置常量的混合颜色。

 

内存和资源

 http://img.blog.csdn.net/20150831094247433?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

 

分配,代表一些大块物理或虚拟地址空间

资源,一个内存和其特定布局的结合

一个视图,为了特殊的用途准备一个资源(比如一个颜色target)

举个例子

进行分配时,你可能会选择不同的缓存行为,并决定是否需要CPU可视、GPU可视,或两者兼而有。

在创建一个资源时,你会选择是否是线性缓冲区,或一些纹理模型。你可能决定一块内存存放一个2 d 多采样纹理。

创建一个视图时,你可能决定层结构数组作为用一个特定的格式的深度-模板目标。


 

资源绑定

 http://img.blog.csdn.net/20150831094301406?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

 

我们有完整的GPU状态向量,看看PSO状态与无PSO状态。

此外,我们有一些概念上的“绑定表”,我们填入绑定纹理,采样器,并缓冲到GPU状态。

 http://img.blog.csdn.net/20150831094315523?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

 

描述符是一块数据,可以编写、复制和移动描述符,并不需要分配或释放内存。

例如,一个纹理描述符可能包括一个纹理数据指针,并随着宽度/高度,格式,等等。

根据描述符所代表的不同,你可以有不同的类型的描述符。

不同的gpu将存储的信息不同,格式不透明。

 
 

 http://img.blog.csdn.net/20150831094333198?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

http://img.blog.csdn.net/20150831094347465?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

画一个新的资源绑定模型。现在应用程序管理的描述符表指向我们的纹理,取样器,和缓冲区,GPU状态只是指向这些表。

一环扣一环的,PSO包含所有GPU状态,GPU状态指向描述符表,描述符表是这些数据的指针,全部指向这些数据。

 http://img.blog.csdn.net/20150831094410377

 

每个材质都要强加一些限制表的布局来得到约束。有人可能会说描述符2 在表0 最好是一个贴图,“否则结果将是未定义的。

为了捕捉到这些信息,新API有“管道布局”的概念,这是一个明确的API,描述什么类型的描述符应该出现在每个绑定表的哪个槽中。这实际上形成了PSO的shader之间的接口,和描述符表。

多个shader(或者更确切地说,多个PSO)可以使用相同的布局,所以你可以很容易地绑定一组表并且通过多个draw call

使用它们。

 

 http://img.blog.csdn.net/20150831094426216

http://img.blog.csdn.net/20150831094438215

 

D3D12和Vulkan 有描述符表分配的堆或池。

Vulkan称描述符表为”“ descriptor setsD3D12称之为“descriptor tables”,但仅仅是一个堆的子区间。

这两种api对象来代表一个完整的绑定布局。D3D称之为“root layout”因为它是根表的布局,而 vulkan称之为“pipeline layout。”

http://img.blog.csdn.net/20150831094451409

 

Unity5.2现在已经实现了资源绑定

 http://img.blog.csdn.net/20150831094504028

 

但是最主要的功能还没有实现,有点可惜

 

 

总的来说

 http://img.blog.csdn.net/20150831094517056

 

而且unity使用DX12变得运行很慢

 http://img.blog.csdn.net/20150831094524900

 

Unity还没有做vulkan

Vulkan™是Khronos Group研发的新一代高性能图像处理和计算API,它要比OpenGL ES更高效。

 http://img.blog.csdn.net/20150831094535671

图来自http://imgtec.eetrend.com/article/5245展示了Vulkan和OpenGL ES 3.0 CPU占用差异

Vulkan实现了应用对GPU加速的直接控制,从而最大化性能和可预测性,同时,使用Khronos的新标准SPIR-V™中间语言规范可以带来更高的渲染语言灵活性。Vulkan在移动、桌面、控制台和嵌入式平台上实现最小化驱动过载并提高了多线程性能。http://cn.khronos.org/news/press/khronos-to-create-new-open-standard-for-computer-vision

 http://img.blog.csdn.net/20150831094548663

 

这些数据是来自两个不同基准的场景(一个是静态的;另一个很多材料动画参数)。在测3个人电脑上进行不同的硬件配置试。

也就是说unity现在并没有完全发挥DX12的作用

http://img.blog.csdn.net/20150831094600520

 

 

着色语言方面
Unity认为HLSL不是理想的着色/计算语言,但是有巨大的,大量的已经编好了的着色器。 unity希望继续使用HLSL,但最终会走向MetalSL

D3D9/11/12: 使用 d3dcompiler_xx.dll   GL2, GLES2: HLSL -> (hlsl2glslfork) -> GLSL -> (glsl-optimizer) -> GLSL   GL3/4, GLES3: HLSL -> (hlslcc) -> GLSL   Metal: HLSL -> (hlsl2glslfork) -> GLSL -> (glsl-optimizer) -> MetalSL   Vulkan: 目前没有

总之希望unity尽快发展渲染技术,充分发挥DX12强大特性

 

博主之后可能会发几篇unity现在渲染方面的情况。。。。

 

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引