Command Buffers

VkCommandBufferOpaque handle to a command buffer object

Recorded commands include commands to bind pipelines and descriptor sets to the command buffer, commands to modify dynamic state, commands to draw (for graphics rendering), commands to dispatch (for compute), commands to execute secondary command buffers (for primary command buffers only), commands to copy buffers and images, and other commands.

Each command buffer manages state independently of other command buffers. There is no inheritance of state across primary and secondary command buffers, or between secondary command buffers. When a command buffer begins recording, all state in that command buffer is undefined:. When secondary command buffer(s) are recorded to execute on a primary command buffer, the secondary command buffer inherits no state from the primary command buffer, and all state of the primary command buffer is undefined: after an execute secondary command buffer command is recorded. There is one exception to this rule - if the primary command buffer is inside a render pass instance, then the render pass and subpass state is not disturbed by executing secondary command buffers. For state dependent commands (such as draws and dispatches), any state consumed by those commands must not be undefined:.

VkCommandBufferInheritanceViewportScissorInfoNV defines an exception allowing limited inheritance of dynamic viewport and scissor state.

Unless otherwise specified, and without explicit synchronization, the various commands submitted to a queue via command buffers may execute in arbitrary order relative to each other, and/or concurrently. Also, the memory side effects of those commands may not be directly visible to other commands without explicit memory dependencies. This is true within a command buffer, and across command buffers submitted to a given queue. See the synchronization chapter for information on implicit and explicit synchronization between commands.

Command Buffer Lifecycle

Each command buffer is always in one of the following states:

Initial

When a command buffer is allocated, it is in the initial state. Some commands are able to reset a command buffer (or a set of command buffers) back to this state from any of the executable, recording or invalid state. Command buffers in the initial state can only be moved to the recording state, or freed.

Recording

vkBeginCommandBuffer changes the state of a command buffer from the initial state to the recording state. Once a command buffer is in the recording state, vkCmd* commands can be used to record to the command buffer.

Executable

vkEndCommandBuffer ends the recording of a command buffer, and moves it from the recording state to the executable state. Executable command buffers can be submitted, reset, or recorded to another command buffer.

Pending

Queue submission of a command buffer changes the state of a command buffer from the executable state to the pending state. Whilst in the pending state, applications must not attempt to modify the command buffer in any way - as the device may be processing the commands recorded to it. Once execution of a command buffer completes, the command buffer either reverts back to the executable state, or if it was recorded with VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, it moves to the invalid state. A synchronization command should be used to detect when this occurs.

Invalid

Some operations, such as modifying or deleting a resource that was used in a command recorded to a command buffer, will transition the state of that command buffer into the invalid state. Command buffers in the invalid state can only be reset or freed.

Any given command that operates on a command buffer has its own requirements on what state a command buffer must be in, which are detailed in the valid usage constraints for that command.

Resetting a command buffer is an operation that discards any previously recorded commands and puts a command buffer in the initial state. Resetting occurs as a result of vkResetCommandBuffer or vkResetCommandPool, or as part of vkBeginCommandBuffer (which additionally puts the command buffer in the recording state).

Secondary command buffers can be recorded to a primary command buffer via vkCmdExecuteCommands. This partially ties the lifecycle of the two command buffers together - if the primary is submitted to a queue, both the primary and any secondaries recorded to it move to the pending state. Once execution of the primary completes, so it does for any secondary recorded within it. After all executions of each command buffer complete, they each move to their appropriate completion state (either to the executable state or the invalid state, as specified above).

If a secondary moves to the invalid state or the initial state, then all primary buffers it is recorded in move to the invalid state. A primary moving to any other state does not affect the state of a secondary recorded in it.

Resetting or freeing a primary command buffer removes the lifecycle linkage to all secondary command buffers that were recorded into it.

Command Pools

VkCommandPoolOpaque handle to a command pool object
vkCreateCommandPoolCreate a new command pool object
VkCommandPoolCreateInfoStructure specifying parameters of a newly created command pool
VkCommandPoolCreateFlagBitsBitmask specifying usage behavior for a command pool
VkCommandPoolCreateFlagsBitmask of VkCommandPoolCreateFlagBits
vkTrimCommandPoolTrim a command pool
VkCommandPoolTrimFlagsReserved for future use
vkResetCommandPoolReset a command pool
VkCommandPoolResetFlagBitsBitmask controlling behavior of a command pool reset
VkCommandPoolResetFlagsBitmask of VkCommandPoolResetFlagBits
vkDestroyCommandPoolDestroy a command pool object

Command Buffer Allocation and Management

vkAllocateCommandBuffersAllocate command buffers from an existing command pool
VkCommandBufferAllocateInfoStructure specifying the allocation parameters for command buffer object
VkCommandBufferLevelEnumerant specifying a command buffer level
vkResetCommandBufferReset a command buffer to the initial state
VkCommandBufferResetFlagBitsBitmask controlling behavior of a command buffer reset
VkCommandBufferResetFlagsBitmask of VkCommandBufferResetFlagBits
vkFreeCommandBuffersFree command buffers

Command Buffer Recording

vkBeginCommandBufferStart recording a command buffer
VkCommandBufferBeginInfoStructure specifying a command buffer begin operation
VkCommandBufferUsageFlagBitsBitmask specifying usage behavior for command buffer
VkCommandBufferUsageFlagsBitmask of VkCommandBufferUsageFlagBits
VkCommandBufferInheritanceInfoStructure specifying command buffer inheritance information

On some implementations, not using the VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT bit enables command buffers to be patched in-place if needed, rather than creating a copy of the command buffer.

If a command buffer is in the invalid, or executable state, and the command buffer was allocated from a command pool with the VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT flag set, then vkBeginCommandBuffer implicitly resets the command buffer, behaving as if vkResetCommandBuffer had been called with VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT not set. After the implicit reset, commandBuffer is moved to the recording state.

VkCommandBufferInheritanceConditionalRenderingInfoEXTStructure specifying command buffer inheritance information
VkCommandBufferInheritanceRenderPassTransformInfoQCOMStructure describing transformed render pass parameters command buffer
VkCommandBufferInheritanceViewportScissorInfoNVStructure specifying command buffer inheritance information
VkCommandBufferInheritanceRenderingInfoStructure specifying command buffer inheritance info for dynamic render pass instances
VkAttachmentSampleCountInfoAMDStructure specifying command buffer inheritance info for dynamic render pass instances

Once recording starts, an application records a sequence of commands (vkCmd*) to set state in the command buffer, draw, dispatch, and other commands.

Several commands can also be recorded indirectly from VkBuffer content, see Device-Generated Commands.

vkEndCommandBufferFinish recording a command buffer

When a command buffer is in the executable state, it can be submitted to a queue for execution.

Command Buffer Submission

Submission can be a high overhead operation, and applications should attempt to batch work together into as few calls to vkQueueSubmit or vkQueueSubmit2 as possible.

vkQueueSubmit2Submits command buffers to a queue
VkSubmitInfo2Structure specifying a queue submit operation
VkSubmitFlagBitsBitmask specifying behavior of a submission
VkSubmitFlagsBitmask of VkSubmitFlagBits
VkSemaphoreSubmitInfoStructure specifying a semaphore signal or wait operation
VkCommandBufferSubmitInfoStructure specifying a command buffer submission
VkRenderPassStripeSubmitInfoARMStructure specifying striped rendering submit information
vkQueueSubmitSubmits a sequence of semaphores or command buffers to a queue
VkSubmitInfoStructure specifying a queue submit operation
VkTimelineSemaphoreSubmitInfoStructure specifying signal and wait values for timeline semaphores
VkD3D12FenceSubmitInfoKHRStructure specifying values for Direct3D 12 fence-backed semaphores
VkWin32KeyedMutexAcquireReleaseInfoKHRUse the Windows keyed mutex mechanism to synchronize work
VkWin32KeyedMutexAcquireReleaseInfoNVUse Windows keyex mutex mechanism to synchronize work
VkDeviceGroupSubmitInfoStructure indicating which physical devices execute semaphore operations and command buffers

If the pNext chain of VkSubmitInfo includes a VkPerformanceQuerySubmitInfoKHR structure, then the structure indicates which counter pass is active for the batch in that submit.

VkPerformanceQuerySubmitInfoKHRStructure indicating which counter pass index is active for performance queries

Queue Forward Progress

When using binary semaphores, the application must ensure that command buffer submissions will be able to complete without any subsequent operations by the application on any queue. After any call to vkQueueSubmit (or other queue operation), for every queued wait on a semaphore created with a VkSemaphoreType of VK_SEMAPHORE_TYPE_BINARY there must be a prior signal of that semaphore that will not be consumed by a different wait on the semaphore.

When using timeline semaphores, wait-before-signal behavior is well-defined and applications can submit work via vkQueueSubmit defining a timeline semaphore wait operation before submitting a corresponding semaphore signal operation. For each timeline semaphore wait operation defined by a call to vkQueueSubmit, the application must ensure that a corresponding semaphore signal operation is executed before forward progress can be made.

If a command buffer submission waits for any events to be signaled, the application must ensure that command buffer submissions will be able to complete without any subsequent operations by the application. Events signaled by the host must be signaled before the command buffer waits on those events.

The ability for commands to wait on the host to set an events was originally added to allow low-latency updates to resources between host and device. However, to ensure quality of service, implementations would necessarily detect extended stalls in execution and timeout after a short period. As this period is not defined in the Vulkan specification, it is impossible to correctly validate any application with any wait period. Since the original users of this functionality were highly limited and platform-specific, this functionality is now considered defunct and should not be used.

Secondary Command Buffer Execution

vkCmdExecuteCommandsExecute a secondary command buffer from a primary command buffer

Nested Command Buffers

In addition to secondary command buffer execution from primary command buffers, an implementation may support nested command buffers, which enable secondary command buffers to be executed from other secondary command buffers. If the nestedCommandBuffer feature is enabled, the implementation supports nested command buffers.

Nested command buffer execution works the same as primary-to-secondary execution, except that it is subject to some additional implementation-defined limits.

Each secondary command buffer has a command buffer nesting level, which is determined at vkEndCommandBuffer time and evaluated at vkCmdExecuteCommands time. A secondary command buffer that executes no other secondary command buffers has a command buffer nesting level of zero. Otherwise, the command buffer nesting level of a secondary command buffer is equal to the maximum nesting level of all secondary command buffers executed by that command buffer plus one. Some implementations may have a limit on the maximum nesting level of secondary command buffers that can be recorded. This limit is advertised in maxCommandBufferNestingLevel.

If the nestedCommandBufferRendering feature is enabled, the implementation supports calling vkCmdExecuteCommands inside secondary command buffers recorded with VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT. If the nestedCommandBufferSimultaneousUse feature is enabled, the implementation supports calling vkCmdExecuteCommands with secondary command buffers recorded with VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT.

Whenever vkCmdExecuteCommands is recorded inside a secondary command buffer recorded with VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, each member of pCommandBuffers must have been recorded with a VkCommandBufferBeginInfo with VkCommandBufferInheritanceInfo compatible with the VkCommandBufferInheritanceInfo of the command buffer into which the vkCmdExecuteCommands call is being recorded. The VkCommandBufferInheritanceRenderingInfo structures are compatible when the VkCommandBufferInheritanceRenderingInfo::renderpass are compatible, or if they are VK_NULL_HANDLE then the VkCommandBufferInheritanceRenderingInfo members match, and all other members of VkCommandBufferInheritanceRenderingInfo match. This requirement applies recursively, down to the most nested command buffer and up to the command buffer where the render pass was originally begun.

Command Buffer Device Mask

Each command buffer has a piece of state storing the current device mask of the command buffer. This mask controls which physical devices within the logical device all subsequent commands will execute on, including state-setting commands, action commands, and synchronization commands.

Scissor, exclusive scissor, and viewport state (excluding the count of each) can be set to different values on each physical device (only when set as dynamic state), and each physical device will render using its local copy of the state. Other state is shared between physical devices, such that all physical devices use the most recently set values for the state. However, when recording an action command that uses a piece of state, the most recent command that set that state must have included all physical devices that execute the action command in its current device mask.

The command buffer’s device mask is orthogonal to the pCommandBufferDeviceMasks member of VkDeviceGroupSubmitInfo. Commands only execute on a physical device if the device index is set in both device masks.

VkDeviceGroupCommandBufferBeginInfoSet the initial device mask for a command buffer
vkCmdSetDeviceMaskModify device mask of a command buffer