如上所述here vkQueueWaitIdle相当于vkFence。 那么在哪种情况下使用其中任何一种。
答案 0 :(得分:5)
正如你所说,vkQueueWaitIdle()
只是围栏使用的一个特例。
所以当你不得不写10行等效的Fence代码时,你会使用它 - 特别是如果你不记得所有以前的队列提交。它有点像调试功能(最常用的是暂时用它来测试同步)。它在清理过程中可能很有用(例如,应用程序终止或重建交换链)。
在所有其他情况下,您应该更喜欢VkFence
s,这更通用:
您可以利用高级vkWaitForFences()
用法。即wait-one vs wait-all和timeout
。
您将其提供给一些应该发出信号的命令(不能用vkQueueWaitIdle()
执行此操作)。你可以这样做:
vkQueueSubmit( q, 1, si1, fence1 );
vkQueueSubmit( q, 1, si2, fence2 );
vkWaitFences( fence1 ); // won't block on the 2nd submit unlike vkQueueWaitIdle(q)
甚至可能比以下更快:
vkQueueSubmit( q, 1, si1, 0 );
vkQueueWaitIdle(q);
vkQueueSubmit( q, 1, si2, 0 );
您可以在不等待vkGetFenceStatus()
的情况下查询围栏的状态。例如。有一些后勤工作,并且只是在你做其他工作时定期询问它是否已经完成。
VkFence
也可能更快。 vkQueueWaitIdle()
可能会被实现为
vkQueueSubmit( q, 0, nullptr, fence );
vkWaitFences( fence, infiniteWait );
您可能会为vkQueueSubmit
支付额外费用。
答案 1 :(得分:3)
坦率地说,你应该总是喜欢等待围栏,因为它更灵活。
使用围栏,您可以等待完成工作,而无需等待您等待工作后提交的工作。 fence还允许其他线程将命令缓冲区推送到队列而不会干扰等待。
此外,与等待围栏相比,WaitQueueIdle的实现方式可能不同(效率较低)。
答案 2 :(得分:3)
对于vkQueueSubmit,VkFence在什么情况下比vkQueueWaitIdle更好?
当不关闭Vulkan上下文时,即在几乎所有情况下。 vkQueueWaitIdle
是一种大锤同步方法,大致类似于glFlush()
。 Vulkan队列是你想要保持填充的东西,因为当它是空的时候,这是一种低效率。使用vkQueueWaitIdle
在客户端代码和Vulkan驱动程序的部分之间创建一种同步点,这可能会导致GPU管道中的停顿和气泡。
围栏的纹理要细得多。您只需询问何时完成在围栏之前或与围栏一起排队的特定工作集,而不是要求队列清空所有工作。即使它仍然通过必须将客户端CPU线程与驱动程序CPU线程同步来创建同步点,这仍然使驱动程序可以继续处理队列中的其余项目。
信号量甚至比围栏更好,因为它们告诉司机一项工作依赖于另一项工作并让司机完全在内部完成同步,但它们并非适用于所有情况,因为有时客户需要知道什么时候完成了一些工作。