如何在 Vulkan 中获取下一个子通道的渲染结果?

How to get render result for next subpass in Vulkan?

现在,我想做 post-processing 并使用 subpass 方式来做。我创建了两个子通道并在第二个子通道的屏幕上绘制了一个大三角形。

但问题是我不知道如何获得第一个子通道的渲染结果,因为我需要将它提供给第二个子通道的片段着色器,然后我可以在片段着色器中做一些效果第二个子通道。

我猜结果是swapchain_imageView。但是我不能使用它。 Vulkan 告诉我 Cannot use image 0x8 with specific layout VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL that doesn't match the actual current layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL。 估计是方法不对。

如何为下一个子通道获取正确的渲染结果?

您想要一个带有子通道附件引用和依赖项的渲染通道,如下所示:

pSubpasses = [
  {
    pInputAttachments = [],
    pColorAttachments = [{0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}]
  },
  {
    pInputAttachments = [{0, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL}]
    pColorAttachments = [{1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}]
  }
]

pDependencies = [
  {
    0, 1,
    VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
    VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
    VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
    VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
    VK_DEPENDENCY_BY_REGION_BIT,
  }
]

在第二个子通道中,您还需要使用 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT 描述符将附件 0 中的图像绑定到片段着色器。

在着色器中,输入附件的用法如下:

layout (input_attachment_index=i, set=m, binding=n) uniform subpassInput inputAttachment;
vec4 fragment = subpassLoad(inputAttachment);

您不能任意读取 任何图像 当前是渲染通道的附件。请注意,我说的是 "render pass",而不是 "subpass"。启动渲染过程图像后,这些图像将禁止任何未明确附加操作的操作。

如果您的 post 处理效果是只需要对图像的每个纹素执行 read/modify/write 操作的效果,如果它不需要读取相邻像素来执行其操作作业,那么您可以将图像用作输入附件。这将用于色调映射等效果。

但是如果您确实需要从渲染图像访问多个纹素,那么这个 post 处理效果必须存在于创建它的渲染通道实例中。

另外:

Because I set inputAttachment in subpass 2, I guess the system should send the render result of the subpass 1 to my fragment shader of the subpass 2 automatically.

你"guess"?这是 Vulkan;这里没有 "guessing"。除非您告诉系统这些操作之间存在依赖关系,否则不会存在。因此尝试从中读取是 UB。

如果子通道 2 要读取由子通道 1 写入的输入附件,那么您必须放置从子通道 1 到子通道 2 的子通道依赖项。最好使用"by-region" 依赖性(除非你正在阅读之前子通道中编写的其他内容)。