vulkan - 什么是 DirectX 12 相当于 Vulkan 的 "transient attachment"?

标签 vulkan directx-12

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

我认为中间存储应该是 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 没有这个概念。这种限制的原因最终归结为为什么存在 transient 分配。 TL;DR:这不是为了做你想做的事情。

Vulkan 的渲染 channel 系统存在一个目的:使基于图 block 的渲染器成为渲染系统的一等公民。 TBR 不适合 OpenGL 或 D3D 的帧缓冲模型。在这两个 API 中,您可以随时交换帧缓冲区。

TBR 不直接渲染到内存。它们在内部缓冲区中执行渲染操作,这些缓冲区从内存中播种,然后可能在渲染操作完成后写入内存。随时切换渲染图像会违反这种结构,这就是为什么 TBR 供应商列出了如果您希望 OpenGL ES 代码具有高性能时不应该做的事情的原因。

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

现在考虑延迟渲染。在延迟渲染中,您渲染到 g 缓冲区,然后您在光照 channel 中读取这些缓冲区以生成最终图像。一旦你生成了最终图像,你就不再需要那些 g 缓冲区了。在普通 GPU 中,这没有任何意义。因为渲染直接进入内存,这些 g 缓冲区必须占用实际存储空间。

但是考虑一下 TBR 是如何工作的。它会渲染到单个图 block 中;在最佳情况下,它一次处理单个图 block 的所有片段。这意味着它通过几何和照明 channel 。对于 TBR,g-buffer 只是你用来获得最终答案的一 block 暂存内存;它不需要从内存中读取或复制到内存中。

简而言之,它不需要内存。

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

Vulkan API 使这个用例的具体程度非常明确。您不能将一 block 延迟分配的内存绑定(bind)到没有 USAGE_TRANSIENT_ATTACHMENT 的图像上。在其上设置的标志(或任何类型的缓冲区)。你会注意到它说的是“ transient 附件”,就像在渲染 channel 附件中一样。之所以这样说是因为您还会注意到临时附件不能用于非附件用途(valid usage tests for VkImageCreateInfo 的一部分)。完全没有。

您想要做的不是延迟分配内存的那种事情。它行不通。

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

关于vulkan - 什么是 DirectX 12 相当于 Vulkan 的 "transient attachment"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56819614/

相关文章:

rust - 如何使用 Vulkano 计算着色器计算交换链图像?

c++ - d3dx12.h 给出了一堆错误

directx-12 - 如何取回传递给 ID3D12Object::SetName() 的名称?

vulkan - Vulkan 的新扩展 VK_KHR_vulkan_memory_model 的目的是什么?

graphics - VkAttachmentReference::layout 的目的是什么?

c++ - ofstream.is_open() 在使用 VS 2015 的 DirectX12 应用程序中始终为 false

c++ - 使用 Directx 9 的屏幕空间反射

c++ - 亲爱的 IMGUI 和 DirectX 12 覆盖 (DXGI_ERROR_INVALID_CALL)

vulkan - 是否可以在 Vulkan 中不使用 Surface 进行屏幕外渲染?

c++ - VK_KHR_WIN32_SURFACE_EXTENSION_NAME 未定义,在 Vulkan 代码中