27. Fragment Operations
Fragment operations execute on a per-fragment or per-sample basis, affecting whether or how a fragment or sample is written to the framebuffer. Some operations execute before fragment shading, and others after. Fragment operations always adhere to rasterization order.
27.1. Early Per-Fragment Tests
Once fragments are produced by rasterization, a number of per-fragment operations are performed prior to fragment shader execution. If a fragment is discarded during any of these operations, it will not be processed by any subsequent stage, including fragment shader execution.
The scissor test, exclusive scissor test, and sample mask generation are always performed during early fragment tests.
Fragment operations are performed in the following order:
-
the discard rectangles test (see Discard Rectangles Test)
-
the scissor test (see Scissor Test)
-
the exclusive scissor test (see Exclusive Scissor Test)
-
multisample fragment operations (see Sample Mask)
If early per-fragment operations are enabled by the fragment shader, these operations are also performed:
If post-depth coverage operation is
enabled by the fragment
shader, the SampleMask
coverage is determined after the early stencil and depth tests.
27.2. Discard Rectangles Test
The discard rectangles test determines if fragment’s framebuffer coordinates
(xf,yf) are inclusive or exclusive to a set of discard-space
rectangles.
The discard rectangles are set with the
VkPipelineDiscardRectangleStateCreateInfoEXT pipeline state, which is
defined as:
typedef struct VkPipelineDiscardRectangleStateCreateInfoEXT {
VkStructureType sType;
const void* pNext;
VkPipelineDiscardRectangleStateCreateFlagsEXT flags;
VkDiscardRectangleModeEXT discardRectangleMode;
uint32_t discardRectangleCount;
const VkRect2D* pDiscardRectangles;
} VkPipelineDiscardRectangleStateCreateInfoEXT;
-
sTypeis the type of this structure. -
pNextisNULLor a pointer to an extension-specific structure. -
flagsis reserved for future use. -
discardRectangleModeis the mode used to determine whether fragments that lie within the discard rectangle are discarded or not. -
discardRectangleCountis the number of discard rectangles used by the pipeline. -
pDiscardRectanglesis a pointer to an array of VkRect2D structures, defining the discard rectangles. If the discard rectangle state is dynamic, this member is ignored.
typedef VkFlags VkPipelineDiscardRectangleStateCreateFlagsEXT;
VkPipelineDiscardRectangleStateCreateFlagsEXT is a bitmask type for
setting a mask, but is currently reserved for future use.
The VkPipelineDiscardRectangleStateCreateInfoEXT state is set by
adding an instance of this structure to the pNext chain of an instance
of the VkGraphicsPipelineCreateInfo structure and setting the graphics
pipeline state with vkCreateGraphicsPipelines.
If the bound pipeline state object was not created with the
VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT dynamic state enabled, discard
rectangles are specified using the pDiscardRectangles member of
VkPipelineDiscardRectangleStateCreateInfoEXT linked to the pipeline
state object.
If the pipeline state object was created with the
VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT dynamic state enabled, the
discard rectangles are dynamically set and changed with the command:
void vkCmdSetDiscardRectangleEXT(
VkCommandBuffer commandBuffer,
uint32_t firstDiscardRectangle,
uint32_t discardRectangleCount,
const VkRect2D* pDiscardRectangles);
-
commandBufferis the command buffer into which the command will be recorded. -
firstDiscardRectangleis the index of the first discard rectangle whose state is updated by the command. -
discardRectangleCountis the number of discard rectangles whose state are updated by the command. -
pDiscardRectanglesis a pointer to an array of VkRect2D structures specifying discard rectangles.
The discard rectangle taken from element i of pDiscardRectangles
replace the current state for the discard rectangle index
firstDiscardRectangle + i, for i in [0,
discardRectangleCount).
The VkOffset2D::x and VkOffset2D::y values of the
discard rectangle VkRect2D specify the upper-left origin of the
discard rectangle box.
The lower-right corner of the discard rectangle box is specified as the
VkExtent2D::width and VkExtent2D::height from the
upper-left origin.
If offset.x ≤ xf < offset.x +
extent.width and offset.y ≤ yf < offset.y
+ extent.height for the selected discard rectangle, then the
fragment is within the discard rectangle box.
When the discard rectangle mode is
VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT a fragment within at least one
of the active discard rectangle boxes passes the discard rectangle test;
otherwise the fragment fails the discard rectangle test and is discarded.
When the discard rectangle mode is
VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT a fragment within at least one
of the active discard rectangle boxes fails the discard rectangle test, and
the fragment is discarded; otherwise the fragment passes the discard
rectangles test.
The discard rectangles test only applies to drawing commands,
not to other commands like clears or copies.
Possible values of
VkPipelineDiscardRectangleStateCreateInfoEXT::discardRectangleMode,
specifying the behavior of the discard rectangle test, are:
typedef enum VkDiscardRectangleModeEXT {
VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT = 0,
VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT = 1,
VK_DISCARD_RECTANGLE_MODE_MAX_ENUM_EXT = 0x7FFFFFFF
} VkDiscardRectangleModeEXT;
-
VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXTspecifies that a fragment within any discard rectangle satisfies the test. -
VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXTspecifies that a fragment not within any of the discard rectangles satisfies the test.
When the use of a shading rate image results in a fragment covering multiple pixels, the discard rectangle test is performed independently for each pixel in the fragment. If a pixel covered by a fragment fails the discard rectangle test, all samples in the fragment associated with that pixel are treated as not covered. If the discard rectangle test results in a fragment with no samples covered, that fragment is discarded.
27.3. Scissor Test
The scissor test determines if a fragment’s framebuffer coordinates
(xf,yf) lie within the scissor rectangle corresponding to the
viewport index (see Controlling the Viewport)
used by the primitive that generated the fragment.
If the pipeline state object is created without
VK_DYNAMIC_STATE_SCISSOR enabled then the scissor rectangles are set
by the VkPipelineViewportStateCreateInfo state of the pipeline state
object.
Otherwise, to dynamically set the scissor rectangles call:
void vkCmdSetScissor(
VkCommandBuffer commandBuffer,
uint32_t firstScissor,
uint32_t scissorCount,
const VkRect2D* pScissors);
-
commandBufferis the command buffer into which the command will be recorded. -
firstScissoris the index of the first scissor whose state is updated by the command. -
scissorCountis the number of scissors whose rectangles are updated by the command. -
pScissorsis a pointer to an array of VkRect2D structures defining scissor rectangles.
The scissor rectangles taken from element i of pScissors replace
the current state for the scissor index firstScissor + i,
for i in [0, scissorCount).
Each scissor rectangle is described by a VkRect2D structure, with the
offset.x and offset.y values determining the upper left corner
of the scissor rectangle, and the extent.width and extent.height
values determining the size in pixels.
If offset.x ≤ xf < offset.x +
extent.width and offset.y ≤ yf < offset.y
+ extent.height for the selected scissor rectangle, then the
scissor test passes.
Otherwise, the test fails and the fragment is discarded.
For points, lines, and polygons, the scissor rectangle for a primitive is
selected in the same manner as the viewport (see
Controlling the Viewport).
The scissor rectangles test only applies to drawing commands,
not to other commands like clears or copies.
It is legal for offset.x + extent.width or
offset.y + extent.height to exceed the dimensions of
the framebuffer - the scissor test still applies as defined above.
Rasterization does not produce fragments outside of the framebuffer, so such
fragments never have the scissor test performed on them.
The scissor test is always performed. Applications can effectively disable the scissor test by specifying a scissor rectangle that encompasses the entire framebuffer.
When the use of a shading rate image results in a fragment covering multiple pixels, the scissor test is performed independently for each pixel in the fragment. If a pixel covered by a fragment fails the scissor test, all samples in the fragment associated with that pixel are treated as not covered. If the scissor test results in a fragment with no samples covered, that fragment is discarded.
27.4. Exclusive Scissor Test
The exclusive scissor test determines if a pixel’s framebuffer coordinates (xf,yf) lie outside the exclusive scissor rectangle corresponding to the viewport index (see Controlling the Viewport) used by the primitive that generated the fragment. The exclusive scissor test behaves identically to the scissor test, except that it passes only if the pixel is outside the rectangle instead of passing if the pixel is inside the rectangle.
If the pNext chain of VkPipelineViewportStateCreateInfo includes
a VkPipelineViewportExclusiveScissorStateCreateInfoNV structure, then
that structure includes parameters that affect the exclusive scissor test.
The VkPipelineViewportExclusiveScissorStateCreateInfoNV structure is
defined as:
typedef struct VkPipelineViewportExclusiveScissorStateCreateInfoNV {
VkStructureType sType;
const void* pNext;
uint32_t exclusiveScissorCount;
const VkRect2D* pExclusiveScissors;
} VkPipelineViewportExclusiveScissorStateCreateInfoNV;
-
sTypeis the type of this structure. -
pNextisNULLor a pointer to an extension-specific structure. -
exclusiveScissorCountis the number of exclusive scissor rectangles used by the pipeline. -
pExclusiveScissorsis a pointer to an array of VkRect2D structures defining exclusive scissor rectangles. If the exclusive scissor state is dynamic, this member is ignored.
If this structure is not present, exclusiveScissorCount is considered
to be 0 and the exclusive scissor test is disabled.
If the pipeline state object is created with
VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV enabled, then the exclusive
scissor rectangles are set by:
void vkCmdSetExclusiveScissorNV(
VkCommandBuffer commandBuffer,
uint32_t firstExclusiveScissor,
uint32_t exclusiveScissorCount,
const VkRect2D* pExclusiveScissors);
-
commandBufferis the command buffer into which the command will be recorded. -
firstExclusiveScissoris the index of the first exclusive scissor rectangle whose state is updated by the command. -
exclusiveScissorCountis the number of exclusive scissor rectangles updated by the command. -
pExclusiveScissorsis a pointer to an array of VkRect2D structures defining exclusive scissor rectangles.
The scissor rectangles taken from element i of
pExclusiveScissors replace the current state for the scissor index
firstExclusiveScissor + i, for i in [0,
exclusiveScissorCount).
Each scissor rectangle is described by a VkRect2D structure, with the
offset.x and offset.y values determining the upper left corner
of the scissor rectangle, and the extent.width and extent.height
values determining the size in pixels.
If offset.x ≤ xf < offset.x +
extent.width and offset.y ≤ yf < offset.y
+ extent.height for the selected exclusive scissor rectangle,
then the exclusive scissor test fails and the fragment is discarded.
Otherwise, the exclusive scissor test passes.
For points, lines, and polygons, the exclusive scissor rectangle for a
primitive is selected in the same manner as the viewport (see
Controlling the Viewport).
The exclusive scissor test only applies to drawing commands,
not to other commands like clears or copies.
It is legal for offset.x + extent.width or
offset.y + extent.height to exceed the dimensions of
the framebuffer - the exclusive scissor test still applies as defined above.
Rasterization does not produce fragments outside of the framebuffer, so such
fragments never have the exclusive scissor test performed on them.
The exclusive scissor test is performed if and only if the current pipeline
was created with a non-zero exclusiveScissorCount.
Applications can effectively disable the exclusive scissor test for
specific viewports by specifying a scissor rectangle with a width or height
of zero.
When the use of a shading rate image results in a fragment covering multiple pixels, the exclusive scissor test is performed independently for each pixel in the fragment. If a pixel covered by a fragment fails the exclusive scissor test, all samples in the fragment associated with that pixel are treated as not covered. If the exclusive scissor test results in a fragment with no samples covered, that fragment is discarded.
27.5. Sample Mask
This step modifies fragment coverage values based on the values in the
pSampleMask array member of
VkPipelineMultisampleStateCreateInfo, as described previously in
section Graphics Pipelines.
pSampleMask contains an array of static coverage information that is
ANDed with the coverage information generated during rasterization.
Bits that are zero disable coverage for the corresponding sample.
Bit B of mask word M corresponds to sample 32 × M
+ B.
The array is sized to a length of ⌈ rasterizationSamples /
32 ⌉ words.
If pSampleMask is NULL, it is treated as if the mask has all bits
enabled, i.e. no coverage is removed from fragments.
The elements of the sample mask array are of type VkSampleMask,
each representing 32 bits of coverage information:
typedef uint32_t VkSampleMask;
27.6. Early Fragment Test Mode
The depth bounds test, stencil test, depth test, representative fragment test, and occlusion query sample counting are performed before fragment shading if and only if early fragment tests are enabled by the fragment shader (see Early Fragment Tests). When early per-fragment operations are enabled, these operations are performed prior to fragment shader execution, and the stencil buffer, depth buffer, and occlusion query sample counts will be updated accordingly; these operations will not be performed again after fragment shader execution.
If a pipeline’s fragment shader has early fragment tests disabled, these operations are performed only after fragment program execution, in the order described below. If a pipeline does not contain a fragment shader, these operations are performed only once.
If early fragment tests are enabled, any depth value computed by the fragment shader has no effect. Additionally, the depth test (including depth writes), stencil test (including stencil writes) and sample counting operations are performed even for fragments or samples that would be discarded after fragment shader execution due to per-fragment operations such as alpha-to-coverage tests, or due to the fragment being discarded by the shader itself.
27.7. Late Per-Fragment Tests
After programmable fragment processing, per-fragment operations are performed before blending and color output to the framebuffer.
A fragment is produced by rasterization with framebuffer coordinates of (xf,yf) and depth z, as described in Rasterization. The fragment is then modified by programmable fragment processing, which adds associated data as described in Shaders. The fragment is then further modified, and possibly discarded by the late per-fragment operations described in this chapter. Finally, if the fragment was not discarded, it is used to update the framebuffer at the fragment’s framebuffer coordinates for any samples that remain covered.
The depth bounds test, stencil test, and depth test are performed for each sample, rather than just once for each fragment. Stencil and depth operations are performed for a sample only if that sample’s fragment coverage bit is a value of 1 when the fragment executes the corresponding stage of the graphics pipeline. If the corresponding coverage bit is 0, no operations are performed for that sample. Failure of the depth bounds, stencil, or depth test results in termination of the processing of that sample by means of disabling coverage for that sample, rather than discarding of the fragment. If, at any point, a fragment’s coverage becomes zero for all samples, then the fragment is discarded. All operations are performed on the depth and stencil values stored in the depth/stencil attachment of the framebuffer. The contents of the color attachments are not modified at this point.
The depth bounds test, stencil test, depth test, and occlusion query operations described in Depth Bounds Test, Stencil Test, Depth Test, Sample Counting are instead performed prior to fragment processing, as described in Early Fragment Test Mode, if requested by the fragment shader.
27.8. Mixed attachment samples
When the VK_AMD_mixed_attachment_samples extension is enabled, special
rules apply to per-fragment operations when the number of samples of the
color attachments differs from the number of samples of the depth/stencil
attachment used in a subpass.
Let C be the number of color attachment samples and D be the number of depth/stencil attachment samples used by a given subpass.
If C < D then only the first C number of samples are guaranteed
to have a corresponding fragment shader invocation and thus a corresponding
color output value, unless the fragment shaders produce inputs to the late
per-fragment tests (e.g. by outputting to a variable decorated with the
FragDepth built-in decoration).
Implementations are allowed to produce fragment shader invocations for
samples with indices greater than or equal to C but (other than
potential side effects) the color outputs of fragment shader invocations
corresponding to such samples are discarded.
27.9. Multisample Coverage
If a fragment shader is active and its entry point’s interface includes a
built-in output variable decorated with SampleMask and also decorated
with OverrideCoverageNV the fragment coverage is replaced with the
sample mask bits set in the shader.
Otherwise if the built-in output variable decorated with SampleMask is
not also decorated with OverrideCoverageNV then the fragment coverage
is ANDed with the bits of the sample mask to generate a new fragment
coverage value.
If such a fragment shader did not assign a value to SampleMask due to
flow of control, the value ANDed with the fragment coverage is
undefined.
If no fragment shader is active, or if the active fragment shader does not
include SampleMask in its interface, the fragment coverage is not
modified.
Next, the fragment alpha and coverage values are modified based on the
alphaToCoverageEnable and alphaToOneEnable members of the
VkPipelineMultisampleStateCreateInfo structure.
All alpha values in this section refer only to the alpha component of the
fragment shader output that has a Location and Index decoration of
zero (see the Fragment Output Interface
section).
If that shader output has an integer or unsigned integer type, then these
operations are skipped.
If alphaToCoverageEnable is enabled, a temporary coverage value with
rasterizationSamples bits is generated where each bit is determined by
the fragment’s alpha value.
The temporary coverage value is then ANDed with the fragment coverage value
to generate a new fragment coverage value.
No specific algorithm is specified for converting the alpha value to a temporary coverage mask. It is intended that the number of 1’s in this value be proportional to the alpha value (clamped to [0,1]), with all 1’s corresponding to a value of 1.0 and all 0’s corresponding to 0.0. The algorithm may be different at different framebuffer coordinates.
|
Note
Using different algorithms at different framebuffer coordinates may help to avoid artifacts caused by regular coverage sample locations. |
Next, if alphaToOneEnable is enabled, each alpha value is replaced by
the maximum representable alpha value for fixed-point color buffers, or by
1.0 for floating-point buffers.
Otherwise, the alpha values are not changed.
27.10. Depth and Stencil Operations
Pipeline state controlling the depth bounds tests,
stencil test, and depth test is
specified through the members of the
VkPipelineDepthStencilStateCreateInfo structure.
The VkPipelineDepthStencilStateCreateInfo structure is defined as:
typedef struct VkPipelineDepthStencilStateCreateInfo {
VkStructureType sType;
const void* pNext;
VkPipelineDepthStencilStateCreateFlags flags;
VkBool32 depthTestEnable;
VkBool32 depthWriteEnable;
VkCompareOp depthCompareOp;
VkBool32 depthBoundsTestEnable;
VkBool32 stencilTestEnable;
VkStencilOpState front;
VkStencilOpState back;
float minDepthBounds;
float maxDepthBounds;
} VkPipelineDepthStencilStateCreateInfo;
-
sTypeis the type of this structure. -
pNextisNULLor a pointer to an extension-specific structure. -
flagsis reserved for future use. -
depthTestEnablecontrols whether depth testing is enabled. -
depthWriteEnablecontrols whether depth writes are enabled whendepthTestEnableisVK_TRUE. Depth writes are always disabled whendepthTestEnableisVK_FALSE. -
depthCompareOpis the comparison operator used in the depth test. -
depthBoundsTestEnablecontrols whether depth bounds testing is enabled. -
stencilTestEnablecontrols whether stencil testing is enabled. -
frontandbackcontrol the parameters of the stencil test. -
minDepthBoundsandmaxDepthBoundsdefine the range of values used in the depth bounds test.
typedef VkFlags VkPipelineDepthStencilStateCreateFlags;
VkPipelineDepthStencilStateCreateFlags is a bitmask type for setting a
mask, but is currently reserved for future use.
27.11. Depth Bounds Test
The depth bounds test conditionally disables coverage of a sample based on
the outcome of a comparison between the value za in the depth
attachment at location (xf,yf) (for the appropriate sample) and a
range of values.
The test is enabled or disabled by the depthBoundsTestEnable member of
VkPipelineDepthStencilStateCreateInfo: If the pipeline state object is
created without the VK_DYNAMIC_STATE_DEPTH_BOUNDS dynamic state
enabled then the range of values used in the depth bounds test are defined
by the minDepthBounds and maxDepthBounds members of the
VkPipelineDepthStencilStateCreateInfo structure.
Otherwise, to dynamically set the depth bounds range values call:
void vkCmdSetDepthBounds(
VkCommandBuffer commandBuffer,
float minDepthBounds,
float maxDepthBounds);
-
commandBufferis the command buffer into which the command will be recorded. -
minDepthBoundsis the lower bound of the range of depth values used in the depth bounds test. -
maxDepthBoundsis the upper bound of the range.
If minDepthBounds ≤ za ≤ maxDepthBounds, then
the depth bounds test passes.
Otherwise, the test fails and the sample’s coverage bit is cleared in the
fragment.
If there is no depth framebuffer attachment or if the depth bounds test is
disabled, it is as if the depth bounds test always passes.
27.12. Stencil Test
The stencil test conditionally disables coverage of a sample based on the
outcome of a comparison between the stencil value in the depth/stencil
attachment at location (xf,yf) (for the appropriate sample) and a
reference value.
The stencil test also updates the value in the stencil attachment, depending
on the test state, the stencil value and the stencil write masks.
The test is enabled or disabled by the stencilTestEnable member of
VkPipelineDepthStencilStateCreateInfo.
When disabled, the stencil test and associated modifications are not made, and the sample’s coverage is not modified.
The stencil test is controlled with the front and back members
of VkPipelineDepthStencilStateCreateInfo which are of type
VkStencilOpState.
The VkStencilOpState structure is defined as:
typedef struct VkStencilOpState {
VkStencilOp failOp;
VkStencilOp passOp;
VkStencilOp depthFailOp;
VkCompareOp compareOp;
uint32_t compareMask;
uint32_t writeMask;
uint32_t reference;
} VkStencilOpState;
-
failOpis a VkStencilOp value specifying the action performed on samples that fail the stencil test. -
passOpis a VkStencilOp value specifying the action performed on samples that pass both the depth and stencil tests. -
depthFailOpis a VkStencilOp value specifying the action performed on samples that pass the stencil test and fail the depth test. -
compareOpis a VkCompareOp value specifying the comparison operator used in the stencil test. -
compareMaskselects the bits of the unsigned integer stencil values participating in the stencil test. -
writeMaskselects the bits of the unsigned integer stencil values updated by the stencil test in the stencil framebuffer attachment. -
referenceis an integer reference value that is used in the unsigned stencil comparison.
There are two sets of stencil-related state, the front stencil state set and the back stencil state set. Stencil tests and writes use the front set of stencil state when processing front-facing fragments and use the back set of stencil state when processing back-facing fragments. Fragments rasterized from non-polygon primitives (points and lines) are always considered front-facing. Fragments rasterized from polygon primitives inherit their facingness from the polygon, even if the polygon is rasterized as points or lines due to the current VkPolygonMode. Whether a polygon is front- or back-facing is determined in the same manner used for face culling (see Basic Polygon Rasterization).
The operation of the stencil test is also affected by the compareMask,
writeMask, and reference members of VkStencilOpState set
in the pipeline state object if the pipeline state object is created without
the VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, and
VK_DYNAMIC_STATE_STENCIL_REFERENCE dynamic states enabled,
respectively.
If the pipeline state object is created with the
VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK dynamic state enabled, then to
dynamically set the stencil compare mask call:
void vkCmdSetStencilCompareMask(
VkCommandBuffer commandBuffer,
VkStencilFaceFlags faceMask,
uint32_t compareMask);
-
commandBufferis the command buffer into which the command will be recorded. -
faceMaskis a bitmask of VkStencilFaceFlagBits specifying the set of stencil state for which to update the compare mask. -
compareMaskis the new value to use as the stencil compare mask.
Bits which can be set in the
vkCmdSetStencilCompareMask::faceMask parameter, and similar
parameters of other commands specifying which stencil state to update
stencil masks for, are:
typedef enum VkStencilFaceFlagBits {
VK_STENCIL_FACE_FRONT_BIT = 0x00000001,
VK_STENCIL_FACE_BACK_BIT = 0x00000002,
VK_STENCIL_FRONT_AND_BACK = 0x00000003,
VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkStencilFaceFlagBits;
-
VK_STENCIL_FACE_FRONT_BITspecifies that only the front set of stencil state is updated. -
VK_STENCIL_FACE_BACK_BITspecifies that only the back set of stencil state is updated. -
VK_STENCIL_FRONT_AND_BACKis the combination ofVK_STENCIL_FACE_FRONT_BITandVK_STENCIL_FACE_BACK_BIT, and specifies that both sets of stencil state are updated.
typedef VkFlags VkStencilFaceFlags;
VkStencilFaceFlags is a bitmask type for setting a mask of zero or
more VkStencilFaceFlagBits.
If the pipeline state object is created with the
VK_DYNAMIC_STATE_STENCIL_WRITE_MASK dynamic state enabled, then to
dynamically set the stencil write mask call:
void vkCmdSetStencilWriteMask(
VkCommandBuffer commandBuffer,
VkStencilFaceFlags faceMask,
uint32_t writeMask);
-
commandBufferis the command buffer into which the command will be recorded. -
faceMaskis a bitmask of VkStencilFaceFlagBits specifying the set of stencil state for which to update the write mask, as described above for vkCmdSetStencilCompareMask. -
writeMaskis the new value to use as the stencil write mask.
If the pipeline state object is created with the
VK_DYNAMIC_STATE_STENCIL_REFERENCE dynamic state enabled, then to
dynamically set the stencil reference value call:
void vkCmdSetStencilReference(
VkCommandBuffer commandBuffer,
VkStencilFaceFlags faceMask,
uint32_t reference);
-
commandBufferis the command buffer into which the command will be recorded. -
faceMaskis a bitmask of VkStencilFaceFlagBits specifying the set of stencil state for which to update the reference value, as described above for vkCmdSetStencilCompareMask. -
referenceis the new value to use as the stencil reference value.
reference is an integer reference value that is used in the unsigned
stencil comparison.
The reference value used by stencil comparison must be within the range
[0,2s-1] , where s is the number of bits in the stencil
framebuffer attachment, otherwise the reference value is considered
undefined.
The s least significant bits of compareMask are bitwise
ANDed with both the reference and the stored stencil value, and the
resulting masked values are those that participate in the comparison
controlled by compareOp.
Let R be the masked reference value and S be the masked stored
stencil value.
Possible values of VkStencilOpState::compareOp, specifying the
stencil comparison function, are:
typedef enum VkCompareOp {
VK_COMPARE_OP_NEVER = 0,
VK_COMPARE_OP_LESS = 1,
VK_COMPARE_OP_EQUAL = 2,
VK_COMPARE_OP_LESS_OR_EQUAL = 3,
VK_COMPARE_OP_GREATER = 4,
VK_COMPARE_OP_NOT_EQUAL = 5,
VK_COMPARE_OP_GREATER_OR_EQUAL = 6,
VK_COMPARE_OP_ALWAYS = 7,
VK_COMPARE_OP_MAX_ENUM = 0x7FFFFFFF
} VkCompareOp;
-
VK_COMPARE_OP_NEVERspecifies that the test never passes. -
VK_COMPARE_OP_LESSspecifies that the test passes when R < S. -
VK_COMPARE_OP_EQUALspecifies that the test passes when R = S. -
VK_COMPARE_OP_LESS_OR_EQUALspecifies that the test passes when R ≤ S. -
VK_COMPARE_OP_GREATERspecifies that the test passes when R > S. -
VK_COMPARE_OP_NOT_EQUALspecifies that the test passes when R ≠ S. -
VK_COMPARE_OP_GREATER_OR_EQUALspecifies that the test passes when R ≥ S. -
VK_COMPARE_OP_ALWAYSspecifies that the test always passes.
Possible values of the failOp, passOp, and depthFailOp
members of VkStencilOpState, specifying what happens to the stored
stencil value if this or certain subsequent tests fail or pass, are:
typedef enum VkStencilOp {
VK_STENCIL_OP_KEEP = 0,
VK_STENCIL_OP_ZERO = 1,
VK_STENCIL_OP_REPLACE = 2,
VK_STENCIL_OP_INCREMENT_AND_CLAMP = 3,
VK_STENCIL_OP_DECREMENT_AND_CLAMP = 4,
VK_STENCIL_OP_INVERT = 5,
VK_STENCIL_OP_INCREMENT_AND_WRAP = 6,
VK_STENCIL_OP_DECREMENT_AND_WRAP = 7,
VK_STENCIL_OP_MAX_ENUM = 0x7FFFFFFF
} VkStencilOp;
-
VK_STENCIL_OP_KEEPkeeps the current value. -
VK_STENCIL_OP_ZEROsets the value to 0. -
VK_STENCIL_OP_REPLACEsets the value toreference. -
VK_STENCIL_OP_INCREMENT_AND_CLAMPincrements the current value and clamps to the maximum representable unsigned value. -
VK_STENCIL_OP_DECREMENT_AND_CLAMPdecrements the current value and clamps to 0. -
VK_STENCIL_OP_INVERTbitwise-inverts the current value. -
VK_STENCIL_OP_INCREMENT_AND_WRAPincrements the current value and wraps to 0 when the maximum value would have been exceeded. -
VK_STENCIL_OP_DECREMENT_AND_WRAPdecrements the current value and wraps to the maximum possible value when the value would go below 0.
For purposes of increment and decrement, the stencil bits are considered as an unsigned integer.
If the stencil test fails, the sample’s coverage bit is cleared in the fragment. If there is no stencil framebuffer attachment, stencil modification cannot occur, and it is as if the stencil tests always pass.
If the stencil test passes, the writeMask member of the
VkStencilOpState structures controls how the updated stencil value is
written to the stencil framebuffer attachment.
The least significant s bits of writeMask, where s is the
number of bits in the stencil framebuffer attachment, specify an integer
mask.
Where a 1 appears in this mask, the corresponding bit in the stencil
value in the depth/stencil attachment is written; where a 0 appears,
the bit is not written.
The writeMask value uses either the front-facing or back-facing state
based on the facingness of the fragment.
Fragments generated by front-facing primitives use the front mask and
fragments generated by back-facing primitives use the back mask.
27.13. Depth Test
The depth test conditionally disables coverage of a sample based on the
outcome of a comparison between the fragment’s depth value at the sample
location and the sample’s depth value in the depth/stencil attachment at
location (xf,yf).
The comparison is enabled or disabled with the depthTestEnable member
of the VkPipelineDepthStencilStateCreateInfo structure.
When disabled, the depth comparison and subsequent possible updates to the
value of the depth component of the depth/stencil attachment are bypassed
and the fragment is passed to the next operation.
The stencil value, however, can be modified as indicated above as if the
depth test passed.
If enabled, the comparison takes place and the depth/stencil attachment
value can subsequently be modified.
The comparison is specified with the depthCompareOp member of
VkPipelineDepthStencilStateCreateInfo.
Let zf be the incoming fragment’s depth value for a sample,
and let za be the depth/stencil attachment value in memory for that
sample.
The depth test passes under the following conditions:
-
VK_COMPARE_OP_NEVER: the test never passes. -
VK_COMPARE_OP_LESS: the test passes when zf < za. -
VK_COMPARE_OP_EQUAL: the test passes when zf = za. -
VK_COMPARE_OP_LESS_OR_EQUAL: the test passes when zf ≤ za. -
VK_COMPARE_OP_GREATER: the test passes when zf > za. -
VK_COMPARE_OP_NOT_EQUAL: the test passes when zf ≠ za. -
VK_COMPARE_OP_GREATER_OR_EQUAL: the test passes when zf ≥ za. -
VK_COMPARE_OP_ALWAYS: the test always passes.
If VkPipelineRasterizationStateCreateInfo::depthClampEnable is
enabled, before the incoming fragment’s zf is compared to
za, zf is clamped to [min(n,f),max(n,f)],
where n and f are the minDepth and maxDepth depth
range values of the viewport used by this fragment, respectively.
If the depth test fails, the sample’s coverage bit is cleared in the fragment. The stencil value at the sample’s location is updated according to the function currently in effect for depth test failure.
If the depth test passes, the sample’s (possibly clamped) zf
value is conditionally written to the depth framebuffer attachment based on
the depthWriteEnable member of
VkPipelineDepthStencilStateCreateInfo.
If depthWriteEnable is VK_TRUE the value is written, and if it
is VK_FALSE the value is not written.
If the depth framebuffer attachment is a fixed-point format and the depth
value is outside of the 0.0 to 1.0 range the depth value is clamped
between 0.0 and 1.0 inclusive before writing.
The stencil value at the sample’s location is updated according to the
function currently in effect for depth test success.
If there is no depth framebuffer attachment, it is as if the depth test always passes.
27.14. Representative Fragment Test
The representative fragment test allows implementations to reduce the amount of rasterization and fragment processing work performed for each point, line, or triangle primitive. For any primitive that produces one or more fragments that pass all prior early fragment tests, the implementation may choose one or more “representative” fragments for processing and discard all other fragments. For draw calls rendering multiple points, lines, or triangles arranged in lists, strips, or fans, the representative fragment test is performed independently for each of those primitives. The set of fragments discarded by the representative fragment test is implementation-dependent. In some cases, the representative fragment test may not discard any fragments for a given primitive.
If the pNext chain of VkGraphicsPipelineCreateInfo includes a
VkPipelineRepresentativeFragmentTestStateCreateInfoNV structure, then
that structure includes parameters that control the representative fragment
test.
The VkPipelineRepresentativeFragmentTestStateCreateInfoNV structure is
defined as:
typedef struct VkPipelineRepresentativeFragmentTestStateCreateInfoNV {
VkStructureType sType;
const void* pNext;
VkBool32 representativeFragmentTestEnable;
} VkPipelineRepresentativeFragmentTestStateCreateInfoNV;
-
sTypeis the type of this structure. -
pNextisNULLor a pointer to an extension-specific structure. -
representativeFragmentTestEnablecontrols whether the representative fragment test is enabled.
If this structure is not present, representativeFragmentTestEnable is
considered to be VK_FALSE, and the representative fragment test is
disabled.
If early fragment tests are not enabled in the active fragment shader, the representative fragment shader test has no effect, even if enabled.
27.15. Sample Counting
Occlusion queries use query pool entries to track the number of samples that pass all the per-fragment tests. The mechanism of collecting an occlusion query value is described in Occlusion Queries.
The occlusion query sample counter increments by one for each sample with a coverage value of 1 in each fragment that survives all the per-fragment tests, including scissor, exclusive scissor, sample mask, alpha to coverage, stencil, and depth tests.
27.16. Fragment Coverage To Color
If the pNext chain of VkPipelineMultisampleStateCreateInfo
includes a VkPipelineCoverageToColorStateCreateInfoNV structure, then
that structure controls whether the fragment coverage is substituted for a
fragment color output and, if so, which output is replaced.
The VkPipelineCoverageToColorStateCreateInfoNV structure is defined
as:
typedef struct VkPipelineCoverageToColorStateCreateInfoNV {
VkStructureType sType;
const void* pNext;
VkPipelineCoverageToColorStateCreateFlagsNV flags;
VkBool32 coverageToColorEnable;
uint32_t coverageToColorLocation;
} VkPipelineCoverageToColorStateCreateInfoNV;
-
sTypeis the type of this structure -
pNextisNULLor a pointer to an extension-specific structure -
flagsis reserved for future use. -
coverageToColorEnablecontrols whether the fragment coverage value replaces a fragment color output. -
coverageToColorLocationcontrols which fragment shader color output value is replaced.
If coverageToColorEnable is VK_TRUE, the fragment coverage
information is treated as a bitmask with one bit for each sample (as in the
Sample Mask section), and this bitmask replaces the
first component of the color value corresponding to the fragment shader
output location with Location equal to coverageToColorLocation
and Index equal to zero.
If the color attachment format has fewer bits than the sample coverage, the
low bits of the sample coverage bitmask are taken without any clamping.
If the color attachment format has more bits than the sample coverage, the
high bits of the sample coverage bitmask are filled with zeros.
If Sample Shading is in use, the coverage bitmask only has bits set for samples that correspond to the fragment shader invocation that shades those samples.
This pipeline stage occurs after sample counting and before blending, and is
always performed after fragment shading regardless of the setting of
EarlyFragmentTests.
If coverageToColorEnable is VK_FALSE, these operations are
skipped.
If this structure is not present, it is as if coverageToColorEnable is
VK_FALSE.
typedef VkFlags VkPipelineCoverageToColorStateCreateFlagsNV;
VkPipelineCoverageToColorStateCreateFlagsNV is a bitmask type for
setting a mask, but is currently reserved for future use.
27.17. Coverage Reduction
Coverage reduction generates a color sample mask from the coverage mask, with one bit for each sample in the color attachment(s) for the subpass. If a bit in the color sample mask is 0, then blending and writing to the framebuffer are not performed for that sample.
When the VK_NV_framebuffer_mixed_samples extension is not enabled, each
color sample is associated with a unique rasterization sample, and the value
of the coverage mask is assigned to the color sample mask.
If the render pass has a fragment density map attachment,
rasterizationSamples is greater than 1, and the fragment area covers
multiple pixels; there is an implementation-dependent association of
rasterization samples to color attachment samples within the fragment.
Each color sample’s mask bit is assigned the union of the coverage bits of
its associated raster samples.
If the pipeline’s
VkPipelineMultisampleStateCreateInfo::rasterizationSamples is
greater than the VkAttachmentDescription::samples of the color
attachments in the subpass, then the fragment’s coverage is reduced from
rasterizationSamples bits to a color sample mask with
VkAttachmentDescription::samples bits.
When the VK_NV_coverage_reduction_mode extension is enabled, the pipeline
state controlling coverage reduction is specified through the members of the
VkPipelineCoverageReductionStateCreateInfoNV structure.
The VkPipelineCoverageReductionStateCreateInfoNV structure is defined
as:
typedef struct VkPipelineCoverageReductionStateCreateInfoNV {
VkStructureType sType;
const void* pNext;
VkPipelineCoverageReductionStateCreateFlagsNV flags;
VkCoverageReductionModeNV coverageReductionMode;
} VkPipelineCoverageReductionStateCreateInfoNV;
-
sTypeis the type of this structure. -
pNextisNULLor a pointer to an extension-specific structure. -
flagsis reserved for future use. -
coverageReductionModecontrols how the color sample mask is generated from the coverage mask and is of type VkCoverageReductionModeNV.
If this structure is not present, the default coverage reduction mode is inferred as follows:
-
If the
VK_NV_framebuffer_mixed_samplesextension is enabled, then it is as if thecoverageReductionModeisVK_COVERAGE_REDUCTION_MODE_MERGE_NV. -
If the
VK_AMD_mixed_attachment_samplesextension is enabled, then it is as if thecoverageReductionModeisVK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV. -
If both
VK_NV_framebuffer_mixed_samplesandVK_AMD_mixed_attachment_samplesare enabled, then the default coverage reduction mode is implementation-dependent.
typedef VkFlags VkPipelineCoverageReductionStateCreateFlagsNV;
VkPipelineCoverageReductionStateCreateFlagsNV is a bitmask type for
setting a mask, but is currently reserved for future use.
Possible values of
VkPipelineCoverageReductionStateCreateInfoNV::coverageReductionMode,
specifying how the coverage mask is reduced to color sample mask, are:
typedef enum VkCoverageReductionModeNV {
VK_COVERAGE_REDUCTION_MODE_MERGE_NV = 0,
VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV = 1,
VK_COVERAGE_REDUCTION_MODE_MAX_ENUM_NV = 0x7FFFFFFF
} VkCoverageReductionModeNV;
-
VK_COVERAGE_REDUCTION_MODE_MERGE_NV: In this mode, there is an implementation-dependent association of each raster sample to a color sample. The reduced color sample mask is computed such that the bit for each color sample is 1 if any of the associated bits in the fragment’s coverage is on, and 0 otherwise. -
VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV: In this mode, only the first M raster samples are associated with the color samples such that raster sample i maps to color sample i, where M is the number of color samples.
If the VK_NV_coverage_reduction_mode extension is not enabled, there is an
implementation-dependent association of raster samples to color samples.
The reduced color sample mask is computed such that the bit for each color
sample is 1 if any of the associated bits in the fragment’s coverage is on,
and 0 otherwise.
To query the set of mixed sample combinations of coverage reduction mode, rasterization samples and color, depth, stencil attachment sample counts that are supported by a physical device, call:
VkResult vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV(
VkPhysicalDevice physicalDevice,
uint32_t* pCombinationCount,
VkFramebufferMixedSamplesCombinationNV* pCombinations);
-
physicalDeviceis the physical device from which to query the set of combinations. -
pCombinationCountis a pointer to an integer related to the number of combinations available or queried, as described below. -
pCombinationsis eitherNULLor a pointer to an array of VkFramebufferMixedSamplesCombinationNV values, indicating the supported combinations of coverage reduction mode, rasterization samples, and color, depth, stencil attachment sample counts.
If pCombinations is NULL, then the number of supported combinations
for the given physicalDevice is returned in pCombinationCount.
Otherwise, pCombinationCount must point to a variable set by the user
to the number of elements in the pCombinations array, and on return
the variable is overwritten with the number of values actually written to
pCombinations.
If the value of pCombinationCount is less than the number of
combinations supported for the given physicalDevice, at most
pCombinationCount values will be written pCombinations and
VK_INCOMPLETE will be returned instead of VK_SUCCESS to indicate
that not all the supported values were returned.
The VkFramebufferMixedSamplesCombinationNV structure is defined as:
typedef struct VkFramebufferMixedSamplesCombinationNV {
VkStructureType sType;
void* pNext;
VkCoverageReductionModeNV coverageReductionMode;
VkSampleCountFlagBits rasterizationSamples;
VkSampleCountFlags depthStencilSamples;
VkSampleCountFlags colorSamples;
} VkFramebufferMixedSamplesCombinationNV;
-
sTypeis the type of this structure. -
pNextisNULLor a pointer to an extension-specific structure. -
coverageReductionModespecifies the coverage reduction mode and is of type VkCoverageReductionModeNV. -
rasterizationSamplesspecifies the number of rasterization samples in the supported combination. -
depthStencilSamplesspecifies the number of samples in the depth stencil attachment in the supported combination. A value of 0 indicates the combination does not have a depth stencil attachment. -
colorSamplesspecifies the number of color samples in a color attachment in the supported combination. A value of 0 indicates the combination does not have a color attachment.
27.17.1. Coverage Modulation
As part of coverage reduction, fragment color values can also be modulated (multiplied) by a value that is a function of fraction of covered rasterization samples associated with that color sample.
Pipeline state controlling coverage modulation is specified through the
members of the VkPipelineCoverageModulationStateCreateInfoNV
structure.
The VkPipelineCoverageModulationStateCreateInfoNV structure is defined
as:
typedef struct VkPipelineCoverageModulationStateCreateInfoNV {
VkStructureType sType;
const void* pNext;
VkPipelineCoverageModulationStateCreateFlagsNV flags;
VkCoverageModulationModeNV coverageModulationMode;
VkBool32 coverageModulationTableEnable;
uint32_t coverageModulationTableCount;
const float* pCoverageModulationTable;
} VkPipelineCoverageModulationStateCreateInfoNV;
-
sTypeis the type of this structure. -
pNextisNULLor a pointer to an extension-specific structure. -
flagsis reserved for future use. -
coverageModulationModecontrols which color components are modulated and is of type VkCoverageModulationModeNV. -
coverageModulationTableEnablecontrols whether the modulation factor is looked up from a table inpCoverageModulationTable. -
coverageModulationTableCountis the number of elements inpCoverageModulationTable. -
pCoverageModulationTableis a table of modulation factors containing a value for each number of covered samples.
If coverageModulationTableEnable is VK_FALSE, then for each
color sample the associated bits of the fragment’s coverage are counted and
divided by the number of associated bits to produce a modulation factor
R in the range (0,1] (a value of zero would have been killed due
to a color coverage of 0).
Specifically:
-
N = value of
rasterizationSamples -
M = value of VkAttachmentDescription::
samplesfor any color attachments -
R = popcount(associated coverage bits) / (N / M)
If coverageModulationTableEnable is VK_TRUE, the value R
is computed using a programmable lookup table.
The lookup table has N / M elements, and the element of the table is
selected by:
-
R =
pCoverageModulationTable[popcount(associated coverage bits)-1]
Note that the table does not have an entry for popcount(associated coverage bits) = 0, because such samples would have been killed.
The values of pCoverageModulationTable may be rounded to an
implementation-dependent precision, which is at least as fine as 1 /
N, and clamped to [0,1].
For each color attachment with a floating point or normalized color format,
each fragment output color value is replicated to M values which can
each be modulated (multiplied) by that color sample’s associated value of
R.
Which components are modulated is controlled by
coverageModulationMode.
If this structure is not present, it is as if coverageModulationMode
is VK_COVERAGE_MODULATION_MODE_NONE_NV.
typedef VkFlags VkPipelineCoverageModulationStateCreateFlagsNV;
VkPipelineCoverageModulationStateCreateFlagsNV is a bitmask type for
setting a mask, but is currently reserved for future use.
Possible values of
VkPipelineCoverageModulationStateCreateInfoNV::coverageModulationMode,
specifying which color components are modulated, are:
typedef enum VkCoverageModulationModeNV {
VK_COVERAGE_MODULATION_MODE_NONE_NV = 0,
VK_COVERAGE_MODULATION_MODE_RGB_NV = 1,
VK_COVERAGE_MODULATION_MODE_ALPHA_NV = 2,
VK_COVERAGE_MODULATION_MODE_RGBA_NV = 3,
VK_COVERAGE_MODULATION_MODE_MAX_ENUM_NV = 0x7FFFFFFF
} VkCoverageModulationModeNV;
-
VK_COVERAGE_MODULATION_MODE_NONE_NVspecifies that no components are multiplied by the modulation factor. -
VK_COVERAGE_MODULATION_MODE_RGB_NVspecifies that the red, green, and blue components are multiplied by the modulation factor. -
VK_COVERAGE_MODULATION_MODE_ALPHA_NVspecifies that the alpha component is multiplied by the modulation factor. -
VK_COVERAGE_MODULATION_MODE_RGBA_NVspecifies that all components are multiplied by the modulation factor.