15

msdn 文档解释说,在 directx 11 中,有多种方法可以以编程方式填充 directx 11 纹理:

(1) 使用默认使用纹理创建纹理并使用内存中的数据对其进行初始化

(2)使用动态使用创建纹理,使用DeviceContext Map获取指向纹理内存的指针,写入它,然后使用Unmap指示您已完成(此时我猜它已复制到gpu)

(3) 使用 staging 使用创建纹理,并按照与动态纹理相同的步骤,但遵循调用 ID3D11DeviceContext.CopyResource 以使用此 staging 纹理依次填充(非不可变)默认或动态纹理。

但是文档根本没有解释每种方法的优缺点,而且我对directx还是很陌生,所以对我来说根本不清楚。

在directx 11中以编程方式创建纹理的每种方法的优缺点是什么?

旁注:我已经读过在暂存纹理的上下文中,从 gpu回的内容没有缓冲,因此您必须自己进行双缓冲。但我不知道这是否准确,以及它是否适用于使用 staging 纹理(甚至它的真正含义)的写作。

第二个注意事项: Map 方法文档说它获取指向子资源中数据的指针,并拒绝 GPU 访问该子资源。当 GPU 想要访问其底层数据已被 Map 调用的纹理时,它会做什么?地摊?(我问是因为这听起来像是我询问的利弊的一部分)

4

1 回答 1

25

正确的答案取决于您要使用纹理的目的。这三个选项是将数据从 CPU 获取到纹理的不同方式。如果这是一个渲染目标,您通常不会从 CPU 提供初始数据,因此您可以忽略这些:创建纹理,并在您准备好渲染到其中时(可能首先对其进行 Clear())。

因此,假设您在应用程序内存中有想要进入纹理的数据:

如果这只是一个静态纹理(我的意思是读取的纹理远多于写入的纹理),那么您需要一个 USAGE_DEFAULT 或 USAGE_IMMUTABLE 纹理。与 USAGE_DYNAMIC 相比,这些通常针对 GPU 读取性能进行了优化。如果您在创建纹理时手头有数据,那么选项 (1) 最简单,使用最少的中间内存,并且在 DX11 中,可以在与渲染线程不同的线程上完成向 GPU 的数据传输。如果您在创建纹理时没有数据,请在拥有数据时使用 UpdateSubresource() 或选项 (3) 提供数据。

如果它是动态纹理,这意味着您经常从 CPU 提供新内容(基于 CPU 的视频播放是典型情况:数据由 CPU 每帧提供一次,然后由 GPU 每帧读取一次),那么您可能想要使用 USAGE_DYNAMIC 和选项 (2)。USAGE_DYNAMIC 纹理针对从 CPU 到 GPU 的流式数据进行优化,而不仅仅是针对 GPU 读取。硬件供应商之间的细节(和性能影响)有所不同,但通常你只想使用 USAGE_DYNAMIC 如果你真的是从 CPU 流式传输数据到 GPU,而不是仅仅因为它是一种预先加载静态数据的便捷方式。

选项 (3) 更专业,可用于将初始数据加载到静态纹理中(重用暂存表面以加载许多纹理的数据)或流式传输数据以供相对动态使用。它使您可以精确控制 GPU/CPU 同步以及用于传输的中间内存。通常您会使用一个暂存缓冲区环,并使用 D3D11_MAP_FLAG_DO_NOT_WAIT 检查每个缓冲区是否仍被先前的 CopyResource 使用。我认为这是一个专家选项——如果你不小心,你可能会因为阻止 CPU 和 GPU 异步运行而严重损害性能。

完全披露:我在 Nvidia 从事 D3D 驱动程序的工作,但这些是我个人的意见。

于 2011-06-30T18:42:50.647 回答