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 | |
Line | |
Triangle | |
Patch |
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.
The ordering of the vertices in each successive triangle is reversed, so that the winding order is consistent throughout the strip.
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.
If the VK_KHR_portability_subset extension is enabled, and
VkPhysicalDevicePortabilitySubsetFeaturesKHR::triangleFans
is
VK_FALSE
, then triangle fans are not supported by the implementation,
and VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN
must 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.
The ordering of the vertices in each successive triangle is altered so that the winding order is consistent throughout the strip.
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.
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
vertexIndex
to 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
vertexIndex
to 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
vertexIndex
value for the vertex shader. These commands are:
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.
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.