Vulkan 对于vkQueueSubmit,VkFence在哪些情况下优于vkQueueWaitIdle?

Vulkan 对于vkQueueSubmit,VkFence在哪些情况下优于vkQueueWaitIdle?,vulkan,Vulkan,如上所述,vkQueueWaitIdle相当于vkFence。 所以在哪种情况下可以使用它们中的任何一个。坦率地说,你应该总是选择等待,因为等待更灵活 有了围栏,你可以等待工作完成,而不必等待等待工作完成后提交的工作。围栏还允许其他线程将命令缓冲区推送到队列,而不会干扰等待 除此之外,WaitQueueIdle的实现方式可能与在围栏上等待不同(且效率较低) 正如您所说,vkQueueWaitIdle()只是围栏使用的一个特例 因此,当您需要编写10行等效的Fence代码时,您可以使用它,尤其是当

如上所述,vkQueueWaitIdle相当于vkFence。
所以在哪种情况下可以使用它们中的任何一个。

坦率地说,你应该总是选择等待,因为等待更灵活

有了围栏,你可以等待工作完成,而不必等待等待工作完成后提交的工作。围栏还允许其他线程将命令缓冲区推送到队列,而不会干扰等待


除此之外,WaitQueueIdle的实现方式可能与在围栏上等待不同(且效率较低)

正如您所说,
vkQueueWaitIdle()
只是围栏使用的一个特例

因此,当您需要编写10行等效的Fence代码时,您可以使用它,尤其是当您不想记住以前提交的所有队列时。这在某种程度上是一种调试功能(通常您会临时使用它来测试同步)。在清理过程中(例如,应用程序终止或重建swapchain),它可能很有用

在所有其他情况下,您应该选择更通用的
VkFence
s:

  • 您可以利用高级
    vkWaitForFences()
    用法。也就是说,等待一个vs等待全部和
    超时

  • 您将它提供给某个应该向它发送信号的命令(不能使用
    vkQueueWaitIdle()
    )。您可以执行以下操作:
    vkQueueSubmit(q,1,si1,fence1)
    vkQueueSubmit(q,1,si2,fence2)
    vkwaitfeens(fence1);//与vkQueueWaitIdle(q)不同,不会在第二次提交时阻止
    甚至可能比:
    vkQueueSubmit(q,1,si1,0)
    vkQueueWaitIdle(q)
    vkQueueSubmit(q,1,si2,0)

  • 您可以使用
    vkGetFenceStatus()
    查询围栏的状态,而无需等待。例如,有一些背景工作,只是在做其他工作时定期询问是否已经完成

  • VkFence
    即使在相同的情况下也可能更快
    vkQueueWaitIdle()
    可以实现为
    
    vkQueueSubmit(q,0,空PTR,围栏);
    vkWaitFences(围栏,无限远);
    
    您可能会为
    vkQueueSubmit
    支付额外费用

  • 对于vkQueueSubmit,VkFence在哪些情况下优于vkQueueWaitIdle

    当您没有关闭Vulkan上下文时,即在几乎所有情况下
    vkQueueWaitIdle
    是一种大锤式的同步方法,大致类似于
    glFlush()
    。Vulkan队列是您希望填充的,因为当它为空时,这是一种低效。使用
    vkQueueWaitIdle
    在客户机代码和Vulkan驱动程序部分之间创建一种同步点,这可能导致GPU管道中出现暂停和气泡

    栅栏的纹理要细得多。与其要求队列清空所有工作,您只需询问它何时完成围栏之前或使用围栏排队的特定工作集。即使它仍然通过必须将客户机CPU线程与驱动程序CPU线程同步来创建同步点,这仍然使驱动程序可以继续处理队列中的其余项目

    信号量甚至比fences更好,因为它们告诉驱动程序一项工作依赖于另一项工作,并让驱动程序完全在内部完成同步,但它们并不适用于所有情况,因为有时客户端需要知道某项工作何时完成