Vulkan是否需要在多个具有透明度的平局调用之间进行同步

Is synchronization needed between multiple draw calls with transparency in Vulkan?

本文关键字:调用 平局 之间 同步 透明度 是否 Vulkan      更新时间:2023-10-16

我正在学习Vulkan,我刚刚使用原始ImGui repo中的Vulkan GLFW示例将ImGui集成到我的代码中,它运行良好。

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

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

我很困惑。在这种情况下,是否真的需要同步,或者我对命令重新排序或混合有什么误解?谢谢

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

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

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

因此,不知何故,深度测试的RMW在没有任何显式同步的情况下工作。那么…为什么你认为这是不真实的混合阶段的RMW?

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

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

所以你有很多选择(从最快到最慢(:

  • 在与非UI相同的子路径中渲染UI。只要适当地更换管道即可
  • 在显式依赖于非UI子通道的帧缓冲区图像的子通道中渲染UI。虽然这在技术上较慢,但它可能不会慢很多。此外,这对于延迟渲染也很有用,因为UI需要在照明过程之后进行,这无疑是它自己的子过程
  • 在不同的渲染过程中渲染您的UI。只有在需要执行一些全屏操作(SSAO(的情况下才真正需要这样做,这将迫使您的非UI渲染过程终止