Fences are a synchronization primitive that can be used to insert a
dependency from a queue to the host.
Fences have two states - signaled and unsignaled.
A fence can be signaled as part of the execution of a
queue submission command.
Fences can be unsignaled on the host with vkResetFences.
Fences can be waited on by the host with the vkWaitForFences command,
and the current state can be queried with vkGetFenceStatus.
Fences are represented by VkFence handles:
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFence)
To create a fence, call:
VkResult vkCreateFence(
VkDevice device,
const VkFenceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkFence* pFence);
device is the logical device that creates the fence.
pCreateInfo is a pointer to an instance of the
VkFenceCreateInfo structure which contains information about how
the fence is to be created.
pAllocator controls host memory allocation as described in the
Memory Allocation chapter.
pFence points to a handle in which the resulting fence object is
returned.
The VkFenceCreateInfo structure is defined as:
typedef struct VkFenceCreateInfo {
VkStructureType sType;
const void* pNext;
VkFenceCreateFlags flags;
} VkFenceCreateInfo;
sType is the type of this structure.
pNext is NULL or a pointer to an extension-specific structure.
flags defines the initial state and behavior of the fence.
Bits which can be set include:
typedef enum VkFenceCreateFlagBits {
VK_FENCE_CREATE_SIGNALED_BIT = 0x00000001,
} VkFenceCreateFlagBits;
If flags contains VK_FENCE_CREATE_SIGNALED_BIT then the fence
object is created in the signaled state; otherwise it is created in the
unsignaled state.
To destroy a fence, call:
void vkDestroyFence(
VkDevice device,
VkFence fence,
const VkAllocationCallbacks* pAllocator);
device is the logical device that destroys the fence.
fence is the handle of the fence to destroy.
pAllocator controls host memory allocation as described in the
Memory Allocation chapter.
To query the status of a fence from the host, call:
VkResult vkGetFenceStatus(
VkDevice device,
VkFence fence);
device is the logical device that owns the fence.
fence is the handle of the fence to query.
Upon success, vkGetFenceStatus returns the status of the fence object,
with the following return codes:
Table 6.3. Fence Object Status Codes
| Status | Meaning |
|---|---|
| The fence specified by |
| The fence specified by |
If a queue submission command is pending execution, then the value returned by this command may immediately be out of date.
To set the state of fences to unsignaled from the host, call:
VkResult vkResetFences(
VkDevice device,
uint32_t fenceCount,
const VkFence* pFences);
device is the logical device that owns the fences.
fenceCount is the number of fences to reset.
pFences is a pointer to an array of fence handles to reset.
When vkResetFences is executed on the host, it defines a fence
unsignal operation for each fence, which resets the fence to the unsignaled
state.
If any member of pFences is already in the unsignaled state when
vkResetFences is executed, then vkResetFences has no effect on
that fence.
When a fence is submitted to a queue as part of a queue submission command, it defines a memory dependency on the batches that were submitted as part of that command, and defines a fence signal operation which sets the fence to the signaled state.
The first synchronization scope
includes every batch submitted in the same queue submission command.
Fence signal operations that are defined by vkQueueSubmit additionally
include all previous queue submissions to the same queue via
vkQueueSubmit in the first synchronization scope.
The second synchronization scope only includes the fence signal operation.
The first access scope includes all memory access performed by the device.
The second access scope is empty.
To wait for one or more fences to enter the signaled state on the host, call:
VkResult vkWaitForFences(
VkDevice device,
uint32_t fenceCount,
const VkFence* pFences,
VkBool32 waitAll,
uint64_t timeout);
device is the logical device that owns the fences.
fenceCount is the number of fences to wait on.
pFences is a pointer to an array of fenceCount fence
handles.
waitAll is the condition that must be satisfied to successfully
unblock the wait.
If waitAll is VK_TRUE, then the condition is that all fences
in pFences are signaled.
Otherwise, the condition is that at least one fence in pFences is
signaled.
timeout is the timeout period in units of nanoseconds.
timeout is adjusted to the closest value allowed by the
implementation-dependent timeout accuracy, which may be substantially
longer than one nanosecond, and may be longer than the requested
period.
If the condition is satisfied when vkWaitForFences is called, then
vkWaitForFences returns immediately.
If the condition is not satisfied at the time vkWaitForFences is
called, then vkWaitForFences will block and wait up to timeout
nanoseconds for the condition to become satisfied.
If timeout is zero, then vkWaitForFences does not wait, but
simply returns the current state of the fences.
VK_TIMEOUT will be returned in this case if the condition is not
satisfied, even though no actual wait was performed.
If the specified timeout period expires before the condition is satisfied,
vkWaitForFences returns VK_TIMEOUT.
If the condition is satisfied before timeout nanoseconds has expired,
vkWaitForFences returns VK_SUCCESS.
An execution dependency is defined by waiting for a fence to become
signaled, either via vkWaitForFences or by polling on
vkGetFenceStatus.
The first synchronization scope includes only the fence signal operation.
The second synchronization scope
includes the host operations of vkWaitForFences or
vkGetFenceStatus indicating that the fence has become signaled.
| Note | |
|---|---|
Signaling a fence and waiting on the host does not guarantee that the
results of memory accesses will be visible to the host.
To provide that guarantee, the application must insert a memory barrier
between the device writes and the end of the submission that will signal the
fence, with |