27. Fixed-Function Vertex Post-Processing
After pre-rasterization shader stages, the following fixed-function operations are applied to vertices of the resulting primitives:
-
Transform feedback (see Transform Feedback)
-
Viewport swizzle (see Viewport Swizzle)
-
Flat shading (see Flat Shading).
-
Primitive clipping, including client-defined half-spaces (see Primitive Clipping).
-
Shader output attribute clipping (see Clipping Shader Outputs).
-
Clip space W scaling (see Controlling Viewport W Scaling).
-
Perspective division on clip coordinates (see Coordinate Transformations).
-
Viewport mapping, including depth range scaling (see Controlling the Viewport).
-
Front face determination for polygon primitives (see Basic Polygon Rasterization).
editing-note
TODO:Odd that this one link to a different chapter is in this list. |
Next, rasterization is performed on primitives as described in chapter Rasterization.
27.1. Transform Feedback
Before any other fixed-function vertex post-processing, vertex outputs from
the last shader in the
pre-rasterization shader
stage can be written out to one or more transform feedback buffers bound
to the command buffer.
To capture vertex outputs the last
pre-rasterization shader
stage shader must be declared with the Xfb
execution mode.
Outputs decorated with XfbBuffer
will be written out to the
corresponding transform feedback buffers bound to the command buffer when
transform feedback is active.
Transform feedback buffers are bound to the command buffer by using
vkCmdBindTransformFeedbackBuffersEXT.
Transform feedback is made active by calling
vkCmdBeginTransformFeedbackEXT and made inactive by calling
vkCmdEndTransformFeedbackEXT.
After vertex data is written it is possible to use
vkCmdDrawIndirectByteCountEXT to start a new draw where the
vertexCount
is derived from the number of bytes written by a previous
transform feedback.
When an individual point, line, or triangle primitive reaches the transform
feedback stage while transform feedback is active, the values of the
specified output variables are assembled into primitives and appended to the
bound transform feedback buffers.
After activating transform feedback, the values of the first assembled
primitive are written at the starting offsets of the bound transform
feedback buffers, and subsequent primitives are appended to the buffer.
If the optional pCounterBuffers
and pCounterBufferOffsets
parameters are specified, the starting points within the transform feedback
buffers are adjusted so data is appended to the previously written values
indicated by the value stored by the implementation in the counter buffer.
For multi-vertex primitives, all values for a given vertex are written
before writing values for any other vertex.
When transformFeedbackPreservesProvokingVertex
is not enabled,
implementations
may write out any vertex within the primitive first, but all subsequent
vertices for that primitive must be written out in a consistent winding
order defined as follows:
-
If neither geometry or tessellation shading is active, vertices within a primitive are appended according to the winding order described by the primitive topology defined by the VkPipelineInputAssemblyStateCreateInfo:
topology
used to execute the drawing command. -
If geometry shading is active, vertices within a primitive are appended according to the winding order described by the primitive topology defined by the
OutputPoints
,OutputLineStrips
, orOutputTriangleStrips
execution mode. -
If tessellation shading is active but geometry shading is not, vertices within a primitive are appended according to the winding order defined by triangle tessellation, quad tessellation, and isoline tessellation.
When transformFeedbackPreservesProvokingVertex
is enabled, then in
addition to writing vertices with a consistent winding order, the vertex
order must preserve the provoking vertex of
each primitive:
-
When the pipeline’s provoking vertex mode is
VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT
, the primitive’s provoking vertex must be the first vertex written. -
When the pipeline’s provoking vertex mode is
VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT
, the primitive’s provoking vertex must be the last vertex written.
If transformFeedbackPreservesTriangleFanProvokingVertex
is
VK_FALSE
, neither geometry nor tessellation shading is active, and the primitive topology is VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN
, then the
first vertex written from each primitive is implementation-defined even when
transformFeedbackPreservesProvokingVertex
is enabled.
When capturing vertices, the stride associated with each transform feedback
buffer, as indicated by the XfbStride
decoration, indicates the number
of bytes of storage reserved for each vertex in the transform feedback
buffer.
For every vertex captured, each output attribute with a Offset
decoration will be written to the storage reserved for the vertex at the
associated transform feedback buffer.
When writing output variables that are arrays or structures, individual
array elements or structure members are written tightly packed in order.
For vector types, individual components are written in order.
For matrix types, outputs are written as an array of column vectors.
If any component of an output with an assigned transform feedback offset was not written to by its shader, the value recorded for that component is undefined. All components of an output variable must be written at an offset aligned to the size of the component. The size of each component of an output variable must be at least 32-bits. When capturing a vertex, any portion of the reserved storage not associated with an output variable with an assigned transform feedback offset will be unmodified.
When transform feedback is inactive, no vertices are recorded.
If there is a valid counter buffer handle and counter buffer offset in the
pCounterBuffers
and pCounterBufferOffsets
arrays, writes to the
corresponding transform feedback buffer will start at the byte offset
represented by the value stored in the counter buffer location.
Individual lines or triangles of a strip or fan primitive will be extracted and recorded separately. Incomplete primitives are not recorded.
When using a geometry shader that emits vertices to multiple vertex streams, a primitive will be assembled and output for each stream when there are enough vertices emitted for the output primitive type. All outputs assigned to a given transform feedback buffer are required to come from a single vertex stream.
The sizes of the transform feedback buffers are defined by the
vkCmdBindTransformFeedbackBuffersEXT pSizes
parameter for each
of the bound buffers, or the size of the bound buffer, whichever is the
lesser.
If there is less space remaining in any of the transform feedback buffers
than the size of all of the vertex data for that primitive based on the
XfbStride
for that XfbBuffer
then no vertex data of that primitive
is recorded in any transform feedback buffer, and the value for the number
of primitives written in the corresponding
VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT
query for all transform
feedback buffers is no longer incremented.
Any outputs made to a XfbBuffer
that is not bound to a transform
feedback buffer is ignored.
To bind transform feedback buffers to a command buffer for use in subsequent drawing commands, call:
// Provided by VK_EXT_transform_feedback
void vkCmdBindTransformFeedbackBuffersEXT(
VkCommandBuffer commandBuffer,
uint32_t firstBinding,
uint32_t bindingCount,
const VkBuffer* pBuffers,
const VkDeviceSize* pOffsets,
const VkDeviceSize* pSizes);
-
commandBuffer
is the command buffer into which the command is recorded. -
firstBinding
is the index of the first transform feedback binding whose state is updated by the command. -
bindingCount
is the number of transform feedback bindings whose state is updated by the command. -
pBuffers
is a pointer to an array of buffer handles. -
pOffsets
is a pointer to an array of buffer offsets. -
pSizes
isNULL
or a pointer to an array of VkDeviceSize buffer sizes, specifying the maximum number of bytes to capture to the corresponding transform feedback buffer. IfpSizes
isNULL
, or the value of thepSizes
array element isVK_WHOLE_SIZE
, then the maximum number of bytes captured will be the size of the corresponding buffer minus the buffer offset.
The values taken from elements i of pBuffers
, pOffsets
and
pSizes
replace the current state for the transform feedback binding
firstBinding
+ i, for i in [0,
bindingCount
).
The transform feedback binding is updated to start at the offset indicated
by pOffsets
[i] from the start of the buffer pBuffers
[i].
Transform feedback for specific transform feedback buffers is made active by calling:
// Provided by VK_EXT_transform_feedback
void vkCmdBeginTransformFeedbackEXT(
VkCommandBuffer commandBuffer,
uint32_t firstCounterBuffer,
uint32_t counterBufferCount,
const VkBuffer* pCounterBuffers,
const VkDeviceSize* pCounterBufferOffsets);
-
commandBuffer
is the command buffer into which the command is recorded. -
firstCounterBuffer
is the index of the first transform feedback buffer corresponding topCounterBuffers
[0] andpCounterBufferOffsets
[0]. -
counterBufferCount
is the size of thepCounterBuffers
andpCounterBufferOffsets
arrays. -
pCounterBuffers
isNULL
or a pointer to an array of VkBuffer handles to counter buffers. Each buffer contains a 4 byte integer value representing the byte offset from the start of the corresponding transform feedback buffer from where to start capturing vertex data. If the byte offset stored to the counter buffer location was done using vkCmdEndTransformFeedbackEXT it can be used to resume transform feedback from the previous location. IfpCounterBuffers
isNULL
, then transform feedback will start capturing vertex data to byte offset zero in all bound transform feedback buffers. For each element ofpCounterBuffers
that is VK_NULL_HANDLE, transform feedback will start capturing vertex data to byte zero in the corresponding bound transform feedback buffer. -
pCounterBufferOffsets
isNULL
or a pointer to an array of VkDeviceSize values specifying offsets within each of thepCounterBuffers
where the counter values were previously written. The location in each counter buffer at these offsets must be large enough to contain 4 bytes of data. This data is the number of bytes captured by the previous transform feedback to this buffer. IfpCounterBufferOffsets
isNULL
, then it is assumed the offsets are zero.
The active transform feedback buffers will capture primitives emitted from
the corresponding XfbBuffer
in the bound graphics pipeline.
Any XfbBuffer
emitted that does not output to an active transform
feedback buffer will not be captured.
Transform feedback for specific transform feedback buffers is made inactive by calling:
// Provided by VK_EXT_transform_feedback
void vkCmdEndTransformFeedbackEXT(
VkCommandBuffer commandBuffer,
uint32_t firstCounterBuffer,
uint32_t counterBufferCount,
const VkBuffer* pCounterBuffers,
const VkDeviceSize* pCounterBufferOffsets);
-
commandBuffer
is the command buffer into which the command is recorded. -
firstCounterBuffer
is the index of the first transform feedback buffer corresponding topCounterBuffers
[0] andpCounterBufferOffsets
[0]. -
counterBufferCount
is the size of thepCounterBuffers
andpCounterBufferOffsets
arrays. -
pCounterBuffers
isNULL
or a pointer to an array of VkBuffer handles to counter buffers. The counter buffers are used to record the current byte positions of each transform feedback buffer where the next vertex output data would be captured. This can be used by a subsequent vkCmdBeginTransformFeedbackEXT call to resume transform feedback capture from this position. It can also be used by vkCmdDrawIndirectByteCountEXT to determine the vertex count of the draw call. -
pCounterBufferOffsets
isNULL
or a pointer to an array of VkDeviceSize values specifying offsets within each of thepCounterBuffers
where the counter values can be written. The location in each counter buffer at these offsets must be large enough to contain 4 bytes of data. The data stored at this location is the byte offset from the start of the transform feedback buffer binding where the next vertex data would be written. IfpCounterBufferOffsets
isNULL
, then it is assumed the offsets are zero.
27.2. Viewport Swizzle
Each primitive sent to a given viewport has a swizzle and optional negation
applied to its clip coordinates.
The swizzle that is applied depends on the viewport index, and is controlled
by the VkPipelineViewportSwizzleStateCreateInfoNV
pipeline state:
// Provided by VK_NV_viewport_swizzle
typedef struct VkPipelineViewportSwizzleStateCreateInfoNV {
VkStructureType sType;
const void* pNext;
VkPipelineViewportSwizzleStateCreateFlagsNV flags;
uint32_t viewportCount;
const VkViewportSwizzleNV* pViewportSwizzles;
} VkPipelineViewportSwizzleStateCreateInfoNV;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
flags
is reserved for future use. -
viewportCount
is the number of viewport swizzles used by the pipeline. -
pViewportSwizzles
is a pointer to an array of VkViewportSwizzleNV structures, defining the viewport swizzles.
// Provided by VK_NV_viewport_swizzle
typedef VkFlags VkPipelineViewportSwizzleStateCreateFlagsNV;
VkPipelineViewportSwizzleStateCreateFlagsNV
is a bitmask type for
setting a mask, but is currently reserved for future use.
The VkPipelineViewportSwizzleStateCreateInfoNV
state is set by adding
this structure to the pNext
chain of a
VkPipelineViewportStateCreateInfo
structure and setting the graphics
pipeline state with vkCreateGraphicsPipelines.
To dynamically set the viewport swizzle state, call:
// Provided by VK_EXT_extended_dynamic_state3 with VK_NV_viewport_swizzle, VK_EXT_shader_object with VK_NV_viewport_swizzle
void vkCmdSetViewportSwizzleNV(
VkCommandBuffer commandBuffer,
uint32_t firstViewport,
uint32_t viewportCount,
const VkViewportSwizzleNV* pViewportSwizzles);
-
commandBuffer
is the command buffer into which the command will be recorded. -
firstViewport
is the index of the first viewport whose parameters are updated by the command. -
viewportCount
is the number of viewports whose parameters are updated by the command. -
pViewportSwizzles
is a pointer to an array of VkViewportSwizzleNV structures specifying viewport swizzles.
This command sets the viewport swizzle state for subsequent drawing commands
when the graphics pipeline is created with
VK_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV
set in
VkPipelineDynamicStateCreateInfo::pDynamicStates
.
Otherwise, this state is specified by the
VkPipelineViewportSwizzleStateCreateInfoNV::viewportCount
, and
VkPipelineViewportSwizzleStateCreateInfoNV::pViewportSwizzles
values used to create the currently active pipeline.
Each viewport specified from 0 to viewportCount
- 1 has its x,y,z,w
swizzle state set to the corresponding x
, y
, z
and w
in the VkViewportSwizzleNV structure.
Each component is of type VkViewportCoordinateSwizzleNV, which
determines the type of swizzle for that component.
The value of x
computes the new x component of the position as:
if (x == VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV) x' = x;
if (x == VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV) x' = -x;
if (x == VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV) x' = y;
if (x == VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Y_NV) x' = -y;
if (x == VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV) x' = z;
if (x == VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV) x' = -z;
if (x == VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV) x' = w;
if (x == VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV) x' = -w;
Similar selections are performed for the y
, z
, and w
coordinates.
This swizzling is applied before clipping and perspective divide.
If the swizzle for an active viewport index is not specified, the swizzle
for x
is VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV
, y
is VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV
, z
is
VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV
and w
is
VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV
.
Viewport swizzle parameters are specified by setting the pNext
pointer
of VkGraphicsPipelineCreateInfo
to point to a
VkPipelineViewportSwizzleStateCreateInfoNV
structure.
VkPipelineViewportSwizzleStateCreateInfoNV uses
VkViewportSwizzleNV
to set the viewport swizzle parameters.
The VkViewportSwizzleNV
structure is defined as:
// Provided by VK_NV_viewport_swizzle
typedef struct VkViewportSwizzleNV {
VkViewportCoordinateSwizzleNV x;
VkViewportCoordinateSwizzleNV y;
VkViewportCoordinateSwizzleNV z;
VkViewportCoordinateSwizzleNV w;
} VkViewportSwizzleNV;
-
x
is a VkViewportCoordinateSwizzleNV value specifying the swizzle operation to apply to the x component of the primitive -
y
is a VkViewportCoordinateSwizzleNV value specifying the swizzle operation to apply to the y component of the primitive -
z
is a VkViewportCoordinateSwizzleNV value specifying the swizzle operation to apply to the z component of the primitive -
w
is a VkViewportCoordinateSwizzleNV value specifying the swizzle operation to apply to the w component of the primitive
Possible values of the VkViewportSwizzleNV::x
, y
, z
,
and w
members, specifying swizzling of the corresponding components of
primitives, are:
// Provided by VK_NV_viewport_swizzle
typedef enum VkViewportCoordinateSwizzleNV {
VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV = 0,
VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_X_NV = 1,
VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV = 2,
VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Y_NV = 3,
VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV = 4,
VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_Z_NV = 5,
VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV = 6,
VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV = 7,
} VkViewportCoordinateSwizzleNV;
These values are described in detail in Viewport Swizzle.
27.3. Flat Shading
Flat shading a vertex output attribute means to assign all vertices of the
primitive the same value for that output.
The output values assigned are those of the provoking vertex of the
primitive.
Flat shading is applied to those vertex attributes that
match fragment input attributes which
are decorated as Flat
.
If neither
mesh,
geometry nor tessellation shading is active,
the provoking vertex is determined by the primitive topology defined by
VkPipelineInputAssemblyStateCreateInfo:topology
used to execute
the drawing command.
If a shader using MeshNV
Execution
Model
is active, the provoking
vertex is determined by the primitive
topology defined by the OutputPoints
,
OutputLinesNV
, or OutputTrianglesNV
execution mode.
If a shader using MeshEXT
Execution
Model
is active, the provoking
vertex is determined by the primitive
topology defined by the OutputPoints
,
OutputLinesEXT
, or OutputTrianglesEXT
execution mode.
If geometry shading is active, the provoking vertex is
determined by the primitive topology
defined by the OutputPoints
,
OutputLineStrips
, or
OutputTriangleStrips
execution mode.
If tessellation shading is active but geometry shading is not, the provoking vertex may be any of the vertices in each primitive.
For a given primitive topology, the pipeline’s provoking vertex mode
determines which vertex is the provoking vertex.
To specify the provoking vertex mode, include a
VkPipelineRasterizationProvokingVertexStateCreateInfoEXT
structure in
the VkPipelineRasterizationStateCreateInfo::pNext
chain when
creating the pipeline.
The VkPipelineRasterizationProvokingVertexStateCreateInfoEXT
structure
is defined as:
// Provided by VK_EXT_provoking_vertex
typedef struct VkPipelineRasterizationProvokingVertexStateCreateInfoEXT {
VkStructureType sType;
const void* pNext;
VkProvokingVertexModeEXT provokingVertexMode;
} VkPipelineRasterizationProvokingVertexStateCreateInfoEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
provokingVertexMode
is a VkProvokingVertexModeEXT value selecting the provoking vertex mode.
If this struct is not provided when creating the pipeline, the pipeline will
use the VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT
mode.
If the provokingVertexModePerPipeline
limit is VK_FALSE
, then all
pipelines bound within a render pass instance must have the same
provokingVertexMode
.
Possible values of
VkPipelineRasterizationProvokingVertexStateCreateInfoEXT::provokingVertexMode
are:
// Provided by VK_EXT_provoking_vertex
typedef enum VkProvokingVertexModeEXT {
VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT = 0,
VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT = 1,
} VkProvokingVertexModeEXT;
-
VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT
specifies that the provoking vertex is the first non-adjacency vertex in the list of vertices used by a primitive. -
VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT
specifies that the provoking vertex is the last non-adjacency vertex in the list of vertices used by a primitive.
These modes are described more precisely in Primitive Topologies.
To dynamically set the
provokingVertexMode
state, call:
// Provided by VK_EXT_extended_dynamic_state3, VK_EXT_shader_object
void vkCmdSetProvokingVertexModeEXT(
VkCommandBuffer commandBuffer,
VkProvokingVertexModeEXT provokingVertexMode);
-
commandBuffer
is the command buffer into which the command will be recorded. -
provokingVertexMode
specifies theprovokingVertexMode
state.
This command sets the provokingVertexMode
state for subsequent drawing
commands
when the graphics pipeline is created with
VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT
set in
VkPipelineDynamicStateCreateInfo::pDynamicStates
.
Otherwise, this state is specified by the
VkPipelineRasterizationProvokingVertexStateCreateInfoEXT::provokingVertexMode
value used to create the currently active pipeline.
27.4. Primitive Clipping
Primitives are culled against the cull volume and then clipped to the clip volume. In clip coordinates, the view volume is defined by:
where
if
VkPipelineViewportDepthClipControlCreateInfoEXT::negativeOneToOne
is VK_TRUE
zm is equal to -wc otherwise
zm is equal to zero.
This view volume can be further restricted by as many as
VkPhysicalDeviceLimits
::maxClipDistances
client-defined
half-spaces.
The cull volume is the intersection of up to
VkPhysicalDeviceLimits
::maxCullDistances
client-defined
half-spaces (if no client-defined cull half-spaces are enabled, culling
against the cull volume is skipped).
A shader must write a single cull distance for each enabled cull half-space
to elements of the CullDistance
array.
If the cull distance for any enabled cull half-space is negative for all of
the vertices of the primitive under consideration, the primitive is
discarded.
Otherwise the primitive is clipped against the clip volume as defined below.
The clip volume is the intersection of up to
VkPhysicalDeviceLimits
::maxClipDistances
client-defined
half-spaces with the view volume (if no client-defined clip half-spaces are
enabled, the clip volume is the view volume).
A shader must write a single clip distance for each enabled clip half-space
to elements of the ClipDistance
array.
Clip half-space i is then given by the set of points satisfying the
inequality
-
ci(P) ≥ 0
where ci(P) is the clip distance i at point P. For point primitives, ci(P) is simply the clip distance for the vertex in question. For line and triangle primitives, per-vertex clip distances are interpolated using a weighted mean, with weights derived according to the algorithms described in sections Basic Line Segment Rasterization and Basic Polygon Rasterization, using the perspective interpolation equations.
The number of client-defined clip and cull half-spaces that are enabled is
determined by the explicit size of the built-in arrays ClipDistance
and
CullDistance
, respectively, declared as an output in the interface of
the entry point of the final shader stage before clipping.
If VkPipelineRasterizationDepthClipStateCreateInfoEXT is present in
the graphics pipeline state then depth clipping is disabled if
VkPipelineRasterizationDepthClipStateCreateInfoEXT::depthClipEnable
is VK_FALSE
.
Otherwise, if VkPipelineRasterizationDepthClipStateCreateInfoEXT is
not present, depth clipping is disabled when
VkPipelineRasterizationStateCreateInfo::depthClampEnable
is
VK_TRUE
.
To dynamically set enable or disable depth clamping, call:
// Provided by VK_EXT_extended_dynamic_state3, VK_EXT_shader_object
void vkCmdSetDepthClampEnableEXT(
VkCommandBuffer commandBuffer,
VkBool32 depthClampEnable);
-
commandBuffer
is the command buffer into which the command will be recorded. -
depthClampEnable
specifies whether depth clamping is enabled.
This command sets whether depth clamping is enabled or disabled for
subsequent drawing commands
when the graphics pipeline is created with
VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT
set in
VkPipelineDynamicStateCreateInfo::pDynamicStates
.
Otherwise, this state is specified by the
VkPipelineRasterizationStateCreateInfo::depthClampEnable
value
used to create the currently active pipeline.
If the depth clamping state is changed dynamically, and the pipeline was not
created with VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT
enabled, then
depth clipping is enabled when depth clamping is disabled and vice versa.
To dynamically set enable or disable depth clipping, call:
// Provided by VK_EXT_extended_dynamic_state3, VK_EXT_shader_object
void vkCmdSetDepthClipEnableEXT(
VkCommandBuffer commandBuffer,
VkBool32 depthClipEnable);
-
commandBuffer
is the command buffer into which the command will be recorded. -
depthClipEnable
specifies whether depth clipping is enabled.
This command sets whether depth clipping is enabled or disabled for
subsequent drawing commands
when the graphics pipeline is created with
VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT
set in
VkPipelineDynamicStateCreateInfo::pDynamicStates
.
Otherwise, this state is specified by the
VkPipelineRasterizationDepthClipStateCreateInfoEXT::depthClipEnable
value used to create the currently active pipeline, or is set to the inverse
of VkPipelineRasterizationStateCreateInfo::depthClampEnable
if
VkPipelineRasterizationDepthClipStateCreateInfoEXT
is not specified.
When depth clipping is disabled, the plane equation
-
zm ≤ zc ≤ wc
(see the clip volume definition above) is ignored by view volume clipping (effectively, there is no near or far plane clipping).
If the primitive under consideration is a point or line segment, then clipping passes it unchanged if its vertices lie entirely within the clip volume.
Possible values of
VkPhysicalDevicePointClippingProperties::pointClippingBehavior
,
specifying clipping behavior of a point primitive whose vertex lies outside
the clip volume, are:
// Provided by VK_VERSION_1_1
typedef enum VkPointClippingBehavior {
VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES = 0,
VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY = 1,
// Provided by VK_KHR_maintenance2
VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES,
// Provided by VK_KHR_maintenance2
VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY_KHR = VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY,
} VkPointClippingBehavior;
or the equivalent
// Provided by VK_KHR_maintenance2
typedef VkPointClippingBehavior VkPointClippingBehaviorKHR;
-
VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES
specifies that the primitive is discarded if the vertex lies outside any clip plane, including the planes bounding the view volume. -
VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY
specifies that the primitive is discarded only if the vertex lies outside any user clip plane.
If either of a line segment’s vertices lie outside of the clip volume, the line segment may be clipped, with new vertex coordinates computed for each vertex that lies outside the clip volume. A clipped line segment endpoint lies on both the original line segment and the boundary of the clip volume.
This clipping produces a value, 0 ≤ t ≤ 1, for each clipped vertex. If the coordinates of a clipped vertex are P and the unclipped line segment’s vertex coordinates are P1 and P2, then t satisfies the following equation
-
P = t P1 + (1-t) P2.
t is used to clip vertex output attributes as described in Clipping Shader Outputs.
If the primitive is a polygon, it passes unchanged if every one of its edges lies entirely inside the clip volume, and is either clipped or discarded otherwise. If the edges of the polygon intersect the boundary of the clip volume, the intersecting edges are reconnected by new edges that lie along the boundary of the clip volume - in some cases requiring the introduction of new vertices into a polygon.
If a polygon intersects an edge of the clip volume’s boundary, the clipped polygon must include a point on this boundary edge.
Primitives rendered with user-defined half-spaces must satisfy a complementarity criterion. Suppose a series of primitives is drawn where each vertex i has a single specified clip distance di (or a number of similarly specified clip distances, if multiple half-spaces are enabled). Next, suppose that the same series of primitives are drawn again with each such clip distance replaced by -di (and the graphics pipeline is otherwise the same). In this case, primitives must not be missing any pixels, and pixels must not be drawn twice in regions where those primitives are cut by the clip planes.
The VkPipelineViewportDepthClipControlCreateInfoEXT
structure is
defined as:
// Provided by VK_EXT_depth_clip_control
typedef struct VkPipelineViewportDepthClipControlCreateInfoEXT {
VkStructureType sType;
const void* pNext;
VkBool32 negativeOneToOne;
} VkPipelineViewportDepthClipControlCreateInfoEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
negativeOneToOne
sets the zm in the view volume to -wc
To dynamically set negativeOneToOne
,
call:
// Provided by VK_EXT_extended_dynamic_state3, VK_EXT_shader_object
void vkCmdSetDepthClipNegativeOneToOneEXT(
VkCommandBuffer commandBuffer,
VkBool32 negativeOneToOne);
-
commandBuffer
is the command buffer into which the command will be recorded. -
negativeOneToOne
specifies thenegativeOneToOne
state.
This command sets the negativeOneToOne
state for subsequent drawing
commands
when the graphics pipeline is created with
VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT
set in
VkPipelineDynamicStateCreateInfo::pDynamicStates
.
Otherwise, this state is specified by the
VkPipelineViewportDepthClipControlCreateInfoEXT::negativeOneToOne
value used to create the currently active pipeline.
27.5. Clipping Shader Outputs
Next, vertex output attributes are clipped. The output values associated with a vertex that lies within the clip volume are unaffected by clipping. If a primitive is clipped, however, the output values assigned to vertices produced by clipping are clipped.
Let the output values assigned to the two vertices P1 and P2 of an unclipped edge be c1 and c2. The value of t (see Primitive Clipping) for a clipped point P is used to obtain the output value associated with P as
-
c = t c1 + (1-t) c2.
(Multiplying an output value by a scalar means multiplying each of x, y, z, and w by the scalar.)
Since this computation is performed in clip space before division by wc, clipped output values are perspective-correct.
Polygon clipping creates a clipped vertex along an edge of the clip volume’s boundary. This situation is handled by noting that polygon clipping proceeds by clipping against one half-space at a time. Output value clipping is done in the same way, so that clipped points always occur at the intersection of polygon edges (possibly already clipped) with the clip volume’s boundary.
For vertex output attributes whose matching fragment input attributes are
decorated with NoPerspective
, the value of t used to obtain the
output value associated with P will be adjusted to produce results
that vary linearly in framebuffer space.
Output attributes of integer or unsigned integer type must always be flat shaded. Flat shaded attributes are constant over the primitive being rasterized (see Basic Line Segment Rasterization and Basic Polygon Rasterization), and no interpolation is performed. The output value c is taken from either c1 or c2, since flat shading has already occurred and the two values are identical.
27.6. Controlling Viewport W Scaling
If viewport W scaling is enabled, the W component of the clip coordinate is modified by the provided coefficients from the corresponding viewport as follows.
-
wc' = xcoeff xc + ycoeff yc + wc
The VkPipelineViewportWScalingStateCreateInfoNV
structure is defined
as:
// Provided by VK_NV_clip_space_w_scaling
typedef struct VkPipelineViewportWScalingStateCreateInfoNV {
VkStructureType sType;
const void* pNext;
VkBool32 viewportWScalingEnable;
uint32_t viewportCount;
const VkViewportWScalingNV* pViewportWScalings;
} VkPipelineViewportWScalingStateCreateInfoNV;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
viewportWScalingEnable
controls whether viewport W scaling is enabled. -
viewportCount
is the number of viewports used by W scaling, and must match the number of viewports in the pipeline if viewport W scaling is enabled. -
pViewportWScalings
is a pointer to an array of VkViewportWScalingNV structures defining the W scaling parameters for the corresponding viewports. If the viewport W scaling state is dynamic, this member is ignored.
The VkPipelineViewportWScalingStateCreateInfoNV
state is set by adding
this structure to the pNext
chain of a
VkPipelineViewportStateCreateInfo
structure and setting the graphics
pipeline state with vkCreateGraphicsPipelines.
To dynamically set the
viewportWScalingEnable
state, call:
// Provided by VK_EXT_extended_dynamic_state3 with VK_NV_clip_space_w_scaling, VK_EXT_shader_object with VK_NV_clip_space_w_scaling
void vkCmdSetViewportWScalingEnableNV(
VkCommandBuffer commandBuffer,
VkBool32 viewportWScalingEnable);
-
commandBuffer
is the command buffer into which the command will be recorded. -
viewportWScalingEnable
specifies theviewportWScalingEnable
state.
This command sets the viewportWScalingEnable
state for subsequent
drawing commands
when the graphics pipeline is created with
VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_ENABLE_NV
set in
VkPipelineDynamicStateCreateInfo::pDynamicStates
.
Otherwise, this state is specified by the
VkPipelineViewportWScalingStateCreateInfoNV::viewportWScalingEnable
value used to create the currently active pipeline.
To dynamically set the viewport W scaling parameters, call:
// Provided by VK_NV_clip_space_w_scaling
void vkCmdSetViewportWScalingNV(
VkCommandBuffer commandBuffer,
uint32_t firstViewport,
uint32_t viewportCount,
const VkViewportWScalingNV* pViewportWScalings);
-
commandBuffer
is the command buffer into which the command will be recorded. -
firstViewport
is the index of the first viewport whose parameters are updated by the command. -
viewportCount
is the number of viewports whose parameters are updated by the command. -
pViewportWScalings
is a pointer to an array of VkViewportWScalingNV structures specifying viewport parameters.
The viewport parameters taken from element i of
pViewportWScalings
replace the current state for the viewport index
firstViewport
+ i, for i in [0,
viewportCount
).
This command sets the viewport W scaling for subsequent drawing commands
when the graphics pipeline is created with
VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV
set in
VkPipelineDynamicStateCreateInfo::pDynamicStates
.
Otherwise, this state is specified by the
VkPipelineViewportWScalingStateCreateInfoNV::pViewportWScalings
values used to create the currently active pipeline.
Both VkPipelineViewportWScalingStateCreateInfoNV and
vkCmdSetViewportWScalingNV use VkViewportWScalingNV
to set the
viewport transformation parameters.
The VkViewportWScalingNV
structure is defined as:
// Provided by VK_NV_clip_space_w_scaling
typedef struct VkViewportWScalingNV {
float xcoeff;
float ycoeff;
} VkViewportWScalingNV;
-
xcoeff
andycoeff
are the viewport’s W scaling factor for x and y respectively.
27.7. Coordinate Transformations
Clip coordinates for a vertex result from shader execution, which yields a
vertex coordinate Position
.
Perspective division on clip coordinates yields normalized device coordinates, followed by a viewport transformation (see Controlling the Viewport) to convert these coordinates into framebuffer coordinates.
If a vertex in clip coordinates has a position given by
then the vertex’s normalized device coordinates are
27.8. Render Pass Transform
A render pass transform can be enabled for render pass instances. The clip coordinates (xc, yc) that result from vertex shader execution are transformed by a rotation of 0, 90, 180, or 270 degrees in the XY plane, centered at the origin.
When Render pass transform is enabled, the transform applies to all primitives for all subpasses of the render pass. The transformed vertex in clip coordinates has a position given by
where
-
θ is 0 degrees for
VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR
-
θ is 90 degrees for
VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR
-
θ is 180 degrees for
VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR
-
θ is 270 degrees for
VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR
The transformed vertex’s normalized device coordinates are
When render pass transform is enabled for a render pass instance, the following additional features are enabled:
-
Each VkViewport specified by either VkPipelineViewportStateCreateInfo::
pViewports
or vkCmdSetViewport will have its width/height (px, py) and its center (ox, oy) similarly transformed by the implementation. -
Each scissor specified by VkPipelineViewportStateCreateInfo::
pScissors
or vkCmdSetScissor will have its (offsetx, offsety) and (extentx, extenty) similarly transformed by the implementation. -
The
renderArea
specified in VkCommandBufferInheritanceRenderPassTransformInfoQCOM and VkRenderPassBeginInfo will be similarly transformed by the implementation. -
The (x, y) components of shader variables with built-in decorations
FragCoord
,SamplePosition
, orPointCoord
will be similarly transformed by the implementation. -
The (x,y) components of the
offset
operand of theInterpolateAtOffset
extended instruction will be similarly transformed by the implementation. -
The values returned by SPIR-V derivative instructions
OpDPdx
,OpDPdy
,OpDPdxCourse
,OpDPdyCourse
,OpDPdxFine
,OpDPdyFine
will be similarly transformed by the implementation.
The net result of the above, is that applications can act as if rendering
to a framebuffer oriented with the
VkSurfaceCapabilitiesKHR::currentTransform
.
In other words, applications can act as if the presentation engine will be
performing the transformation of the swapchain image after rendering and
prior to presentation to the user.
In fact, the transformation of the various items cited above are being
handled by the implementation as the rendering takes place.
27.9. Controlling the Viewport
The viewport transformation is determined by the selected viewport’s width and height in pixels, px and py, respectively, and its center (ox, oy) (also in pixels), as well as its depth range min and max determining a depth range scale value pz and a depth range bias value oz (defined below). The vertex’s framebuffer coordinates (xf, yf, zf) are given by
-
xf = (px / 2) xd + ox
-
yf = (py / 2) yd + oy
-
zf = pz × zd + oz
Multiple viewports are available, numbered zero up to
VkPhysicalDeviceLimits
::maxViewports
minus one.
The number of viewports used by a pipeline is controlled by the
viewportCount
member of the VkPipelineViewportStateCreateInfo
structure used in pipeline creation.
xf and yf have limited precision, where the number of
fractional bits retained is specified by
VkPhysicalDeviceLimits
::subPixelPrecisionBits
.
When rasterizing line segments, the number of fractional
bits is specified by
VkPhysicalDeviceLineRasterizationPropertiesEXT
::lineSubPixelPrecisionBits
.
The VkPipelineViewportStateCreateInfo
structure is defined as:
// Provided by VK_VERSION_1_0
typedef struct VkPipelineViewportStateCreateInfo {
VkStructureType sType;
const void* pNext;
VkPipelineViewportStateCreateFlags flags;
uint32_t viewportCount;
const VkViewport* pViewports;
uint32_t scissorCount;
const VkRect2D* pScissors;
} VkPipelineViewportStateCreateInfo;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
flags
is reserved for future use. -
viewportCount
is the number of viewports used by the pipeline. -
pViewports
is a pointer to an array of VkViewport structures, defining the viewport transforms. If the viewport state is dynamic, this member is ignored. -
scissorCount
is the number of scissors and must match the number of viewports. -
pScissors
is a pointer to an array of VkRect2D structures defining the rectangular bounds of the scissor for the corresponding viewport. If the scissor state is dynamic, this member is ignored.
To dynamically set the viewport count and viewports, call:
// Provided by VK_VERSION_1_3
void vkCmdSetViewportWithCount(
VkCommandBuffer commandBuffer,
uint32_t viewportCount,
const VkViewport* pViewports);
or the equivalent command
// Provided by VK_EXT_extended_dynamic_state, VK_EXT_shader_object
void vkCmdSetViewportWithCountEXT(
VkCommandBuffer commandBuffer,
uint32_t viewportCount,
const VkViewport* pViewports);
-
commandBuffer
is the command buffer into which the command will be recorded. -
viewportCount
specifies the viewport count. -
pViewports
specifies the viewports to use for drawing.
This command sets the viewport count and viewports state for subsequent
drawing commands
when the graphics pipeline is created with
VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT
set in
VkPipelineDynamicStateCreateInfo::pDynamicStates
.
Otherwise, this state is specified by the corresponding
VkPipelineViewportStateCreateInfo::viewportCount
and
pViewports
values used to create the currently active pipeline.
To dynamically set the scissor count and scissor rectangular bounds, call:
// Provided by VK_VERSION_1_3
void vkCmdSetScissorWithCount(
VkCommandBuffer commandBuffer,
uint32_t scissorCount,
const VkRect2D* pScissors);
or the equivalent command
// Provided by VK_EXT_extended_dynamic_state, VK_EXT_shader_object
void vkCmdSetScissorWithCountEXT(
VkCommandBuffer commandBuffer,
uint32_t scissorCount,
const VkRect2D* pScissors);
-
commandBuffer
is the command buffer into which the command will be recorded. -
scissorCount
specifies the scissor count. -
pScissors
specifies the scissors to use for drawing.
This command sets the scissor count and scissor rectangular bounds state for
subsequent drawing commands
when the graphics pipeline is created with
VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT
set in
VkPipelineDynamicStateCreateInfo::pDynamicStates
.
Otherwise, this state is specified by the corresponding
VkPipelineViewportStateCreateInfo::scissorCount
and
pScissors
values used to create the currently active pipeline.
// Provided by VK_VERSION_1_0
typedef VkFlags VkPipelineViewportStateCreateFlags;
VkPipelineViewportStateCreateFlags
is a bitmask type for setting a
mask, but is currently reserved for future use.
A pre-rasterization shader
stage can direct each primitive to zero or more viewports.
The destination viewports for a primitive are selected by the last active
pre-rasterization shader
stage that has an output variable decorated with ViewportIndex
(selecting a single viewport) or ViewportMaskNV
(selecting multiple
viewports).
The viewport transform uses the viewport corresponding to either the value
assigned to ViewportIndex
or one of the bits set in
ViewportMaskNV
, and taken from an implementation-dependent vertex of
each primitive.
If ViewportIndex
or any of the bits in ViewportMaskNV
are outside
the range zero to viewportCount
minus one for a primitive, or if the
last active pre-rasterization
shader stage did not assign a value to either ViewportIndex
or
ViewportMaskNV
for all vertices of a primitive due to flow control, the
values resulting from the viewport transformation of the vertices of such
primitives are undefined.
If the last pre-rasterization
shader stage does not have an output decorated with ViewportIndex
or
ViewportMaskNV
, the viewport numbered zero is used by the viewport
transformation.
A single vertex can be used in more than one individual primitive, in
primitives such as VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
.
In this case, the viewport transformation is applied separately for each
primitive.
To dynamically set the viewport transformation parameters, call:
// Provided by VK_VERSION_1_0
void vkCmdSetViewport(
VkCommandBuffer commandBuffer,
uint32_t firstViewport,
uint32_t viewportCount,
const VkViewport* pViewports);
-
commandBuffer
is the command buffer into which the command will be recorded. -
firstViewport
is the index of the first viewport whose parameters are updated by the command. -
viewportCount
is the number of viewports whose parameters are updated by the command. -
pViewports
is a pointer to an array of VkViewport structures specifying viewport parameters.
This command sets the viewport transformation parameters state for
subsequent drawing commands
when the graphics pipeline is created with VK_DYNAMIC_STATE_VIEWPORT
set in VkPipelineDynamicStateCreateInfo::pDynamicStates
.
Otherwise, this state is specified by the
VkPipelineViewportStateCreateInfo
::pViewports
values used to
create the currently active pipeline.
The viewport parameters taken from element i of pViewports
replace the current state for the viewport index firstViewport
+ i, for i in [0, viewportCount
).
Both VkPipelineViewportStateCreateInfo and vkCmdSetViewport use
VkViewport
to set the viewport transformation parameters.
The VkViewport
structure is defined as:
// Provided by VK_VERSION_1_0
typedef struct VkViewport {
float x;
float y;
float width;
float height;
float minDepth;
float maxDepth;
} VkViewport;
-
x
andy
are the viewport’s upper left corner (x,y). -
width
andheight
are the viewport’s width and height, respectively. -
minDepth
andmaxDepth
are the depth range for the viewport.
Note
Despite their names, |
The framebuffer depth coordinate z
f may be represented using
either a fixed-point or floating-point representation.
However, a floating-point representation must be used if the depth/stencil
attachment has a floating-point depth component.
If an m-bit fixed-point representation is used, we assume that it
represents each value , where k ∈ {
0, 1, …, 2m-1 }, as k (e.g. 1.0 is represented in binary as a
string of all ones).
The viewport parameters shown in the above equations are found from these values as
-
ox =
x
+width
/ 2 -
oy =
y
+height
/ 2 -
oz =
minDepth
(or (maxDepth
+minDepth
) / 2 if VkPipelineViewportDepthClipControlCreateInfoEXT::negativeOneToOne
isVK_TRUE
) -
px =
width
-
py =
height
-
pz =
maxDepth
-minDepth
(or (maxDepth
-minDepth
) / 2 if VkPipelineViewportDepthClipControlCreateInfoEXT::negativeOneToOne
isVK_TRUE
)
If a render pass transform is enabled, the values (px,py) and (ox, oy) defining the viewport are transformed as described in render pass transform before participating in the viewport transform.
The application can specify a negative term for height
, which has the
effect of negating the y coordinate in clip space before performing the
transform.
When using a negative height
, the application should also adjust the
y
value to point to the lower left corner of the viewport instead of
the upper left corner.
Using the negative height
allows the application to avoid having to
negate the y component of the Position
output from the last
pre-rasterization shader
stage.
The width and height of the implementation-dependent maximum viewport dimensions must be greater than or equal to the width and height of the largest image which can be created and attached to a framebuffer.
The floating-point viewport bounds are represented with an implementation-dependent precision.