summaryrefslogtreecommitdiff
path: root/chapters/VK_NV_device_generated_commands/indirectcommands.adoc
blob: fdebffa5d6a9a14312ba82eacfed93e9bade603c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
// 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.adoc[]

Each indirect command layout must: have exactly one action command token and
it must: be the last token in the sequence.
--


=== 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.adoc[]

  * pname:device is the logical device that creates the indirect command
    layout.
  * pname:pCreateInfo is a pointer to a
    slink: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.adoc[]
--

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

  * pname:sType is a elink:VkStructureType value identifying 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:

[source,c]
----
void cmdProcessAllSequences(cmd, pipeline, indirectCommandsLayout, pIndirectCommandsTokens, sequencesCount, indexbuffer, indexbufferOffset)
{
  for (s = 0; s < sequencesCount; s++)
  {
    sUsed = s;

    if (indirectCommandsLayout.flags & VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NV) {
      sUsed = indexbuffer.load_uint32( sUsed * sizeof(uint32_t) + indexbufferOffset);
    }

    if (indirectCommandsLayout.flags & VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NV) {
      sUsed = incoherent_implementation_dependent_permutation[ sUsed ];
    }

    cmdProcessSequence( cmd, pipeline, indirectCommandsLayout, pIndirectCommandsTokens, sUsed );
  }
}
----

When tokens are consumed, an offset is computed based on token offset and
stream stride.
The resulting offset is required to be aligned.
The alignment for a specific token is equal to the scalar alignment of the
data type as defined in <<interfaces-alignment-requirements,Alignment
Requirements>>, or
sname:VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV::pname:minIndirectCommandsBufferOffsetAlignment,
whichever is lower.

[NOTE]
.Note
====
A pname:minIndirectCommandsBufferOffsetAlignment of 4 allows
basetype:VkDeviceAddress to be packed as code:uvec2 with scalar layout
instead of code:uint64_t with 8 byte alignment.
This enables direct compatibility with D3D12 command signature layouts.
====

.Valid Usage
****
  * [[VUID-VkIndirectCommandsLayoutCreateInfoNV-pipelineBindPoint-02930]]
    The pname:pipelineBindPoint must: be
    ename:VK_PIPELINE_BIND_POINT_GRAPHICS
ifdef::VK_NV_device_generated_commands_compute[]
    or ename:VK_PIPELINE_BIND_POINT_COMPUTE
endif::VK_NV_device_generated_commands_compute[]
  * [[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
ifdef::VK_NV_device_generated_commands_compute[]
  * [[VUID-VkIndirectCommandsLayoutCreateInfoNV-pTokens-09585]]
    If pname:pTokens contains an entry of
    ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NV it must: be the first
    element of the array and there must: be only a single element of such
    token type
endif::VK_NV_device_generated_commands_compute[]
  * [[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 before any action command
    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,
    ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_NV
ifdef::VK_NV_device_generated_commands_compute[]
    , ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NV
endif::VK_NV_device_generated_commands_compute[]
    )
  * [[VUID-VkIndirectCommandsLayoutCreateInfoNV-pTokens-02935]]
    The content of pname:pTokens must: include one single action command
    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
ifdef::VK_NV_device_generated_commands_compute[]
  * [[VUID-VkIndirectCommandsLayoutCreateInfoNV-pipelineBindPoint-09088]]
    If pname:pipelineBindPoint is ename:VK_PIPELINE_BIND_POINT_COMPUTE then
    the <<features-deviceGeneratedCompute,
    sname:VkPhysicalDeviceDeviceGeneratedCommandsComputeFeaturesNV::pname:deviceGeneratedCompute>>
    feature must: be enabled
  * [[VUID-VkIndirectCommandsLayoutCreateInfoNV-pipelineBindPoint-09089]]
    If pname:pipelineBindPoint is ename:VK_PIPELINE_BIND_POINT_COMPUTE then
    the state tokens in pname:pTokens must: only include
    ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NV,
    ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NV, or
    ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV
  * [[VUID-VkIndirectCommandsLayoutCreateInfoNV-pipelineBindPoint-09090]]
    If pname:pipelineBindPoint is ename:VK_PIPELINE_BIND_POINT_COMPUTE and
    pname:pTokens includes
    ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NV, then the
    <<features-deviceGeneratedComputePipelines,
    sname:VkPhysicalDeviceDeviceGeneratedCommandsComputeFeaturesNV::pname:deviceGeneratedComputePipelines>>
    feature must: be enabled
endif::VK_NV_device_generated_commands_compute[]
****

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

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

  * 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.
ifdef::VK_NV_device_generated_commands_compute[]
    This flag is ignored when the pname:pipelineBindPoint is
    ename:VK_PIPELINE_BIND_POINT_COMPUTE as it is implied that the dispatch
    sequence is always unordered.
endif::VK_NV_device_generated_commands_compute[]
--

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

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

  * 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
ifndef::VKSC_VERSION_1_0[]
  * [[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`
endif::VKSC_VERSION_1_0[]
  * [[VUID-vkDestroyIndirectCommandsLayoutNV-deviceGeneratedCommands-02941]]
    The <<features-deviceGeneratedCommands,
    sname:VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV::pname:deviceGeneratedCommands>>
    feature must: be enabled
****

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


=== 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.adoc[]

  * 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.adoc[]
--

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[]
ifdef::VK_EXT_mesh_shader[]
  * slink:VkDrawMeshTasksIndirectCommandEXT
endif::VK_EXT_mesh_shader[]
ifdef::VK_NV_device_generated_commands_compute[]
  * slink:VkDispatchIndirectCommand
endif::VK_NV_device_generated_commands_compute[]

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

  * pname:groupIndex 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.adoc[]
--

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

  * 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.adoc[]
--

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

  * 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.adoc[]
--

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

  * 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.adoc[]
--

[open,refpage='VkIndirectStateFlagBitsNV',desc='Bitmask specifying 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.adoc[]

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

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

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

[open,refpage='VkBindPipelineIndirectCommandNV',desc='Structure specifying input data for the compute pipeline dispatch token',type='structs']
--
The sname:VkBindPipelineIndirectCommandNV structure specifies the input data
for the ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NV token.

include::{generated}/api/structs/VkBindPipelineIndirectCommandNV.adoc[]

  * pname:pipelineAddress specifies the pipeline address of the compute
    pipeline that will be used in device generated rendering.

.Valid Usage
****
  * [[VUID-VkBindPipelineIndirectCommandNV-deviceGeneratedComputePipelines-09091]]
    The <<features-deviceGeneratedComputePipelines,
    sname:VkPhysicalDeviceDeviceGeneratedCommandsComputeFeaturesNV::pname:deviceGeneratedComputePipelines>>
    feature must: be enabled
  * [[VUID-VkBindPipelineIndirectCommandNV-None-09092]]
    The referenced pipeline must: have been created with
    ename:VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV
  * [[VUID-VkBindPipelineIndirectCommandNV-None-09093]]
    The referenced pipeline must: have been updated with
    flink:vkCmdUpdatePipelineIndirectBufferNV
  * [[VUID-VkBindPipelineIndirectCommandNV-None-09094]]
    The referenced pipeline's address must: have been queried with
    flink:vkGetPipelineIndirectDeviceAddressNV
****

include::{generated}/validity/structs/VkBindPipelineIndirectCommandNV.adoc[]
--

=== 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 before any action command tokens 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 specifying
command tokens (other elements of the array specify command parameters) are:

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

.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[]
ifdef::VK_EXT_mesh_shader[]
|ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_NV   | flink:vkCmdDrawMeshTasksIndirectEXT
endif::VK_EXT_mesh_shader[]
ifdef::VK_NV_device_generated_commands_compute[]
|ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NV          | flink:vkCmdBindPipeline
|ename:VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NV          | flink:vkCmdDispatchIndirect
endif::VK_NV_device_generated_commands_compute[]
|====
--

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

  * pname:sType is a elink:VkStructureType value identifying this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:tokenType is a elink:VkIndirectCommandsTokenTypeNV specifying the
    token command type.
  * pname:stream is the index of the input stream containing 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 is a tlink:VkIndirectStateFlagsNV bitfield
    indicating 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 elink:VkIndexType.
  * pname:pIndexTypes is the used elink: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-offset-06888]]
    pname:offset must: be aligned to the scalar alignment of pname:tokenType
    or pname:minIndirectCommandsBufferOffsetAlignment, whichever is lower
  * [[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.adoc[]
--

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){
    case VK_INDIRECT_COMMANDS_TOKEN_TYPE_SHADER_GROUP_NV:
      VkBindShaderGroupIndirectCommandNV* bind = input;

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

    case 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;

    case VK_INDIRECT_COMMANDS_TOKEN_TYPE_PUSH_CONSTANT_NV:
      uint32_t* data = input;

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

    case 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;

    case 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;

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

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

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

    // only available if VK_EXT_mesh_shader is supported
    case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_MESH_TASKS_NV:
      vkCmdDrawMeshTasksIndirectEXT(cmd,
        stream.buffer, offset, 1, 0);
    break;

ifdef::VK_NV_device_generated_commands_compute[]
    case VK_INDIRECT_COMMANDS_TOKEN_TYPE_PIPELINE_NV:
      VkBindPipelineIndirectCommandNV *data = input;
      VkPipeline computePipeline = deriveFromDeviceAddress(data->pipelineAddress);
      vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline);
    break;

    case VK_INDIRECT_COMMANDS_TOKEN_TYPE_DISPATCH_NV:
      vkCmdDispatchIndirect(cmd, stream.buffer, offset);
    break;
endif::VK_NV_device_generated_commands_compute[]
    }
  }
}
----