在 Vulkan 中具有透明度的多个绘制调用之间是否需要同步?

Chl*_*rie 4 c++ synchronization rendering vulkan

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

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

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

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

Nic*_*las 5

想一想你在做什么。为什么您认为两组命令之间需要同步?因为第二组命令需要与第一组中的数据混合,对吗?因此,它需要做一个读/修改/写(RMW),它必须能够读取由前一组命令写入的数据。正在读取的数据必须已写入,这通常需要同步。

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

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

因此,不知何故,深度测试的 RMW 无需任何显式同步即可工作。那么......为什么你认为这对于混合阶段的 RMW 来说是不正确的?

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

这就是为什么你的深度测试不需要同步;Vulkan 要求处理此问题。这也是为什么您的混合不需要同步(在子通道内)。

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

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