As described here vkQueueWaitIdle is equivalent of vkFence. So in which situation to use either of them.
3 Answers
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 VkFence
s, 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.VkFence
may 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
.

- 12,301
- 1
- 20
- 34
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.
-
Surely `vkQueueWaitIdle` is actually more like `glFinish`, with `glFlush` rather being analogous to `vkEndCommandBuffer` and `vkQueueSubmit`? – rdb Jan 17 '22 at 09:44
-
@rdb `glFinish` effectively says "ensure that the commands I've executed are sent to the device in finite time, even if I send you no more commands". It's useful when you're streaming data and might deadlock if what you've already sent is never completed. However, the nature of `vkQueueWaitIdle` virtually guarantees that you will create a queue "bubble" because no work is waiting in the queue anymore, at least in a single-threaded single-queue application, which is similar to what `glFlush` does. `glFlush` is probably more similar to queue wait idle + device wait idle, but YMMV. – Jherico Mar 23 '22 at 22:53
-
You have the meanings of `glFlush()` and `glFinish()` reversed in your mind - please see their respective documentation pages. – rdb Mar 25 '22 at 06:31
-
Whoops, you're correct. – Jherico Mar 31 '22 at 21:45
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.

- 47,288
- 5
- 68
- 106