西瓜的演讲
ppt翻译+解释+其他: wolf96
在最基本的层面上,这些新api是为了改进CPU性能和效率,通过:
减少CPU渲染瓶颈的情况,
提供更多可预测和稳定的驱动的行为,
给应用程序更多控制,就像在控制台开发一样
在传统的api,通常只有单个CPU线程提交GPU的工作。当试图渲染一个极其复杂的场景时,可能成为一个瓶颈。
因此,大多数应用程序尝试在“渲染线程”做尽可能少的事情,和驱动多线程也可以分担一点,但可伸缩性当然是有限的。
相比之下,我们会发现这些新的api,而不是处理这个问题而是更直接通过支持GPU创建很多线程来解决问题。
在
谈到一个驱动的可预见性和稳定性,当你的应用程序提交一个draw
call,或者映射一个缓冲区来写入,你的驱动可能通过即时编译着色器代码来应对,插入栅栏或刷新缓存来避免冲突,甚至可能去分配内存。所有这些意味着两
次调用相同API函数可能会在非常不同的时间里(甚至跨帧),这使得它很难获得一致的帧时间。
与在PC上的这种驱动行为相比,现代控制台图形api给应用程序更大控制,在这些操作中:当发生编译时,当发生同步时,当分配内存时。
命令缓冲区
CPU创建线程调用对GPU发出命令,驱动交给了GPU的前端进行处理
更好的模型就是认为cpu线程把这些命令写入内存。这段内存就是我们说的“命令缓冲区”。
命令缓冲区的格式通常是GPU特定的,所以只有驱动知道的确切格式。
当命令缓冲区的命令已满,或者当应用程序请求刷新,缓冲就会被提交到GPU上执行
驱动将添加完整的缓冲队列到GPU前端进行处理。
通过这种方式,CPU和GPU可以异步运行。
前一代图形API的用户如D3D11或OpenGL通常不知道这些命令缓冲区的存在,因此,更简单的模型是可行的。
但是,GPU处理命令的速度比CPU产生的要快。如果我们要提高渲染性能,就需要扩展多个CPU线程。
但是当这样的命令缓冲区是隐藏的,并不可能扩展多个CPU线程来创建GPU命令。
所以为了解决这些问题,所有新的API包括一个更明确的具体的概念关于命令缓冲区或“命令列表”。
像图示:4个CPU线程都在写命令到另一个命令缓冲区…
当其中一个线程完成命令,它将提交执行的缓冲队列。
如果想要产生更多的GPU命令,线程将要开始填写一个新命令缓冲区。
所有这些api还支持多个队列,所以GPU可以使用多个异步流的命令。
大多数这些api使用方法,常常被称为“free threading
可以调用任何API函数在任何线程上,并不需要渲染线程,但应用程序的任何操作必须确保正确地同步读写相同的对象
命令缓冲区的内容是不透明的,不能像在控制台一样预建立缓冲传输。
Metal只有一次命令缓冲,一旦提交,就会隐式删除
Vulkan, D3D12允许更多缓冲区重用,可以重提交相同的缓冲通过帧/框架
Unity5中的情况
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
OpenGL是一个状态机,通过启用/禁用来改变状态,D3D9也有类似的“SetRenderState”来改变状态。但随着10和11,转向较粗粒度的状态对象。所以单个对象表现blend-related状态。
这些新的API,有一个状态对象,该对象封装了几乎全部GPU状态向量。
所以改变个体的状态,要切换到管道状态,绘制,然后切换到状态B,绘制,等等。
这些非常粗粒度,整体状态对象允许驱动程序在可预见的时期编译和验证状态,。当你刚开始在新的状态下渲染时,避免驱动暂停。
什么进入了PSO?最重要的部分是不同编程阶段的shader。所以你需要一个独特的PSO把每一个你将会用到的着色器组合起来。一些引擎的工作方式,但是如果你依赖于混搭的能力,这可能是棘手的。
同时,PSO也包含大部分的固定功能状态,如混合相关的、光栅化等。
它还包含所有顶点属性的格式信息和颜色/深度targets。
什么不能进入PSO?最重要的是你的资源绑定:实际的顶点/索引/持续的缓冲,纹理,取样器等等。
此外,每个APIs的一些固定功能状态也是与PSO分开的。每个API都有点不同,但就是一个例子,但是都允许动态设置常量的混合颜色。
内存和资源
分配,代表一些大块物理或虚拟地址空间
资源,一个内存和其特定布局的结合
一个视图,为了特殊的用途准备一个资源(比如一个颜色target)
举个例子
进行分配时,你可能会选择不同的缓存行为,并决定是否需要CPU可视、GPU可视,或两者兼而有。
在创建一个资源时,你会选择是否是线性缓冲区,或一些纹理模型。你可能决定一块内存存放一个2 d 多采样纹理。
创建一个视图时,你可能决定层结构数组作为用一个特定的格式的深度-模板目标。
资源绑定
我们有完整的GPU状态向量,看看PSO状态与无PSO状态。
此外,我们有一些概念上的“绑定表”,我们填入绑定纹理,采样器,并缓冲到GPU状态。
描述符是一块数据,可以编写、复制和移动描述符,并不需要分配或释放内存。
例如,一个纹理描述符可能包括一个纹理数据指针,并随着宽度/高度,格式,等等。
根据描述符所代表的不同,你可以有不同的类型的描述符。
不同的gpu将存储的信息不同,格式不透明。
画一个新的资源绑定模型。现在应用程序管理的描述符表指向我们的纹理,取样器,和缓冲区,GPU状态只是指向这些表。
一环扣一环的,PSO包含所有GPU状态,GPU状态指向描述符表,描述符表是这些数据的指针,全部指向这些数据。
每个材质都要强加一些限制表的布局来得到约束。有人可能会说“描述符2 在表0 最好是一个贴图,“否则结果将是未定义的。
为了捕捉到这些信息,新API有“管道布局”的概念,这是一个明确的API,描述什么类型的描述符应该出现在每个绑定表的哪个槽中。这实际上形成了PSO的shader之间的接口,和描述符表。
多个shader(或者更确切地说,多个PSO)可以使用相同的布局,所以你可以很容易地绑定一组表并且通过多个draw call
使用它们。
D3D12和Vulkan 有描述符表分配的堆或池。
Vulkan称描述符表为”“ descriptor sets“。“D3D12称之为“descriptor tables”,但仅仅是一个堆的子区间。
这两种api对象来代表一个完整的绑定布局。D3D称之为“root layout”因为它是根表的布局,而 vulkan称之为“pipeline layout。”
Unity5.2现在已经实现了资源绑定
但是最主要的功能还没有实现,有点可惜
总的来说
而且unity使用DX12变得运行很慢
Unity还没有做vulkan
Vulkan™是Khronos Group研发的新一代高性能图像处理和计算API,它要比OpenGL ES更高效。
上图来自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
这些数据是来自两个不同基准的场景(一个是静态的;另一个很多材料动画参数)。在测3个人电脑上进行不同的硬件配置试。
也就是说unity现在并没有完全发挥DX12的作用
着色语言方面
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现在渲染方面的情况。。。。
----------- by wolf96