DirectX11 中的纹理流,不可变与动态
Texture streaming in DirectX11, Immutable vs Dynamic
我们经常遇到需要将纹理流式传输到显卡的情况(在游戏中:地形,在我的例子中来自不同输入源的图像,例如 cameras/capture cards/videos)
当然在相机的情况下,我在一个单独的线程中接收我的数据,但仍然需要将该数据上传到 GPU 进行显示。
我知道 2 个型号。
使用动态资源:
您创建一个与输入图像具有相同大小和格式的动态纹理,当您收到一个新图像时,您设置一个标志,告诉您需要上传,然后在设备上下文中使用映射来上传纹理数据(最终双当然是缓冲区)。
优点是你有一个单一的内存位置,因此你不会随着时间的推移而产生内存碎片。
缺点是您需要在即时上下文中上传,因此您的上传必须在渲染循环中。
使用不可变和load/discard
在这种情况下,您在图像接收线程中上传,通过创建新资源,推送数据并丢弃旧资源。
优点是你应该有一个免费上传(不需要即时上下文,你仍然可以在上传纹理时运行你的命令列表),资源可以用一个简单的触发器一旦可用(到交换 SRV).
缺点是您可能会随着时间的推移对内存进行分段(通过以恒定的方式分配和释放资源(例如标准相机为 30 fps)。
您还必须处理节流问题(但这部分没什么大不了的)。
那么我是否遗漏了这些技术,或者是否有更好的方法来处理这个问题?
这是更新纹理D3D11的两种主要方法。
但是,第一种方法不会导致与第二种情况相同的内存使用模式的假设取决于驱动程序,并且可能不正确。如果要覆盖整个图像(这听起来像您正在做的),您将使用 D3D11_MAP_WRITE_DISCARD
,这意味着缓冲区的当前内容变得不确定。然而,这仅从 CPU 的观点来看是正确的。如果它们可能用于挂起的绘制操作,它们将保留给 GPU。在这种情况下,大多数(也许是全部?)驱动程序实际上会为映射纹理的写入位置分配新的存储空间,否则命令缓冲区处理将需要停止。如果您不使用丢弃标志,则同样如此。相反,当在命令缓冲区中处理 map 命令时,资源的缓冲区将更新为从 D3D11_MAPPED_SUBRESOURCE
.
中的 Map 返回的值。
此外,您必须在即时上下文中更新动态纹理是不正确的。只有当您在延迟上下文中更新它们时,您才必须使用 D3D11_MAP_DISCARD
标志。这意味着如果要覆盖整个纹理,您可以在工作线程上更新纹理。
最重要的是,由于 PC 上的 CPU/GPU 系统不是统一的内存系统,因此在更新来自 CPU 的 GPU 资源时会出现同步问题。
我们经常遇到需要将纹理流式传输到显卡的情况(在游戏中:地形,在我的例子中来自不同输入源的图像,例如 cameras/capture cards/videos)
当然在相机的情况下,我在一个单独的线程中接收我的数据,但仍然需要将该数据上传到 GPU 进行显示。
我知道 2 个型号。
使用动态资源: 您创建一个与输入图像具有相同大小和格式的动态纹理,当您收到一个新图像时,您设置一个标志,告诉您需要上传,然后在设备上下文中使用映射来上传纹理数据(最终双当然是缓冲区)。
优点是你有一个单一的内存位置,因此你不会随着时间的推移而产生内存碎片。
缺点是您需要在即时上下文中上传,因此您的上传必须在渲染循环中。
使用不可变和load/discard 在这种情况下,您在图像接收线程中上传,通过创建新资源,推送数据并丢弃旧资源。
优点是你应该有一个免费上传(不需要即时上下文,你仍然可以在上传纹理时运行你的命令列表),资源可以用一个简单的触发器一旦可用(到交换 SRV).
缺点是您可能会随着时间的推移对内存进行分段(通过以恒定的方式分配和释放资源(例如标准相机为 30 fps)。
您还必须处理节流问题(但这部分没什么大不了的)。
那么我是否遗漏了这些技术,或者是否有更好的方法来处理这个问题?
这是更新纹理D3D11的两种主要方法。
但是,第一种方法不会导致与第二种情况相同的内存使用模式的假设取决于驱动程序,并且可能不正确。如果要覆盖整个图像(这听起来像您正在做的),您将使用 D3D11_MAP_WRITE_DISCARD
,这意味着缓冲区的当前内容变得不确定。然而,这仅从 CPU 的观点来看是正确的。如果它们可能用于挂起的绘制操作,它们将保留给 GPU。在这种情况下,大多数(也许是全部?)驱动程序实际上会为映射纹理的写入位置分配新的存储空间,否则命令缓冲区处理将需要停止。如果您不使用丢弃标志,则同样如此。相反,当在命令缓冲区中处理 map 命令时,资源的缓冲区将更新为从 D3D11_MAPPED_SUBRESOURCE
.
此外,您必须在即时上下文中更新动态纹理是不正确的。只有当您在延迟上下文中更新它们时,您才必须使用 D3D11_MAP_DISCARD
标志。这意味着如果要覆盖整个纹理,您可以在工作线程上更新纹理。
最重要的是,由于 PC 上的 CPU/GPU 系统不是统一的内存系统,因此在更新来自 CPU 的 GPU 资源时会出现同步问题。