377 lines
15 KiB
Plaintext
377 lines
15 KiB
Plaintext
[[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
|
|
ename: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 elink: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='flags']
|
|
--
|
|
include::../../api/flags/VkIndirectCommandsLayoutUsageFlagsNVX.txt[]
|
|
|
|
tname:VkIndirectCommandsLayoutUsageFlagsNVX is a bitmask type for setting a
|
|
mask of zero or more elink: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[]
|
|
--
|