我正在学习Khronos Vulkan API,而且我很难在多个线程中同步工作。
我试图将渲染工作分解为自己的线程。我的想法是有一个主线程,它将负责高级应用程序管理的东西,更重要的是,它将调用VkQueuePresentKHR()来呈现表面。但是,实际的VkCmd *渲染工作将在专用线程上完成。
我希望我的应用程序使用三重缓冲,因为对我来说,拥有平滑的60fps非常重要。在视频演示中,NVIDIA提到您希望每个帧缓冲区有1个VkCommandPool,并在每次使用后清除整个池;这比尝试清理单个命令缓冲区更有效。我更进了一步:我试图将渲染工作分解为6个队列:
我的GTX770显卡有16个通用队列+ 1个专用传输队列,所以这应该没问题。每个队列都有自己的VkCommandPool。 Queues,CommandPool和CommandBuffer对象在主线程中创建,然后在Render线程中使用。
我遇到了以下问题:
答案 0 :(得分:4)
vkAcquireNextImageKHR
获取图片的所有权,vkQueuePresentKHR
将其所有权发布回演示引擎。 PE需要拥有当前显示的图像,有时还需要拥有其他图像。获取将阻止,直到图像可用或超时到期。当您无法依赖Acquire返回时,您会收到验证错误,因为您没有提供足够的图像。规范说:
让 n 为交换链中的图片总数, m 为
VkSurfaceCapabilitiesKHR::minImageCount
的值, a 为应用程序当前获取的可呈现图像的数量(即使用vkAcquireNextImageKHR
获取但尚未显示vkQueuePresentKHR
的图像)。如果在调用vkAcquireNextImageKHR
时 a ≤ n - m ,vkAcquireNextImageKHR
总能成功。如果 a >,则不应调用vkAcquireNextImageKHR
n - m ,超时为UINT64_MAX
;在这种情况下,vkAcquireNextImageKHR
可能无限期阻止。
传入vkAcquireNextImageKHR
的信号量/围栏将在PE完成从图像读取时发出信号。此时,您可以再次开始写入,并在准备好时将其显示出来。
只要命令池中的任何命令缓冲区仍在执行,您就无法清除它。当栅栏传递给vkQueueSubmit
信号时,您知道它们何时完成执行。
是的,您可以在单个线程中使用任意类型的任意数量的对象。 Vulkan实现中的任何内容都不会绑定到它所使用的特定线程。从多个线程访问对象并的限制类似于您对自己的对象所拥有的限制:某些对象在内部被序列化,因此并发访问是可以的,而其他对象则没有。
这似乎不对。您应该可以随时在任何有效的围栏上致电vkGetFenceStatus
。