Vulkan-Docs/doc/specs/vulkan/chapters/fragops.txt

549 lines
25 KiB
Plaintext

// Copyright (c) 2015-2016 The Khronos Group Inc.
// Copyright notice at https://www.khronos.org/registry/speccopyright.html
[[fragops]]
= Fragment Operations
[[fragops-early]]
== 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.
Two fragment operations are performed in the following order:
* the scissor test (see <<fragops-scissor,Scissor Test>>)
* multisample fragment operations (see <<fragops-samplemask,Sample Mask>>)
If early per-fragment operations are <<shaders-fragment-earlytest,enabled by
the fragment shader>>, these tests are also performed in the following
order:
* the depth bounds tests (see <<fragops-dbt,Depth Bounds Tests>>)
* the stencil test (see <<fragops-stencil,Stencil Test>>)
* the depth test (see <<fragops-depth,Depth Test>>)
* sample counting (see <<fragops-samplecount,Sample Counting>>)
[[fragops-scissor]]
== Scissor Test
The scissor test determines if a fragment's framebuffer coordinates
latexmath:[$(x_f,y_f)$] lie within the scissor rectangle corresponding to
the viewport index (see <<vertexpostproc-viewport,Controlling the
Viewport>>) used by the primitive that generated the fragment. If the
pipeline state object is created without ename:VK_DYNAMIC_STATE_SCISSOR
enabled then the scissor rectangles are set by the
slink:VkPipelineViewportStateCreateInfo state of the pipeline state object.
Otherwise, to dynamically set the scissor rectangles call:
include::../protos/vkCmdSetScissor.txt[]
* pname:commandBuffer is the command buffer into which the command will be
recorded.
* pname:firstScissor is the index of the first scissor whose state is
updated by the command.
* pname:scissorCount is the number of scissors whose rectangles are
updated by the command.
* pname:pScissors is a pointer to an array of slink:VkRect2D structures
defining scissor rectangles.
The scissor rectangles taken from element latexmath:[$i$] of pname:pScissors
replace the current state for the scissor index
latexmath:[$\mathit{firstScissor}+i$], for latexmath:[$i$] in
latexmath:[$[0, scissorCount)$].
Each scissor rectangle is described by a slink:VkRect2D structure, with the
pname:offset.x and pname:offset.y values determining the upper left corner
of the scissor rectangle, and the pname:extent.width and pname:extent.height
values determining the size in pixels.
include::../validity/protos/vkCmdSetScissor.txt[]
If latexmath:[$\mathit{offset.x} \le x_f \lt \mathit{offset.x} +
\mathit{extent.width}$] and latexmath:[$\mathit{offset.y} \le y_f \lt
\mathit{offset.y} + \mathit{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 <<vertexpostproc-viewport,Controlling the Viewport>>). The scissor
rectangles only apply to drawing commands, not to other commands like clears
or copies.
It is legal for latexmath:[$\mathit{offset.x} + \mathit{extent.width}$] or
latexmath:[$\mathit{offset.y} + \mathit{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.
[[fragops-samplemask]]
== Sample Mask
This step modifies fragment coverage values based on the values in the
pname:pSampleMask array member of
slink:VkPipelineMultisampleStateCreateInfo, as described previously in
section <<pipelines-graphics>>.
pname:pSampleMask contains a bitmask of static coverage information that is
code: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 latexmath:[$32 \times M + B$]. The array
is sized to a length of latexmath:[$\lceil{rasterizationSamples /
32}\rceil$] words. If pname:pSampleMask is `NULL`, it is treated as if the
mask has all bits enabled, i.e. no coverage is removed from fragments.
[[fragops-early-mode]]
== Early Fragment Test Mode
The depth bounds test, stencil test, depth 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
<<shaders-fragment-earlytest,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.
[[fragops-late]]
== 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
latexmath:[$(x_f,y_f)$] and depth latexmath:[$z$], as described in
<<primsrast,Rasterization>>. The fragment is then modified by programmable
fragment processing, which adds associated data as described in
<<shaders,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.
ifdef::editing-notes[]
[NOTE]
.editing-note
==================
There used to be a sentence of form "These operations are diagrammed in
figure ((fig-fragops,Fragment Operations)), in the order in which they are
performed" following "described in this chapter." above, but the referred
figure doesn't yet exist.
==================
endif::editing-notes[]
The depth bounds test, stencil test, and depth test are performed for each
pixel sample, rather than just once for each fragment. Stencil and depth
operations are performed for a pixel 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 <<fragops-dbt,Depth Bounds Test>>,
<<fragops-stencil,Stencil Test>>, <<fragops-depth,Depth Test>>,
<<fragops-samplecount,Sample Counting>> are instead performed prior to
fragment processing, as described in <<fragops-early-mode,Early Fragment
Test Mode>>, if requested by the fragment shader.
[[fragops-covg]]
== Multisample Coverage
If a fragment shader is active and its entry point's interface includes a
built-in output variable decorated with code:SampleMask, the fragment
coverage is code: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 code:SampleMask due to flow of
control, the value code:ANDed with the fragment coverage is undefined. If no
fragment shader is active, or if the active fragment shader does not
include code:SampleMask in its interface, the fragment coverage is not
modified.
Next, the fragment alpha and coverage values are modified based on the
pname:alphaToCoverageEnable and pname:alphaToOneEnable members
of the slink:VkPipelineMultisampleStateCreateInfo structure.
All alpha values in this section refer only to the alpha component of the
fragment shader output that has a code:Location and code:Index decoration of
zero (see the <<interfaces-fragmentoutput,Fragment Output Interface>>
section). If that shader output has an integer or unsigned integer type,
then these operations are skipped.
If pname:alphaToCoverageEnable is enabled, a temporary coverage value 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
latexmath:[$[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 pixel
locations.
[NOTE]
.Note
====
Using different algorithms at different pixel location may: help to
avoid artifacts caused by regular coverage sample locations.
====
Next, if pname: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.
[[fragops-ds-state]]
== Depth and Stencil Operations
Pipeline state controlling the <<fragops-dbt,depth bounds tests>>,
<<fragops-stencil,stencil test>>, and <<fragops-depth,depth test>> is
specified through the members of the
sname:VkPipelineDepthStencilStateCreateInfo structure.
The sname:VkPipelineDepthStencilStateCreateInfo structure is defined as:
include::../structs/VkPipelineDepthStencilStateCreateInfo.txt[]
* pname:sType is the type of this structure.
* pname:pNext is `NULL` or a pointer to an extension-specific structure.
* pname:flags is reserved for future use.
* pname:depthTestEnable controls whether <<fragops-depth,depth testing>>
is enabled.
* pname:depthWriteEnable controls whether
<<fragops-depth-write,depth writes>> are enabled.
* pname:depthCompareOp is the comparison operator used in the
<<fragops-depth,depth test>>.
* pname:depthBoundsTestEnable controls whether <<fragops-dbt,depth bounds
testing>> is enabled.
* pname:stencilTestEnable controls whether <<fragops-stencil,stencil
testing>> is enabled.
* pname:front and pname:back control the parameters of the
<<fragops-stencil,stencil test>>.
* pname:minDepthBounds and pname:maxDepthBounds define the range of values
used in the <<fragops-dbt,depth bounds test>>.
include::../validity/structs/VkPipelineDepthStencilStateCreateInfo.txt[]
[[fragops-dbt]]
== Depth Bounds Test
The depth bounds test conditionally disables coverage of a sample based on
the outcome of a comparison between the value latexmath:[$z_a$] in the depth
attachment at location latexmath:[$(x_f,y_f)$] (for the appropriate sample)
and a range of values. The test is enabled or disabled by the
pname:depthBoundsTestEnable member of
slink:VkPipelineDepthStencilStateCreateInfo: If the pipeline state object
is created without the ename:VK_DYNAMIC_STATE_DEPTH_BOUNDS dynamic state
enabled then the range of values used in the depth bounds test are defined
by the pname:minDepthBounds and pname:maxDepthBounds members of the
slink:VkPipelineDepthStencilStateCreateInfo structure. Otherwise, to
dynamically set the depth bounds range values call:
include::../protos/vkCmdSetDepthBounds.txt[]
* pname:commandBuffer is the command buffer into which the command will be
recorded.
* pname:minDepthBounds is the lower bound of the range of depth values
used in the depth bounds test.
* pname:maxDepthBounds is the upper bound of the range.
include::../validity/protos/vkCmdSetDepthBounds.txt[]
If latexmath:[$\mathit{minDepthBounds} \leq z_a \leq
\mathit{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.
[[fragops-stencil]]
== 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 latexmath:[$(x_f,y_f)$] (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
pname:stencilTestEnable member of
slink: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 pname:front and pname:back members
of sname:VkPipelineDepthStencilStateCreateInfo which are of type
sname:VkStencilOpState.
The sname:VkStencilOpState structure is defined as:
include::../structs/VkStencilOpState.txt[]
* pname:failOp is the action performed on samples that fail the stencil
test.
* pname:passOp is the action performed on samples that pass both the depth
and stencil tests.
* pname:depthFailOp is the action performed on samples that pass the
stencil test and fail the depth test.
* pname:compareOp is the comparison operator used in the stencil test.
* pname:compareMask selects the bits of the unsigned integer stencil
values participating in the stencil test.
* pname:writeMask selects the bits of the unsigned integer stencil values
updated by the stencil test in the stencil framebuffer attachment.
* pname:reference is an integer reference value that is used in the
unsigned stencil comparison.
include::../validity/structs/VkStencilOpState.txt[]
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 fragments rasterized from non-polygon
primitives (points and lines) and front-facing polygon primitives while the
back set of stencil state is used when processing fragments rasterized from
back-facing polygon primitives. For the purposes of stencil testing, a
primitive is still considered a polygon even if the polygon is to be
rasterized as points or lines due to the current elink:VkPolygonMode.
Whether a polygon is front- or back-facing is determined in the same manner
used for face culling (see <<primsrast-polygons-basic,Basic Polygon
Rasterization>>).
The operation of the stencil test is also affected by the
pname:compareMask, pname:writeMask, and pname:reference
members of sname:VkStencilOpState set in the pipeline state object if the
pipeline state object is created without the
ename:VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
ename:VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, and
ename:VK_DYNAMIC_STATE_STENCIL_REFERENCE dynamic states enabled,
respectively.
If the pipeline state object is created with the
ename:VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK dynamic state enabled, then to
dynamically set the stencil compare mask call:
include::../protos/vkCmdSetStencilCompareMask.txt[]
* pname:commandBuffer is the command buffer into which the command will be
recorded.
* pname:faceMask is a bitmask specifying the set of stencil state for
which to update the compare mask. Bits which can: be set include:
+
--
include::../enums/VkStencilFaceFlagBits.txt[]
** ename:VK_STENCIL_FACE_FRONT_BIT indicates that only the front set of
stencil state is updated.
** ename:VK_STENCIL_FACE_BACK_BIT indicates that only the back set of
stencil state is updated.
** ename:VK_STENCIL_FRONT_AND_BACK is the combination of
ename:VK_STENCIL_FACE_FRONT_BIT and ename:VK_STENCIL_FACE_BACK_BIT and
indicates that both sets of stencil state are updated.
--
* pname:compareMask is the new value to use as the stencil compare mask.
include::../validity/protos/vkCmdSetStencilCompareMask.txt[]
If the pipeline state object is created with the
ename:VK_DYNAMIC_STATE_STENCIL_WRITE_MASK dynamic state enabled, then to
dynamically set the stencil write mask call:
include::../protos/vkCmdSetStencilWriteMask.txt[]
* pname:commandBuffer is the command buffer into which the command will be
recorded.
* pname:faceMask is a bitmask of elink:VkStencilFaceFlagBits specifying
the set of stencil state for which to update the write mask, as
described above for flink:vkCmdSetStencilCompareMask.
* pname:writeMask is the new value to use as the stencil write mask.
include::../validity/protos/vkCmdSetStencilWriteMask.txt[]
If the pipeline state object is created with the
ename:VK_DYNAMIC_STATE_STENCIL_REFERENCE dynamic state enabled, then to
dynamically set the stencil reference value call:
include::../protos/vkCmdSetStencilReference.txt[]
* pname:commandBuffer is the command buffer into which the command will be
recorded.
* pname:faceMask is a bitmask of elink:VkStencilFaceFlagBits specifying
the set of stencil state for which to update the reference value, as
described above for flink:vkCmdSetStencilCompareMask.
* pname:reference is the new value to use as the stencil reference value.
include::../validity/protos/vkCmdSetStencilReference.txt[]
pname:reference is an integer reference value that is used in the
unsigned stencil comparison. Stencil comparison clamps the reference value
to latexmath:[$[0,2^s-1\]$], where latexmath:[$s$] is the number
of bits in the stencil framebuffer attachment. The latexmath:[$s$] least
significant bits of pname:compareMask are bitwise code:ANDed with
both the reference and the stored stencil value, and the resulting masked
values are those that participate in the comparison controlled by
pname:compareOp. Let latexmath:[$R$] be the masked reference value
and latexmath:[$S$] be the masked stored stencil value.
pname:compareOp is a symbolic constant that determines the stencil
comparison function:
include::../enums/VkCompareOp.txt[]
* ename:VK_COMPARE_OP_NEVER: the test never passes.
* ename:VK_COMPARE_OP_LESS: the test passes when latexmath:[$R \lt S$].
* ename:VK_COMPARE_OP_EQUAL: the test passes when latexmath:[$R = S$].
* ename:VK_COMPARE_OP_LESS_OR_EQUAL: the test passes when latexmath:[$R
\leq S$].
* ename:VK_COMPARE_OP_GREATER: the test passes when latexmath:[$R \gt S$].
* ename:VK_COMPARE_OP_NOT_EQUAL: the test passes when latexmath:[$R \neq
S$].
* ename:VK_COMPARE_OP_GREATER_OR_EQUAL: the test passes when latexmath:[$R
\geq S$].
* ename:VK_COMPARE_OP_ALWAYS: the test always passes.
As described earlier, the pname:failOp, pname:passOp, and pname:depthFailOp
members of slink:VkStencilOpState indicate what happens to the stored
stencil value if this or certain subsequent tests fail or pass. Each enum is
of type elink:VkStencilOp, which is defined as:
include::../enums/VkStencilOp.txt[]
The possible values are:
* ename:VK_STENCIL_OP_KEEP keeps the current value.
* ename:VK_STENCIL_OP_ZERO sets the value to 0.
* ename:VK_STENCIL_OP_REPLACE sets the value to pname:reference.
* ename:VK_STENCIL_OP_INCREMENT_AND_CLAMP increments the current value and
clamps to the maximum representable unsigned value.
* ename:VK_STENCIL_OP_DECREMENT_AND_CLAMP decrements the current value and
clamps to 0.
* ename:VK_STENCIL_OP_INVERT bitwise-inverts the current value.
* ename:VK_STENCIL_OP_INCREMENT_AND_WRAP increments the current value and
wraps to 0 when the maximum value would have been exceeded.
* ename:VK_STENCIL_OP_DECREMENT_AND_WRAP decrements 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 pname:writeMask member of the
slink:VkStencilOpState structures controls how the updated stencil value is
written to the stencil framebuffer attachment.
The least significant latexmath:[$s$] bits of pname:writeMask, where
latexmath:[$s$] is the number of bits in the stencil framebuffer attachment,
specify an integer mask. Where a latexmath:[$1$] appears in this mask, the
corresponding bit in the stencil value in the depth/stencil attachment is
written; where a latexmath:[$0$] appears, the bit is not written. The
pname:writeMask value uses either the front-facing or back-facing state
based on the facing-ness of the fragment. Fragments generated by
front-facing primitives use the front mask and fragments generated by
back-facing primitives use the back mask.
[[fragops-depth]]
== 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 latexmath:[$(x_f,y_f)$]. The comparison is enabled or disabled with
the pname:depthTestEnable member of the
slink: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 pname:depthCompareOp member of
slink:VkPipelineDepthStencilStateCreateInfo. Let latexmath:[$z_f$] be the
incoming fragment's depth value for a sample, and let latexmath:[$z_a$] be
the depth/stencil attachment value in memory for that sample. The depth test
passes under the following conditions:
* ename:VK_COMPARE_OP_NEVER: the test never passes.
* ename:VK_COMPARE_OP_LESS: the test passes when
latexmath:[$z_f \lt z_a$].
* ename:VK_COMPARE_OP_EQUAL: the test passes when
latexmath:[$z_f = z_a$].
* ename:VK_COMPARE_OP_LESS_OR_EQUAL: the test passes when
latexmath:[$z_f \leq z_a$].
* ename:VK_COMPARE_OP_GREATER: the test passes when
latexmath:[$z_f \gt z_a$].
* ename:VK_COMPARE_OP_NOT_EQUAL: the test passes when
latexmath:[$z_f \neq z_a$].
* ename:VK_COMPARE_OP_GREATER_OR_EQUAL: the test passes when
latexmath:[$z_f \geq z_a$].
* ename:VK_COMPARE_OP_ALWAYS: the test always passes.
If depth clamping (see <<vertexpostproc-clipping,Primitive Clipping>>) is
enabled, before the incoming fragment's latexmath:[$z_f$] is compared to
latexmath:[$z_a$], latexmath:[$z_f$] is clamped to
latexmath:[$[\min(n,f), \max(n,f)\]$], where latexmath:[$n$] and
latexmath:[$f$] are the pname:minDepth and pname: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.
[[fragops-depth-write]]
If the depth test passes, the sample's (possibly clamped) latexmath:[$z_f$]
value is conditionally written to the depth framebuffer attachment based on
the pname:depthWriteEnable member of
slink:VkPipelineDepthStencilStateCreateInfo. If pname:depthWriteEnable is
ename:VK_TRUE the value is written, and if it is ename:VK_FALSE the value is
not written. 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.
[[fragops-samplecount]]
== 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 <<queries-occlusion,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, sample mask, alpha to coverage, stencil, and depth
tests.