[[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 <> 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 <> 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[] --