msdn documentation解释说,在directx 11中,有多种方法可以编程方式填充directx 11纹理:
(1)使用默认使用纹理创建纹理,并使用内存中的数据
对其进行初始化(2)使用动态用法创建纹理,使用DeviceContext Map获取指向纹理内存的指针,写入,然后使用Unmap指示您已完成(此时我猜它已复制到gpu)< / p>
(3)创建具有分段用法的纹理,并按照与动态纹理相同的步骤,但是通过调用ID3D11DeviceContext.CopyResource来使用此分段纹理依次填充(非不可变的)默认或动态纹理。
然而,文档并没有解释每种方法的优点和缺点,而且我对directx还是很陌生,所以我一点也不清楚。
在directx 11中以编程方式创建纹理的每种方法的优缺点是什么?
旁注:我已经读过,在暂存纹理的上下文中,从gpu返回的读取没有缓冲,所以你必须自己进行双缓冲。但我不知道这是否准确,是否适用于使用分段纹理进行编写(甚至是真正的意义)。
第二方注释: Map方法文档说它获取了一个指向子资源中数据的指针,并拒绝GPU访问该子资源。当GPU想要访问其底层数据已被Map调用的纹理时,它会做什么?失速? (我问,因为这听起来像是我询问的利弊的一部分)
答案 0 :(得分:22)
正确答案取决于您将使用纹理的内容。这三个选项是将数据从CPU获取到纹理的不同方法。如果这是一个rendertarget,你通常不会从CPU提供初始数据,所以你可以忽略这些:创建纹理,当你准备好渲染它时(可能首先清除它)。
假设您确实在应用程序内存中有要进入纹理的数据:
如果这只是一个静态纹理(我的意思是纹理的读取比写入的要多得多),那么你需要一个USAGE_DEFAULT或USAGE_IMMUTABLE纹理。与USAGE_DYNAMIC相比,这些通常针对GPU读取性能进行了优化。如果在创建纹理时有方便的数据,则选项(1)最简单,使用最少的中间内存,而在DX11中,可以在与渲染线程不同的线程上完成向GPU的数据传输。如果在创建纹理时没有数据,请使用UpdateSubresource()或选项(3)在提供数据时提供数据。
如果它是动态纹理,意味着您经常从CPU提供新内容(基于CPU的视频播放是规范的情况:数据由CPU每帧提供一次,然后每帧由GPU读取一次)然后你可能想要使用USAGE_DYNAMIC和选项(2)。 USAGE_DYNAMIC纹理针对从CPU到GPU的流数据进行了优化,而不仅仅是GPU读取。硬件供应商之间的细节(和性能影响)各不相同,但如果您真的要将数据从CPU传输到GPU,通常只想使用USAGE_DYNAMIC,而不是仅仅因为它是预先加载静态数据的便捷方式。
选项(3)更加专业化,可用于将初始数据加载到静态纹理中(重用分段表面以加载许多纹理的数据)或用于流数据以进行相对动态的使用。它可以精确控制GPU / CPU同步以及用于传输的中间存储器。通常,您将使用一个临时缓冲区环,并使用D3D11_MAP_FLAG_DO_NOT_WAIT来检查先前的CopyResource是否仍在使用每个缓冲区。我认为这是一个专家选择 - 如果你不小心你可以通过防止CPU和GPU异步运行来严重损害性能。
完全披露:我在Nvidia工作的D3D驱动程序,但这些是我个人的意见。