如此处所述, vkQueueWaitIdle相当于vkFence.那么在哪种情况下使用其中任何一种.
对于 vkQueueSubmit,在什么情况下 VkFence 比 vkQueueWaitIdle 更好?
当您不关闭 Vulkan 上下文时,即在几乎所有情况下。 vkQueueWaitIdle
是一种大锤同步方法,大致类似于glFlush()
. Vulkan 队列是您想要保持填充的东西,因为当它为空时,这是一种低效率。使用vkQueueWaitIdle
会在客户端代码和部分 Vulkan 驱动程序之间创建一种同步点,这可能会导致 GPU 管道中的停顿和气泡。
栅栏的粒度要细得多。不是要求队列清空所有工作,您只是询问它何时完成在栅栏之前或与栅栏一起排队的特定工作集。即使它仍然必须通过将客户端 CPU 线程与驱动程序 CPU 线程同步来创建同步点,但这仍然使驱动程序可以自由地继续处理队列中的剩余项目。
信号量甚至比栅栏更好,因为它们告诉驱动程序一项工作依赖于另一项工作,并让驱动程序完全在内部进行同步,但它们并非适用于所有情况,因为有时客户需要知道某项工作何时完成。
正如你所说,vkQueueWaitIdle()
只是围栏使用的一个特例.
因此,当您必须编写10行等效的Fence代码时,您将使用它 - 特别是如果您不记得所有先前的队列提交.它有点像调试功能(最常用的是暂时用它来测试同步).它在清理期间可能很有用(例如,应用程序终止或重建交换链).
在所有其他情况下,您应该更喜欢VkFence
s,它们更通用:
您可以利用高级vkWaitForFences()
用法.即等待一对等等全部和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 );
您可以直接查询Fence的状态而无需等待vkGetFenceStatus()
.例如,有一些背景工作,只是在你做其他工作时定期询问它是否已经完成.
VkFence
即使在相同的情况下也可能更快.vkQueueWaitIdle()
可能会被实施为
vkQueueSubmit( q, 0, nullptr, fence );
vkWaitFences( fence, infiniteWait );
您可能为此支付额外费用的地方vkQueueSubmit
.
坦率地说,您应该总是更喜欢等待围栏,因为它更加灵活。
使用栅栏,您可以等待工作完成,而不必等待您正在等待的工作之后提交的工作。栅栏还允许其他线程将命令缓冲区推送到队列,而不会干扰等待。
除此之外,与围观等待相比,WaitQueueIdle 的实现方式可能有所不同(且效率较低)。
归档时间: |
|
查看次数: |
1371 次 |
最近记录: |