// Copyright (c) 2019-2020 NVIDIA Corporation
//
// SPDX-License-Identifier: CC-BY-4.0

[[indirectmdslayout]]
== Indirect Commands Layout

[open,refpage='VkIndirectCommandsLayoutNV',desc='Opaque handle to an indirect commands layout object',type='handles']
--
The device-side command generation happens through an iterative processing
of an atomic sequence comprised of command tokens, which are represented by:

include::{generated}/api/handles/VkIndirectCommandsLayoutNV.txt[]
--


=== Creation and Deletion

[open,refpage='vkCreateIndirectCommandsLayoutNV',desc='Create an indirect command layout object',type='protos']
--
Indirect command layouts are created by:

include::{generated}/api/protos/vkCreateIndirectCommandsLayoutNV.txt[]

  * pname:device is the logical device that creates the indirect command
    layout.
  * pname:pCreateInfo is a pointer to an instance of the
    sname:VkIndirectCommandsLayoutCreateInfoNV structure containing
    parameters affecting creation of the indirect command layout.
  * pname:pAllocator controls host memory allocation as described in the
    <<memory-allocation, Memory Allocation>> chapter.
  * pname:pIndirectCommandsLayout is a pointer to a
    sname:VkIndirectCommandsLayoutNV handle in which the resulting indirect
    command layout is returned.

.Valid Usage
****
  * [[VUID-vkCreateIndirectCommandsLayoutNV-deviceGeneratedCommands-02929]]
    The <<features-deviceGeneratedCommands,
    sname:VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV::pname:deviceGeneratedCommands>>
    feature must: be enabled
****

include::{generated}/validity/protos/vkCreateIndirectCommandsLayoutNV.txt[]
--

[open,refpage='VkIndirectCommandsLayoutCreateInfoNV',desc='Structure specifying the parameters of a newly created indirect commands layout object',type='structs']
--
The sname:VkIndirectCommandsLayoutCreateInfoNV structure is defined as:

include::{generated}/api/structs/VkIndirectCommandsLayoutCreateInfoNV.txt[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:pipelineBindPoint is the elink:VkPipelineBindPoint that this
    layout targets.
  * pname:flags is a bitmask of
    elink:VkIndirectCommandsLayoutUsageFlagBitsNV specifying usage hints of
    this layout.
  * pname:tokenCount is the length of the individual command sequence.
  * pname:pTokens is an array describing each command token in detail.
    See elink:VkIndirectCommandsTokenTypeNV and
    slink:VkIndirectCommandsLayoutTokenNV below for details.
  * pname:streamCount is the number of streams used to provide the token
    inputs.
  * pname:pStreamStrides is an array defining the byte stride for each input
    stream.

The following code illustrates some of the flags:

// Jon: split this out separately as a temporary workaround for the reflow
// tool getting confused by a source block with ---- delimiters being inside
//  an open block with ---- delimiters.
include::cmdProcessAllSequences.txt[]

.Valid Usage
****
  * [[VUID-VkIndirectCommandsLayoutCreateInfoNV-pipelineBindPoint-02930]]
    The pname:pipelineBindPoint must: be
    ename:VK_PIPELINE_BIND_POINT_GRAPHICS
  * [[VUID-VkIndirectCommandsLayoutCreateInfoNV-tokenCount-02931]]
    pname:tokenCount must: be greater than `0` and less than or equal to
    sname:VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV::pname:maxIndirectCommandsTokenCount
  * [[VUID-VkIndirectCommandsLayoutCreateInfoNV-pTokens-02932]]
    If pname:pTokens contains an entry of
    ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV it must: be the
    first element of the array and there must: be only a single element of
    such token type
  * [[VUID-VkIndirectCommandsLayoutCreateInfoNV-pTokens-02933]]
    If pname:pTokens contains an entry of
    ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_STATE_FLAGS_NV there must: be only
    a single element of such token type
  * [[VUID-VkIndirectCommandsLayoutCreateInfoNV-pTokens-02934]]
    All state tokens in pname:pTokens must: occur prior work provoking
    tokens (ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NV,
    ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NV,
    ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV)
  * [[VUID-VkIndirectCommandsLayoutCreateInfoNV-pTokens-02935]]
    The content of pname:pTokens must: include one single work provoking
    token that is compatible with the pname:pipelineBindPoint
  * [[VUID-VkIndirectCommandsLayoutCreateInfoNV-streamCount-02936]]
    pname:streamCount must: be greater than `0` and less or equal to
    sname:VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV::pname:maxIndirectCommandsStreamCount
  * [[VUID-VkIndirectCommandsLayoutCreateInfoNV-pStreamStrides-02937]]
    each element of pname:pStreamStrides must: be greater than `0`and less
    than or equal to
    sname:VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV::pname:maxIndirectCommandsStreamStride.
    Furthermore the alignment of each token input must: be ensured
****

include::{generated}/validity/structs/VkIndirectCommandsLayoutCreateInfoNV.txt[]
--

[open,refpage='VkIndirectCommandsLayoutUsageFlagBitsNV',desc='Bitmask specifying allowed usage of an indirect commands layout',type='enums']
--
Bits which can: be set in
slink:VkIndirectCommandsLayoutCreateInfoNV::pname:flags, specifying usage
hints of an indirect command layout, are:

include::{generated}/api/enums/VkIndirectCommandsLayoutUsageFlagBitsNV.txt[]

  * ename:VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_NV
    specifies that the layout is always used with the manual preprocessing
    step through calling flink:vkCmdPreprocessGeneratedCommandsNV and
    executed by flink:vkCmdExecuteGeneratedCommandsNV with `isPreprocessed`
    set to ename:VK_TRUE.
  * ename: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 a user provided sname:VkBuffer
    encoding the index is provided.
  * ename: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.
--

[open,refpage='VkIndirectCommandsLayoutUsageFlagsNV',desc='Bitmask of VkIndirectCommandsLayoutUsageFlagBitsNV',type='flags']
--
include::{generated}/api/flags/VkIndirectCommandsLayoutUsageFlagsNV.txt[]

tname:VkIndirectCommandsLayoutUsageFlagsNV is a bitmask type for setting a
mask of zero or more elink:VkIndirectCommandsLayoutUsageFlagBitsNV.
--

[open,refpage='vkDestroyIndirectCommandsLayoutNV',desc='Destroy an indirect commands layout',type='protos']
--
Indirect command layouts are destroyed by:

include::{generated}/api/protos/vkDestroyIndirectCommandsLayoutNV.txt[]

  * pname:device is the logical device that destroys the layout.
  * pname:indirectCommandsLayout is the layout to destroy.
  * pname:pAllocator controls host memory allocation as described in the
    <<memory-allocation, Memory Allocation>> chapter.

.Valid Usage
****
  * [[VUID-vkDestroyIndirectCommandsLayoutNV-indirectCommandsLayout-02938]]
    All submitted commands that refer to pname:indirectCommandsLayout must:
    have completed execution
  * [[VUID-vkDestroyIndirectCommandsLayoutNV-indirectCommandsLayout-02939]]
    If sname:VkAllocationCallbacks were provided when
    pname:indirectCommandsLayout was created, a compatible set of callbacks
    must: be provided here
  * [[VUID-vkDestroyIndirectCommandsLayoutNV-indirectCommandsLayout-02940]]
    If no sname:VkAllocationCallbacks were provided when
    pname:indirectCommandsLayout was created, pname:pAllocator must: be
    `NULL`
  * [[VUID-vkDestroyIndirectCommandsLayoutNV-deviceGeneratedCommands-02941]]
    The <<features-deviceGeneratedCommands,
    sname:VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV::pname:deviceGeneratedCommands>>
    feature must: be enabled
****

include::{generated}/validity/protos/vkDestroyIndirectCommandsLayoutNV.txt[]
--


=== Token Input Streams

[open,refpage='VkIndirectCommandsStreamNV',desc='Structure specifying input streams for generated command tokens',type='structs']
--
The sname:VkIndirectCommandsStreamNV structure specifies the input data for
one or more tokens at processing time.

include::{generated}/api/structs/VkIndirectCommandsStreamNV.txt[]

  * pname:buffer specifies the slink:VkBuffer storing the functional
    arguments for each sequence.
    These arguments can: be written by the device.
  * pname:offset specified an offset into pname:buffer where the arguments
    start.

.Valid Usage
****
  * [[VUID-VkIndirectCommandsStreamNV-buffer-02942]]
    The pname:buffer's usage flag must: have the
    ename:VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT bit set
  * [[VUID-VkIndirectCommandsStreamNV-offset-02943]]
    The pname:offset must: be aligned to
    sname:VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV::pname:minIndirectCommandsBufferOffsetAlignment
  * [[VUID-VkIndirectCommandsStreamNV-buffer-02975]]
    If pname:buffer is non-sparse then it must: be bound completely and
    contiguously to a single sname:VkDeviceMemory object
****

include::{generated}/validity/structs/VkIndirectCommandsStreamNV.txt[]
--

The input streams can: contain raw `uint32_t` values, existing indirect
commands such as:

* slink:VkDrawIndirectCommand
* slink:VkDrawIndexedIndirectCommand
ifdef::VK_NV_mesh_shader[]
* slink:VkDrawMeshTasksIndirectCommandNV
endif::VK_NV_mesh_shader[]

or additional commands as listed below.
How the data is used is described in the next section.

[open,refpage='VkBindShaderGroupIndirectCommandNV',desc='Structure specifying input data for a single shader group command token',type='structs']
--
The sname:VkBindShaderGroupIndirectCommandNV structure specifies the input
data for the ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV token.

include::{generated}/api/structs/VkBindShaderGroupIndirectCommandNV.txt[]

  * pname:index specifies which shader group of the current bound graphics
    pipeline is used.

.Valid Usage
****
  * [[VUID-VkBindShaderGroupIndirectCommandNV-None-02944]]
    The current bound graphics pipeline, as well as the pipelines it may
    reference, must: have been created with
    ename:VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV
  * [[VUID-VkBindShaderGroupIndirectCommandNV-index-02945]]
    The pname:index must: be within range of the accessible shader groups of
    the current bound graphics pipeline.
    See flink:vkCmdBindPipelineShaderGroupNV for further details
****

include::{generated}/validity/structs/VkBindShaderGroupIndirectCommandNV.txt[]
--

[open,refpage='VkBindIndexBufferIndirectCommandNV',desc='Structure specifying input data for a single index buffer command token',type='structs']
--
The sname:VkBindIndexBufferIndirectCommandNV structure specifies the input
data for the ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NV token.

include::{generated}/api/structs/VkBindIndexBufferIndirectCommandNV.txt[]

  * pname:bufferAddress specifies a physical address of the slink:VkBuffer
    used as index buffer.
  * pname:size is the byte size range which is available for this operation
    from the provided address.
  * pname:indexType is a elink:VkIndexType value specifying how indices are
    treated.
    Instead of the Vulkan enum values, a custom `uint32_t` value can: be
    mapped to an elink:VkIndexType by specifying the
    sname:VkIndirectCommandsLayoutTokenNV::pname:pIndexTypes and
    sname:VkIndirectCommandsLayoutTokenNV::pname:pIndexTypeValues arrays.

.Valid Usage
****
  * [[VUID-VkBindIndexBufferIndirectCommandNV-None-02946]]
    The buffer's usage flag from which the address was acquired must: have
    the ename:VK_BUFFER_USAGE_INDEX_BUFFER_BIT bit set
  * [[VUID-VkBindIndexBufferIndirectCommandNV-bufferAddress-02947]]
    The pname:bufferAddress must: be aligned to the pname:indexType used
  * [[VUID-VkBindIndexBufferIndirectCommandNV-None-02948]]
    Each element of the buffer from which the address was acquired and that
    is non-sparse must: be bound completely and contiguously to a single
    sname:VkDeviceMemory object
****

include::{generated}/validity/structs/VkBindIndexBufferIndirectCommandNV.txt[]
--

[open,refpage='VkBindVertexBufferIndirectCommandNV',desc='Structure specifying input data for a single vertex buffer command token',type='structs']
--
The sname:VkBindVertexBufferIndirectCommandNV structure specifies the input
data for the ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NV token.

include::{generated}/api/structs/VkBindVertexBufferIndirectCommandNV.txt[]

  * pname:bufferAddress specifies a physical address of the slink:VkBuffer
    used as vertex input binding.
  * pname:size is the byte size range which is available for this operation
    from the provided address.
  * pname:stride is the byte size stride for this vertex input binding as in
    sname:VkVertexInputBindingDescription::pname:stride.
    It is only used if
    sname:VkIndirectCommandsLayoutTokenNV::pname:vertexDynamicStride was
    set, otherwise the stride is inherited from the current bound graphics
    pipeline.

.Valid Usage
****
  * [[VUID-VkBindVertexBufferIndirectCommandNV-None-02949]]
    The buffer's usage flag from which the address was acquired must: have
    the ename:VK_BUFFER_USAGE_VERTEX_BUFFER_BIT bit set
  * [[VUID-VkBindVertexBufferIndirectCommandNV-None-02950]]
    Each element of the buffer from which the address was acquired and that
    is non-sparse must: be bound completely and contiguously to a single
    sname:VkDeviceMemory object
****

include::{generated}/validity/structs/VkBindVertexBufferIndirectCommandNV.txt[]
--

[open,refpage='VkSetStateFlagsIndirectCommandNV',desc='Structure specifying input data for a single state flag command token',type='structs']
--
The sname:VkSetStateFlagsIndirectCommandNV structure specifies the input
data for the ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_STATE_FLAGS_NV token.
Which state is changed depends on the elink:VkIndirectStateFlagBitsNV
specified at sname:VkIndirectCommandsLayoutNV creation time.

include::{generated}/api/structs/VkSetStateFlagsIndirectCommandNV.txt[]

  * pname:data encodes packed state that this command alters.
  ** Bit `0`: If set represents ename:VK_FRONT_FACE_CLOCKWISE, otherwise
     ename:VK_FRONT_FACE_COUNTER_CLOCKWISE

include::{generated}/validity/structs/VkSetStateFlagsIndirectCommandNV.txt[]
--

[open,refpage='VkIndirectStateFlagBitsNV',desc='Bitmask specifiying state that can be altered on the device',type='enums']
--
A subset of the graphics pipeline state can: be altered using indirect state
flags:

include::{generated}/api/enums/VkIndirectStateFlagBitsNV.txt[]

* ename:VK_INDIRECT_STATE_FLAG_FRONTFACE_BIT_NV allows to toggle the
  elink:VkFrontFace rasterization state for subsequent draw operations.
--

[open,refpage='VkIndirectStateFlagsNV',desc='Bitmask of VkIndirectStateFlagBitsNV',type='flags']
--
include::{generated}/api/flags/VkIndirectStateFlagsNV.txt[]

tname:VkIndirectStateFlagsNV is a bitmask type for setting a mask of zero or
more elink:VkIndirectStateFlagBitsNV.
--


=== Tokenized Command Processing

The processing is in principle illustrated below:

[source,c]
---------------------------------------------------
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 prior work provoking commands within the sequence.
A single sequence is strictly targeting the elink:VkPipelineBindPoint it was
created with.

The primary input data for each token is provided through sname:VkBuffer
content at preprocessing using flink:vkCmdPreprocessGeneratedCommandsNV or
execution time using flink:vkCmdExecuteGeneratedCommandsNV, however some
functional arguments, for example binding sets, are specified at layout
creation time.
The input size is different for each token.

[open,refpage='VkIndirectCommandsTokenTypeNV',desc='Enum specifying token commands',type='enums']
--
Possible values of those elements of the
slink:VkIndirectCommandsLayoutCreateInfoNV::pname:pTokens array which
specify command tokens (other elements of the array specify command
parameters) are:

include::{generated}/api/enums/VkIndirectCommandsTokenTypeNV.txt[]

.Supported indirect command tokens
[width="80%",cols="67%,33%",options="header",align="center"]
|====
|Token type                                                 | Equivalent command
|ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV      | flink:vkCmdBindPipelineShaderGroupNV
|ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_STATE_FLAGS_NV       | -
|ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NV      | flink:vkCmdBindIndexBuffer
|ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NV     | flink:vkCmdBindVertexBuffers
|ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV     | flink:vkCmdPushConstants
|ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NV      | flink:vkCmdDrawIndexedIndirect
|ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NV              | flink:vkCmdDrawIndirect
ifdef::VK_NV_mesh_shader[]
|ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV        | flink:vkCmdDrawMeshTasksIndirectNV
endif::VK_NV_mesh_shader[]
|====
--

[open,refpage='VkIndirectCommandsLayoutTokenNV',desc='Struct specifying the details of an indirect command layout token',type='structs']
--
The sname:VkIndirectCommandsLayoutTokenNV structure specifies details to the
function arguments that need to be known at layout creation time:

include::{generated}/api/structs/VkIndirectCommandsLayoutTokenNV.txt[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:tokenType specifies the token command type.
  * pname:stream is the index of the input stream that contains the token
    argument data.
  * pname:offset is a relative starting offset within the input stream
    memory for the token argument data.
  * pname:vertexBindingUnit is used for the vertex buffer binding command.
  * pname:vertexDynamicStride sets if the vertex buffer stride is provided
    by the binding command rather than the current bound graphics pipeline
    state.
  * pname:pushconstantPipelineLayout is the sname:VkPipelineLayout used for
    the push constant command.
  * pname:pushconstantShaderStageFlags are the shader stage flags used for
    the push constant command.
  * pname:pushconstantOffset is the offset used for the push constant
    command.
  * pname:pushconstantSize is the size used for the push constant command.
  * pname:indirectStateFlags are the active states for the state flag
    command.
  * pname:indexTypeCount is the optional size of the pname:pIndexTypes and
    pname:pIndexTypeValues array pairings.
    If not zero, it allows to register a custom `uint32_t` value to be
    treated as specific ename:VkIndexType.
  * pname:pIndexTypes is the used ename:VkIndexType for the corresponding
    `uint32_t` value entry in pname:pIndexTypeValues.

.Valid Usage
****
  * [[VUID-VkIndirectCommandsLayoutTokenNV-stream-02951]]
    pname:stream must: be smaller than
    sname:VkIndirectCommandsLayoutCreateInfoNV::pname:streamCount
  * [[VUID-VkIndirectCommandsLayoutTokenNV-offset-02952]]
    pname:offset must: be less than or equal to
    sname:VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV::pname:maxIndirectCommandsTokenOffset
  * [[VUID-VkIndirectCommandsLayoutTokenNV-tokenType-02976]]
    If pname:tokenType is
    ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NV,
    pname:vertexBindingUnit must: stay within device supported limits for
    the appropriate commands
  * [[VUID-VkIndirectCommandsLayoutTokenNV-tokenType-02977]]
    If pname:tokenType is
    ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV,
    pname:pushconstantPipelineLayout must: be valid
  * [[VUID-VkIndirectCommandsLayoutTokenNV-tokenType-02978]]
    If pname:tokenType is
    ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV,
    pname:pushconstantOffset must: be a multiple of `4`
  * [[VUID-VkIndirectCommandsLayoutTokenNV-tokenType-02979]]
    If pname:tokenType is
    ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV,
    pname:pushconstantSize must: be a multiple of `4`
  * [[VUID-VkIndirectCommandsLayoutTokenNV-tokenType-02980]]
    If pname:tokenType is
    ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV,
    pname:pushconstantOffset must: be less than
    sname:VkPhysicalDeviceLimits::pname:maxPushConstantsSize
  * [[VUID-VkIndirectCommandsLayoutTokenNV-tokenType-02981]]
    If pname:tokenType is
    ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV,
    pname:pushconstantSize must: be less than or equal to
    sname:VkPhysicalDeviceLimits::pname:maxPushConstantsSize minus
    pname:pushconstantOffset
  * [[VUID-VkIndirectCommandsLayoutTokenNV-tokenType-02982]]
    If pname:tokenType is
    ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV, for each byte in
    the range specified by pname:pushconstantOffset and
    pname:pushconstantSize and for each shader stage in
    pname:pushconstantShaderStageFlags, there must: be a push constant range
    in pname:pushconstantPipelineLayout that includes that byte and that
    stage
  * [[VUID-VkIndirectCommandsLayoutTokenNV-tokenType-02983]]
    If pname:tokenType is
    ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV, for each byte in
    the range specified by pname:pushconstantOffset and
    pname:pushconstantSize and for each push constant range that overlaps
    that byte, pname:pushconstantShaderStageFlags must: include all stages
    in that push constant range's
    slink:VkPushConstantRange::pname:stageFlags
  * [[VUID-VkIndirectCommandsLayoutTokenNV-tokenType-02984]]
    If pname:tokenType is
    ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_STATE_FLAGS_NV,
    pname:indirectStateFlags must: not be `0`
****

include::{generated}/validity/structs/VkIndirectCommandsLayoutTokenNV.txt[]
--

The following code provides detailed information on how an individual
sequence is processed.
For valid usage, all restrictions from the regular commands apply.

[source,c]
---------------------------------------------------
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){
    VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV:
      VkBindShaderGroupIndirectCommandNV* bind = input;

      vkCmdBindPipelineShaderGroupNV(cmd, indirectCommandsLayout.pipelineBindPoint,
        pipeline, bind->groupIndex);
    break;

    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;

    VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV:
      uint32_t* data = input;

      vkCmdPushConstants(cmd,
        token.pushconstantPipelineLayout
        token.pushconstantStageFlags,
        token.pushconstantOffset,
        token.pushconstantSize, data);
    break;

    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;

    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;

    VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NV:
      vkCmdDrawIndexedIndirect(cmd,
        stream.buffer, offset, 1, 0);
    break;

    VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NV:
      vkCmdDrawIndirect(cmd,
        stream.buffer,
        offset, 1, 0);
    break;

    // only available if VK_NV_mesh_shader is supported
    VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NV:
      vkCmdDrawMeshTasksIndirectNV(cmd,
        stream.buffer, offset, 1, 0);
    break;
    }
  }
}
---------------------------------------------------
