Vulkan API:将渲染工作转移到自己的线程中

Vulkan API: moving rending work into its own thread

我正在学习 Khronos Vulkan API,但我很难跨多个线程进行同步。

我正在尝试将渲染工作分解到它自己的线程中。我的想法是有一个主线程,它将负责高级应用程序管理,重要的是,它将调用 VkQueuePresentKHR() 来呈现表面。然而,实际的 VkCmd* 渲染工作是在专用线程上完成的。

我希望我的应用程序使用三重缓冲,因为流畅的 60fps 对我来说非常重要。在视频演示中,NVIDIA 提到您需要每个帧缓冲区有 1 个 VkCommandPool,并且在每次使用后清除整个池;这比尝试清理单个命令缓冲区更有效。我要更进一步:我正在尝试将渲染工作分解为 6 ​​个队列:

我的GTX770显卡有16个通用队列+1个专用传输队列,所以这应该没问题。每个队列都有自己的 VkCommandPool。 Queues、CommandPool、CommandBuffer对象在主线程中创建,然后在Render线程中使用。

我 运行 遇到以下问题:

  1. vkAcquireNextImageKHR 获取图像的所有权,并且 vkQueuePresentKHR 将其所有权释放回呈现引擎。 PE 需要拥有它当前显示的图像,有时还需要拥有其他图像。获取将阻塞,直到图像可用或超时到期。当无法依赖 Acquire 到 return 时,您会收到验证错误,因为您没有提供足够的图像。规范说:

    Let n be the total number of images in the swapchain, m be the value of VkSurfaceCapabilitiesKHR::minImageCount, and a be the number of presentable images that the application has currently acquired (i.e. images acquired with vkAcquireNextImageKHR, but not yet presented with vkQueuePresentKHR). vkAcquireNextImageKHR can always succeed if an - m at the time vkAcquireNextImageKHR is called. vkAcquireNextImageKHR should not be called if a > n - m with a timeout of UINT64_MAX; in such a case, vkAcquireNextImageKHR may block indefinitely.

  2. 您传递给 vkAcquireNextImageKHR 的 semaphore/fence 将在 PE 完成从图像读取时发出信号。届时,您可以再次开始写入,并在准备好时出示它。

  3. 只要其中的任何命令缓冲区仍在执行,您就无法清除命令池。当栅栏传递给 vkQueueSubmit 信号时,你知道它们何时完成执行。

  4. 是的,您可以在单个线程中使用任意数量的任意类型的对象。 Vulkan 实现中的任何内容都不会绑定到它所使用的特定线程。从多个线程并发访问对象的限制类似于您对自己的对象的限制:某些对象在内部序列化,因此可以并发访问,而其他对象则不行。

  5. 这好像不对。您应该可以随时在任何有效的围栏上调用 vkGetFenceStatus