【问题标题】:Is synchronization needed between multiple draw calls with transparency in Vulkan?在 Vulkan 中是否需要在多个具有透明度的绘图调用之间进行同步?
【发布时间】:2019-11-05 16:59:04
【问题描述】:

我正在学习 Vulkan,我刚刚使用原始 ImGui 存储库中的 Vulkan-GLFW 示例将 ImGui 集成到我的代码中,并且效果很好。

现在我想在屏幕上同时渲染 GUI 和我的 3D 模型,由于 GUI 和模型肯定需要不同的着色器,我需要使用多个管道并提交多个命令。 GUI 是部分透明的,所以我希望它在模型之后呈现。 Vulkan 规范指出命令的执行顺序不太可能是我记录命令的顺序,因此我需要某种同步。在this Reddit post 中提出了几种完全实现我的目标的方法,我曾经认为我必须使用多个子通道(连同子通道依赖)或屏障或其他类似的同步方法来解决这个问题。

然后我查看了SaschaWillems' Vulkan examples,虽然在 ImGui 示例中,我看到两个绘制调用之间没有同步,它只是先记录绘制模型的命令,然后记录绘制 GUI 的命令。

我很困惑。在这种情况下真的需要同步,还是我误解了命令重新排序或混合的一些内容?谢谢。

【问题讨论】:

    标签: c++ synchronization rendering vulkan


    【解决方案1】:

    想想你在做什么。为什么你认为两组命令之间需要同步?因为第二组命令需要和第一组的数据混合,对吧?因此,它需要进行读/修改/写(RMW),它必须能够读取上一组命令写入的数据。读取的数据必须已经写入,这通常需要同步。

    但请多想想这意味着什么。混合必须从帧缓冲区中读取来完成它的工作。但是......深度测试也是如此,对吗?它必须读取现有样本的深度值,将其与传入的片段进行比较,然后根据深度测试是否丢弃片段。所以基本上每个使用深度测试的绘图调用都包含一个帧缓冲区读取/修改/写入。

    然而……你的深度测试有效。它们不仅可以在没有显式同步的绘制调用之间工作,它们还可以在绘制调用工作。如果绘制调用中的两个三角形重叠,则通过顶部看到底部的三角形没有任何问题,对吗?您不必进行三角形间同步以确保先前三角形的写入在读取之前完成。

    不知何故,深度测试的 RMW 无需任何显式同步即可工作。那么...为什么您认为混合阶段的 RMW 不正确?

    Vulkan 规范规定命令和命令中的阶段将以基本上无序的方式执行,但有几个例外。最明显的是存在显式执行障碍/依赖关系。但它也表示,固定功能的每个样本测试和混合阶段将始终(好像)按提交顺序(在子通道内)执行。不仅如此,它还要求生成的三角形命令中也以特定的、明确定义的顺序执行这些阶段(好像)。

    这就是您的深度测试不需要同步的原因; Vulkan 要求对此进行处理。这也是您的混合不需要同步(在子通道内)的原因。

    所以你有很多选择(按照从最快到最慢的顺序):

    • 在与非 UI 相同的子通道中呈现您的 UI。只需根据需要更改管道即可。
    • 在子通道中渲染您的 UI,显式依赖于非 UI 子通道的帧缓冲区图像。虽然这在技术上较慢,但如果有的话,它可能不会慢很多。此外,这对于延迟渲染很有用,因为您的 UI 需要在光照通道之后发生,这无疑是它自己的子通道。
    • 在不同的渲染过程中渲染您的 UI。这仅在您需要执行一些全屏工作 (SSAO) 的情况下才真正需要,这些工作会强制您的非 UI 渲染过程无论如何都要终止。

    【讨论】:

    • 感谢您的出色回答。但实际上我认为深度测试和混合之间存在差异,深度测试只是比较,无论顺序是什么,它总是会丢弃更远的片段,但混合确实关心什么是源,什么是目的地。我说的对吗?
    • @Chlorie:但我们在这里讨论的是内存同步的观点。两个操作都需要进行 RMW 操作,并且这两个操作都需要能够根据之前写入的数据来完成它们的工作。无论是按三角形还是按绘制调用,您仍然需要能够阅读以前的内容。此外,将深度测试与模板测试相结合可能会导致以不同三角形顺序评估操作会导致不同结果的情况,因此它们也必须按顺序进行。
    • 您说绘制 cmd 1 的深度将在 cmd 2 写入或测试深度之前写入。因此您可以像 cmd1 发生在 cmd1 之前一样(即使未指定)至少在深度写作和测试阶段。因为这只适用于特定阶段(深度测试和写入),所以您不能假设颜色缓冲区将在 cmd2 之前由 cmd 1 写入。难道你不能假设绘制 cmd 1 发生在 cmd2 之前吗?在什么情况下它不会那样做?例如 cmd1 绘制和 cmd2 读取?那必须在同一个渲染中......
    • 通过还是次通过?你能在同一个渲染(子)通道中写入和读取同一个帧缓冲区吗(我的意思是除了混合)
    • @Zebrafish:“你能不能在同一个渲染(子)通道中写入和读取同一个帧缓冲区(我的意思是除了混合)”不。唯一写入附件的方法是通过片段着色器的输出。您可以从输入附件中读取,也可以在同一子通道中将其作为颜色附件写入,但是对于如何执行此操作以及何时需要屏障存在特定限制。
    猜你喜欢
    • 1970-01-01
    • 2014-12-21
    • 2013-07-04
    • 2018-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-04
    相关资源
    最近更新 更多