Vulkan 渲染在没有 vkQueuePresentKHR() 的情况下完成同步

Vulkan render finished synchronisation without vkQueuePresentKHR()

在 Oculus 移动版 VrApi 中,我们无法访问 vkQueuePresentKHR(),我们为每只眼睛提供了一层 vrapi_SubmitFrame2()。

vulkan 示例使用栅栏与 vkQueueSubmit() 和 vkWaitForFence() 同步。 它适用于简单的渲染,但是如果我使用更长的渲染,它在屏幕上显示时还没有完成。

据我了解,这是正常的,因为栅栏允许在 CPU 级别同步,但与 GPU 的同步是通过信号量完成的。

我可以用 vkQueueSubmit() 中的信号量表示渲染已完成,但我等不及发出信号量了,因为 vrapi_SubmitFrame2() 不使用“.pWaitSemaphores”字段.

如何等待渲染完成?

求助,Vulkan版本是1.0,不过我觉得可以用v1.1.

vrapi_SubmitFrame2 接受一个 CompletionFence,它是一个 EGLsync 对象,因为 VrApi 被设计为使用 OpenGL ES,而不是 Vulkan。所以没有单步实现无气泡同步的方法。

最简单的解决方案是在调用 vrapi_SubmitFrame2 之前确保渲染已完成。通过栅栏进入 vkQueueSubmit,等待它发出信号,然后调用 vrapi_SubmitFrame2。但是,这会增加延迟并降低性能(通过减少 CPU 和 GPU 工作之间的并发性),这对于 VR 来说尤其难以接受。

更复杂的解决方案是使用 VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT 句柄类型创建 Vulkan 外部信号量。将其作为信号量传递给 vkQueueSubmit。然后,您可以使用 vkGetSemaphoreFdKHR 提取底层同步 fd。使用 EGL_ANDROID_native_fence_sync 扩展从中创建一个 EGLsyncKHR,并将其作为您的 CompletionFence 传递到 vrapi_SubmitFrame2。这是很多步骤,但底层同步(渲染完成 -> timewarp 开始)应该与使用 GLES 渲染或 VrApi 原生支持 Vulkan 时获得的同步一样高效。