## 6.3. Events

Events represent a fine-grained synchronization primitive that can be used to gauge progress through a sequence of commands executed on a queue by Vulkan. An event is initially in the unsignaled state. It can be signaled by a device, using commands inserted into the command buffer, or by the host. It can also be reset to the unsignaled state by a device or the host. The host can query the state of an event. A device can wait for one or more events to become signaled.

Events are represented by `VkEvent` handles:

    VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkEvent)

To create an event, call:

    VkResult vkCreateEvent(
        VkDevice                                    device,
        const VkEventCreateInfo*                    pCreateInfo,
        const VkAllocationCallbacks*                pAllocator,
        VkEvent*                                    pEvent);

- `device` is the logical device that creates the event.
- `pCreateInfo` is a pointer to an instance of the `VkEventCreateInfo` structure which contains information about how the event is to be created.
- `pAllocator` controls host memory allocation as described in the Memory Allocation chapter.
- `pEvent` points to a handle in which the resulting event object is returned.

When created, the event object is in the unsignaled state.

The `VkEventCreateInfo` structure is defined as:

    typedef struct VkEventCreateInfo {
        VkStructureType       sType;
        const void*           pNext;
        VkEventCreateFlags    flags;
    } VkEventCreateInfo;

- `flags` is reserved for future use.

To destroy an event, call:

    void vkDestroyEvent(
        VkDevice                                    device,
        VkEvent                                     event,
        const VkAllocationCallbacks*                pAllocator);

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

To query the state of an event from the host, call:

    VkResult vkGetEventStatus(
        VkDevice                                    device,
        VkEvent                                     event);

- `device` is the logical device that owns the event.
- `event` is the handle of the event to query.

Upon success, `vkGetEventStatus` returns the state of the event object with the following return codes:

Table 6.1. Event Object Status Codes

Status | Meaning
--- | ---
`VK_EVENT_SET` | The event specified by `event` is signaled.
`VK_EVENT_RESET` | The event specified by `event` is unsignaled.

If a `vkCmdSetEvent` or `vkCmdResetEvent` command is pending execution, then the value returned by this command may immediately be out of date.

The state of an event can be updated by the host. The state of the event is immediately changed, and subsequent calls to `vkGetEventStatus` will return the new state. If an event is already in the requested state, then updating it to the same state has no effect.

To set the state of an event to signaled from the host, call:

    VkResult vkSetEvent(
        VkDevice                                    device,
        VkEvent                                     event);

- `device` is the logical device that owns the event.
- `event` is the event to set.

To set the state of an event to unsignaled from the host, call:

    VkResult vkResetEvent(
        VkDevice                                    device,
        VkEvent                                     event);

- `device` is the logical device that owns the event.
- `event` is the event to reset.

The state of an event can also be updated on the device by commands inserted in command buffers. To set the state of an event to signaled from a device, call:

    void vkCmdSetEvent(
        VkCommandBuffer                             commandBuffer,
        VkEvent                                     event,
        VkPipelineStageFlags                        stageMask);

- `commandBuffer` is the command buffer into which the command is recorded.
- `event` is the event that will be signaled.
- `stageMask` specifies the pipeline stage at which the state of `event` is updated as described below.

To set the state of an event to unsignaled from a device, call:

    void vkCmdResetEvent(
        VkCommandBuffer                             commandBuffer,
        VkEvent                                     event,
        VkPipelineStageFlags                        stageMask);

- `commandBuffer` is the command buffer into which the command is recorded.
- `event` is the event that will be reset.
- `stageMask` specifies the pipeline stage at which the state of `event` is updated as described below.

For both `vkCmdSetEvent` and `vkCmdResetEvent`, the status of `event` is updated once the pipeline stages specified by `stageMask` (see Section 6.5.2, “Pipeline Stage Flags”) have completed executing prior commands. The command modifying the event is passed through the pipeline bound to the command buffer at time of execution.

To wait for one or more events to enter the signaled state on a device, call:

    void vkCmdWaitEvents(
        VkCommandBuffer                             commandBuffer,
        uint32_t                                    eventCount,
        const VkEvent*                              pEvents,
        VkPipelineStageFlags                        srcStageMask,
        VkPipelineStageFlags                        dstStageMask,
        uint32_t                                    memoryBarrierCount,
        const VkMemoryBarrier*                      pMemoryBarriers,
        uint32_t                                    bufferMemoryBarrierCount,
        const VkBufferMemoryBarrier*                pBufferMemoryBarriers,
        uint32_t                                    imageMemoryBarrierCount,
        const VkImageMemoryBarrier*                 pImageMemoryBarriers);

- `commandBuffer` is the command buffer into which the command is recorded.
- `eventCount` is the length of the `pEvents` array.
- `pEvents` is an array of event object handles to wait on.
- `srcStageMask` (see Section 6.5.2, “Pipeline Stage Flags”) is the bitwise OR of the pipeline stages used to signal the event object handles in `pEvents`.
- `dstStageMask` is the pipeline stages at which the wait will occur.
- `pMemoryBarriers` is a pointer to an array of `memoryBarrierCount` `VkMemoryBarrier` structures.
- `pBufferMemoryBarriers` is a pointer to an array of `bufferMemoryBarrierCount` `VkBufferMemoryBarrier` structures.
- `pImageMemoryBarriers` is a pointer to an array of `imageMemoryBarrierCount` `VkImageMemoryBarrier` structures. See Section 6.5.3, “Memory Barriers” for more details about memory barriers.

`vkCmdWaitEvents` waits for events set by either `vkSetEvent` or `vkCmdSetEvent` to become signaled. Logically, it has three phases:

1. Wait at the pipeline stages specified by `dstStageMask` (see Section 6.5.2, “Pipeline Stage Flags”) until the `eventCount` event objects specified by `pEvents` become signaled. Implementations may wait for each event object to become signaled in sequence (starting with the first event object in `pEvents`, and ending with the last), or wait for all of the event objects to become signaled at the same time.
2. Execute the memory barriers specified by `pMemoryBarriers`, `pBufferMemoryBarriers` and `pImageMemoryBarriers` (see Section 6.5.3, “Memory Barriers”).
3. Resume execution of pipeline stages specified by `dstStageMask`

Implementations may not execute commands in a pipelined manner, so `vkCmdWaitEvents` may not observe the results of a subsequent `vkCmdSetEvent` or `vkCmdResetEvent` command, even if the stages in `dstStageMask` occur after the stages in `srcStageMask`.

Commands that update the state of events in different pipeline stages may execute out of order, unless the ordering is enforced by execution dependencies.

| Note
Applications should be careful to avoid race conditions when using events. For example, an event should only be reset if no `vkCmdWaitEvents` command is executing that waits upon that event.

An act of setting or resetting an event in one queue may not affect or be visible to other queues. For cross-queue synchronization, semaphores can be used.