Vulkan:带有隐式布局转换的附件同步

Posted

技术标签:

【中文标题】Vulkan:带有隐式布局转换的附件同步【英文标题】:Vulkan: attachment synchronisation with implicit layout transitions 【发布时间】:2019-06-08 17:14:03 【问题描述】:

我已经阅读了谷歌给我的关于这个主题的几乎所有内容,但未能得出令人满意的结论。这基本上是这个问题的后续问题:

Moving image layouts with barrier or renderpasses

假设我有一个颜色附件,它在一个渲染过程中写入并在第二个渲染过程中采样。让两个渲染通道中只有一个子通道。处理布局转换和依赖关系的一种方法是在两个渲染通道之间添加屏障,这会将布局从 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL 更改为 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL。

但 Vulkan 还提供隐式布局转换(vkAttachmentDescription、initialLayout 和 finalLayout)。我想使用它们有性能优势,所以让我们简单地尝试摆脱我们的障碍。我们在 vkAttachmentDescription 结构中设置了 initialLayout 和 finalLayout 字段,并移除了屏障。问题是,我们失去了屏障提供的同步,所以我们需要通过其他方式取回同步。这就是混乱开始的地方,导致我的问题:

1) 在两个渲染通道之间同步附件的推荐方法是什么?显然我可以简单地重新添加障碍而不改变布局,但这不会破坏整个练习的目的,即通过使用隐式布局转换并摆脱障碍来获得更好的性能吗?或者我应该从渲染通道 1 的单个子通道添加一个子通道依赖项到 VK_SUBPASS_EXTERNAL?在性能方面使用 VK_SUBPASS_EXTERNAL 有什么注意事项吗?

2) 向后同步附件怎么样?将附件转换为正确的初始布局是应用程序的责任,显然,这可以通过屏障来完成。能否更换此屏障以获得性能优势?我能想到的唯一方法是使用从 VK_SUBPASS_EXTERNAL 到渲染通道 1 的单个子通道的子通道依赖项来执行依赖项部分,并使用仅执行布局变化。这有意义吗?那道屏障会是什么样子?或者在这种情况下“完整”障碍是不可避免的吗?

我的问题的简短版本很简单:其他人如何结合隐式布局转换进行附件同步?

【问题讨论】:

【参考方案1】:

一般来说,当 Vulkan 或类似的低级 API 为您提供多种工具来满足您的需求时,您应该优先选择能够解决您的问题的最具体工具(无需从根本上重新构建您的代码或从根本上影响您的设计)。

在您的情况下,您有 2 个选项:屏障或渲染通道机制(子通道依赖项和布局转换)。障碍适用于任何事物;他们不在乎图像来自何处、用于何处或将去往何处。渲染通道机制仅适用于渲染通道中发生的事情,主要处理附加到渲染通道的图像(隐式布局转换适用于附件)。

渲染通道机制更具体,因此如果它们满足您的需求,您应该更喜欢使用这些工具。

这也是为什么,如果您有两个“单独的”渲染操作,可能在同一个渲染通道中(如果您以一种可以在限制范围内使用的方式读取附件)输入附件),您应该更愿意将它们放在同一个渲染通道中。

【讨论】:

【参考方案2】:

我的问题的简短版本很简单:其他人如何结合隐式布局转换进行附件同步?

渲染通道依赖是您正在寻找的。如果有两个渲染通道,您需要使用提到的VK_SUBPASS_EXTERNAL 值。

将附件转换为正确的初始布局是应用程序的责任,显然,这可以通过屏障来完成。是否可以替换此障碍以获得性能优势?

但是你执行布局转换,没关系。您有责任将图像的布局转移到指定为初始布局的布局。但我认为最好的方法是再次使用渲染通道提供的隐式布局转换。如果您已经在使用它们,那么应该可以以这样的方式设置它们,以便第一个渲染通道将图像转换为与第二个渲染通道的初始布局和第二个渲染通道的最终布局相同的布局pass 与第一个渲染 pass 的初始布局相同。

【讨论】:

谢谢,这几乎完全回答了我的问题。如果附件在之前的渲染过程中没有用作附件,那么 2) 的答案是什么? 这并没有太大改变情况。您仍然需要将图像转换为适当的布局(与第二个渲染通道的初始布局相同)。如果您没有将其用作渲染通道内的附件,则无法使用隐式布局转换,因此您需要使用屏障。 快到了:假设我想将图像从渲染通道 1 中的着色器读取转换为渲染通道 2 中的附件写入。实现转换和同步的方法有两种:A)完整两个渲染通道之间的屏障 B) 与渲染通道 2 中的子通道依赖项同步(从 VK_SUBPASS_EXTERNAL 到子通道),并在两个渲染通道之间使用无同步屏障 (TOP_OF_PIPE -> BOTTOM_OF_PIPE) 转换布局。 A) 总是正确的,我在问 B) 是否也正确,以及从性能的角度来看它是否有潜在的好处。 @S.Jordan 我认为建议做所有事情,正如 Nicol Bolas 所说,只使用渲染通道提供的机制。所以我认为这将是 C) 与子通道依赖项同步(我认为应该在两个渲染通道中定义适当的依赖关系,但有人应该确认这一点)并使用隐式渲染通道布局转换来转换布局。如果可能的话,我认为应该避免明确的障碍(出于性能原因)。 在我在评论中描述的场景中,不可能使用隐式转换,因为图像在第一个渲染过程中不用作附件。所以 C) 在那里不起作用。因此,在这种情况下,问题仍然是 A) 或 B) 是要走的路。 B) 基本上是 C) 用一个无同步屏障作为隐式转换的替代品。

以上是关于Vulkan:带有隐式布局转换的附件同步的主要内容,如果未能解决你的问题,请参考以下文章

使用带有约束的泛型时无法隐式转换类型[重复]

带有空值的 Seq[(Int,Int)] 隐式转换为 DataFrame

Scala基础:隐式转换与隐式参数

Scala 系列(十三)—— 隐式转换和隐式参数

Scala 学习笔记之隐式参数和隐式转换并用

Scala中的隐式转换|理解