首页 > 解决方案 > 没有 vkQueuePresentKHR() 的 Vulkan 渲染完成同步

问题描述

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

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

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

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

如何等待渲染完成?

有关信息,Vulkan 版本是 1.0,但我想我可以使用 v1.1。

标签: synchronizationsemaphorevulkan

解决方案


vrapi_SubmitFrame2接受 a 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. EGLsyncKHR使用EGL_ANDROID_native_fence_sync扩展名创建一个,并将其vrapi_SubmitFrame2作为您的CompletionFence. 这是很多步骤,但底层同步(渲染完成 -> 时间扭曲开始)应该与使用 GLES 渲染或 VrApi 原生支持 Vulkan 所获得的一样有效。


推荐阅读