'In what situations is VkFence better than vkQueueWaitIdle for vkQueueSubmit?
As described here vkQueueWaitIdle is equivalent of vkFence. So in which situation to use either of them.
Solution 1:[1]
As you say, vkQueueWaitIdle() is just a special case of Fence use.
So you would use it when you would have to write 10 lines of equivalent Fence code instead — especially if you do not care to remember all the previous queue submissions. It is somewhat a debug feature (most frequently you would use it temporarily to test your synchronization). And it may be useful during cleanup (e.g. application termination, or rebuilding the swapchain).
In all other cases you should prefer VkFences, which are more general:
You can take advantage of advanced
vkWaitForFences()usage. I.e. wait-one vs wait-all andtimeout.You supply it to some command that is supposed to signal it (can't do that with
vkQueueWaitIdle()). You can do something like:vkQueueSubmit( q, 1, si1, fence1 );vkQueueSubmit( q, 1, si2, fence2 );vkWaitFences( fence1 ); // won't block on the 2nd submit unlike vkQueueWaitIdle(q)
which can even be potentially faster than:vkQueueSubmit( q, 1, si1, 0 );vkQueueWaitIdle(q);vkQueueSubmit( q, 1, si2, 0 );You can just query the state of the Fence without waiting with
vkGetFenceStatus(). E.g. having some background job and just periodically asking if it's done already while you do other jobs.VkFencemay be faster even in identical situations.vkQueueWaitIdle()might be implemented asvkQueueSubmit( q, 0, nullptr, fence ); vkWaitFences( fence, infiniteWait );where you would potentially pay extra for thevkQueueSubmit.
Solution 2:[2]
In what situations is VkFence better than vkQueueWaitIdle for vkQueueSubmit?
When you aren't shutting down the Vulkan context, i.e. in virtually all situations. vkQueueWaitIdle is a sledgehammer approach to synchronization, roughly analogous to glFinish(). A Vulkan queue is something you want to keep populated, because when it's empty that's a kind of inefficiency. Using vkQueueWaitIdle creates a kind of synchronization point between the client code and parts of the Vulkan driver, which can potentially lead to stalls and bubbles in the GPU pipeline.
A fence is much more fine-grained. Instead of asking the queue to be empty of all work, you're just asking when it finished the specific set of work queued prior to or with the fence. Even though it still creates a synchronization point by having to sync the client CPU thread with the driver CPU thread, this still leaves the driver free to continue working on the remaining items in the queue.
Semaphores are even better than fences, because they're telling the driver that one piece of work is dependent on another piece of work and letting the driver work out the synchronization entirely internally, but they're not viable for all situations, since sometimes the client needs to know when some piece of work is done.
Solution 3:[3]
Quite frankly you should always prefer waiting on a fence because it is much more flexible.
With a fence you can wait on completion of work without having to wait on work submitted after the work you are waiting on. A fence also allows other threads to push command buffers to the queue without interfering with the wait.
Besides that the WaitQueueIdle may be implemented differently (and less efficiently) compared to waiting on the fence.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | rdb |
| Solution 3 | ratchet freak |
