Table of Contents
Fences and Semaphores
The GPU runs the work you submit while your program goes on. Two objects say when it has finished:
- A fence lets the program wait for the GPU: work signals it when it completes, and the program waits for it.
- A binary semaphore orders work on the GPU: one queue operation signals it and another waits for it, without the program taking part.
These are the two that acquiring and presenting swapchain images need. Timeline semaphores and events are reached through the raw layer.
Fences
(let ((in-flight (vk:create-fence device :signaled t)))
;; each frame:
(vk:wait-for-fence in-flight) ; the previous frame's work is done
(vk:reset-fence in-flight)
;; ... submit work that signals IN-FLIGHT ...
(vk:destroy-fence in-flight))
| Function | What it does |
|---|---|
create-fence device &key signaled |
Make a fence, signaled already if :signaled is true. Start signaled when the first wait comes before the first submit, as in a frame loop. |
wait-for-fence fence &key timeout |
Wait until it is signaled, for at most :timeout nanoseconds (forever by default). Returns true if signaled, false on timeout. |
reset-fence fence |
Make it unsignaled again. |
fence-signaled-p fence |
True if it is signaled, without waiting. |
destroy-fence fence |
Destroy it. No pending work may still signal it. |
Timeouts are vk:nanoseconds, an (unsigned-byte 64); vk:+forever+
waits forever.
(vk:wait-for-fence fence :timeout 16000000) ; at most 16 ms
;; => NIL ; not signaled yet
To pass a fence to a raw command, such as vkQueueSubmit2, use
(vk:raw-handle fence). A struct field that takes a fence takes the
fence object itself.
Binary semaphores
(let ((image-available (vk:create-binary-semaphore device))
(render-finished (vk:create-binary-semaphore device)))
;; acquire signals IMAGE-AVAILABLE; the submit waits for it and
;; signals RENDER-FINISHED; present waits for RENDER-FINISHED.
...
(vk:destroy-binary-semaphore render-finished)
(vk:destroy-binary-semaphore image-available))
| Function | What it does |
|---|---|
create-binary-semaphore device |
Make a binary semaphore. |
destroy-binary-semaphore semaphore |
Destroy it. No queue operation may still use it. |
A semaphore signaled for present to wait on may still be in use until
that image is acquired again. Use one such semaphore per swapchain image,
indexed by the image's index, as the frame loop in Recipes
does, rather than one per frame in flight.
Errors and lifetimes
Using a destroyed fence or semaphore signals destroyed-object-error. A
device cannot be destroyed while its fences and semaphores are alive; it
signals live-children-error naming them. A failing wait, such as one
that finds the device lost, signals a result-error: a
device-lost-error in that case.
Thread rules
Waiting for a fence may happen on several threads at once; resetting or destroying it must not overlap any other use. Destroying a semaphore must not overlap any other use of it.
Allocation
wait-for-fence, reset-fence and fence-signaled-p allocate nothing,
so they may be called every frame.