| [[indirectmdslayout]] |
| == Indirect Commands Layout |
| |
| [open,refpage='VkIndirectCommandsLayoutNVX',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::../../api/handles/VkIndirectCommandsLayoutNVX.txt[] |
| |
| -- |
| |
| |
| === Tokenized Command Processing |
| |
| The processing is in principle illustrated below: |
| |
| [source,c] |
| --------------------------------------------------- |
| void cmdProcessSequence(cmd, objectTable, indirectCommandsLayout, pIndirectCommandsTokens, s) |
| { |
| for (c = 0; c < indirectCommandsLayout.tokenCount; c++) |
| { |
| indirectCommandsLayout.pTokens[c].command (cmd, objectTable, pIndirectCommandsTokens[c], s); |
| } |
| } |
| |
| void cmdProcessAllSequences(cmd, objectTable, indirectCommandsLayout, pIndirectCommandsTokens, sequencesCount) |
| { |
| for (s = 0; s < sequencesCount; s++) |
| { |
| cmdProcessSequence(cmd, objectTable, indirectCommandsLayout, pIndirectCommandsTokens, 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 either strictly targeting |
| sname:VK_PIPELINE_BIND_POINT_GRAPHICS or |
| ename:VK_PIPELINE_BIND_POINT_COMPUTE. |
| |
| The primary input data for each token is provided through sname:VkBuffer |
| content at command generation time using flink:vkCmdProcessCommandsNVX, |
| however some functional arguments, for example binding sets, are specified |
| at layout creation time. |
| The input size is different for each token. |
| |
| [open,refpage='VkIndirectCommandsTokenTypeNVX',desc='Enum specifying',type='enums'] |
| -- |
| |
| Possible values of those elements of the |
| slink:VkIndirectCommandsLayoutCreateInfoNVX::pname:pTokens array which |
| specify command tokens (other elements of the array specify command |
| parameters) are: |
| |
| include::../../api/enums/VkIndirectCommandsTokenTypeNVX.txt[] |
| |
| .Supported indirect command tokens |
| [width="80%",cols="67%,33%",options="header",align="center"] |
| |==== |
| |Token type | Equivalent command |
| |ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX | fname:vkCmdBindPipeline |
| |ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_DESCRIPTOR_SET_NVX | fname:vkCmdBindDescriptorSets |
| |ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NVX | fname:vkCmdBindIndexBuffer |
| |ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NVX | fname:vkCmdBindVertexBuffers |
| |ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NVX | fname:vkCmdPushConstants |
| |ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NVX | fname:vkCmdDrawIndexedIndirect |
| |ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NVX | fname:vkCmdDrawIndirect |
| |ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX | fname:vkCmdDispatchIndirect |
| |==== |
| |
| -- |
| |
| [open,refpage='VkIndirectCommandsLayoutTokenNVX',desc='Struct specifying the details of an indirect command layout token',type='structs'] |
| -- |
| |
| The sname:VkIndirectCommandsLayoutTokenNVX structure specifies details to |
| the function arguments that need to be known at layout creation time: |
| |
| include::../../api/structs/VkIndirectCommandsLayoutTokenNVX.txt[] |
| |
| * pname:type specifies the token command type. |
| * pname:bindingUnit has a different meaning depending on the type, please |
| refer pseudo code further down for details. |
| * pname:dynamicCount has a different meaning depending on the type, please |
| refer pseudo code further down for details. |
| * pname:divisor defines the rate at which the input data buffers are |
| accessed. |
| |
| .Valid Usage |
| **** |
| * [[VUID-VkIndirectCommandsLayoutTokenNVX-bindingUnit-01342]] |
| pname:bindingUnit must: stay within device supported limits for the |
| appropriate commands. |
| * [[VUID-VkIndirectCommandsLayoutTokenNVX-dynamicCount-01343]] |
| pname:dynamicCount must: stay within device supported limits for the |
| appropriate commands. |
| * [[VUID-VkIndirectCommandsLayoutTokenNVX-divisor-01344]] |
| pname:divisor must: be greater than `0` and a power of two. |
| **** |
| |
| include::../../validity/structs/VkIndirectCommandsLayoutTokenNVX.txt[] |
| -- |
| |
| [open,refpage='VkIndirectCommandsTokenNVX',desc='Structure specifying parameters for the reservation of command buffer space',type='structs'] |
| -- |
| |
| The sname:VkIndirectCommandsTokenNVX structure specifies the input data for |
| a token at processing time. |
| |
| include::../../api/structs/VkIndirectCommandsTokenNVX.txt[] |
| |
| * pname:tokenType specifies the token command type. |
| * pname:buffer specifies the slink:VkBuffer storing the functional |
| arguments for each squence. |
| These argumetns can be written by the device. |
| * pname:offset specified an offset into pname:buffer where the arguments |
| start. |
| |
| .Valid Usage |
| **** |
| * [[VUID-VkIndirectCommandsTokenNVX-buffer-01345]] |
| The pname:buffer's usage flag must: have the |
| ename:VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT bit set. |
| * [[VUID-VkIndirectCommandsTokenNVX-offset-01346]] |
| The pname:offset must: be aligned to |
| sname:VkDeviceGeneratedCommandsLimitsNVX::pname:minCommandsTokenBufferOffsetAlignment. |
| **** |
| |
| include::../../validity/structs/VkIndirectCommandsTokenNVX.txt[] |
| -- |
| |
| |
| The following code provides detailed information on how an individual |
| sequence is processed: |
| |
| [source,c] |
| --------------------------------------------------- |
| void cmdProcessSequence(cmd, objectTable, indirectCommandsLayout, pIndirectCommandsTokens, s) |
| { |
| for (uint32_t c = 0; c < indirectCommandsLayout.tokenCount; c++){ |
| input = pIndirectCommandsTokens[c]; |
| i = s / indirectCommandsLayout.pTokens[c].divisor; |
| |
| switch(input.type){ |
| VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX: |
| size_t stride = sizeof(uint32_t); |
| uint32_t* data = input.buffer.pointer( input.offset + stride * i ); |
| uint32_t object = data[0]; |
| |
| vkCmdBindPipeline(cmd, indirectCommandsLayout.pipelineBindPoint, |
| objectTable.pipelines[ object ].pipeline); |
| break; |
| |
| VK_INDIRECT_COMMANDS_TOKEN_TYPE_DESCRIPTOR_SET_NVX: |
| size_t stride = sizeof(uint32_t) + sizeof(uint32_t) * indirectCommandsLayout.pTokens[c].dynamicCount; |
| uint32_t* data = input.buffer.pointer( input.offset + stride * i); |
| uint32_t object = data[0]; |
| |
| vkCmdBindDescriptorSets(cmd, indirectCommandsLayout.pipelineBindPoint, |
| objectTable.descriptorsets[ object ].layout, |
| indirectCommandsLayout.pTokens[ c ].bindingUnit, |
| 1, &objectTable.descriptorsets[ object ].descriptorSet, |
| indirectCommandsLayout.pTokens[ c ].dynamicCount, data + 1); |
| break; |
| |
| VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NVX: |
| size_t stride = sizeof(uint32_t) + indirectCommandsLayout.pTokens[c].dynamicCount; |
| uint32_t* data = input.buffer.pointer( input.offset + stride * i ); |
| uint32_t object = data[0]; |
| |
| vkCmdPushConstants(cmd, |
| objectTable.pushconstants[ object ].layout, |
| objectTable.pushconstants[ object ].stageFlags, |
| indirectCommandsLayout.pTokens[ c ].bindingUnit, indirectCommandsLayout.pTokens[c].dynamicCount, data + 1); |
| break; |
| |
| VK_INDIRECT_COMMANDS_TOKEN_TYPE_INDEX_BUFFER_NVX: |
| size_t s tride = sizeof(uint32_t) + sizeof(uint32_t) * indirectCommandsLayout.pTokens[c].dynamicCount; |
| uint32_t* data = input.buffer.pointer( input.offset + stride * i ); |
| uint32_t object = data[0]; |
| |
| vkCmdBindIndexBuffer(cmd, |
| objectTable.vertexbuffers[ object ].buffer, |
| indirectCommandsLayout.pTokens[ c ].dynamicCount ? data[1] : 0, |
| objectTable.vertexbuffers[ object ].indexType); |
| break; |
| |
| VK_INDIRECT_COMMANDS_TOKEN_TYPE_VERTEX_BUFFER_NVX: |
| size_t stride = sizeof(uint32_t) + sizeof(uint32_t) * indirectCommandsLayout.pTokens[c].dynamicCount; |
| uint32_t* data = input.buffer.pointer( input.offset + stride * i ); |
| uint32_t object = data[0]; |
| |
| vkCmdBindVertexBuffers(cmd, |
| indirectCommandsLayout.pTokens[ c ].bindingUnit, 1, |
| &objectTable.vertexbuffers[ object ].buffer, |
| indirectCommandsLayout.pTokens[ c ].dynamicCount ? data + 1 : {0}); // device size handled as uint32_t |
| break; |
| |
| VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NVX: |
| vkCmdDrawIndexedIndirect(cmd, |
| input.buffer, |
| sizeof(VkDrawIndexedIndirectCommand) * i + input.offset, 1, 0); |
| break; |
| |
| VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NVX: |
| vkCmdDrawIndirect(cmd, |
| input.buffer, |
| sizeof(VkDrawIndirectCommand) * i + input.offset, 1, 0); |
| break; |
| |
| VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX: |
| vkCmdDispatchIndirect(cmd, |
| input.buffer, |
| sizeof(VkDispatchIndirectCommand) * i + input.offset); |
| break; |
| } |
| } |
| } |
| --------------------------------------------------- |
| |
| |
| === Creation and Deletion |
| |
| [open,refpage='vkCreateIndirectCommandsLayoutNVX',desc='Create an indirect command layout object',type='protos'] |
| -- |
| Indirect command layouts are created by: |
| |
| include::../../api/protos/vkCreateIndirectCommandsLayoutNVX.txt[] |
| |
| * pname:device is the logical device that creates the indirect command |
| layout. |
| * pname:pCreateInfo is a pointer to an instance of the |
| sname:VkIndirectCommandsLayoutCreateInfoNVX 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 points to a |
| sname:VkIndirectCommandsLayoutNVX handle in which the resulting indirect |
| command layout is returned. |
| |
| include::../../validity/protos/vkCreateIndirectCommandsLayoutNVX.txt[] |
| -- |
| |
| [open,refpage='VkIndirectCommandsLayoutCreateInfoNVX',desc='Structure specifying the parameters of a newly created indirect commands layout object',type='structs'] |
| -- |
| |
| The sname:VkIndirectCommandsLayoutCreateInfoNVX structure is defined as: |
| |
| include::../../api/structs/VkIndirectCommandsLayoutCreateInfoNVX.txt[] |
| |
| * pname:sType is the type of this structure. |
| * pname:pNext is `NULL` or a pointer to an extension-specific structure. |
| * pname:pipelineBindPoint is the slink:VkPipelineBindPoint that this |
| layout targets. |
| * pname:flags is a bitmask of |
| elink:VkIndirectCommandsLayoutUsageFlagBitsNVX specifying usage hints of |
| this layout. |
| * pname:tokenCount is the length of the individual command sequnce. |
| * pname:pTokens is an array describing each command token in detail. |
| See elink:VkIndirectCommandsTokenTypeNVX and |
| slink:VkIndirectCommandsLayoutTokenNVX below for details. |
| |
| The following code illustrates some of the key flags: |
| |
| [source,c] |
| --------------------------------------------------- |
| void cmdProcessAllSequences(cmd, objectTable, indirectCommandsLayout, pIndirectCommandsTokens, sequencesCount, indexbuffer, indexbufferoffset) |
| { |
| for (s = 0; s < sequencesCount; s++) |
| { |
| sequence = s; |
| |
| if (indirectCommandsLayout.flags & VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NVX) { |
| sequence = incoherent_implementation_dependent_permutation[ sequence ]; |
| } |
| if (indirectCommandsLayout.flags & VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NVX) { |
| sequence = indexbuffer.load_uint32( sequence * sizeof(uint32_t) + indexbufferoffset); |
| } |
| |
| cmdProcessSequence( cmd, objectTable, indirectCommandsLayout, pIndirectCommandsTokens, sequence ); |
| } |
| } |
| --------------------------------------------------- |
| |
| .Valid Usage |
| **** |
| * [[VUID-VkIndirectCommandsLayoutCreateInfoNVX-tokenCount-01347]] |
| pname:tokenCount must: be greater than `0` and below |
| sname:VkDeviceGeneratedCommandsLimitsNVX::pname:maxIndirectCommandsLayoutTokenCount |
| * [[VUID-VkIndirectCommandsLayoutCreateInfoNVX-computeBindingPointSupport-01348]] |
| If the |
| sname:VkDeviceGeneratedCommandsFeaturesNVX::pname:computeBindingPointSupport |
| feature is not enabled, then pname:pipelineBindPoint must: not be |
| ename:VK_PIPELINE_BIND_POINT_COMPUTE |
| * [[VUID-VkIndirectCommandsLayoutCreateInfoNVX-pTokens-01349]] |
| If pname:pTokens contains an entry of |
| ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NVX it must: be the first |
| element of the array and there must: be only a single element of such |
| token type. |
| * [[VUID-VkIndirectCommandsLayoutCreateInfoNVX-pTokens-01350]] |
| All state binding tokens in pname:pTokens must: occur prior work |
| provoking tokens (ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NVX, |
| ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_INDEXED_NVX, |
| ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NVX). |
| * [[VUID-VkIndirectCommandsLayoutCreateInfoNVX-pTokens-01351]] |
| The content of pname:pTokens must: include one single work provoking |
| token that is compatible with the pname:pipelineBindPoint. |
| **** |
| |
| include::../../validity/structs/VkIndirectCommandsLayoutCreateInfoNVX.txt[] |
| -- |
| |
| [open,refpage='VkIndirectCommandsLayoutUsageFlagBitsNVX',desc='Bitmask specifying allowed usage of an indirect commands layout',type='enums'] |
| -- |
| |
| Bits which can: be set in |
| slink:VkIndirectCommandsLayoutCreateInfoNVX::pname:flags, specifying usage |
| hints of an indirect command layout, are: |
| |
| include::../../api/enums/VkIndirectCommandsLayoutUsageFlagBitsNVX.txt[] |
| |
| * ename:VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NVX |
| specifies that the processing of sequences can: happen at an |
| implementation-dependent order, which is not guaranteed to be coherent |
| across multiple invocations. |
| * ename:VK_INDIRECT_COMMANDS_LAYOUT_USAGE_SPARSE_SEQUENCES_BIT_NVX |
| specifies that there is likely a high difference between allocated |
| number of sequences and actually used. |
| * ename:VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EMPTY_EXECUTIONS_BIT_NVX |
| specifies that there are likely many draw or dispatch calls that are |
| zero-sized (zero grid dimension, no primitives to render). |
| * ename:VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NVX |
| 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. |
| |
| -- |
| |
| [open,refpage='VkIndirectCommandsLayoutUsageFlagsNVX',desc='Bitmask of VkIndirectCommandsLayoutUsageFlagBitsNVX',type='enums'] |
| -- |
| include::../../api/flags/VkIndirectCommandsLayoutUsageFlagsNVX.txt[] |
| |
| sname:VkIndirectCommandsLayoutUsageFlagsNVX is a bitmask type for setting a |
| mask of zero or more slink:VkIndirectCommandsLayoutUsageFlagBitsNVX. |
| -- |
| |
| [open,refpage='vkDestroyIndirectCommandsLayoutNVX',desc='Destroy an object table',type='protos'] |
| -- |
| |
| Indirect command layouts are destroyed by: |
| |
| include::../../api/protos/vkDestroyIndirectCommandsLayoutNVX.txt[] |
| |
| * pname:device is the logical device that destroys the layout. |
| * pname:indirectCommandsLayout is the table to destroy. |
| * pname:pAllocator controls host memory allocation as described in the |
| <<memory-allocation, Memory Allocation>> chapter. |
| |
| .Valid Usage |
| **** |
| * [[VUID-vkDestroyIndirectCommandsLayoutNVX-indirectCommandsLayout-01352]] |
| All submitted commands that refer to pname:indirectCommandsLayout must: |
| have completed execution |
| * [[VUID-vkDestroyIndirectCommandsLayoutNVX-objectTable-01353]] |
| If sname:VkAllocationCallbacks were provided when pname:objectTable was |
| created, a compatible set of callbacks must: be provided here |
| * [[VUID-vkDestroyIndirectCommandsLayoutNVX-objectTable-01354]] |
| If no sname:VkAllocationCallbacks were provided when pname:objectTable |
| was created, pname:pAllocator must: be `NULL` |
| **** |
| |
| include::../../validity/protos/vkDestroyIndirectCommandsLayoutNVX.txt[] |
| -- |