1 Fences and Semaphores
dxtr edited this page 2026-10-11 20:16:09 +02:00

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.