译者:林公子编程
出处:木木的二进制人生windows
转载请注明做者和出处,谢谢!多线程
原文连接是https://msdn.microsoft.com/en-us/library/windows/desktop/dn899194(v=vs.85).aspxide
Direct3D 12到Direct3D 11的重大改变函数
Direct3D 12是对Direct3D 11编程模型的一个巨大颠覆。Direct3D 12让应用程序比以往更接近硬件底层。经过接近底层,Direct3D 12更加的快速和高效。不过你的应用程序使用Direct3D 12带来的速度和效率提高相应的代价是你要比使用Direct3D 11负责更多的工做。性能
Direct3D 12是底层编程的回归。经过引入这些新特性,它给予你对游戏和应用程序中图形元素的更多的控制: 用于表明管线总体状态的的对象,用于任务提交的command list和bundles,用于资源访问的descriptor heap/table。学习
Direct3D 12 vs Direct3D 11的取舍编码
使用Direct3D 12你的应用程序的速度和效率获得了提高,不过你要负责相对与Direct3D 11更多的工做。spa
l 在Direct3D 12中,CPU-GPU的同步明确由应用程序负责,再也不像Direct3D 11中由运行时隐式执行。这也意味着Direct3D 12没有对pipeline hazard的自动检查,所以这也成为了应用程序的职责。线程
l 在Direct3D 12中,应用程序负责管线数据更新。也就是Direct3D 11中的"Map/Lock-Discard"模式在Direct3D 12中必须手动进行。在Direct3D 11中,当你使用D3D11_MAP_WRITE_DISCARD标识调用ID3D11DeviceContext::Map时,运行时返回一个新内存区块的指针代替旧的缓冲数据。这让GPU可以在应用程序往新缓冲填充数据的同时使用旧的数据。应用程序不须要额外的内存管理。旧的缓冲在GPU使用完后会自动销毁或重用。
l 在Direct3D 12中,全部的动态更新(包括constant buffer,dynamic vertex buffer,dynamic textures等等)明确由应用程序来控制。这些动态更新包括任何请求的GPU fence和buffer。应用程序有责任保证内存在使用完以前是有效的。
l Direct3D 12只将COM风格的引用计数用于interface的生命周期(经过Direct3D的弱引用模型关联到device的生命周期)。全部的resource和description内存生命周期由应用程序来负责保证适当的存活时间,并且它们都没有使用引用计数。Direct3D 11也使用引用计数来管理interface相关的对象。
管线状态对象
Direct3D11容许使用大量独立的对象的集合来操纵管线状态。例如,input assembler state,pixel shader state,rasterizer state和output merge state都可以独立的进行修改。这种设计提供了便利性和相对高层的图形管线表示。可是没有利用现代硬件的能力。主要是各类各样的state一般是互相关联的。例如,不少GPU将pixel shader和output merger state合并为一个硬件表示。然而由于Direct3D 11 API这些管线阶段状态被分别设置,显示驱动不能决议管线状态直到状态最后肯定下来,而这要等到绘制的时候。这种规划延迟了硬件的状态设置,也就意味着额外的开销和更少的每帧DP。
Direct3D 12经过将大部分管线状态统一到不可变的管线状态对象(PSOs)来解决这个问题,PSOs在建立的时间就决定了。硬件和驱动可以当即将PSO转换为用来驱动GPU工做的硬件本地指令和状态。你仍然能够动态切换使用的PSO。这么作硬件只须要直接拷贝最少的预计算状态到硬件寄存器,而不是实时计算硬件状态。经过使用PSOs,DP的开销显著的减小,而后每帧能够有更多的DP。更多关于PSOs的信息见Managing graphics pipeline state in Direct3D 12. 。
命令列表和集合(bundle)
在Direct3D 11中,全部的任务提交都经过immediate context完成,immediate context表明了一条送往GPU的指令流。要实现多线程,游戏还有deferred context可使用。Direct3D 11中的Deferred Context不能完美的映射到硬件,因此它们能作的事情有限。
Direct3D 12引入了给予命令列表的任务提交模型。命令列表包含了在GPU上执行一个具体工做所需的全部信息。每一个命令列表包含的信息有使用哪一个PSO,须要什么纹理和缓冲资源和全部DP的参数。由于每一个命令列表是自包含的而且没有状态继承。驱动可以预先计算全部须要的GPU命令,而且是以一种自由线程化(free-threaded)的方式。接下来惟一须要进行的处理是经过命令队列将命令列表最终提交到GPU。
除了命令列表,Direct3D 12还引入了一个二级的任务预计算方式:bundle。不像命令列表,彻底的自包含,通常性的被构造,提交一次而后丢弃,bundle提供了某种形式的状态继承来容许复用。例如,若是游戏想要用不一样的纹理绘制两个角色模型。一种方法是用一个命令列表记录两组完整同样的DP。另外一种方法是记录一个绘制单一角色模型的bundle,而后用不一样的资源在命令列表上“回放”bundle两次。在后一种状况下,显示驱动只须要计算相应的指令一次,而建立命令列表本质上至关于两个低开销的函数调用。
更多关于命令列表和bundle的信息,见Work Submission in Direct3D 12。
描述符堆和表(Descriptor Heap and Table)
Direct3D 11中的资源绑定高度抽象和便利,却留下不少现代硬件能力没有被利用到。在Direct3D 11中,游戏建立资源的视图对象,而后绑定这些视图到管线中不一样shader阶段的slot中。而后Shader从显式绑定的 slot读取数据,这些绑定slot在绘制时是固定的。这个模型意味着每当游戏使用不一样的资源绘制,它必须从新绑定不一样的视图到不一样的slot,而后再次调用绘制函数。这种状况也表现出额外的开销可以经过彻底利用硬件能力来消除。
Direct3D 12改变了绑定模型来匹配现代硬件并显著的提高了性能。和须要独立的资源视图和显式的绑定到slot相反,Direct3D 12提供了一个descriptor heap用来建立游戏中不一样的资源。这个方案提供了一种机制让GPU预先直接写入硬件本地资源描述(descriptor)到内存。由于descriptor heap已经被恰当的特定于硬件的descriptor数据填充,改变descriptor table是消耗至关低的操做
除了由descriptor heap和table带来的性能提高。Direct3D 12还容许资源在shader里被动态的索引,这提供了空前的灵活性并开启了新渲染技术的大门。举例来讲,现代延迟渲染引擎通常将一个某种形式的材质或物体标识符编码到中间的G-Buffer。在Direct3D 11中,这些引擎必须当心的避免使用太多的材质,由于在一个G-Buffer中包含太多会极大的影响最终渲染pass的速度。有了能动态索引的资源,一个有上千材质的场景可以最终和只有十个材质的场景同样快。
更多关于descriptor head和table的信息,见Resource Binding。