英文:
How to synchronize Vulkan swapchain presentation with sempahore destruction
问题
当使用vkQueuePresentKHR()
进行Vulkan呈现时,可以提供多个信号量以在实际进行呈现之前由驱动程序等待。如果我稍后想要使用vkDestroySemaphore()
销毁这些信号量,我需要首先确保呈现操作已经执行完毕。我该如何做到这一点呢?不幸的是,与vkQueueSubmit()
不同,vkQueuePresentKHR()
不支持传递主机可以等待的栅栏。
我考虑的一些不太令人满意的解决方案包括:
-
在呈现队列上调用
vkQueueWaitIdle()
:我阅读Vulkan规范的理解是它只等待“接受栅栏的队列提交命令”,而vkQueuePresentKHR()
不是队列提交命令,它不接受栅栏。此外,这将迫使我在等待完成时完全停止线程,而如果我有一个栅栏,我只需不时轮询它,一旦看到它被触发,就可以立即销毁信号量。 -
调用
vkDeviceWaitIdle()
:存在几乎相同的问题。 -
使用来自扩展
VK_EXT_swapchain_maintenance1
的VkSwapchainPresentFenceInfoEXT
,它显然可以做到我所需要的。不幸的是,这在大多数驱动程序上似乎没有实现。
有没有其他方法建议我可以尝试?
英文:
When presenting with Vulkan using vkQueuePresentKHR()
a number of semaphores can be provided to be waited upon by the driver before really doing the presentation. If I later want to destroy the semaphores with vkDestroySemaphore()
, I need to first make sure that the presentation operation has finished execution. How do I do that? Unfortunately, differently from vkQueueSubmit()
, vkQueuePresentKHR()
does not support passing a fence the host can wait upon.
Some unsatisfying solutions I considered are:
-
Calling
vkQueueWaitIdle()
on the presentation queue: my reading of the Vulkan specifications is that it only waits for "queue submission commands that accept a fence", andvkQueuePresentKHR()
is not a queue submission command and it doesn't accept a fence. Also, it would force me to entirely stop the thread until the wait is done, while if I had a fence I could just poll it every now and then and destroy the semaphores as soon as I see it signaled. -
Calling
vkDeviceWaitIdle()
: has pretty much the same problems. -
Using
VkSwapchainPresentFenceInfoEXT
from extensionVK_EXT_swapchain_maintenance1
, which apparently does precisely what I would need. Unfortunately this doesn't appear to be implemented an basically any driver.
Any suggestion on another approach I could try?
答案1
得分: 2
vkDestroySemaphore
的有效使用规则如下:
所有引用信号量的已提交批次必须已完成执行
有趣的是,vkQueuePresentKHR
不会创建"批次"。您可以从"批次"的定义中看到这一点:它是由"队列提交命令"创建的,而vkQueuePresentKHR
不是。您还可以在呈现函数的文档中看到这一点。将其与其他实际的"队列提交命令"进行比较,您会发现它们都表示它们创建"批次",而呈现函数却没有。
因此,根据标准,很奇怪,但在等待已信号的队列提交操作后销毁这些信号量是100%可行的,而不是等待它们的呈现命令。鉴于vkQueuePresentKHR
与信号量的行为已经有些奇怪(它们不能使用时间线信号量),我想它们可能在幕后阻止信号量被完全销毁或其他一些操作。
请注意,这个问题已经讨论了一段时间。因此,尽管规范似乎表明可以销毁它们,但不清楚这是否是意图或实现方式。尤其是因为扩展EXT_swapchain_mainenance1存在,明确添加了一种在信号后呈现的机制。它明确表示,您允许在信号后销毁信号量。
由于措辞如此宽泛,验证层无法捕捉到它,因为它们甚至不理解正确的行为是什么。
我建议,在能够使用vkQueueWaitIdle
来"确保"呈现完成之前,尽量不要销毁在此处使用的信号量。根据规范,它目前不能保证这一点,但实际上可能会如此。
英文:
vkDestroySemaphore
has, as a Valid Usage rule:
> All submitted batches that refer to semaphore must have completed execution
Here's a fun fact: vkQueuePresentKHR
does not create a "batch". You can see this from the definition of "batch": it's something created by "queue submission commands", which vkQueuePresentKHR
is not. You can also see it in the docs for the present function. Compare it to other actual "queue submission commands", and you see that they all say that they create "batches" while the present function does not.
So as strange as it may be, according to the standard, it is 100% OK to destroy those semaphores after waiting on the queue submission operation that signaled them, not the present command that is waiting on them. Given that vkQueuePresentKHR
already has funny behavior with regard to semaphores (they can't use timeline semaphores), I imagine that they prevent the semaphores from being fully destroyed or whatever behind the scenes.
Note that there has been some discussion of this issue for a while now. So while the specification seems to say that it's OK to destroy them, it's unclear if that is the intent or the way implementations work. Especially since the extension EXT_swapchain_mainenance1 exists which explicitly adds a mechanism to presenting to signal a fence. And it explicitly says that you're allowed to destroy the semaphores after the fence is signaled.
And because the wording is so loose, validation layers can't catch it, since they don't understand what the right behavior even is.
I would say, for the time being, try not to destroy semaphores used here until you can do a vkQueueWaitIdle
to "ensure" that the present is done. By the spec presently, it doesn't ensure this, but practically it probably will.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论