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
VkBuffer
with the appropriate content that gets interpreted by the command layout. -
Create a
preprocess
VkBuffer
using 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.
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.
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. |
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);
-
device
is the logical device that creates the indirect command layout. -
pCreateInfo
is a pointer to a VkIndirectCommandsLayoutCreateInfoEXT structure containing parameters affecting creation of the indirect command layout. -
pAllocator
controls host memory allocation as described in the Memory Allocation chapter. -
pIndirectCommandsLayout
is a pointer to aVkIndirectCommandsLayoutEXT
handle 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;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
flags
is a bitmask of VkIndirectCommandsLayoutUsageFlagBitsEXT specifying usage rules for this layout. -
shaderStages
is the VkShaderStageFlags that this layout supports. -
indirectStride
is the distance in bytes between sequences in the indirect buffer -
pipelineLayout
is the optional VkPipelineLayout that tokens in this layout use. If thedynamicGeneratedPipelineLayout
feature is enabled,pipelineLayout
can be VK_NULL_HANDLE and the layout must be specified by chaining the VkPipelineLayoutCreateInfo structure off thepNext
-
tokenCount
is the length of the individual command sequence. -
pTokens
is 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_EXT
specifies that the layout is always used with the manual preprocessing step through calling vkCmdPreprocessGeneratedCommandsEXT and executed by vkCmdExecuteGeneratedCommandsEXT withisPreprocessed
set toVK_TRUE
. -
VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_EXT
specifies 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 theshaderStages
isVK_SHADER_STAGE_COMPUTE_BIT
as 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);
-
device
is the logical device that destroys the layout. -
indirectCommandsLayout
is the layout to destroy. -
pAllocator
controls 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);
-
device
is the logical device that creates the indirect command layout. -
pCreateInfo
is a pointer to a VkIndirectCommandsLayoutCreateInfoNV structure containing parameters affecting creation of the indirect command layout. -
pAllocator
controls host memory allocation as described in the Memory Allocation chapter. -
pIndirectCommandsLayout
is a pointer to aVkIndirectCommandsLayoutNV
handle 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;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
pipelineBindPoint
is the VkPipelineBindPoint that this layout targets. -
flags
is a bitmask of VkIndirectCommandsLayoutUsageFlagBitsNV specifying usage hints of this layout. -
tokenCount
is the length of the individual command sequence. -
pTokens
is an array describing each command token in detail. See VkIndirectCommandsTokenTypeNV and VkIndirectCommandsLayoutTokenNV below for details. -
streamCount
is the number of streams used to provide the token inputs. -
pStreamStrides
is 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.
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_NV
specifies that the layout is always used with the manual preprocessing step through calling vkCmdPreprocessGeneratedCommandsNV and executed by vkCmdExecuteGeneratedCommandsNV withisPreprocessed
set toVK_TRUE
. -
VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NV
specifies that the input data for the sequences is not implicitly indexed from 0..sequencesUsed, but an application-providedVkBuffer
encoding the index is provided. -
VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NV
specifies 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 thepipelineBindPoint
isVK_PIPELINE_BIND_POINT_COMPUTE
as 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);
-
device
is the logical device that destroys the layout. -
indirectCommandsLayout
is the layout to destroy. -
pAllocator
controls host memory allocation as described in the Memory Allocation chapter.
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;
-
bufferAddress
specifies a physical address of the VkBuffer used as index buffer. -
size
is the byte size range which is available for this operation from the provided address. -
indexType
is 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;
-
bufferAddress
specifies a physical address of the VkBuffer used as vertex input binding. -
size
is the byte size range which is available for this operation from the provided address. -
stride
is 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;
-
bufferAddress
specifies a physical address of the VkBuffer used for draw commands. -
stride
is the byte size stride for the command arguments -
commandCount
is the number of commands to execute
The corresponding indirect draw struct 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;
-
buffer
specifies the VkBuffer storing the functional arguments for each sequence. These arguments can be written by the device. -
offset
specified an offset intobuffer
where 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;
-
groupIndex
specifies 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;
-
bufferAddress
specifies a physical address of the VkBuffer used as index buffer. -
size
is the byte size range which is available for this operation from the provided address. -
indexType
is a VkIndexType value specifying how indices are treated. Instead of the Vulkan enum values, a customuint32_t
value can be mapped to VkIndexType by specifying theVkIndirectCommandsLayoutTokenNV
::pIndexTypes
andVkIndirectCommandsLayoutTokenNV
::pIndexTypeValues
arrays.
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;
-
bufferAddress
specifies a physical address of the VkBuffer used as vertex input binding. -
size
is the byte size range which is available for this operation from the provided address. -
stride
is the byte size stride for this vertex input binding as inVkVertexInputBindingDescription
::stride
. It is only used ifVkIndirectCommandsLayoutTokenNV
::vertexDynamicStride
was 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;
-
data
encodes 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_NV
allows 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;
-
pipelineAddress
specifies the pipeline address of the compute pipeline that will be used in device generated rendering.
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;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
type
specifies the VkIndirectCommandsTokenTypeEXT fordata
. -
data
specifies a VkIndirectCommandsTokenDataEXT containing token-specific details for command execution. It is ignored iftype
does not match any member of the VkIndirectCommandsTokenDataEXT union. -
offset
is 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;
-
pPushConstant
is a pointer to a VkIndirectCommandsPushConstantTokenEXT struct needed forVK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_EXT
andVK_INDIRECT_COMMANDS_TOKEN_TYPE_SEQUENCE_INDEX_EXT
tokens -
pVertexBuffer
is a pointer to a VkIndirectCommandsVertexBufferTokenEXT struct needed forVK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_EXT
tokens -
pIndexBuffer
is a pointer to a VkIndirectCommandsIndexBufferTokenEXT struct needed forVK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_EXT
tokens -
pExecutionSet
is a pointer to a VkIndirectCommandsExecutionSetTokenEXT struct needed forVK_INDIRECT_COMMANDS_TOKEN_TYPE_EXECUTION_SET_EXT
tokens
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;
-
updateRange
is 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;
-
vertexBindingUnit
is 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;
-
mode
specifies 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_EXT
specifies that the indirect buffer contains VkBindIndexBufferIndirectCommandEXT. -
VK_INDIRECT_COMMANDS_INPUT_MODE_DXGI_INDEX_BUFFER_EXT
specifies 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;
-
type
describes the type of indirect execution set in use. -
shaderStages
specifies 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;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
tokenType
is a VkIndirectCommandsTokenTypeNV specifying the token command type. -
stream
is the index of the input stream containing the token argument data. -
offset
is a relative starting offset within the input stream memory for the token argument data. -
vertexBindingUnit
is used for the vertex buffer binding command. -
vertexDynamicStride
sets if the vertex buffer stride is provided by the binding command rather than the current bound graphics pipeline state. -
pushconstantPipelineLayout
is theVkPipelineLayout
used for the push constant command. -
pushconstantShaderStageFlags
are the shader stage flags used for the push constant command. -
pushconstantOffset
is the offset used for the push constant command. -
pushconstantSize
is the size used for the push constant command. -
indirectStateFlags
is a VkIndirectStateFlagsNV bitfield indicating the active states for the state flag command. -
indexTypeCount
is the optional size of thepIndexTypes
andpIndexTypeValues
array pairings. If not zero, it allows to register a customuint32_t
value to be treated as specific VkIndexType. -
pIndexTypes
is the used VkIndexType for the correspondinguint32_t
value 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;
}
}
}
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);
-
device
is the logical device that owns the buffer. -
pInfo
is a pointer to a VkGeneratedCommandsMemoryRequirementsInfoEXT structure containing parameters required for the memory requirements query. -
pMemoryRequirements
is 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;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
indirectExecutionSet
is the indirect execution set to be used for binding shaders. -
indirectCommandsLayout
is the VkIndirectCommandsLayoutEXT that this buffer memory is intended to be used with. -
maxSequenceCount
is the maximum number of sequences that this buffer memory can be used with. -
maxDrawCount
is 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;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
pipeline
is 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;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
shaderCount
is the size of thepShaders
array. -
pShaders
is 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);
-
device
is the logical device that owns the buffer. -
pInfo
is a pointer to a VkGeneratedCommandsMemoryRequirementsInfoNV structure containing parameters required for the memory requirements query. -
pMemoryRequirements
is 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;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
pipelineBindPoint
is the VkPipelineBindPoint of thepipeline
that this buffer memory is intended to be used with during the execution. -
pipeline
is the VkPipeline that this buffer memory is intended to be used with during the execution. -
indirectCommandsLayout
is the VkIndirectCommandsLayoutNV that this buffer memory is intended to be used with. -
maxSequencesCount
is 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);
-
device
is the logical device on which the pipeline was created. -
pInfo
is 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;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
pipelineBindPoint
is a VkPipelineBindPoint value specifying the type of pipeline whose device address is being queried. -
pipeline
specifies 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);
-
device
is the logical device that owns the buffer. -
pCreateInfo
is a VkComputePipelineCreateInfo structure specifying the creation parameters of the compute pipeline whose memory requirements are being queried. -
pMemoryRequirements
is 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.
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);
-
device
is the logical device that creates the indirect execution set. -
pCreateInfo
is a pointer to a VkIndirectExecutionSetCreateInfoEXT structure containing parameters affecting creation of the indirect execution set. -
pAllocator
controls host memory allocation as described in the Memory Allocation chapter. -
pIndirectExecutionSet
is 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;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
type
is a VkIndirectExecutionSetInfoTypeEXT describing the type of set being created and determining which field of theinfo
union will be used. -
info
is 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_EXT
specifies that the indirect execution set contains VkPipeline objects. -
VK_INDIRECT_EXECUTION_SET_INFO_TYPE_SHADER_OBJECTS_EXT
specifies 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;
-
pPipelineInfo
is a pointer to a VkIndirectExecutionSetPipelineInfoEXT struct containing pipeline layout information for the set. -
pShaderInfo
is a pointer to a VkIndirectExecutionSetShaderInfoEXT struct 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;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
initialPipeline
is the initial pipeline for the set. This pipeline will be automatically added to the set at index0
. -
maxPipelineCount
is 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;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
shaderCount
is the number of members in thepInitialShaders
andpSetLayoutInfos
arrays. -
pInitialShaders
is 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
. -
pSetLayoutInfos
is a pointer to an array containing a VkIndirectExecutionSetShaderLayoutInfoEXT used by each correspondingpInitialShaders
shader stage in the set. -
maxShaderCount
is the maximum number of shader objects stored in the set. -
pushConstantRangeCount
is the number of members in thepPushConstantRanges
array. -
pPushConstantRanges
is 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;
-
setLayoutCount
is the number of members in thepSetLayouts
array -
pSetLayouts
is a pointer to an array containing VkDescriptorSetLayout objects used by the shader stage.
Destroy an Indirect Execution Set by calling:
// Provided by VK_EXT_device_generated_commands
void vkDestroyIndirectExecutionSetEXT(
VkDevice device,
VkIndirectExecutionSetEXT indirectExecutionSet,
const VkAllocationCallbacks* pAllocator);
-
device
is the logical device that owns the indirect execution set. -
indirectExecutionSet
is the indirect execution set to destroy. -
pAllocator
controls host memory allocation as described in the Memory Allocation chapter.
The VkWriteIndirectExecutionSetPipelineEXT
struct is defined as:
// Provided by VK_EXT_device_generated_commands
typedef struct VkWriteIndirectExecutionSetPipelineEXT {
VkStructureType sType;
const void* pNext;
uint32_t index;
VkPipeline pipeline;
} VkWriteIndirectExecutionSetPipelineEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
index
is the element of the set to update -
pipeline
is the pipeline to store in the indirect execution set
The VkWriteIndirectExecutionSetShaderEXT
struct 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;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
index
is the element of the set to update -
shader
is 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);
-
device
is the logical device that owns the indirect execution set. -
indirectExecutionSet
is the indirect execution set being updated. -
executionSetWriteCount
is the number of elements in thepExecutionSetWrites
array. -
pExecutionSetWrites
is 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);
-
device
is the logical device that owns the indirect execution set. -
indirectExecutionSet
is the indirect execution set being updated. -
executionSetWriteCount
is the number of elements in thepExecutionSetWrites
array. -
pExecutionSetWrites
is 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);
-
commandBuffer
is the command buffer into which the command is recorded. -
isPreprocessed
represents whether the input data has already been preprocessed on the device. If it isVK_FALSE
this command will implicitly trigger the preprocessing step, otherwise not. -
pGeneratedCommandsInfo
is 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;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
pipelineBindPoint
is the VkPipelineBindPoint used for thepipeline
. -
pipeline
is the VkPipeline used in the generation and execution process. -
indirectCommandsLayout
is the VkIndirectCommandsLayoutNV that provides the command sequence to generate. -
streamCount
defines the number of input streams -
pStreams
is a pointer to an array ofstreamCount
VkIndirectCommandsStreamNV structures providing the input data for the tokens used inindirectCommandsLayout
. -
sequencesCount
is the maximum number of sequences to reserve. IfsequencesCountBuffer
is VK_NULL_HANDLE, this is also the actual number of sequences generated. -
preprocessBuffer
is the VkBuffer that is used for preprocessing the input data for execution. If this structure is used with vkCmdExecuteGeneratedCommandsNV with itsisPreprocessed
set 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. -
preprocessOffset
is the byte offset intopreprocessBuffer
where the preprocessed data is stored. -
preprocessSize
is the maximum byte size within thepreprocessBuffer
after thepreprocessOffset
that is available for preprocessing. -
sequencesCountBuffer
is aVkBuffer
in which the actual number of sequences is provided as singleuint32_t
value. -
sequencesCountOffset
is the byte offset intosequencesCountBuffer
where the count value is stored. -
sequencesIndexBuffer
is aVkBuffer
that encodes the used sequence indices asuint32_t
array. -
sequencesIndexOffset
is the byte offset intosequencesIndexBuffer
where 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)
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);
-
commandBuffer
is the command buffer which does the preprocessing. -
pGeneratedCommandsInfo
is 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);
-
commandBuffer
is the command buffer into which the command is recorded. -
isPreprocessed
represents whether the input data has already been preprocessed on the device. If it isVK_FALSE
this command will implicitly trigger the preprocessing step, otherwise not. -
pGeneratedCommandsInfo
is 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;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
shaderStages
is the mask of shader stages used by the commands. -
indirectExecutionSet
is the indirect execution set to be used for binding shaders. -
indirectCommandsLayout
is the VkIndirectCommandsLayoutEXT that specifies the command sequence data. -
indirectAddress
is an address that holds the indirect buffer data. -
indirectAddressSize
is the size in bytes of indirect buffer data starting atindirectAddress
. -
preprocessAddress
specifies a physical address of theVkBuffer
used for preprocessing the input data for execution. If this structure is used with vkCmdExecuteGeneratedCommandsEXT with itsisPreprocessed
set 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. -
preprocessSize
is the maximum byte size withinpreprocessAddress
that is available for preprocessing. -
maxSequenceCount
is used to determine the number of sequences to execute. -
sequenceCountAddress
specifies an optional physical address of a singleuint32_t
value containing the requested number of sequences to execute. -
maxDrawCount
is 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);
-
commandBuffer
is the command buffer which does the preprocessing. -
pGeneratedCommandsInfo
is a pointer to a VkGeneratedCommandsInfoEXT structure containing parameters affecting the preprocessing step. -
stateCommandBuffer
is 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