## 6.1. Fences

Fences can be used by the host to determine completion of execution of queue operations.

A fence’s status is always either signaled or unsignaled. The host can poll the status of a single fence, or wait for any or all of a group of fences to become signaled.

Fences are represented by `VkFence` handles:

    VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFence)

To create a new fence object, use the command

    VkResult vkCreateFence(
        VkDevice                                    device,
        const VkFenceCreateInfo*                    pCreateInfo,
        const VkAllocationCallbacks*                pAllocator,
        VkFence*                                    pFence);

- `device` is the logical device that creates the fence.
- `pCreateInfo` points to a `VkFenceCreateInfo` structure specifying the state of the fence object.
- `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;

- `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, use the command

    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, which is one of:

- `VK_SUCCESS` indicates that the fence is signaled.
- `VK_NOT_READY` indicates that the fence is unsignaled.

To reset the status of one or more fences to the unsignaled state, use the command:

    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 `fenceCount` fence handles to reset.

If a fence is already in the unsignaled state, then resetting it has no effect.

Fences can be signaled by including them in a queue submission command, defining a queue operation to signal that fence. This fence signal operation defines the first half of a memory dependency, guaranteeing that all memory accesses defined by the queue submission are made available, and that queue operations described by that submission have completed execution. This half of the memory dependency does not include host availability of memory accesses. The second half of the dependency can be defined by `vkWaitForFences`.

Fence signal operations for `vkQueueSubmit` additionally include all queue operations previously submitted via `vkQueueSubmit` in their half of a memory dependency.

To cause the host to wait until any one or all of a group of fences is signaled, use the command:

    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`.

`vkWaitForFences` defines the second half of a memory dependency with the host, for each fence being waited on. The memory dependency defined by signaling a fence and waiting on the host does not guarantee that the results of memory accesses will be visible to the host, or that the memory is available. 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 `dstAccessMask` having the `VK_ACCESS_HOST_READ_BIT` bit set, with `dstStageMask` having the `VK_PIPELINE_STAGE_HOST_BIT` bit set, and with the appropriate `srcStageMask` and `srcAccessMask` members set to guarantee completion of the writes. If the memory was allocated without the `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT` set, then `vkInvalidateMappedMemoryRanges` must be called after the fence is signaled in order to ensure the writes are visible to the host, as described in Host Access to Device Memory Objects.