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

== Indirect Commands Generation And Execution

[open,refpage='vkGetGeneratedCommandsMemoryRequirementsNV',desc='Retrieve the buffer allocation requirements for generated commands',type='protos']
--
The generation of commands on the device requires a `preprocess` buffer.
To retrieve the memory size and alignment requirements of a particular
execution state call:

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

  * pname:device is the logical device that owns the buffer.
  * pname:pInfo is a pointer to an instance of the
    sname:VkGeneratedCommandsMemoryRequirementsInfoNV structure containing
    parameters required for the memory requirements query.
  * pname:pMemoryRequirements is a pointer to a slink:VkMemoryRequirements2
    structure in which the memory requirements of the buffer object are
    returned.

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

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

[open,refpage='VkGeneratedCommandsMemoryRequirementsInfoNV',desc='Structure specifying parameters for the reservation of preprocess buffer space',type='structs']
--
include::{generated}/api/structs/VkGeneratedCommandsMemoryRequirementsInfoNV.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 of the
    pname:pipeline that this buffer memory is intended to be used with
    during the execution.
  * pname:pipeline is the slink:VkPipeline that this buffer memory is
    intended to be used with during the execution.
  * pname:indirectCommandsLayout is the slink:VkIndirectCommandsLayoutNV
    that this buffer memory is intended to be used with.
  * pname:maxSequencesCount is the maximum number of sequences that this
    buffer memory in combination with the other state provided can: be used
    with.

.Valid Usage
****
  * [[VUID-VkGeneratedCommandsMemoryRequirementsInfoNV-maxSequencesCount-02907]]
    pname:maxSequencesCount must: be less or equal to
    slink:VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV::pname:maxIndirectSequenceCount
****

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

[open,refpage='vkCmdExecuteGeneratedCommandsNV',desc='Generate and execute commands on the device',type='protos']
--
:refpage: vkCmdExecuteGeneratedCommandsNV

The actual generation of commands as well as their execution on the device
is handled as single action with:

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

  * pname:commandBuffer is the command buffer into which the command is
    recorded.
  * pname:isPreprocessed represents whether the input data has already been
    preprocessed on the device.
    If it is ename:VK_FALSE this command will implicitly trigger the
    preprocessing step, otherwise not.
  * pname:pGeneratedCommandsInfo is a pointer to an instance of the
    slink:VkGeneratedCommandsInfoNV structure containing parameters
    affecting the generation of commands.

.Valid Usage
****
include::{chapters}/commonvalidity/draw_common.txt[]
include::{chapters}/commonvalidity/draw_vertex_binding.txt[]
ifdef::VK_VERSION_1_1[]
  * [[VUID-vkCmdExecuteGeneratedCommandsNV-commandBuffer-02970]]
    pname:commandBuffer must: not be a protected command buffer
endif::VK_VERSION_1_1[]
  * [[VUID-vkCmdExecuteGeneratedCommandsNV-isPreprocessed-02908]]
    If pname:isPreprocessed is ename:VK_TRUE then
    flink:vkCmdPreprocessGeneratedCommandsNV must: have already been
    executed on the device, using the same pname:pGeneratedCommandsInfo
    content as well as the content of the input buffers it references (all
    except slink:VkGeneratedCommandsInfoNV::pname:preprocessBuffer).
    Furthermore pname:pGeneratedCommandsInfo`s pname:indirectCommandsLayout
    must: have been created with the
    ename:VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_NV bit
    set
  * [[VUID-vkCmdExecuteGeneratedCommandsNV-pipeline-02909]]
    sname:VkGeneratedCommandsInfoNV::pname:pipeline must: match the current
    bound pipeline at
    sname:VkGeneratedCommandsInfoNV::pname:pipelineBindPoint
ifdef::VK_EXT_transform_feedback[]
  * [[VUID-vkCmdExecuteGeneratedCommandsNV-None-02910]]
    Transform feedback must: not be active
endif::VK_EXT_transform_feedback[]
  * [[VUID-vkCmdExecuteGeneratedCommandsNV-deviceGeneratedCommands-02911]]
    The <<features-deviceGeneratedCommands,
    sname:VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV::pname:deviceGeneratedCommands>>
    feature must: be enabled
****

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

[open,refpage='VkGeneratedCommandsInfoNV',desc='Structure specifying parameters for the generation of commands',type='structs']
--
include::{generated}/api/structs/VkGeneratedCommandsInfoNV.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 used for the
    pname:pipeline.
  * pname:pipeline is the slink:VkPipeline used in the generation and
    execution process.
  * pname:indirectCommandsLayout is the slink:VkIndirectCommandsLayoutNV
    that provides the command sequence to generate.
  * pname:streamCount defines the number of input streams
  * pname:pStreams is a pointer to an array of pname:streamCount
    slink:VkIndirectCommandsStreamNV structures providing the input data for
    the tokens used in pname:indirectCommandsLayout.
  * pname:sequencesCount is the maximum number of sequences to reserve.
    If pname:sequencesCountBuffer is dlink:VK_NULL_HANDLE, this is also the
    actual number of sequences generated.
  * pname:preprocessBuffer is the slink:VkBuffer that is used for
    preprocessing the input data for execution.
    If this structure is used with flink:vkCmdExecuteGeneratedCommandsNV
    with its pname:isPreprocessed set to `VK_TRUE`, then the preprocessing
    step is skipped and data is only read from this buffer.
  * pname:preprocessOffset is the byte offset into pname:preprocessBuffer
    where the preprocessed data is stored.
  * pname:preprocessSize is the maximum byte size within the
    pname:preprocessBuffer after the pname:preprocessOffset that is
    available for preprocessing.
  * pname:sequencesCountBuffer is a sname:VkBuffer in which the actual
    number of sequences is provided as single code:uint32_t value.
  * pname:sequencesCountOffset is the byte offset into
    pname:sequencesCountBuffer where the count value is stored.
  * pname:sequencesIndexBuffer is a sname:VkBuffer that encodes the used
    sequence indices as code:uint32_t array.
  * pname:sequencesIndexOffset is the byte offset into
    pname:sequencesIndexBuffer where the index values start.

.Valid Usage
****
  * [[VUID-VkGeneratedCommandsInfoNV-pipeline-02912]]
    The provided pname:pipeline must: match the pipeline bound at execution
    time
  * [[VUID-VkGeneratedCommandsInfoNV-indirectCommandsLayout-02913]]
    If the pname:indirectCommandsLayout uses a token of
    ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV, then the
    pname:pipeline must: have been created with multiple shader groups
  * [[VUID-VkGeneratedCommandsInfoNV-indirectCommandsLayout-02914]]
    If the pname:indirectCommandsLayout uses a token of
    ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV, then the
    pname:pipeline must: have been created with
    ename:VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV set in
    sname:VkGraphicsPipelineCreateInfo::pname:flags
  * [[VUID-VkGeneratedCommandsInfoNV-indirectCommandsLayout-02915]]
    If the pname:indirectCommandsLayout uses a token of
    ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV, then the
    pname:pipeline`s sname:VkPipelineLayout must: match the
    slink:VkIndirectCommandsLayoutTokenNV::pname:pushconstantPipelineLayout
  * [[VUID-VkGeneratedCommandsInfoNV-streamCount-02916]]
    pname:streamCount must: match the pname:indirectCommandsLayout's
    pname:streamCount
  * [[VUID-VkGeneratedCommandsInfoNV-sequencesCount-02917]]
    pname:sequencesCount must: be less or equal to
    slink:VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV::pname:maxIndirectSequenceCount
    and
    slink:VkGeneratedCommandsMemoryRequirementsInfoNV::pname:maxSequencesCount
    that was used to determine the pname:preprocessSize
  * [[VUID-VkGeneratedCommandsInfoNV-preprocessBuffer-02918]]
    pname:preprocessBuffer must: have the
    ename:VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT bit set in its usage flag
  * [[VUID-VkGeneratedCommandsInfoNV-preprocessOffset-02919]]
    pname:preprocessOffset must: be aligned to
    slink:VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV::pname:minIndirectCommandsBufferOffsetAlignment
  * [[VUID-VkGeneratedCommandsInfoNV-preprocessBuffer-02971]]
    If pname:preprocessBuffer is non-sparse then it must: be bound
    completely and contiguously to a single sname:VkDeviceMemory object
  * [[VUID-VkGeneratedCommandsInfoNV-preprocessSize-02920]]
    pname:preprocessSize must: be at least equal to the memory requirement`s
    size returned by flink:vkGetGeneratedCommandsMemoryRequirementsNV using
    the matching inputs (pname:indirectCommandsLayout, ...) as within this
    structure
  * [[VUID-VkGeneratedCommandsInfoNV-sequencesCountBuffer-02921]]
    pname:sequencesCountBuffer can: be set if the actual used count of
    sequences is sourced from the provided buffer.
    In that case the pname:sequencesCount serves as upper bound
  * [[VUID-VkGeneratedCommandsInfoNV-sequencesCountBuffer-02922]]
    If pname:sequencesCountBuffer is not dlink:VK_NULL_HANDLE, its usage
    flag must: have the ename:VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT bit set
  * [[VUID-VkGeneratedCommandsInfoNV-sequencesCountBuffer-02923]]
    If pname:sequencesCountBuffer is not dlink:VK_NULL_HANDLE,
    pname:sequencesCountOffset must: be aligned to
    sname:VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV::pname:minSequencesCountBufferOffsetAlignment
  * [[VUID-VkGeneratedCommandsInfoNV-sequencesCountBuffer-02972]]
    If pname:sequencesCountBuffer is not dlink:VK_NULL_HANDLE and is
    non-sparse then it must: be bound completely and contiguously to a
    single sname:VkDeviceMemory object
  * [[VUID-VkGeneratedCommandsInfoNV-sequencesIndexBuffer-02924]]
    If pname:indirectCommandsLayout's
    ename:VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NV is set,
    pname:sequencesIndexBuffer must: be set otherwise it must: be
    dlink:VK_NULL_HANDLE
  * [[VUID-VkGeneratedCommandsInfoNV-sequencesIndexBuffer-02925]]
    If pname:sequencesIndexBuffer is not dlink:VK_NULL_HANDLE, its usage
    flag must: have the ename:VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT bit set
  * [[VUID-VkGeneratedCommandsInfoNV-sequencesIndexBuffer-02926]]
    If pname:sequencesIndexBuffer is not dlink:VK_NULL_HANDLE,
    pname:sequencesIndexOffset must: be aligned to
    sname:VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV::pname:minSequencesIndexBufferOffsetAlignment
  * [[VUID-VkGeneratedCommandsInfoNV-sequencesIndexBuffer-02973]]
    If pname:sequencesIndexBuffer is not dlink:VK_NULL_HANDLE and is
    non-sparse then it must: be bound completely and contiguously to a
    single sname:VkDeviceMemory object
****

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

Referencing the functions defined in <<indirectmdslayout>>,
fname:vkCmdExecuteGeneratedCommandsNV behaves as:

[source,c]
---------------------------------------------------
uint32_t sequencesCount = sequencesCountBuffer ?
      min(maxSequencesCount, sequencesCountBuffer.load_uint32(sequencesCountOffset) :
      maxSequencesCount;


cmdProcessAllSequences(commandBuffer, pipeline,
                       indirectCommandsLayout, pIndirectCommandsStreams,
                       sequencesCount,
                       sequencesIndexBuffer, sequencesIndexOffset);

// The stateful commands within indirectCommandsLayout will not
// affect the state of subsequent commands in the target
// command buffer (cmd)
---------------------------------------------------

[NOTE]
.Note
====
It is important to note that the values of all state related to the
pname:pipelineBindPoint used are undefined: after this command.
====

[open,refpage='vkCmdPreprocessGeneratedCommandsNV',desc='Performs preprocessing for generated commands',type='protos']
--
Commands can: be preprocessed prior execution using the following command:

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

  * pname:commandBuffer is the command buffer which does the preprocessing.
  * pname:pGeneratedCommandsInfo is a pointer to an instance of the
    slink:VkGeneratedCommandsInfoNV structure containing parameters
    affecting the preprocessing step.

.Valid Usage
****
ifdef::VK_VERSION_1_1[]
  * [[VUID-vkCmdPreprocessGeneratedCommandsNV-commandBuffer-02974]]
    pname:commandBuffer must: not be a protected command buffer
endif::VK_VERSION_1_1[]
  * [[VUID-vkCmdPreprocessGeneratedCommandsNV-pGeneratedCommandsInfo-02927]]
    pname:pGeneratedCommandsInfo`s pname:indirectCommandsLayout must: have
    been created with the
    ename:VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EXPLICIT_PREPROCESS_BIT_NV bit
    set
  * [[VUID-vkCmdPreprocessGeneratedCommandsNV-deviceGeneratedCommands-02928]]
    The <<features-deviceGeneratedCommands,
    sname:VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV::pname:deviceGeneratedCommands>>
    feature must: be enabled
****

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

