一些 VkSubpassDependency 问题,关于 Sascha Willems 的离屏渲染示例

Some VkSubpassDependency questions, regarding Sascha Willems's offscreen rendering sample

在 Sascha Willems 的离屏渲染示例中,主 renderPass 有 2 个 VkSubpassDependency,离屏 renderPass 有 2 个。 首先,我经常看到成对的VkSubpassDependency,不明白为什么。

主要renderPass的VkSubpassDependency:

dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
dependencies[0].dstSubpass = 0;
dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;

dependencies[1].srcSubpass = 0;
dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL;
dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;

离屏 renderPass 的 VkSubpassDependency:

dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
dependencies[0].dstSubpass = 0;
dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;

dependencies[1].srcSubpass = 0;
dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL;
dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;

在主renderPass中,第二个VkSubpassDependency (dependencies[1]) 是否只在这里用于呈现给交换链?是强制性的吗?

对于offScreen renderPass,一般来说我不明白依赖点[0]:

因为我们只需要写入帧缓冲区,并在完成时告诉主 renderPass,在我看来这就是依赖项 [1] 所做的。

dependencies是什么意思[0].srcSubpass = VK_SUBPASS_EXTERNAL;因为在offscreen renderPass之前没有涉及其他pass。是否只是为了让屏幕外渲染通道等待主渲染通道完成呈现到交换链?

我的最后一个问题更具体:如果我使用这 4 个 VkSubpassDependency,与 Sasha 在这个示例中使用的方式类似,那么为了执行屏幕外 renderPass,我遇到了验证错误 "Dependency graph must be specified such that an earlier pass cannot depend on a later pass."我在互联网上找不到有关此错误的任何信息。我刚刚发现触发此错误的原因是:dependency.srcSubpass > dependency.dstSubpass。有什么想法吗?

这是 Sascha Willems 的离屏渲染示例 link: https://github.com/SaschaWillems/Vulkan/blob/master/examples/offscreen/offscreen.cpp

这个问题与 相似,是相同的代码库。

正如我在 SaschaWillems/Vulkan#665 中所说,示例有点过时了。从那时起,规范得到了广泛的澄清。所以偶尔会有一些不必要的混乱争论。


main renderPass, dependencies[1]

是的,这种依赖性在其后跟一个信号量信号时是典型的。例如。向交换链展示。

现在,dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT 的 dst 外部依赖项不执行任何操作。响应。它与隐式依赖相同。尽管如此,无论如何,在这种情况下明确是审美选择。

VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT 没有访问权限,所以 dstAccessMask 应该只是 0.

VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT 对最后一次访问是哪个访问有点困惑。最后一次访问颜色附件是 storeOp,它只是 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT 对于 STOREDONT_CARE


offScreen renderPass, dependencies[0]

依赖的dst 方面应该是显而易见的。这只是颜色缓冲区访问。它应该匹配 loadOp,在颜色缓冲区 CLEAR 的情况下是 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BITVK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT.

现在,srcVK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT 中是 VK_ACCESS_SHADER_READ_BIT。这是在片段着色器中作为纹理访问的图像。似乎只有一个屏幕外帧缓冲区。因此,在不过多研究样本的情况下,我会假设这种依赖性确保 "main renderPass" 完成读取屏幕外缓冲区,然后再由屏幕外 renderPass 再次写入。


What is the meaning of dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; because there is no other pass involved before the offscreen renderPass.

当然有。它是这样的:offscreen, main, offscreen, main, offscreen, main, offscreen, main, ...。因此,除非它是第一帧,否则在给定的渲染通道之前总是有 东西


I just found that this error is triggered because: dependency.srcSubpass > dependency.dstSubpass. Any idea?

没错。看来你想通了?

srcSubpassdstSubpass 必须是 VK_SUBPASS_EXTERNAL,或者 srcSubpass 必须小于 dstSubpass,以免意外产生循环和死锁在依赖 DAG 中。