## 6.2. Semaphores

Semaphores are used to coordinate queue operations both within a queue and between different queues. A semaphore’s status is always either signaled or unsignaled.

Semaphores are represented by `VkSemaphore` handles:

    VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSemaphore)

To create a new semaphore object, use the command

    VkResult vkCreateSemaphore(
        VkDevice                                    device,
        const VkSemaphoreCreateInfo*                pCreateInfo,
        const VkAllocationCallbacks*                pAllocator,
        VkSemaphore*                                pSemaphore);

- `device` is the logical device that creates the semaphore.
- `pCreateInfo` points to a `VkSemaphoreCreateInfo` structure specifying the state of the semaphore object.
- `pAllocator` controls host memory allocation as described in the Memory Allocation chapter.
- `pSemaphore` points to a handle in which the resulting semaphore object is returned. The semaphore is created in the unsignaled state.

The `VkSemaphoreCreateInfo` structure is defined as:

    typedef struct VkSemaphoreCreateInfo {
        VkStructureType           sType;
        const void*               pNext;
        VkSemaphoreCreateFlags    flags;
    } VkSemaphoreCreateInfo;

- `sType` is the type of this structure.
- `pNext` is `NULL` or a pointer to an extension-specific structure.
- `flags` is reserved for future use.

To destroy a semaphore, call:

    void vkDestroySemaphore(
        VkDevice                                    device,
        VkSemaphore                                 semaphore,
        const VkAllocationCallbacks*                pAllocator);

- `device` is the logical device that destroys the semaphore.
- `semaphore` is the handle of the semaphore to destroy.
- `pAllocator` controls host memory allocation as described in the Memory Allocation chapter.

Semaphores can be signaled by including them in a batch as part of a queue submission command, defining a queue operation to signal that semaphore. This semaphore signal operation defines the first half of a memory dependency, guaranteeing that all memory accesses defined by the submitted queue operations in the batch are made available, and that those queue operations have completed execution.

Semaphore signal operations for `vkQueueSubmit` additionally include all queue operations previously submitted via `vkQueueSubmit` in their half of a memory dependency, and all batches that are stored at a lower index in the same `pSubmits` array.

Signaling of semaphores can be waited on by similarly including them in a batch, defining a queue operation to wait for a signal. A semaphore wait operation defines the second half of a memory dependency for the semaphores being waited on. This half of the memory dependency guarantees that the first half has completed execution, and also guarantees that all available memory accesses are made visible to the queue operations in the batch.

Semaphore wait operations for `vkQueueSubmit` additionally include all queue operations subsequently submitted via `vkQueueSubmit` in their half of a memory dependency, and all batches that are stored at a higher index in the same `pSubmits` array.

When queue execution reaches a semaphore wait operation, the queue will stall execution of queue operations in the batch until each semaphore becomes signaled. Once all semaphores are signaled, the semaphores will be reset to the unsignaled state, and subsequent queue operations will be permitted to execute.

Semaphore wait operations defined by `vkQueueSubmit` only wait at specific pipeline stages, rather than delaying all of each command buffer’s execution, with the pipeline stages determined by the corresponding element of the `pWaitDstStageMask` member of `VkSubmitInfo`. Execution of work by those stages in subsequent commands is stalled until the corresponding semaphore reaches the signaled state.

| Note
A common scenario for using `pWaitDstStageMask` with values other than `VK_PIPELINE_STAGE_ALL_COMMANDS_BIT` is when synchronizing a window system presentation operation against subsequent command buffers which render the next frame. In this case, a presentation image must not be overwritten until the presentation operation completes, but other pipeline stages can execute without waiting. A mask of `VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT` prevents subsequent color attachment writes from executing until the semaphore signals. Some implementations may be able to execute transfer operations and/or vertex processing work before the semaphore is signaled. If an image layout transition needs to be performed on a swapchain image before it is used in a framebuffer, that can be performed as the first operation submitted to the queue after acquiring the image, and should not prevent other work from overlapping with the presentation operation. For example, a `VkImageMemoryBarrier` could use: `srcStageMask` = `VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT` `srcAccessMask` = `VK_ACCESS_MEMORY_READ_BIT` `dstStageMask` = `VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT` `dstAccessMask` = `VK_ACCESS_COLOR_ATTACHMENT_READ_BIT` | `VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT`. `oldLayout` = `VK_IMAGE_LAYOUT_PRESENT_SRC_KHR` `newLayout` = `VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL` Alternatively, `oldLayout` can be `VK_IMAGE_LAYOUT_UNDEFINED`, if the image’s contents need not be preserved. This barrier accomplishes a dependency chain between previous presentation operations and subsequent color attachment output operations, with the layout transition performed in between, and does not introduce a dependency between previous work and any vertex processing stages. More precisely, the semaphore signals after the presentation operation completes, then the semaphore wait stalls the `VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT` stage, then there is a dependency from that same stage to itself with the layout transition performed in between. (The primary use case for this example is with the presentation extensions, thus the `VK_IMAGE_LAYOUT_PRESENT_SRC_KHR` token is used even though it is not defined in the core Vulkan specification.)