Drawing Commands
Drawing commands (commands with Draw in the name) provoke work in a
graphics pipeline.
Drawing commands are recorded into a command buffer and when executed by a
queue, will produce work which executes according to the bound graphics
pipeline, or if the shaderObject feature is
enabled, any shader objects bound to graphics stages.
A graphics pipeline
or a combination of one or more graphics shader objects
must be bound to a command buffer before any drawing commands are recorded
in that command buffer.
Primitive Topologies
Primitive topology determines how consecutive vertices are organized into primitives, and determines the type of primitive that is used at the beginning of the graphics pipeline. The effective topology for later stages of the pipeline is altered by tessellation or geometry shading (if either is in use) and depends on the execution modes of those shaders. In the case of mesh shading the only effective topology is defined by the execution mode of the mesh shader.
Topology Class
The primitive topologies are grouped into the following topology classes:
| Topology Class | Primitive Topology |
|---|---|
| Point | VK_PRIMITIVE_TOPOLOGY_POINT_LIST |
| Line | VK_PRIMITIVE_TOPOLOGY_LINE_LIST,VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY |
| Triangle | VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY |
| Patch | VK_PRIMITIVE_TOPOLOGY_PATCH_LIST |
Point Lists
When the topology is VK_PRIMITIVE_TOPOLOGY_POINT_LIST, each
consecutive vertex defines a single point primitive, according to the
equation:
- pi = {vi}
As there is only one vertex, that vertex is the provoking vertex.
The number of primitives generated is equal to vertexCount.
Line Lists
When the primitive topology is VK_PRIMITIVE_TOPOLOGY_LINE_LIST, each
consecutive pair of vertices defines a single line primitive, according to
the equation:
- pi = {v2i, v2i+1}
The number of primitives generated is equal to
⌊vertexCount/2⌋.
When the provokingVertexMode is
VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT, the
provoking vertex for pi is v2i.
When the provokingVertexMode is
VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT, the provoking vertex for
pi is v2i+1.
Line Strips
When the primitive topology is VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, one
line primitive is defined by each vertex and the following vertex, according
to the equation:
- pi = {vi, vi+1}
The number of primitives generated is equal to
max(0,vertexCount-1).
When the provokingVertexMode is
VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT, the
provoking vertex for pi is vi.
When the provokingVertexMode is
VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT, the provoking vertex for
pi is vi+1.
Triangle Lists
When the primitive topology is VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
each consecutive set of three vertices defines a single triangle primitive,
according to the equation:
- pi = {v3i, v3i+1, v3i+2}
The number of primitives generated is equal to
⌊vertexCount/3⌋.
When the provokingVertexMode is
VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT, the
provoking vertex for pi is v3i.
When the provokingVertexMode is
VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT, the provoking vertex for
pi is v3i+2.
Triangle Strips
When the primitive topology is VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
one triangle primitive is defined by each vertex and the two vertices that
follow it, according to the equation:
- pi = {vi, vi+(1+i%2), vi+(2-i%2)}
The number of primitives generated is equal to
max(0,vertexCount-2).
When the provokingVertexMode is
VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT, the
provoking vertex for pi is vi.
When the provokingVertexMode is
VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT, the provoking vertex for
pi is vi+2.
Triangle Fans
When the primitive topology is VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
triangle primitives are defined around a shared common vertex, according to
the equation:
- pi = {vi+1, vi+2, v0}
The number of primitives generated is equal to
max(0,vertexCount-2).
When the provokingVertexMode is
VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT, the
provoking vertex for pi is vi+1.
When the provokingVertexMode is
VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT, the provoking vertex for
pi is vi+2.
triangleFans is
VK_FALSE, then triangle fans are not supported by the implementation,
and VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FANmust not be used.Line Lists With Adjacency
When the primitive topology is
VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, each consecutive set
of four vertices defines a single line primitive with adjacency, according
to the equation:
- pi = {v4i, v4i+1, v4i+2,v4i+3}
A line primitive is described by the second and third vertices of the total primitive, with the remaining two vertices only accessible in a geometry shader.
The number of primitives generated is equal to
⌊vertexCount/4⌋.
When the provokingVertexMode is
VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT, the
provoking vertex for pi is v4i+1.
When the provokingVertexMode is
VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT, the provoking vertex for
pi is v4i+2.
Line Strips With Adjacency
When the primitive topology is
VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, one line primitive
with adjacency is defined by each vertex and the following vertex, according
to the equation:
- pi = {vi, vi+1, vi+2, vi+3}
A line primitive is described by the second and third vertices of the total primitive, with the remaining two vertices only accessible in a geometry shader.
The number of primitives generated is equal to
max(0,vertexCount-3).
When the provokingVertexMode is
VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT, the
provoking vertex for pi is vi+1.
When the provokingVertexMode is
VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT, the provoking vertex for
pi is vi+2.
Triangle Lists With Adjacency
When the primitive topology is
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, each consecutive
set of six vertices defines a single triangle primitive with adjacency,
according to the equations:
- pi = {v6i, v6i+1, v6i+2, v6i+3, v6i+4, v6i+5}
A triangle primitive is described by the first, third, and fifth vertices of the total primitive, with the remaining three vertices only accessible in a geometry shader.
The number of primitives generated is equal to
⌊vertexCount/6⌋.
When the provokingVertexMode is
VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT, the
provoking vertex for pi is v6i.
When the provokingVertexMode is
VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT, the provoking vertex for
pi is v6i+4.
Triangle Strips With Adjacency
When the primitive topology is
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, one triangle
primitive with adjacency is defined by each vertex and the following 5
vertices.
The number of primitives generated, n, is equal to ⌊max(0,
vertexCount - 4)/2⌋.
If n=1, the primitive is defined as:
- p = {v0, v1, v2, v5, v4, v3}
If n>1, the total primitive consists of different vertices according to where it is in the strip:
- pi = {v2i, v2i+1, v2i+2, v2i+6, v2i+4, v2i+3} when i=0
- pi = {v2i, v2i+3, v2i+4, v2i+6, v2i+2, v2i-2} when i>0, i<n-1, and i%2=1
- pi = {v2i, v2i-2, v2i+2, v2i+6, v2i+4, v2i+3} when i>0, i<n-1, and i%2=0
- pi = {v2i, v2i+3, v2i+4, v2i+5, v2i+2, v2i-2} when i=n-1 and i%2=1
- pi = {v2i, v2i-2, v2i+2, v2i+5, v2i+4, v2i+3} when i=n-1 and i%2=0
A triangle primitive is described by the first, third, and fifth vertices of the total primitive in all cases, with the remaining three vertices only accessible in a geometry shader.
When the provokingVertexMode is
VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT, the
provoking vertex for pi is always v2i.
When the provokingVertexMode is
VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT, the provoking vertex for
pi is always v2i+4.
Patch Lists
When the primitive topology is VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, each
consecutive set of m vertices defines a single patch primitive,
according to the equation:
- pi = {vmi, vmi+1, …, vmi+(m-2), vmi+(m-1)}
where m is equal to
VkPipelineTessellationStateCreateInfo::patchControlPoints.
Patch lists are never passed to vertex post-processing,
and as such no provoking vertex is defined for patch primitives.
The number of primitives generated is equal to
⌊vertexCount/m⌋.
The vertices comprising a patch have no implied geometry, and are used as inputs to tessellation shaders and the fixed-function tessellator to generate new point, line, or triangle primitives.
Effective Primitive Topology
The effective primitive topology is the primitive topology that is consumed or produced by a given stage of the graphics pipeline. The interpretation of this topology depends on the active shader stages and other state set in the graphics pipeline.
Vertex Input Assembler Topology
This is the topology set when the VK_SHADER_STAGE_VERTEX_BIT stage is
used and Programmable Primitive Shading
occurs.
It can be set with
VkPipelineInputAssemblyStateCreateInfo::topology
or vkCmdSetPrimitiveTopology.
Clip Space Topology
This is the output of the last pre-rasterization shader stage involved.
- If
VK_SHADER_STAGE_VERTEX_BITis the last pre-rasterization stage, the topology is not changed from what was set in the input assembly. - If
VK_SHADER_STAGE_TESSELLATION_EVALUATION_BITis the last pre-rasterization stage, the topology depends on theOpExecutionModefound in either tessellation stage.- The
IsolinesExecutionModeis in line topology class. - The
TrianglesandQuadsExecutionModeis in triangle topology class. - The
PointModeExecutionModeis in point topology class and will take precedence over the other tessellation stageExecutionMode.
- The
- If
VK_SHADER_STAGE_GEOMETRY_BITis the last pre-rasterization stage, the topology depends on theOpExecutionModefound in this shader stage.- The
OutputPointsExecutionModeis in point topology class. - The
OutputLineStripExecutionModeis in line topology class. - The
OutputTriangleStripExecutionModeis in triangle topology class.
- The
- If
VK_SHADER_STAGE_MESH_BIT_EXTis the last pre-rasterization stage, the topology depends on theOpExecutionModefound in this shader stage.- The
OutputPointsExecutionModeis in point topology class. - The
OutputLinesEXTExecutionModeis in line topology class. - The
OutputTrianglesEXTExecutionModeis in triangle topology class.
- The
Rasterization Input Topology
After clipping and viewport transformations, the Polygon Mode can set a topology as an input for rasterization. This can be different from what was used in Clip Space Topology.
If
VkPipelineRasterizationStateCreateInfo::rasterizerDiscardEnable
or vkCmdSetRasterizerDiscardEnableEXT::rasterizerDiscardEnable
is set to VK_FALSE, then this Rasterization Input Topology is not
observed.
If the clip space topology is in triangle
topology class then
VK_POLYGON_MODE_LINE will turn it into line topology and
VK_POLYGON_MODE_POINT will turn it into point topology.
If the clip space topology is in line
topology class then
VK_POLYGON_MODE_POINT will turn it into point topology.
Primitive Order
Primitives generated by drawing commands progress through the stages of the graphics pipeline in primitive order. Primitive order is initially determined in the following way:
- Submission order determines the initial ordering
- For indirect drawing commands, the order in which accessed instances of
the VkDrawIndirectCommand are stored in
buffer, from lower indirect buffer addresses to higher addresses. - If a drawing command includes multiple instances, the order in which instances are executed, from lower numbered instances to higher.
- The order in which primitives are specified by a drawing command:
- For non-indexed draws, from vertices with a lower numbered
vertexIndexto a higher numberedvertexIndex. - For indexed draws, vertices sourced from a lower index buffer addresses to higher addresses.
- For draws using mesh shaders, the order is provided by mesh shading.
- For draws using cluster culling shaders, the order is provided by cluster culling shading.
- For non-indexed draws, from vertices with a lower numbered
Within this order implementations further sort primitives:
- If tessellation shading is active, by an implementation-dependent order of new primitives generated by tessellation.
- If geometry shading is active, by the order new primitives are generated by geometry shading.
- If the polygon mode is not
VK_POLYGON_MODE_FILL, orVK_POLYGON_MODE_FILL_RECTANGLE_NV, by an implementation-dependent ordering of the new primitives generated within the original primitive.
Primitive order is later used to define rasterization order, which determines the order in which fragments output results to a framebuffer.
Programmable Primitive Shading
Once primitives are assembled, they proceed to the vertex shading stage of the pipeline. If the draw includes multiple instances, then the set of primitives is sent to the vertex shading stage multiple times, once for each instance.
It is implementation-dependent whether vertex shading occurs on vertices that are discarded as part of incomplete primitives, but if it does occur then it operates as if they were vertices in complete primitives and such invocations can have side effects.
Vertex shading receives two per-vertex inputs from the primitive assembly
stage - the vertexIndex and the instanceIndex.
How these values are generated is defined below, with each command.
Drawing commands fall roughly into two categories:
- Non-indexed drawing commands present a sequential
vertexIndexto the vertex shader. The sequential index is generated automatically by the device (see Fixed-Function Vertex Processing for details on both specifying the vertex attributes indexed byvertexIndex, as well as binding vertex buffers containing those attributes to a command buffer). These commands are: - Indexed drawing commands read index values from an index buffer and
use this to compute the
vertexIndexvalue for the vertex shader. These commands are:
For indexed drawing commands, indices are sourced from a range of memory bound to the command buffer, referred to as the bound index buffer range, and specified by one of the following commands.
The parameters for each drawing command are specified directly in the command or read from buffer memory, depending on the command. Drawing commands that source their parameters from buffer memory are known as indirect drawing commands.
All drawing commands interact with the robustBufferAccess feature.
Drawing Transform Feedback
It is possible to draw vertex data that was previously captured during
active transform feedback by binding
one or more of the transform feedback buffers as vertex buffers.
A pipeline barrier is required between using the buffers as transform
feedback buffers and vertex buffers to ensure all writes to the transform
feedback buffers are visible when the data is read as vertex attributes.
The source access is VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT and
the destination access is VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT for the
pipeline stages VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT and
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT respectively.
The value written to the counter buffer by
vkCmdEndTransformFeedbackEXT can be used to determine the vertex
count for the draw.
A pipeline barrier is required between using the counter buffer for
vkCmdEndTransformFeedbackEXT and vkCmdDrawIndirectByteCountEXT
where the source access is
VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT and the destination
access is VK_ACCESS_INDIRECT_COMMAND_READ_BIT for the pipeline stages
VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT and
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT respectively.
Conditional Rendering
Certain rendering commands can be executed conditionally based on a value in buffer memory. These rendering commands are limited to drawing commands, dispatching commands, and clearing attachments with vkCmdClearAttachments within a conditional rendering block which is defined by commands vkCmdBeginConditionalRenderingEXT and vkCmdEndConditionalRenderingEXT. Other rendering commands remain unaffected by conditional rendering.
The complete list of commands affected by conditional rendering is:
After beginning conditional rendering, it is considered active within the command buffer it was called until it is ended with vkCmdEndConditionalRenderingEXT.
Conditional rendering must begin and end in the same command buffer.
When conditional rendering is active, a primary command buffer can execute
secondary command buffers if the inheritedConditionalRendering feature is enabled.
For a secondary command buffer to be executed while conditional rendering is
active in the primary command buffer, it must set the
conditionalRenderingEnable flag of
VkCommandBufferInheritanceConditionalRenderingInfoEXT, as described in
the Command Buffer Recording section.
Conditional rendering must also either begin and end inside the same subpass of a render pass instance, or must both begin and end outside of a render pass instance (i.e. contain entire render pass instances).
Programmable Mesh Shading
In this drawing approach, primitives are assembled by the mesh shader stage. Mesh shading operates similarly to dispatching compute as the shaders make use of workgroups.
Programmable Cluster Culling Shading
In this drawing approach, cluster are generated by the cluster culling shader stage. It operates similarly to dispatching compute as the shaders make use of workgroups.