32. Device-Generated Commands
This chapter discusses the generation of command buffer content on the device, for which these principle steps are to be taken:
-
Define a layout describing the sequence of commands which should be generated.
-
Optionally set up device-bindable shaders.
-
Retrieve device addresses by vkGetBufferDeviceAddressEXT for setting buffers on the device.
-
Fill one or more
VkBufferwith the appropriate content that gets interpreted by the command layout. -
Create a
preprocessVkBufferusing the device-queried allocation information. -
Optionally preprocess the input data in a separate action.
-
Generate and execute the actual commands.
The preprocessing step executes in a separate logical pipeline from either graphics or compute. When preprocessing commands in a separate step they must be explicitly synchronized against the command execution. When not preprocessing in a separate step, the preprocessing is automatically synchronized against the command execution.
32.1. Indirect Commands Layout
The device-side command generation happens through an iterative processing of an atomic sequence comprised of command tokens, which are represented by:
// Provided by VK_EXT_device_generated_commands
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutEXT)
or:
// Provided by VK_NV_device_generated_commands
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNV)
Each indirect command layout must have exactly one action command token and it must be the last token in the sequence.
|
Note
|
If the indirect commands layout contains only 1 token, it will be an action command token, and the contents of the indirect buffer will be a sequence of indirect command structures, similar to the ones used for indirect draws and dispatches. On some implementations, using indirect draws and dispatches for these cases will result in increased performance compared to using device-generated commands, due to the overhead that results from using the latter. |
32.1.1. Creation and Deletion
Indirect command layouts for VK_EXT_device_generated_commands are
created by:
// Provided by VK_EXT_device_generated_commands
VkResult vkCreateIndirectCommandsLayoutEXT(
VkDevice device,
const VkIndirectCommandsLayoutCreateInfoEXT* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkIndirectCommandsLayoutEXT* pIndirectCommandsLayout);
-
deviceis the logical device that creates the indirect command layout. -
pCreateInfois a pointer to a VkIndirectCommandsLayoutCreateInfoEXT structure containing parameters affecting creation of the indirect command layout. -
pAllocatorcontrols host memory allocation as described in the Memory Allocation chapter. -
pIndirectCommandsLayoutis a pointer to aVkIndirectCommandsLayoutEXThandle in which the resulting indirect command layout is returned.
The VkIndirectCommandsLayoutCreateInfoEXT structure is defined as:
// Provided by VK_EXT_device_generated_commands
typedef struct VkIndirectCommandsLayoutCreateInfoEXT {
VkStructureType sType;
const void* pNext;
VkIndirectCommandsLayoutUsageFlagsEXT flags;
VkShaderStageFlags shaderStages;
uint32_t indirectStride;
VkPipelineLayout pipelineLayout;
uint32_t tokenCount;
const VkIndirectCommandsLayoutTokenEXT* pTokens;
} VkIndirectCommandsLayoutCreateInfoEXT;
-
sTypeis a VkStructureType value identifying this structure. -
pNextisNULLor a pointer to a structure extending this structure. -
flagsis a bitmask of VkIndirectCommandsLayoutUsageFlagBitsEXT specifying usage rules for this layout. -
shaderStagesis the VkShaderStageFlags that this layout supports. -
indirectStrideis the distance in bytes between sequences in the indirect buffer -
pipelineLayoutis the optional VkPipelineLayout that tokens in this layout use. If thedynamicGeneratedPipelineLayoutfeature is enabled,pipelineLayoutcan be VK_NULL_HANDLE and the layout must be specified by chaining the VkPipelineLayoutCreateInfo structure off thepNext -
tokenCountis the length of the individual command sequence. -
pTokensis a pointer to an array of VkIndirectCommandsLayoutTokenEXT describing each command token in detail.
The following code illustrates some of the flags:
void cmdProcessAllSequences(cmd, indirectExecutionSet, indirectCommandsLayout, indirectAddress, sequencesCount)
{
for (s = 0; s < sequencesCount; s++)
{
sUsed = s;
if (indirectCommandsLayout.flags & VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_EXT) {
sUsed = incoherent_implementation_dependent_permutation[ sUsed ];
}
cmdProcessSequence( cmd, indirectExecutionSet, indirectCommandsLayout, indirectAddress, sUsed );
}
}
When tokens are consumed, an offset is computed based on token offset and
stream stride.
The resulting offset is required to be aligned.
The alignment for a specific token is equal to the scalar alignment of the
data type as defined in Alignment
Requirements, or 4, whichever is lower.
Bits which can be set in
VkIndirectCommandsLayoutCreateInfoEXT::flags, specifying usage
hints of an indirect command layout, are:
// Provided by VK_EXT_device_generated_commands
typedef enum VkIndirectCommandsLayoutUsageFlagBitsEXT {
VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_EXT = 0x00000001,
VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_EXT = 0x00000002,
} VkIndirectCommandsLayoutUsageFlagBitsEXT;
-
VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_EXTspecifies that the layout is always used with the manual preprocessing step through calling vkCmdPreprocessGeneratedCommandsEXT and executed by vkCmdExecuteGeneratedCommandsEXT withisPreprocessedset toVK_TRUE. -
VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_EXTspecifies that the processing of sequences will happen at an implementation-dependent order, which is not guaranteed to be deterministic using the same input data. This flag is ignored when theshaderStagesisVK_SHADER_STAGE_COMPUTE_BITas it is implied that the dispatch sequence is always unordered.
// Provided by VK_EXT_device_generated_commands
typedef VkFlags VkIndirectCommandsLayoutUsageFlagsEXT;
VkIndirectCommandsLayoutUsageFlagsEXT is a bitmask type for setting a
mask of zero or more VkIndirectCommandsLayoutUsageFlagBitsEXT.
Indirect command layouts for VK_EXT_device_generated_commands are
destroyed by:
// Provided by VK_EXT_device_generated_commands
void vkDestroyIndirectCommandsLayoutEXT(
VkDevice device,
VkIndirectCommandsLayoutEXT indirectCommandsLayout,
const VkAllocationCallbacks* pAllocator);
-
deviceis the logical device that destroys the layout. -
indirectCommandsLayoutis the layout to destroy. -
pAllocatorcontrols host memory allocation as described in the Memory Allocation chapter.
Indirect command layouts for VK_NV_device_generated_commands are
created by:
// Provided by VK_NV_device_generated_commands
VkResult vkCreateIndirectCommandsLayoutNV(
VkDevice device,
const VkIndirectCommandsLayoutCreateInfoNV* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkIndirectCommandsLayoutNV* pIndirectCommandsLayout);
-
deviceis the logical device that creates the indirect command layout. -
pCreateInfois a pointer to a VkIndirectCommandsLayoutCreateInfoNV structure containing parameters affecting creation of the indirect command layout. -
pAllocatorcontrols host memory allocation as described in the Memory Allocation chapter. -
pIndirectCommandsLayoutis a pointer to aVkIndirectCommandsLayoutNVhandle in which the resulting indirect command layout is returned.
The VkIndirectCommandsLayoutCreateInfoNV structure is defined as:
// Provided by VK_NV_device_generated_commands
typedef struct VkIndirectCommandsLayoutCreateInfoNV {
VkStructureType sType;
const void* pNext;
VkIndirectCommandsLayoutUsageFlagsNV flags;
VkPipelineBindPoint pipelineBindPoint;
uint32_t tokenCount;
const VkIndirectCommandsLayoutTokenNV* pTokens;
uint32_t streamCount;
const uint32_t* pStreamStrides;
} VkIndirectCommandsLayoutCreateInfoNV;
-
sTypeis a VkStructureType value identifying this structure. -
pNextisNULLor a pointer to a structure extending this structure. -
pipelineBindPointis the VkPipelineBindPoint that this layout targets. -
flagsis a bitmask of VkIndirectCommandsLayoutUsageFlagBitsNV specifying usage hints of this layout. -
tokenCountis the length of the individual command sequence. -
pTokensis an array describing each command token in detail. See VkIndirectCommandsTokenTypeNV and VkIndirectCommandsLayoutTokenNV below for details. -
streamCountis the number of streams used to provide the token inputs. -
pStreamStridesis an array defining the byte stride for each input stream.
The following code illustrates some of the flags:
void cmdProcessAllSequences(cmd, pipeline, indirectCommandsLayout, pIndirectCommandsTokens, sequencesCount, indexbuffer, indexbufferOffset)
{
for (s = 0; s < sequencesCount; s++)
{
sUsed = s;
if (indirectCommandsLayout.flags & VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NV) {
sUsed = indexbuffer.load_uint32( sUsed * sizeof(uint32_t) + indexbufferOffset);
}
if (indirectCommandsLayout.flags & VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NV) {
sUsed = incoherent_implementation_dependent_permutation[ sUsed ];
}
cmdProcessSequence( cmd, pipeline, indirectCommandsLayout, pIndirectCommandsTokens, sUsed );
}
}
When tokens are consumed, an offset is computed based on token offset and
stream stride.
The resulting offset is required to be aligned.
The alignment for a specific token is equal to the scalar alignment of the
data type as defined in Alignment
Requirements, or
VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV::minIndirectCommandsBufferOffsetAlignment,
whichever is lower.
|
Note
|
A |
Bits which can be set in
VkIndirectCommandsLayoutCreateInfoNV::flags, specifying usage
hints of an indirect command layout, are:
// Provided by VK_NV_device_generated_commands
typedef enum VkIndirectCommandsLayoutUsageFlagBitsNV {
VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_NV = 0x00000001,
VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NV = 0x00000002,
VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NV = 0x00000004,
} VkIndirectCommandsLayoutUsageFlagBitsNV;
-
VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_NVspecifies that the layout is always used with the manual preprocessing step through calling vkCmdPreprocessGeneratedCommandsNV and executed by vkCmdExecuteGeneratedCommandsNV withisPreprocessedset toVK_TRUE. -
VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NVspecifies that the input data for the sequences is not implicitly indexed from 0..sequencesUsed, but an application-providedVkBufferencoding the index is provided. -
VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NVspecifies that the processing of sequences can happen at an implementation-dependent order, which is not guaranteed to be coherent using the same input data. This flag is ignored when thepipelineBindPointisVK_PIPELINE_BIND_POINT_COMPUTEas it is implied that the dispatch sequence is always unordered.
// Provided by VK_NV_device_generated_commands
typedef VkFlags VkIndirectCommandsLayoutUsageFlagsNV;
VkIndirectCommandsLayoutUsageFlagsNV is a bitmask type for setting a
mask of zero or more VkIndirectCommandsLayoutUsageFlagBitsNV.
Indirect command layouts for VK_NV_device_generated_commands are
destroyed by:
// Provided by VK_NV_device_generated_commands
void vkDestroyIndirectCommandsLayoutNV(
VkDevice device,
VkIndirectCommandsLayoutNV indirectCommandsLayout,
const VkAllocationCallbacks* pAllocator);
-
deviceis the logical device that destroys the layout. -
indirectCommandsLayoutis the layout to destroy. -
pAllocatorcontrols host memory allocation as described in the Memory Allocation chapter.
32.1.2. Token Input Streams
For VK_EXT_device_generated_commands, the input streams can
contain raw uint32_t values, existing indirect commands such as:
or additional commands as listed below. How the data is used is described in the next section.
The VkBindIndexBufferIndirectCommandEXT structure specifies the input
data for the VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_EXT token.
// Provided by VK_EXT_device_generated_commands
typedef struct VkBindIndexBufferIndirectCommandEXT {
VkDeviceAddress bufferAddress;
uint32_t size;
VkIndexType indexType;
} VkBindIndexBufferIndirectCommandEXT;
-
bufferAddressspecifies a physical address of the VkBuffer used as index buffer. -
sizeis the byte size range which is available for this operation from the provided address. -
indexTypeis a VkIndexType value specifying how indices are treated.
The VkBindVertexBufferIndirectCommandEXT structure specifies the input
data for the VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_EXT token.
// Provided by VK_EXT_device_generated_commands
typedef struct VkBindVertexBufferIndirectCommandEXT {
VkDeviceAddress bufferAddress;
uint32_t size;
uint32_t stride;
} VkBindVertexBufferIndirectCommandEXT;
-
bufferAddressspecifies a physical address of the VkBuffer used as vertex input binding. -
sizeis the byte size range which is available for this operation from the provided address. -
strideis the byte size stride for this vertex input binding as inVkVertexInputBindingDescription::stride.
The VkDrawIndirectCountIndirectCommandEXT structure specifies the
input data for all draw-type tokens.
// Provided by VK_EXT_device_generated_commands
typedef struct VkDrawIndirectCountIndirectCommandEXT {
VkDeviceAddress bufferAddress;
uint32_t stride;
uint32_t commandCount;
} VkDrawIndirectCountIndirectCommandEXT;
-
bufferAddressspecifies a physical address of the VkBuffer used for draw commands. -
strideis the byte size stride for the command arguments -
commandCountis the number of commands to execute
The corresponding indirect draw structure data will be read from the buffer address.
The VkIndirectCommandsStreamNV structure specifies the input data for
one or more tokens at processing time.
// Provided by VK_NV_device_generated_commands
typedef struct VkIndirectCommandsStreamNV {
VkBuffer buffer;
VkDeviceSize offset;
} VkIndirectCommandsStreamNV;
-
bufferspecifies the VkBuffer storing the functional arguments for each sequence. These arguments can be written by the device. -
offsetspecified an offset intobufferwhere the arguments start.
For VK_NV_device_generated_commands, the input streams can contain
raw uint32_t values, existing indirect commands such as:
or additional commands as listed below. How the data is used is described in the next section.
The VkBindShaderGroupIndirectCommandNV structure specifies the input
data for the VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV token.
// Provided by VK_NV_device_generated_commands
typedef struct VkBindShaderGroupIndirectCommandNV {
uint32_t groupIndex;
} VkBindShaderGroupIndirectCommandNV;
-
groupIndexspecifies which shader group of the current bound graphics pipeline is used.
The VkBindIndexBufferIndirectCommandNV structure specifies the input
data for the VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NV token.
// Provided by VK_NV_device_generated_commands
typedef struct VkBindIndexBufferIndirectCommandNV {
VkDeviceAddress bufferAddress;
uint32_t size;
VkIndexType indexType;
} VkBindIndexBufferIndirectCommandNV;
-
bufferAddressspecifies a physical address of the VkBuffer used as index buffer. -
sizeis the byte size range which is available for this operation from the provided address. -
indexTypeis a VkIndexType value specifying how indices are treated. Instead of the Vulkan enum values, a customuint32_tvalue can be mapped to VkIndexType by specifying theVkIndirectCommandsLayoutTokenNV::pIndexTypesandVkIndirectCommandsLayoutTokenNV::pIndexTypeValuesarrays.
The VkBindVertexBufferIndirectCommandNV structure specifies the input
data for the VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NV token.
// Provided by VK_NV_device_generated_commands
typedef struct VkBindVertexBufferIndirectCommandNV {
VkDeviceAddress bufferAddress;
uint32_t size;
uint32_t stride;
} VkBindVertexBufferIndirectCommandNV;
-
bufferAddressspecifies a physical address of the VkBuffer used as vertex input binding. -
sizeis the byte size range which is available for this operation from the provided address. -
strideis the byte size stride for this vertex input binding as inVkVertexInputBindingDescription::stride. It is only used ifVkIndirectCommandsLayoutTokenNV::vertexDynamicStridewas set, otherwise the stride is inherited from the current bound graphics pipeline.
The VkSetStateFlagsIndirectCommandNV structure specifies the input
data for the VK_INDIRECT_COMMANDS_TOKEN_TYPE_STATE_FLAGS_NV token.
Which state is changed depends on the VkIndirectStateFlagBitsNV
specified at VkIndirectCommandsLayoutNV creation time.
// Provided by VK_NV_device_generated_commands
typedef struct VkSetStateFlagsIndirectCommandNV {
uint32_t data;
} VkSetStateFlagsIndirectCommandNV;
-
dataencodes packed state that this command alters.-
Bit
0: If set representsVK_FRONT_FACE_CLOCKWISE, otherwiseVK_FRONT_FACE_COUNTER_CLOCKWISE
-
A subset of the graphics pipeline state can be altered using indirect state flags:
// Provided by VK_NV_device_generated_commands
typedef enum VkIndirectStateFlagBitsNV {
VK_INDIRECT_STATE_FLAG_FRONTFACE_BIT_NV = 0x00000001,
} VkIndirectStateFlagBitsNV;
-
VK_INDIRECT_STATE_FLAG_FRONTFACE_BIT_NVallows to toggle the VkFrontFace rasterization state for subsequent drawing commands.
// Provided by VK_NV_device_generated_commands
typedef VkFlags VkIndirectStateFlagsNV;
VkIndirectStateFlagsNV is a bitmask type for setting a mask of zero or
more VkIndirectStateFlagBitsNV.
The VkBindPipelineIndirectCommandNV structure specifies the input data
for the VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NV token.
// Provided by VK_NV_device_generated_commands_compute
typedef struct VkBindPipelineIndirectCommandNV {
VkDeviceAddress pipelineAddress;
} VkBindPipelineIndirectCommandNV;
-
pipelineAddressspecifies the pipeline address of the compute pipeline that will be used in device generated rendering.
32.1.3. Tokenized Command Processing
The processing for VK_EXT_device_generated_commands is in principle
illustrated below:
void cmdProcessSequence(cmd, indirectExecutionSet, indirectCommandsLayout, indirectAddress, s)
{
for (t = 0; t < indirectCommandsLayout.tokenCount; t++)
{
uint32_t offset = indirectCommandsLayout.pTokens[t].offset;
uint32_t stride = indirectCommandsLayout.indirectStride;
VkDeviceAddress streamData = indirectAddress;
const void* input = streamData + stride * s + offset;
// further details later
indirectCommandsLayout.pTokens[t].command (cmd, indirectExecutionSet, input, s);
}
}
void cmdProcessAllSequences(cmd, indirectExecutionSet, indirectCommandsLayout, indirectAddress, sequencesCount)
{
for (s = 0; s < sequencesCount; s++)
{
sUsed = s;
if (indirectCommandsLayout.flags & VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_EXT) {
sUsed = incoherent_implementation_dependent_permutation[ sUsed ];
}
cmdProcessSequence( cmd, indirectExecutionSet, indirectCommandsLayout, indirectAddress, sUsed );
}
}
The processing of each sequence is considered stateless, therefore all state changes must occur prior to action commands within the sequence. A single sequence is strictly targeting the VkShaderStageFlags it was created with.
The primary input data for each token is provided through VkBuffer
content at preprocessing using vkCmdPreprocessGeneratedCommandsEXT or
execution time using vkCmdExecuteGeneratedCommandsEXT, however some
functional arguments, for example push constant layouts, are specified at
layout creation time.
The input size is different for each token.
Possible values of those elements of the
VkIndirectCommandsLayoutCreateInfoEXT::pTokens array specifying
command tokens (other elements of the array specify command parameters) are:
// Provided by VK_EXT_device_generated_commands
typedef enum VkIndirectCommandsTokenTypeEXT {
VK_INDIRECT_COMMANDS_TOKEN_TYPE_EXECUTION_SET_EXT = 0,
VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_EXT = 1,
VK_INDIRECT_COMMANDS_TOKEN_TYPE_SEQUENCE_INDEX_EXT = 2,
VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_EXT = 3,
VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_EXT = 4,
VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_EXT = 5,
VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_EXT = 6,
VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_COUNT_EXT = 7,
VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_COUNT_EXT = 8,
VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_EXT = 9,
// Provided by VK_EXT_device_generated_commands with VK_NV_mesh_shader
VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_NV_EXT = 1000202002,
// Provided by VK_EXT_device_generated_commands with VK_NV_mesh_shader
VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_COUNT_NV_EXT = 1000202003,
// Provided by VK_EXT_device_generated_commands with VK_EXT_mesh_shader
VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_EXT = 1000328000,
// Provided by VK_EXT_device_generated_commands with VK_EXT_mesh_shader
VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_COUNT_EXT = 1000328001,
// Provided by VK_KHR_ray_tracing_maintenance1 with VK_EXT_device_generated_commands
VK_INDIRECT_COMMANDS_TOKEN_TYPE_TRACE_RAYS2_EXT = 1000386004,
} VkIndirectCommandsTokenTypeEXT;
| Common Tokens | Command Data |
|---|---|
|
|
|
|
|
|
Compute Tokens |
|
|
|
Ray Tracing Tokens |
|
|
|
Graphics State Tokens |
|
|
|
|
|
Graphics Draw Tokens |
|
|
|
|
|
|
|
|
|
Graphics Draw Count Tokens |
|
|
VkDrawIndirectCountIndirectCommandEXT with VkDrawIndexedIndirectCommand |
|
VkDrawIndirectCountIndirectCommandEXT with VkDrawIndirectCommand |
|
VkDrawIndirectCountIndirectCommandEXT with VkDrawMeshTasksIndirectCommandEXT |
|
VkDrawIndirectCountIndirectCommandEXT with VkDrawMeshTasksIndirectCommandNV |
The VkIndirectCommandsLayoutTokenEXT structure specifies details to
the function arguments that need to be known at layout creation time:
// Provided by VK_EXT_device_generated_commands
typedef struct VkIndirectCommandsLayoutTokenEXT {
VkStructureType sType;
const void* pNext;
VkIndirectCommandsTokenTypeEXT type;
VkIndirectCommandsTokenDataEXT data;
uint32_t offset;
} VkIndirectCommandsLayoutTokenEXT;
-
sTypeis a VkStructureType value identifying this structure. -
pNextisNULLor a pointer to a structure extending this structure. -
typespecifies the VkIndirectCommandsTokenTypeEXT fordata. -
dataspecifies a VkIndirectCommandsTokenDataEXT containing token-specific details for command execution. It is ignored iftypedoes not match any member of the VkIndirectCommandsTokenDataEXT union. -
offsetis the relative byte offset for the token within one sequence of the indirect buffer. The data stored at that offset is the command data for the token, e.g.VkDispatchIndirectCommand.
The VkIndirectCommandsTokenDataEXT structure provides token-specific
details used to generate the indirect execution layout.
// Provided by VK_EXT_device_generated_commands
typedef union VkIndirectCommandsTokenDataEXT {
const VkIndirectCommandsPushConstantTokenEXT* pPushConstant;
const VkIndirectCommandsVertexBufferTokenEXT* pVertexBuffer;
const VkIndirectCommandsIndexBufferTokenEXT* pIndexBuffer;
const VkIndirectCommandsExecutionSetTokenEXT* pExecutionSet;
} VkIndirectCommandsTokenDataEXT;
-
pPushConstantis a pointer to a VkIndirectCommandsPushConstantTokenEXT structure needed forVK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_EXTandVK_INDIRECT_COMMANDS_TOKEN_TYPE_SEQUENCE_INDEX_EXTtokens -
pVertexBufferis a pointer to a VkIndirectCommandsVertexBufferTokenEXT structure needed forVK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_EXTtokens -
pIndexBufferis a pointer to a VkIndirectCommandsIndexBufferTokenEXT structure needed forVK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_EXTtokens -
pExecutionSetis a pointer to a VkIndirectCommandsExecutionSetTokenEXT structure needed forVK_INDIRECT_COMMANDS_TOKEN_TYPE_EXECUTION_SET_EXTtokens
The appropriate member of the union must be set for each token.
The following code provides detailed information on how an individual sequence is processed. For valid usage, all restrictions from the regular commands apply.
void cmdProcessSequence(cmd, indirectExecutionSet, indirectCommandsLayout, indirectAddress, s)
{
for (uint32_t t = 0; t < indirectCommandsLayout.tokenCount; t++) {
VkIndirectCommandsLayoutTokenEXT *token = &indirectCommandsLayout.pTokens[t];
uint32_t offset = token->offset;
uint32_t stride = indirectCommandsLayout.indirectStride;
VkDeviceAddress streamData = indirectAddress;
const void* input = streamData + stride * s + offset;
switch (token->tokenType) {
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_EXECUTION_SET_EXT:
uint32_t *bind = input;
VkIndirectCommandsExecutionSetTokenEXT *info = token->data.pExecutionSet;
if (info->type == VK_INDIRECT_EXECUTION_SET_INFO_TYPE_PIPELINES_EXT) {
vkCmdBindPipeline(cmd, indirectExecutionSet.pipelineBindPoint, indirectExecutionSet.pipelines[*bind]);
} else {
VkShaderStageFlagBits stages[];
VkShaderEXT shaders[];
uint32_t i = 0;
IterateBitmaskLSBToMSB(iter, info->shaderStages) {
stages[i] = iter;
shaders[i] = indirectExecutionSet.shaders[bind[i]].shaderObject;
i++;
}
vkCmdBindShadersEXT(cmd, i, stages, shaders);
}
break;
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_EXT:
uint32_t* data = input;
VkPushConstantsInfoKHR info = {
VK_STRUCTURE_TYPE_PUSH_CONSTANTS_INFO_KHR,
// this can also use `dynamicGeneratedPipelineLayout' to pass a VkPipelineLayoutCreateInfo from pNext
indirectCommandsLayout.pipelineLayout,
token->token.pushConstant.updateRange.shaderStages,
token->token.pushConstant.updateRange.offset,
token->token.pushConstant.updateRange.size,
data
};
vkCmdPushConstants2KHR(cmd, &info);
break;
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_SEQUENCE_INDEX_EXT:
VkPushConstantsInfoKHR info = {
VK_STRUCTURE_TYPE_PUSH_CONSTANTS_INFO_KHR,
// this can also use `dynamicGeneratedPipelineLayout' to pass a VkPipelineLayoutCreateInfo from pNext
indirectCommandsLayout.pipelineLayout,
token->token.pushConstant.updateRange.shaderStages,
token->token.pushConstant.updateRange.offset,
// this must be 4
token->token.pushConstant.updateRange.size,
// this just updates the sequence index
&s
};
vkCmdPushConstants2KHR(cmd, &info);
break;
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_EXT:
VkBindIndexBufferIndirectCommandEXT* data = input;
vkCmdBindIndexBuffer(cmd, deriveBuffer(data->bufferAddress), deriveOffset(data->bufferAddress), data->indexType);
break;
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_EXT:
VkBindVertexBufferIndirectCommandEXT* data = input;
vkCmdBindVertexBuffers2(cmd, token->token.vertexBuffer->vertexBindingUnit, 1, &deriveBuffer(data->bufferAddress),
&deriveOffset(data->bufferAddress), data->size, data->stride);
break;
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_EXT:
VkDrawIndexedIndirectCommand *data = input;
vkCmdDrawIndexed(cmd, data->indexCount, data->instanceCount, data->firstIndex, data->vertexOffset, data->firstInstance);
break;
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_COUNT_EXT:
VkDrawIndirectCountIndirectCommandEXT* data = input;
vkCmdDrawIndexedIndirect(cmd, deriveBuffer(data->bufferAddress), deriveoffset(data->bufferAddress), min(data->commandCount, indirectCommandsLayout.maxDrawCount), data->stride);
break;
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_EXT:
VkDrawIndirectCommand* data = input;
vkCmdDraw(cmd, data->vertex_count, data->instanceCount, data->firstVertex, data->firstIndex);
break;
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_COUNT_EXT:
VkDrawIndirectCountIndirectCommandEXT* data = input;
vkCmdDrawIndirect(cmd, deriveBuffer(data->bufferAddress), deriveoffset(data->bufferAddress), min(data->commandCount, indirectCommandsLayout.maxDrawCount), data->stride);
break;
// only available if VK_NV_mesh_shader is enabled
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_NV_EXT:
VkDrawMeshTasksIndirectCommandNV *data = input;
vkCmdDrawMeshTasksNV(cmd, data->taskCount, data->firstTask);
break;
// only available if VK_NV_mesh_shader is enabled
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_COUNT_NV_EXT:
VkDrawIndirectCountIndirectCommandEXT* data = input;
vkCmdDrawMeshTasksIndirectCountNV(cmd, deriveBuffer(data->bufferAddress), deriveoffset(data->bufferAddress), min(data->commandCount, indirectCommandsLayout.maxDrawCount), data->stride);
break;
// only available if VK_EXT_mesh_shader is enabled
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_EXT:
VkDrawMeshTasksIndirectCommandEXT *data = input;
vkCmdDrawMeshTasksEXT(cmd, data->groupCountX, data->groupCountY, data->groupCountZ);
break;
// only available if VK_EXT_mesh_shader is enabled
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_COUNT_EXT:
VkDrawIndirectCountIndirectCommandEXT* data = input;
vkCmdDrawMeshTasksIndirectCountEXT(cmd, deriveBuffer(data->bufferAddress), deriveoffset(data->bufferAddress), min(data->commandCount, indirectCommandsLayout.maxDrawCount), data->stride);
break;
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_EXT:
VkDispatchIndirectCommand *data = input;
vkCmdDispatch(cmd, data->x, data->y, data->z);
break;
// only available if VK_KHR_ray_tracing_maintenance1 is enabled
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_TRACE_RAYS2_EXT:
vkCmdTraceRaysIndirect2KHR(cmd, deriveBuffer(input));
break;
}
}
}
The processing for VK_NV_device_generated_commands is in principle
illustrated below:
void cmdProcessSequence(cmd, pipeline, indirectCommandsLayout, pIndirectCommandsStreams, s)
{
for (t = 0; t < indirectCommandsLayout.tokenCount; t++)
{
uint32_t stream = indirectCommandsLayout.pTokens[t].stream;
uint32_t offset = indirectCommandsLayout.pTokens[t].offset;
uint32_t stride = indirectCommandsLayout.pStreamStrides[stream];
stream = pIndirectCommandsStreams[stream];
const void* input = stream.buffer.pointer( stream.offset + stride * s + offset )
// further details later
indirectCommandsLayout.pTokens[t].command (cmd, pipeline, input, s);
}
}
void cmdProcessAllSequences(cmd, pipeline, indirectCommandsLayout, pIndirectCommandsStreams, sequencesCount)
{
for (s = 0; s < sequencesCount; s++)
{
cmdProcessSequence(cmd, pipeline, indirectCommandsLayout, pIndirectCommandsStreams, s);
}
}
The processing of each sequence is considered stateless, therefore all state changes must occur before any action command tokens within the sequence. A single sequence is strictly targeting the VkPipelineBindPoint it was created with.
The primary input data for each token is provided through VkBuffer
content at preprocessing using vkCmdPreprocessGeneratedCommandsNV or
execution time using vkCmdExecuteGeneratedCommandsNV, however some
functional arguments, for example binding sets, are specified at layout
creation time.
The input size is different for each token.
The VkIndirectCommandsPushConstantTokenEXT structure specifies the
layout token info for
VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_EXT and
VK_INDIRECT_COMMANDS_TOKEN_TYPE_SEQUENCE_INDEX_EXT tokens.
// Provided by VK_EXT_device_generated_commands
typedef struct VkIndirectCommandsPushConstantTokenEXT {
VkPushConstantRange updateRange;
} VkIndirectCommandsPushConstantTokenEXT;
-
updateRangeis the push constant range that will be updated by the token.
The stageFlags member of updateRange is ignored.
The VkIndirectCommandsVertexBufferTokenEXT structure specifies the
layout token info for the
VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_EXT token.
// Provided by VK_EXT_device_generated_commands
typedef struct VkIndirectCommandsVertexBufferTokenEXT {
uint32_t vertexBindingUnit;
} VkIndirectCommandsVertexBufferTokenEXT;
-
vertexBindingUnitis the vertex input binding number to be bound.
The VkIndirectCommandsIndexBufferTokenEXT structure specifies the
layout token info for the
VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_EXT token.
// Provided by VK_EXT_device_generated_commands
typedef struct VkIndirectCommandsIndexBufferTokenEXT {
VkIndirectCommandsInputModeFlagBitsEXT mode;
} VkIndirectCommandsIndexBufferTokenEXT;
-
modespecifies the mode to use with this token.
This allows for easy layering of Vulkan atop other APIs.
When VK_INDIRECT_COMMANDS_INPUT_MODE_DXGI_INDEX_BUFFER_EXT is
specified, the indirect buffer can contain a D3D12_INDEX_BUFFER_VIEW
instead of VkBindIndexBufferIndirectCommandEXT as D3D’s DXGI format
value is mapped to the VkIndexType.
It works as both structs are otherwise binary compatible.
Bits which are set in
VkIndirectCommandsIndexBufferTokenEXT::mode, specifying how an
index buffer is used, are:
// Provided by VK_EXT_device_generated_commands
typedef enum VkIndirectCommandsInputModeFlagBitsEXT {
VK_INDIRECT_COMMANDS_INPUT_MODE_VULKAN_INDEX_BUFFER_EXT = 0x00000001,
VK_INDIRECT_COMMANDS_INPUT_MODE_DXGI_INDEX_BUFFER_EXT = 0x00000002,
} VkIndirectCommandsInputModeFlagBitsEXT;
-
VK_INDIRECT_COMMANDS_INPUT_MODE_VULKAN_INDEX_BUFFER_EXTspecifies that the indirect buffer contains VkBindIndexBufferIndirectCommandEXT. -
VK_INDIRECT_COMMANDS_INPUT_MODE_DXGI_INDEX_BUFFER_EXTspecifies that the indirect buffer containsD3D12_INDEX_BUFFER_VIEW.
// Provided by VK_EXT_device_generated_commands
typedef VkFlags VkIndirectCommandsInputModeFlagsEXT;
VkIndirectCommandsInputModeFlagsEXT is a bitmask type for setting a
mask of zero or more VkIndirectCommandsInputModeFlagBitsEXT.
The VkIndirectCommandsExecutionSetTokenEXT structure specifies the
input data for the VK_INDIRECT_COMMANDS_TOKEN_TYPE_EXECUTION_SET_EXT
token.
// Provided by VK_EXT_device_generated_commands
typedef struct VkIndirectCommandsExecutionSetTokenEXT {
VkIndirectExecutionSetInfoTypeEXT type;
VkShaderStageFlags shaderStages;
} VkIndirectCommandsExecutionSetTokenEXT;
-
typedescribes the type of indirect execution set in use. -
shaderStagesspecifies the shaders that will be changed by this token.
Possible values of those elements of the
VkIndirectCommandsLayoutCreateInfoNV::pTokens array specifying
command tokens (other elements of the array specify command parameters) are:
// Provided by VK_NV_device_generated_commands
typedef enum VkIndirectCommandsTokenTypeNV {
VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV = 0,
VK_INDIRECT_COMMANDS_TOKEN_TYPE_STATE_FLAGS_NV = 1,
VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NV = 2,
VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NV = 3,
VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV = 4,
VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NV = 5,
VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NV = 6,
VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV = 7,
// Provided by VK_EXT_mesh_shader with VK_NV_device_generated_commands
VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_NV = 1000328000,
// Provided by VK_NV_device_generated_commands_compute
VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NV = 1000428003,
// Provided by VK_NV_device_generated_commands_compute
VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NV = 1000428004,
} VkIndirectCommandsTokenTypeNV;
| Token type | Equivalent command |
|---|---|
|
|
|
- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The VkIndirectCommandsLayoutTokenNV structure specifies details to the
function arguments that need to be known at layout creation time:
// Provided by VK_NV_device_generated_commands
typedef struct VkIndirectCommandsLayoutTokenNV {
VkStructureType sType;
const void* pNext;
VkIndirectCommandsTokenTypeNV tokenType;
uint32_t stream;
uint32_t offset;
uint32_t vertexBindingUnit;
VkBool32 vertexDynamicStride;
VkPipelineLayout pushconstantPipelineLayout;
VkShaderStageFlags pushconstantShaderStageFlags;
uint32_t pushconstantOffset;
uint32_t pushconstantSize;
VkIndirectStateFlagsNV indirectStateFlags;
uint32_t indexTypeCount;
const VkIndexType* pIndexTypes;
const uint32_t* pIndexTypeValues;
} VkIndirectCommandsLayoutTokenNV;
-
sTypeis a VkStructureType value identifying this structure. -
pNextisNULLor a pointer to a structure extending this structure. -
tokenTypeis a VkIndirectCommandsTokenTypeNV specifying the token command type. -
streamis the index of the input stream containing the token argument data. -
offsetis a relative starting offset within the input stream memory for the token argument data. -
vertexBindingUnitis used for the vertex buffer binding command. -
vertexDynamicStridesets if the vertex buffer stride is provided by the binding command rather than the current bound graphics pipeline state. -
pushconstantPipelineLayoutis theVkPipelineLayoutused for the push constant command. -
pushconstantShaderStageFlagsare the shader stage flags used for the push constant command. -
pushconstantOffsetis the offset used for the push constant command. -
pushconstantSizeis the size used for the push constant command. -
indirectStateFlagsis a VkIndirectStateFlagsNV bitfield indicating the active states for the state flag command. -
indexTypeCountis the optional size of thepIndexTypesandpIndexTypeValuesarray pairings. If not zero, it allows to register a customuint32_tvalue to be treated as specific VkIndexType. -
pIndexTypesis the used VkIndexType for the correspondinguint32_tvalue entry inpIndexTypeValues.
The following code provides detailed information on how an individual sequence is processed. For valid usage, all restrictions from the regular commands apply.
void cmdProcessSequence(cmd, pipeline, indirectCommandsLayout, pIndirectCommandsStreams, s)
{
for (uint32_t t = 0; t < indirectCommandsLayout.tokenCount; t++){
token = indirectCommandsLayout.pTokens[t];
uint32_t stride = indirectCommandsLayout.pStreamStrides[token.stream];
stream = pIndirectCommandsStreams[token.stream];
uint32_t offset = stream.offset + stride * s + token.offset;
const void* input = stream.buffer.pointer( offset )
switch(input.type){
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV:
VkBindShaderGroupIndirectCommandNV* bind = input;
vkCmdBindPipelineShaderGroupNV(cmd, indirectCommandsLayout.pipelineBindPoint,
pipeline, bind->groupIndex);
break;
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_STATE_FLAGS_NV:
VkSetStateFlagsIndirectCommandNV* state = input;
if (token.indirectStateFlags & VK_INDIRECT_STATE_FLAG_FRONTFACE_BIT_NV){
if (state.data & (1 << 0)){
set VK_FRONT_FACE_CLOCKWISE;
} else {
set VK_FRONT_FACE_COUNTER_CLOCKWISE;
}
}
break;
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV:
uint32_t* data = input;
vkCmdPushConstants(cmd,
token.pushconstantPipelineLayout
token.pushconstantStageFlags,
token.pushconstantOffset,
token.pushconstantSize, data);
break;
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NV:
VkBindIndexBufferIndirectCommandNV* data = input;
// the indexType may optionally be remapped
// from a custom uint32_t value, via
// VkIndirectCommandsLayoutTokenNV::pIndexTypeValues
vkCmdBindIndexBuffer(cmd,
deriveBuffer(data->bufferAddress),
deriveOffset(data->bufferAddress),
data->indexType);
break;
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NV:
VkBindVertexBufferIndirectCommandNV* data = input;
// if token.vertexDynamicStride is VK_TRUE
// then the stride for this binding is set
// using data->stride as well
vkCmdBindVertexBuffers(cmd,
token.vertexBindingUnit, 1,
&deriveBuffer(data->bufferAddress),
&deriveOffset(data->bufferAddress));
break;
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NV:
vkCmdDrawIndexedIndirect(cmd,
stream.buffer, offset, 1, 0);
break;
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NV:
vkCmdDrawIndirect(cmd,
stream.buffer,
offset, 1, 0);
break;
// only available if VK_NV_mesh_shader is supported
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV:
vkCmdDrawMeshTasksIndirectNV(cmd,
stream.buffer, offset, 1, 0);
break;
// only available if VK_EXT_mesh_shader is supported
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_NV:
vkCmdDrawMeshTasksIndirectEXT(cmd,
stream.buffer, offset, 1, 0);
break;
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NV:
VkBindPipelineIndirectCommandNV *data = input;
VkPipeline computePipeline = deriveFromDeviceAddress(data->pipelineAddress);
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline);
break;
case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NV:
vkCmdDispatchIndirect(cmd, stream.buffer, offset);
break;
}
}
}
32.2. Indirect Commands Generation and Execution
The generation of commands on the device requires a preprocess buffer.
With VK_EXT_device_generated_commands, to retrieve the memory size
and alignment requirements of a particular execution state call:
// Provided by VK_EXT_device_generated_commands
void vkGetGeneratedCommandsMemoryRequirementsEXT(
VkDevice device,
const VkGeneratedCommandsMemoryRequirementsInfoEXT* pInfo,
VkMemoryRequirements2* pMemoryRequirements);
-
deviceis the logical device that owns the buffer. -
pInfois a pointer to a VkGeneratedCommandsMemoryRequirementsInfoEXT structure containing parameters required for the memory requirements query. -
pMemoryRequirementsis a pointer to a VkMemoryRequirements2 structure in which the memory requirements of the buffer object are returned.
If the size returned is zero, the preprocessing step can be skipped for this layout.
// Provided by VK_EXT_device_generated_commands
typedef struct VkGeneratedCommandsMemoryRequirementsInfoEXT {
VkStructureType sType;
const void* pNext;
VkIndirectExecutionSetEXT indirectExecutionSet;
VkIndirectCommandsLayoutEXT indirectCommandsLayout;
uint32_t maxSequenceCount;
uint32_t maxDrawCount;
} VkGeneratedCommandsMemoryRequirementsInfoEXT;
-
sTypeis a VkStructureType value identifying this structure. -
pNextisNULLor a pointer to a structure extending this structure. -
indirectExecutionSetis the indirect execution set to be used for binding shaders. -
indirectCommandsLayoutis the VkIndirectCommandsLayoutEXT that this buffer memory is intended to be used with. -
maxSequenceCountis the maximum number of sequences that this buffer memory can be used with. -
maxDrawCountis the maximum number of indirect draws that can be executed by any COUNT-type multi-draw indirect tokens. The draw count in the indirect buffer is clamped to this value for these token types.
If the action command token for the layout is not a COUNT-type multi-draw
indirect token, maxDrawCount is ignored.
// Provided by VK_EXT_device_generated_commands
typedef struct VkGeneratedCommandsPipelineInfoEXT {
VkStructureType sType;
void* pNext;
VkPipeline pipeline;
} VkGeneratedCommandsPipelineInfoEXT;
-
sTypeis a VkStructureType value identifying this structure. -
pNextisNULLor a pointer to a structure extending this structure. -
pipelineis a valid pipeline object.
// Provided by VK_EXT_device_generated_commands
typedef struct VkGeneratedCommandsShaderInfoEXT {
VkStructureType sType;
void* pNext;
uint32_t shaderCount;
const VkShaderEXT* pShaders;
} VkGeneratedCommandsShaderInfoEXT;
-
sTypeis a VkStructureType value identifying this structure. -
pNextisNULLor a pointer to a structure extending this structure. -
shaderCountis the size of thepShadersarray. -
pShadersis a pointer to an array of shader objects.
With VK_NV_device_generated_commands, to retrieve the memory size
and alignment requirements of a particular execution state call:
// Provided by VK_NV_device_generated_commands
void vkGetGeneratedCommandsMemoryRequirementsNV(
VkDevice device,
const VkGeneratedCommandsMemoryRequirementsInfoNV* pInfo,
VkMemoryRequirements2* pMemoryRequirements);
-
deviceis the logical device that owns the buffer. -
pInfois a pointer to a VkGeneratedCommandsMemoryRequirementsInfoNV structure containing parameters required for the memory requirements query. -
pMemoryRequirementsis a pointer to a VkMemoryRequirements2 structure in which the memory requirements of the buffer object are returned.
// Provided by VK_NV_device_generated_commands
typedef struct VkGeneratedCommandsMemoryRequirementsInfoNV {
VkStructureType sType;
const void* pNext;
VkPipelineBindPoint pipelineBindPoint;
VkPipeline pipeline;
VkIndirectCommandsLayoutNV indirectCommandsLayout;
uint32_t maxSequencesCount;
} VkGeneratedCommandsMemoryRequirementsInfoNV;
-
sTypeis a VkStructureType value identifying this structure. -
pNextisNULLor a pointer to a structure extending this structure. -
pipelineBindPointis the VkPipelineBindPoint of thepipelinethat this buffer memory is intended to be used with during the execution. -
pipelineis the VkPipeline that this buffer memory is intended to be used with during the execution. -
indirectCommandsLayoutis the VkIndirectCommandsLayoutNV that this buffer memory is intended to be used with. -
maxSequencesCountis the maximum number of sequences that this buffer memory in combination with the other state provided can be used with.
With VK_NV_device_generated_commands, to bind a compute pipeline in
Device-Generated Commands, an application
must query the pipeline’s device address.
To query a compute pipeline’s 64-bit device address, call:
// Provided by VK_NV_device_generated_commands_compute
VkDeviceAddress vkGetPipelineIndirectDeviceAddressNV(
VkDevice device,
const VkPipelineIndirectDeviceAddressInfoNV* pInfo);
-
deviceis the logical device on which the pipeline was created. -
pInfois a pointer to a VkPipelineIndirectDeviceAddressInfoNV structure specifying the pipeline to retrieve the address for.
The VkPipelineIndirectDeviceAddressInfoNV structure is defined as:
// Provided by VK_NV_device_generated_commands_compute
typedef struct VkPipelineIndirectDeviceAddressInfoNV {
VkStructureType sType;
const void* pNext;
VkPipelineBindPoint pipelineBindPoint;
VkPipeline pipeline;
} VkPipelineIndirectDeviceAddressInfoNV;
-
sTypeis a VkStructureType value identifying this structure. -
pNextisNULLor a pointer to a structure extending this structure. -
pipelineBindPointis a VkPipelineBindPoint value specifying the type of pipeline whose device address is being queried. -
pipelinespecifies the pipeline whose device address is being queried.
To determine the memory requirements for a compute pipeline’s metadata, call:
// Provided by VK_NV_device_generated_commands_compute
void vkGetPipelineIndirectMemoryRequirementsNV(
VkDevice device,
const VkComputePipelineCreateInfo* pCreateInfo,
VkMemoryRequirements2* pMemoryRequirements);
-
deviceis the logical device that owns the buffer. -
pCreateInfois a VkComputePipelineCreateInfo structure specifying the creation parameters of the compute pipeline whose memory requirements are being queried. -
pMemoryRequirementsis a pointer to a VkMemoryRequirements2 structure in which the requested pipeline’s memory requirements are returned.
If pCreateInfo->pNext chain includes a pointer to a
VkComputePipelineIndirectBufferInfoNV structure, then the contents of
that structure are ignored.
32.2.1. Indirect Execution Sets
Indirect Execution Sets contain sets of pipelines or shader objects which can be bound individually.
// Provided by VK_EXT_device_generated_commands
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectExecutionSetEXT)
Indirect Execution Sets allow the device to bind different shaders and pipeline states using Device-Generated Commands.
Indirect Execution Sets are created by calling:
// Provided by VK_EXT_device_generated_commands
VkResult vkCreateIndirectExecutionSetEXT(
VkDevice device,
const VkIndirectExecutionSetCreateInfoEXT* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkIndirectExecutionSetEXT* pIndirectExecutionSet);
-
deviceis the logical device that creates the indirect execution set. -
pCreateInfois a pointer to a VkIndirectExecutionSetCreateInfoEXT structure containing parameters affecting creation of the indirect execution set. -
pAllocatorcontrols host memory allocation as described in the Memory Allocation chapter. -
pIndirectExecutionSetis a pointer to a VkIndirectExecutionSetEXT handle in which the resulting indirect execution set is returned.
The VkIndirectExecutionSetCreateInfoEXT structure is defined as:
// Provided by VK_EXT_device_generated_commands
typedef struct VkIndirectExecutionSetCreateInfoEXT {
VkStructureType sType;
const void* pNext;
VkIndirectExecutionSetInfoTypeEXT type;
VkIndirectExecutionSetInfoEXT info;
} VkIndirectExecutionSetCreateInfoEXT;
-
sTypeis a VkStructureType value identifying this structure. -
pNextisNULLor a pointer to a structure extending this structure. -
typeis a VkIndirectExecutionSetInfoTypeEXT describing the type of set being created and determining which field of theinfounion will be used. -
infois a VkIndirectExecutionSetInfoEXT union containing layout information for the set.
Values which can be set in
VkIndirectExecutionSetCreateInfoEXT::type, specifying contents
of an indirect execution set, are:
// Provided by VK_EXT_device_generated_commands
typedef enum VkIndirectExecutionSetInfoTypeEXT {
VK_INDIRECT_EXECUTION_SET_INFO_TYPE_PIPELINES_EXT = 0,
VK_INDIRECT_EXECUTION_SET_INFO_TYPE_SHADER_OBJECTS_EXT = 1,
} VkIndirectExecutionSetInfoTypeEXT;
-
VK_INDIRECT_EXECUTION_SET_INFO_TYPE_PIPELINES_EXTspecifies that the indirect execution set contains VkPipeline objects. -
VK_INDIRECT_EXECUTION_SET_INFO_TYPE_SHADER_OBJECTS_EXTspecifies that the indirect execution set contains VkShaderEXT objects.
The VkIndirectExecutionSetInfoEXT union is defined as:
// Provided by VK_EXT_device_generated_commands
typedef union VkIndirectExecutionSetInfoEXT {
const VkIndirectExecutionSetPipelineInfoEXT* pPipelineInfo;
const VkIndirectExecutionSetShaderInfoEXT* pShaderInfo;
} VkIndirectExecutionSetInfoEXT;
-
pPipelineInfois a pointer to a VkIndirectExecutionSetPipelineInfoEXT structure containing pipeline layout information for the set. -
pShaderInfois a pointer to a VkIndirectExecutionSetShaderInfoEXT structure containing shader object layout information for the set.
The VkIndirectExecutionSetPipelineInfoEXT structure is defined as:
// Provided by VK_EXT_device_generated_commands
typedef struct VkIndirectExecutionSetPipelineInfoEXT {
VkStructureType sType;
const void* pNext;
VkPipeline initialPipeline;
uint32_t maxPipelineCount;
} VkIndirectExecutionSetPipelineInfoEXT;
-
sTypeis a VkStructureType value identifying this structure. -
pNextisNULLor a pointer to a structure extending this structure. -
initialPipelineis the initial pipeline for the set. This pipeline will be automatically added to the set at index0. -
maxPipelineCountis the maximum number of pipelines stored in the set.
The characteristics of initialPipeline will be used to validate all
pipelines added to the set even if they are removed from the set or
destroyed.
When an Indirect Execution Set created with pipelines is used,
initialPipeline constitutes the initial shader state.
The VkIndirectExecutionSetShaderInfoEXT structure is defined as:
// Provided by VK_EXT_device_generated_commands
typedef struct VkIndirectExecutionSetShaderInfoEXT {
VkStructureType sType;
const void* pNext;
uint32_t shaderCount;
const VkShaderEXT* pInitialShaders;
const VkIndirectExecutionSetShaderLayoutInfoEXT* pSetLayoutInfos;
uint32_t maxShaderCount;
uint32_t pushConstantRangeCount;
const VkPushConstantRange* pPushConstantRanges;
} VkIndirectExecutionSetShaderInfoEXT;
-
sTypeis a VkStructureType value identifying this structure. -
pNextisNULLor a pointer to a structure extending this structure. -
shaderCountis the number of members in thepInitialShadersandpSetLayoutInfosarrays. -
pInitialShadersis a pointer to an array containing a VkShaderEXT object for each shader stage that will be used in the set. These shaders will be automatically added to the set beginning at index0. -
pSetLayoutInfosis a pointer to an array containing a VkIndirectExecutionSetShaderLayoutInfoEXT used by each correspondingpInitialShadersshader stage in the set. -
maxShaderCountis the maximum number of shader objects stored in the set. -
pushConstantRangeCountis the number of members in thepPushConstantRangesarray. -
pPushConstantRangesis a pointer to the array of VkPushConstantRange ranges used by all shaders in the set.
The characteristics of pInitialShaders will be used to validate all
shaders added to the set even if they are removed from the set or destroyed.
When an Indirect Execution Set created with shader objects is used,
pInitialShaders constitutes the initial shader state.
The VkIndirectExecutionSetShaderLayoutInfoEXT structure is defined as:
// Provided by VK_EXT_device_generated_commands
typedef struct VkIndirectExecutionSetShaderLayoutInfoEXT {
VkStructureType sType;
const void* pNext;
uint32_t setLayoutCount;
const VkDescriptorSetLayout* pSetLayouts;
} VkIndirectExecutionSetShaderLayoutInfoEXT;
-
sTypeis a VkStructureType value identifying this structure. -
pNextisNULLor a pointer to a structure extending this structure. -
setLayoutCountis the number of members in thepSetLayoutsarray -
pSetLayoutsis a pointer to an array containing VkDescriptorSetLayout objects used by the shader stage. The implementation must not access these objects outside of the duration of the command this structure is passed to.
Destroy an Indirect Execution Set by calling:
// Provided by VK_EXT_device_generated_commands
void vkDestroyIndirectExecutionSetEXT(
VkDevice device,
VkIndirectExecutionSetEXT indirectExecutionSet,
const VkAllocationCallbacks* pAllocator);
-
deviceis the logical device that owns the indirect execution set. -
indirectExecutionSetis the indirect execution set to destroy. -
pAllocatorcontrols host memory allocation as described in the Memory Allocation chapter.
The VkWriteIndirectExecutionSetPipelineEXT structure is defined as:
// Provided by VK_EXT_device_generated_commands
typedef struct VkWriteIndirectExecutionSetPipelineEXT {
VkStructureType sType;
const void* pNext;
uint32_t index;
VkPipeline pipeline;
} VkWriteIndirectExecutionSetPipelineEXT;
-
sTypeis a VkStructureType value identifying this structure. -
pNextisNULLor a pointer to a structure extending this structure. -
indexis the element of the set to update -
pipelineis the pipeline to store in the indirect execution set
The VkWriteIndirectExecutionSetShaderEXT structure is defined as:
// Provided by VK_EXT_device_generated_commands with VK_EXT_shader_object
typedef struct VkWriteIndirectExecutionSetShaderEXT {
VkStructureType sType;
const void* pNext;
uint32_t index;
VkShaderEXT shader;
} VkWriteIndirectExecutionSetShaderEXT;
-
sTypeis a VkStructureType value identifying this structure. -
pNextisNULLor a pointer to a structure extending this structure. -
indexis the element of the set to update -
shaderis the shader to store in the indirect execution set
Shaders need not be stored in the Indirect Execution Set according to their stage. The only restriction for shader indices within a set is that the value of the index must be less than the maximum number of shaders in the set.
Pipeline elements in an Indirect Execution Set can be updated by calling:
// Provided by VK_EXT_device_generated_commands
void vkUpdateIndirectExecutionSetPipelineEXT(
VkDevice device,
VkIndirectExecutionSetEXT indirectExecutionSet,
uint32_t executionSetWriteCount,
const VkWriteIndirectExecutionSetPipelineEXT* pExecutionSetWrites);
-
deviceis the logical device that owns the indirect execution set. -
indirectExecutionSetis the indirect execution set being updated. -
executionSetWriteCountis the number of elements in thepExecutionSetWritesarray. -
pExecutionSetWritesis a pointer to an array of VkWriteIndirectExecutionSetPipelineEXT structures describing the elements to update.
Shader object elements in an Indirect Execution Set can be updated by calling:
// Provided by VK_EXT_device_generated_commands
void vkUpdateIndirectExecutionSetShaderEXT(
VkDevice device,
VkIndirectExecutionSetEXT indirectExecutionSet,
uint32_t executionSetWriteCount,
const VkWriteIndirectExecutionSetShaderEXT* pExecutionSetWrites);
-
deviceis the logical device that owns the indirect execution set. -
indirectExecutionSetis the indirect execution set being updated. -
executionSetWriteCountis the number of elements in thepExecutionSetWritesarray. -
pExecutionSetWritesis a pointer to an array of VkWriteIndirectExecutionSetShaderEXT structures describing the elements to update.
It is legal to update an Indirect Execution Set that is in flight as long as
the element indices in pExecutionSetWrites are not in use.
Any change to an indirect execution set requires recalculating memory
requirements by calling vkGetGeneratedCommandsMemoryRequirementsEXT
for commands that use that modified state.
Commands that are in flight or those not using updated elements require no
changes.
The lifetimes of pipelines and shader objects contained in a set must match or exceed the lifetime of the set.
With VK_NV_device_generated_commands, the actual generation of
commands as well as their execution on the device is handled as single
action with:
// Provided by VK_NV_device_generated_commands
void vkCmdExecuteGeneratedCommandsNV(
VkCommandBuffer commandBuffer,
VkBool32 isPreprocessed,
const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo);
-
commandBufferis the command buffer into which the command is recorded. -
isPreprocessedrepresents whether the input data has already been preprocessed on the device. If it isVK_FALSEthis command will implicitly trigger the preprocessing step, otherwise not. -
pGeneratedCommandsInfois a pointer to a VkGeneratedCommandsInfoNV structure containing parameters affecting the generation of commands.
If the VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NV
flag was used to create the
VkGeneratedCommandsInfoNV::indirectCommandsLayout then the order
of execution of individual draws through this command may execute in any
order, and may not necessarily be in the same order as specified in
VkGeneratedCommandsInfoNV::pStreams.
The order of execution of individual dispatches through this command may
execute in any order and may not necessarily be in the same order as
specified in VkGeneratedCommandsInfoNV::pStreams.
The VkGeneratedCommandsInfoNV is defined as:
// Provided by VK_NV_device_generated_commands
typedef struct VkGeneratedCommandsInfoNV {
VkStructureType sType;
const void* pNext;
VkPipelineBindPoint pipelineBindPoint;
VkPipeline pipeline;
VkIndirectCommandsLayoutNV indirectCommandsLayout;
uint32_t streamCount;
const VkIndirectCommandsStreamNV* pStreams;
uint32_t sequencesCount;
VkBuffer preprocessBuffer;
VkDeviceSize preprocessOffset;
VkDeviceSize preprocessSize;
VkBuffer sequencesCountBuffer;
VkDeviceSize sequencesCountOffset;
VkBuffer sequencesIndexBuffer;
VkDeviceSize sequencesIndexOffset;
} VkGeneratedCommandsInfoNV;
-
sTypeis a VkStructureType value identifying this structure. -
pNextisNULLor a pointer to a structure extending this structure. -
pipelineBindPointis the VkPipelineBindPoint used for thepipeline. -
pipelineis the VkPipeline used in the generation and execution process. -
indirectCommandsLayoutis the VkIndirectCommandsLayoutNV that provides the command sequence to generate. -
streamCountdefines the number of input streams -
pStreamsis a pointer to an array ofstreamCountVkIndirectCommandsStreamNV structures providing the input data for the tokens used inindirectCommandsLayout. -
sequencesCountis the maximum number of sequences to reserve. IfsequencesCountBufferis VK_NULL_HANDLE, this is also the actual number of sequences generated. -
preprocessBufferis the VkBuffer that is used for preprocessing the input data for execution. If this structure is used with vkCmdExecuteGeneratedCommandsNV with itsisPreprocessedset toVK_TRUE, then the preprocessing step is skipped and data in this buffer will not be modified. The contents and the layout of this buffer are opaque to applications and must not be modified outside functions related to device-generated commands or copied to another buffer for reuse. -
preprocessOffsetis the byte offset intopreprocessBufferwhere the preprocessed data is stored. -
preprocessSizeis the maximum byte size within thepreprocessBufferafter thepreprocessOffsetthat is available for preprocessing. -
sequencesCountBufferis aVkBufferin which the actual number of sequences is provided as singleuint32_tvalue. -
sequencesCountOffsetis the byte offset intosequencesCountBufferwhere the count value is stored. -
sequencesIndexBufferis aVkBufferthat encodes the used sequence indices asuint32_tarray. -
sequencesIndexOffsetis the byte offset intosequencesIndexBufferwhere the index values start.
Referencing the functions defined in Indirect Commands Layout,
vkCmdExecuteGeneratedCommandsNV behaves as:
uint32_t sequencesCount = sequencesCountBuffer ?
min(maxSequencesCount, sequencesCountBuffer.load_uint32(sequencesCountOffset) :
maxSequencesCount;
cmdProcessAllSequences(commandBuffer, pipeline,
indirectCommandsLayout, pIndirectCommandsStreams,
sequencesCount,
sequencesIndexBuffer, sequencesIndexOffset);
// The stateful commands within indirectCommandsLayout will not
// affect the state of subsequent commands in the target
// command buffer (cmd)
|
Note
|
It is important to note that the values of all state related to the
|
Commands can be preprocessed prior execution using the following command:
// Provided by VK_NV_device_generated_commands
void vkCmdPreprocessGeneratedCommandsNV(
VkCommandBuffer commandBuffer,
const VkGeneratedCommandsInfoNV* pGeneratedCommandsInfo);
-
commandBufferis the command buffer which does the preprocessing. -
pGeneratedCommandsInfois a pointer to a VkGeneratedCommandsInfoNV structure containing parameters affecting the preprocessing step.
The bound descriptor sets and push constants that will be used with indirect command generation for the compute pipelines must already be specified at the time of preprocessing commands with vkCmdPreprocessGeneratedCommandsNV. They must not change until the execution of indirect commands is submitted with vkCmdExecuteGeneratedCommandsNV.
If push constants for the compute pipeline are also specified in the
VkGeneratedCommandsInfoNV::indirectCommandsLayout with
VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV token, then those
values override the push constants that were previously pushed for the
compute pipeline.
With VK_EXT_device_generated_commands, the actual generation of
commands as well as their execution on the device is handled as single
action with:
// Provided by VK_EXT_device_generated_commands
void vkCmdExecuteGeneratedCommandsEXT(
VkCommandBuffer commandBuffer,
VkBool32 isPreprocessed,
const VkGeneratedCommandsInfoEXT* pGeneratedCommandsInfo);
-
commandBufferis the command buffer into which the command is recorded. -
isPreprocessedrepresents whether the input data has already been preprocessed on the device. If it isVK_FALSEthis command will implicitly trigger the preprocessing step, otherwise not. -
pGeneratedCommandsInfois a pointer to a VkGeneratedCommandsInfoEXT structure containing parameters affecting the generation of commands.
If the VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_EXT
flag was used to create the
VkGeneratedCommandsInfoEXT::indirectCommandsLayout then the
execution of sequences through this command may use implementation-defined
ordering which is not guaranteed to be coherent using the same input data.
It does not affect the order of token processing within a sequence.
This is the implied ordering with
VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_EXT.
After a call to vkCmdExecuteGeneratedCommandsEXT, command buffer state
will become undefined according to the tokens executed.
This table specifies the relationship between tokens used and state
invalidation.
| Common Tokens | States Invalidated |
|---|---|
|
Bound shaders and pipelines |
|
Push constant data |
|
Push constant data |
|
Index buffer |
|
Vertex buffer |
The VkGeneratedCommandsInfoEXT is defined as:
// Provided by VK_EXT_device_generated_commands
typedef struct VkGeneratedCommandsInfoEXT {
VkStructureType sType;
const void* pNext;
VkShaderStageFlags shaderStages;
VkIndirectExecutionSetEXT indirectExecutionSet;
VkIndirectCommandsLayoutEXT indirectCommandsLayout;
VkDeviceAddress indirectAddress;
VkDeviceSize indirectAddressSize;
VkDeviceAddress preprocessAddress;
VkDeviceSize preprocessSize;
uint32_t maxSequenceCount;
VkDeviceAddress sequenceCountAddress;
uint32_t maxDrawCount;
} VkGeneratedCommandsInfoEXT;
-
sTypeis a VkStructureType value identifying this structure. -
pNextisNULLor a pointer to a structure extending this structure. -
shaderStagesis the mask of shader stages used by the commands. -
indirectExecutionSetis the indirect execution set to be used for binding shaders. -
indirectCommandsLayoutis the VkIndirectCommandsLayoutEXT that specifies the command sequence data. -
indirectAddressis an address that holds the indirect buffer data. -
indirectAddressSizeis the size in bytes of indirect buffer data starting atindirectAddress. -
preprocessAddressspecifies a physical address of theVkBufferused for preprocessing the input data for execution. If this structure is used with vkCmdExecuteGeneratedCommandsEXT with itsisPreprocessedset toVK_TRUE, then the preprocessing step is skipped but data in this address may still be modified. The contents and the layout of this address are opaque to applications and must not be modified outside functions related to device-generated commands or copied to another buffer for reuse. -
preprocessSizeis the maximum byte size withinpreprocessAddressthat is available for preprocessing. -
maxSequenceCountis used to determine the number of sequences to execute. -
sequenceCountAddressspecifies an optional physical address of a singleuint32_tvalue containing the requested number of sequences to execute. -
maxDrawCountis the maximum number of indirect draws that can be executed by any COUNT-type multi-draw indirect tokens. The draw count in the indirect buffer is clamped to this value for these token types.
If sequenceCountAddress is not NULL, then maxSequenceCount is
the maximum number of sequences that can be executed.
The actual number is min(maxSequenceCount, *sequenceCountAddress).
If sequenceCountAddress is NULL, then maxSequenceCount is the
exact number of sequences to execute.
If the action command token for the layout is not a COUNT-type multi-draw
indirect token, maxDrawCount is ignored.
Referencing the functions defined in Indirect Commands Layout,
vkCmdExecuteGeneratedCommandsEXT behaves as:
uint32_t sequencesCount = sequenceCountAddress ?
min(maxSequenceCount, sequenceCountAddress.load_uint32()) :
maxSequenceCount;
cmdProcessAllSequences(commandBuffer, indirectExecutionSet,
indirectCommandsLayout, indirectAddress,
sequencesCount);
// The stateful commands within indirectCommandsLayout will not
// affect the state of subsequent commands in the target
// command buffer (cmd)
|
Note
|
It is important to note that the affected values of all state related to the
|
Commands can be preprocessed prior execution using the following command:
// Provided by VK_EXT_device_generated_commands
void vkCmdPreprocessGeneratedCommandsEXT(
VkCommandBuffer commandBuffer,
const VkGeneratedCommandsInfoEXT* pGeneratedCommandsInfo,
VkCommandBuffer stateCommandBuffer);
-
commandBufferis the command buffer which does the preprocessing. -
pGeneratedCommandsInfois a pointer to a VkGeneratedCommandsInfoEXT structure containing parameters affecting the preprocessing step. -
stateCommandBufferis a command buffer from which to snapshot current states affecting the preprocessing step. When a graphics command action token is used, graphics state is snapshotted. When a compute action command token is used, compute state is snapshotted. When a ray tracing action command token is used, ray tracing state is snapshotted. It can be deleted at any time after this command has been recorded.
|
Note
|
|
The bound descriptor sets and push constants that will be used with indirect
command generation must already be specified on stateCommandBuffer at
the time of preprocessing commands with
vkCmdPreprocessGeneratedCommandsEXT.
They must match the bound descriptor sets and push constants used in the
execution of indirect commands with vkCmdExecuteGeneratedCommandsEXT.
If push constants for shader stages are also specified in the
VkGeneratedCommandsInfoEXT::indirectCommandsLayout with a
VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_EXT or
VK_INDIRECT_COMMANDS_TOKEN_TYPE_SEQUENCE_INDEX_EXT token, then those
values override the push constants that were previously pushed.
All state bound on stateCommandBuffer will be used.
All state bound on stateCommandBuffer must be identical to the state
bound at the time vkCmdExecuteGeneratedCommandsEXT is recorded.
The queue family index stateCommandBuffer was allocated from must be
the same as the queue family index of the command buffer used in
vkCmdExecuteGeneratedCommandsEXT.
On some implementations, preprocessing may have no effect on performance.
vkCmdExecuteGeneratedCommandsEXT may write to the preprocess buffer, no matter the isPreprocess parameter. In this case, the implementation must insert appropriate synchronization automatically, which corresponds to the following pseudocode:
-
Barrier
-
srcStageMask = DRAW_INDIRECT
-
srcAccesMask = 0
-
dstStageMask = COMMAND_PREPROCESS_BIT
-
dstAccessMask = COMMAND_PREPROCESS_WRITE_BIT | COMMAND_PREPROCESS_READ_BIT
-
-
Do internal writes
-
Barrier
-
srcStageMask = COMMAND_PREPROCESS_BIT
-
srcAccesMask = COMMAND_PREPROCESS_WRITE_BIT
-
dstStageMask = DRAW_INDIRECT
-
dstAccessMask = INDIRECT_COMMAND_READ_BIT
-
-
Execute