Vulkan "transient attachment" 的 DirectX 12 等价物是什么?

What is the DirectX 12 equivalent of Vulkan's "transient attachment"?

我有一个计算着色器,我想将其输出到 image/buffer,它是两个管道之间的中间存储:计算管道和图形管道。图形管道实际上是一个 "dummy",因为它除了将中间缓冲区的内容复制到交换链图像之外什么都不做。这是必要的,因为 DX12 弃用了计算管道使用 UAVS 直接写入交换链图像的能力。

我认为中间存储应该是一个 "transient" 附件,在 Vulkan 意义上:

VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT specifies that the memory bound to this image will have been allocated with the VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT (see Memory Allocation for more detail). This bit can be set for any image that can be used to create a VkImageView suitable for use as a color, resolve, depth/stencil, or input attachment.`

这在 this article 中有解释:

Finally, Vulkan includes the concept of transient attachments. These are framebuffer attachments that begin in an uninitialized or cleared state at the beginning of a renderpass, are written by one or more subpasses, consumed by one or more subpasses and are ultimately discarded at the end of the renderpass. In this scenario, the data in the attachments only lives within the renderpass and never needs to be written to main memory. Although we’ll still allocate memory for such an attachment, the data may never leave the GPU, instead only ever living in cache. This saves bandwidth, reduces latency and improves power efficiency.

DirectX 12 是否有类似的图像使用概念?

Direct3D 12 没有这个概念。这种限制的原因最终归结为为什么存在瞬态分配。 TL;DR:这不是为了做你想做的事情。

Vulkan 的渲染通道系统存在一个目的:使 tile-based 渲染器成为渲染系统的 first-class 公民。 TBR 不适合 OpenGL 或 D3D 的帧缓冲区模型。在这两个 API 中,您可以随时交换帧缓冲区。

TBR 不直接渲染到内存。它们在内部缓冲区中执行渲染操作,这些缓冲区从内存中播种,然后可能在渲染操作完成后写入内存。随时切换渲染图像不利于这种结构,这就是为什么 TBR 供应商有一个列表,其中列出了你 不应该做的事情 如果你想 high-performance 在你的 OpenGL ES 中代码。

Vulkan 的渲染通道系统是 TBR 系统的抽象。在抽象模型中,渲染通道系统可能会从帧缓冲区中的图像中读取数据,然后对该数据的副本执行一系列子通道,最后可能会将更新后的数据写回到图像中。因此,从流程的外部来看,您似乎正在渲染图像,但实际上并非如此。为了保持这种错觉,在渲染通道的持续时间内,您可以以渲染通道模型允许的方式使用这些帧缓冲区图像:作为附件。

现在考虑延迟渲染。在延迟渲染中,您渲染到 g-buffers,然后在您的光照通道中读取它以生成最终图像。生成最终图像后,您不再需要那些 g-buffers。在普通 GPU 中,这没有任何意义;因为渲染直接进入内存,所以那些 g-buffers 必须占用实际存储空间。

但请考虑 TBR 的工作原理。它确实渲染成单个图块;在最佳情况下,它一次处理单个图块的 所有 个片段。这意味着它通过几何 光照通道。对于 TBR,g-buffer 只是您用来获得最终答案的一块暂存存储器;它不需要从内存中读取或复制到内存中。

总之不需要内存.

输入延迟分配的内存和临时附件图像。它们的存在是为了允许 TBR 将 g-buffers 保留在拼贴内存中,并且永远不必为它们分配实际存储空间(或者至少,只有在某些 运行 时间情况发生时才会发生这种情况迫使它,比如推太GPU 上有很多几何图形)。而且它只在渲染过程中起作用;如果您结束一个渲染通道并且必须在另一个渲染通道中使用 g-buffers 之一,那么魔法必须消失并且数据必须触及实际存储。

Vulkan API 使这个用例的具体程度非常明确。您不能将一块 lazily-allocated 内存绑定到未设置 USAGE_TRANSIENT_ATTACHMENT 标志的图像(或任何类型的缓冲区 )。你会注意到它说 "transient attachment",就像在渲染通道 attachments 中一样。之所以这样说,是因为您还会注意到瞬态附件不能用于 non-attachment 用途(valid usage tests for VkImageCreateInfo 的一部分)。完全没有。

你想做的不是延迟分配内存的目的。不行。

至于 Direct3D 12,API 并非设计用于移动 GPU 上的 运行,并且由于只有移动 GPU 是 tile-based 渲染器(一些最近的桌面 GPU 具有 TBR 相似之处,但不是完整的 TBR),它没有专门为它们设计的设施。因此,它不需要延迟分配的内存或临时附件。