// Copyright 2015-2021 The Khronos Group, Inc.
//
// SPDX-License-Identifier: CC-BY-4.0

[[fragops]]
= Fragment Operations

Fragments produced by rasterization go through a number of operations to
determine whether or how values produced by fragment shading are written to
the framebuffer.

The following fragment operations adhere to <<primrast-order,rasterization
order>>, and are typically performed in this order:

ifdef::VK_EXT_discard_rectangles[]
  . <<fragops-discard-rectangles,Discard rectangles test>>
endif::VK_EXT_discard_rectangles[]
  . <<fragops-scissor,Scissor test>>
ifdef::VK_NV_scissor_exclusive[]
  . <<fragops-exclusive-scissor,Exclusive scissor test>>
endif::VK_NV_scissor_exclusive[]
  . <<fragops-samplemask,Sample mask test>>
  . <<shaders-fragment,Fragment shading>>
  . <<fragops-covg, Multisample coverage>>
  . <<fragops-dbt, Depth bounds test>>
  . <<fragops-stencil, Stencil test>>
  . <<fragops-depth, Depth test>>
ifdef::VK_NV_representative_fragment_test[]
  . <<fragops-rep-frag-test, Representative fragment test>>
endif::VK_NV_representative_fragment_test[]
  . <<fragops-samplecount, Sample counting>>
ifdef::VK_NV_fragment_coverage_to_color[]
  . <<fragops-coverage-to-color, Coverage to color>>
endif::VK_NV_fragment_coverage_to_color[]
  . <<fragops-coverage-reduction, Coverage reduction>>
ifdef::VK_NV_framebuffer_mixed_samples[]
  . <<fragops-coverage-modulation, Coverage modulation>>
endif::VK_NV_framebuffer_mixed_samples[]

The <<primsrast-multisampling-coverage-mask, coverage mask>> generated by
rasterization describes the initial coverage of each sample covered by the
fragment.
Fragment operations will update the coverage mask to add or subtract
coverage where appropriate.
If a fragment operation results in all bits of the coverage mask being `0`,
the fragment is discarded, and no further operations are performed.
Fragments can also be programmatically discarded in a fragment shader by
executing one of

ifdef::VK_KHR_shader_terminate_invocation[]
  * code:OpTerminateInvocation
endif::VK_KHR_shader_terminate_invocation[]
ifdef::VK_EXT_shader_demote_to_helper_invocation[]
  * code:OpDemoteToHelperInvocationEXT
endif::VK_EXT_shader_demote_to_helper_invocation[]
  * code:OpKill.

When one of the fragment operations in this chapter is described as
"`replacing`" a fragment shader output, that output is replaced
unconditionally, even if no fragment shader previously wrote to that output.

ifdef::VK_EXT_post_depth_coverage[]
If <<shaders-fragment-earlytest-postdepthcoverage, post-depth coverage>> is
enabled, the <<fragops-samplemask, sample mask test>> is instead performed
after the <<fragops-depth, depth test>>.
endif::VK_EXT_post_depth_coverage[]

If <<shaders-fragment-earlytest,early per-fragment operations>> are enabled,
<<shaders-fragment,fragment shading>> and <<fragops-covg, multisample
coverage>> operations are instead performed after <<fragops-samplecount,
sample counting>>.

Once all fragment operations have completed, fragment shader outputs for
covered color attachment samples pass through <<framebuffer, framebuffer
operations>>.


ifdef::VK_EXT_discard_rectangles[]
[[fragops-discard-rectangles]]
== Discard Rectangles Test

The discard rectangle test compares the framebuffer coordinates
[eq]#(x~f~,y~f~)# of each sample covered by a fragment against a set of
_discard rectangles_.

Each discard rectangle is defined by a slink:VkRect2D.
These values are either set by the
slink:VkPipelineDiscardRectangleStateCreateInfoEXT structure during pipeline
creation, or dynamically by the flink:vkCmdSetDiscardRectangleEXT command.

A given sample is considered inside a discard rectangle if the [eq]#x~f~# is
in the range [eq]#[slink:VkRect2D::offset.x, slink:VkRect2D::offset.x {plus}
slink:VkRect2D::extent.x)#, and [eq]#y~f~# is in the range
[eq]#[slink:VkRect2D::offset.y, slink:VkRect2D::offset.y {plus}
slink:VkRect2D::extent.y)#.
If the test is set to be inclusive, samples that are not inside any of the
discard rectangles will have their coverage set to `0`.
If the test is set to be exclusive, samples that are inside any of the
discard rectangles will have their coverage set to `0`.

If no discard rectangles are specified, the coverage mask is unmodified by
this operation.

[open,refpage='VkPipelineDiscardRectangleStateCreateInfoEXT',desc='Structure specifying discard rectangle',type='structs']
--
The sname:VkPipelineDiscardRectangleStateCreateInfoEXT structure is defined
as:

include::{generated}/api/structs/VkPipelineDiscardRectangleStateCreateInfoEXT.txt[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:flags is reserved for future use.
  * pname:discardRectangleMode is a elink:VkDiscardRectangleModeEXT value
    determining whether the discard rectangle test is inclusive or
    exclusive.
  * pname:discardRectangleCount is the number of discard rectangles to use.
  * pname:pDiscardRectangles is a pointer to an array of slink:VkRect2D
    structures defining discard rectangles.

If the ename:VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT dynamic state is enabled
for a pipeline, the pname:pDiscardRectangles member is ignored.

When this structure is included in the pname:pNext chain of
slink:VkGraphicsPipelineCreateInfo, it defines parameters of the discard
rectangle test.
If this structure is not included in the pname:pNext chain, it is equivalent
to specifying this structure with a pname:discardRectangleCount of `0`.

.Valid Usage
****
  * [[VUID-VkPipelineDiscardRectangleStateCreateInfoEXT-discardRectangleCount-00582]]
    pname:discardRectangleCount must: be less than or equal to
    sname:VkPhysicalDeviceDiscardRectanglePropertiesEXT::pname:maxDiscardRectangles
****

include::{generated}/validity/structs/VkPipelineDiscardRectangleStateCreateInfoEXT.txt[]
--

[open,refpage='VkPipelineDiscardRectangleStateCreateFlagsEXT',desc='Reserved for future use',type='flags']
--
include::{generated}/api/flags/VkPipelineDiscardRectangleStateCreateFlagsEXT.txt[]

tname:VkPipelineDiscardRectangleStateCreateFlagsEXT is a bitmask type for
setting a mask, but is currently reserved for future use.
--

[open,refpage='VkDiscardRectangleModeEXT',desc='Specify the discard rectangle mode',type='enums']
--
ename:VkDiscardRectangleModeEXT values are:

include::{generated}/api/enums/VkDiscardRectangleModeEXT.txt[]

  * ename:VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT specifies that the discard
    rectangle test is inclusive.
  * ename:VK_DISCARD_RECTANGLE_MODE_EXCLUSIVE_EXT specifies that the discard
    rectangle test is exclusive.
--

[open,refpage='vkCmdSetDiscardRectangleEXT',desc='Set discard rectangles dynamically',type='protos']
--
The discard rectangles can: be set dynamically with the command:

include::{generated}/api/protos/vkCmdSetDiscardRectangleEXT.txt[]

  * pname:commandBuffer is the command buffer into which the command will be
    recorded.
  * pname:firstDiscardRectangle is the index of the first discard rectangle
    whose state is updated by the command.
  * pname:discardRectangleCount is the number of discard rectangles whose
    state are updated by the command.
  * pname:pDiscardRectangles is a pointer to an array of slink:VkRect2D
    structures specifying discard rectangles.

The discard rectangle taken from element [eq]#i# of pname:pDiscardRectangles
replace the current state for the discard rectangle at index
[eq]#pname:firstDiscardRectangle {plus} i#, for [eq]#i# in [eq]#[0,
pname:discardRectangleCount)#.

This command sets the state for a given draw when the graphics pipeline is
created with ename:VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT set in
slink:VkPipelineDynamicStateCreateInfo::pname:pDynamicStates.

.Valid Usage
****
  * [[VUID-vkCmdSetDiscardRectangleEXT-firstDiscardRectangle-00585]]
    The sum of pname:firstDiscardRectangle and pname:discardRectangleCount
    must: be less than or equal to
    slink:VkPhysicalDeviceDiscardRectanglePropertiesEXT::pname:maxDiscardRectangles
  * [[VUID-vkCmdSetDiscardRectangleEXT-x-00587]]
    The pname:x and pname:y member of pname:offset in each slink:VkRect2D
    element of pname:pDiscardRectangles must: be greater than or equal to
    `0`
  * [[VUID-vkCmdSetDiscardRectangleEXT-offset-00588]]
    Evaluation of [eq]#(pname:offset.x {plus} pname:extent.width)# in each
    slink:VkRect2D element of pname:pDiscardRectangles must: not cause a
    signed integer addition overflow
  * [[VUID-vkCmdSetDiscardRectangleEXT-offset-00589]]
    Evaluation of [eq]#(pname:offset.y {plus} pname:extent.height)# in each
    slink:VkRect2D element of pname:pDiscardRectangles must: not cause a
    signed integer addition overflow
ifdef::VK_NV_inherited_viewport_scissor[]
  * [[VUID-vkCmdSetDiscardRectangleEXT-viewportScissor2D-04788]]
    If this command is recorded in a secondary command buffer with
    slink:VkCommandBufferInheritanceViewportScissorInfoNV::pname:viewportScissor2D
    enabled, then this function must: not be called.
endif::VK_NV_inherited_viewport_scissor[]
****

include::{generated}/validity/protos/vkCmdSetDiscardRectangleEXT.txt[]
--
endif::VK_EXT_discard_rectangles[]


[[fragops-scissor]]
== Scissor Test

The scissor test compares the framebuffer coordinates [eq]#(x~f~,y~f~)# of
each sample covered by a fragment against a _scissor rectangle_ at the index
equal to the fragment's <<interfaces-builtin-variables-viewportindex,
code:ViewportIndex>>.

Each scissor rectangle is defined by a slink:VkRect2D.
These values are either set by the slink:VkPipelineViewportStateCreateInfo
structure during pipeline creation, or dynamically by the
flink:vkCmdSetScissor command.

A given sample is considered inside a scissor rectangle if [eq]#x~f~# is in
the range [eq]#[slink:VkRect2D::offset.x, slink:VkRect2D::offset.x {plus}
slink:VkRect2D::extent.x)#, and [eq]#y~f~# is in the range
[eq]#[slink:VkRect2D::offset.y, slink:VkRect2D::offset.y {plus}
slink:VkRect2D::extent.y)#.
Samples with coordinates outside the scissor rectangle at the corresponding
code:ViewportIndex will have their coverage set to `0`.

ifdef::VK_QCOM_render_pass_transform[]
If a render pass transform is enabled, the (pname:offset.x and
pname:offset.y) and (pname:extent.width and pname:extent.height) values are
transformed as described in <<vertexpostproc-renderpass-transform, render
pass transform>> before participating in the scissor test.
endif::VK_QCOM_render_pass_transform[]

[open,refpage='vkCmdSetScissor',desc='Set the dynamic scissor rectangles on a command buffer',type='protos']
--
The scissor rectangles can: be set dynamically with the command:

include::{generated}/api/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 [eq]#i# of pname:pScissors replace
the current state for the scissor index [eq]#pname:firstScissor {plus} i#,
for [eq]#i# in [eq]#[0, pname:scissorCount)#.

This command sets the state for a given draw when the graphics pipeline is
created with ename:VK_DYNAMIC_STATE_SCISSOR set in
slink:VkPipelineDynamicStateCreateInfo::pname:pDynamicStates.

.Valid Usage
****
  * [[VUID-vkCmdSetScissor-firstScissor-00592]]
    The sum of pname:firstScissor and pname:scissorCount must: be between
    `1` and sname:VkPhysicalDeviceLimits::pname:maxViewports, inclusive
  * [[VUID-vkCmdSetScissor-firstScissor-00593]]
    If the <<features-multiViewport,multiple viewports>> feature is not
    enabled, pname:firstScissor must: be `0`
  * [[VUID-vkCmdSetScissor-scissorCount-00594]]
    If the <<features-multiViewport,multiple viewports>> feature is not
    enabled, pname:scissorCount must: be `1`
  * [[VUID-vkCmdSetScissor-x-00595]]
    The pname:x and pname:y members of pname:offset member of any element of
    pname:pScissors must: be greater than or equal to `0`
  * [[VUID-vkCmdSetScissor-offset-00596]]
    Evaluation of [eq]#(pname:offset.x {plus} pname:extent.width)# must: not
    cause a signed integer addition overflow for any element of
    pname:pScissors
  * [[VUID-vkCmdSetScissor-offset-00597]]
    Evaluation of [eq]#(pname:offset.y {plus} pname:extent.height)# must:
    not cause a signed integer addition overflow for any element of
    pname:pScissors
ifdef::VK_NV_inherited_viewport_scissor[]
  * [[VUID-vkCmdSetScissor-viewportScissor2D-04789]]
    If this command is recorded in a secondary command buffer with
    slink:VkCommandBufferInheritanceViewportScissorInfoNV::pname:viewportScissor2D
    enabled, then this function must: not be called.
endif::VK_NV_inherited_viewport_scissor[]
****

include::{generated}/validity/protos/vkCmdSetScissor.txt[]
--


ifdef::VK_NV_scissor_exclusive[]
[[fragops-exclusive-scissor]]
== Exclusive Scissor Test

The exclusive scissor test compares the framebuffer coordinates
[eq]#(x~f~,y~f~)# of each sample covered by a fragment against an _exclusive
scissor rectangle_ at the index equal to the fragment's
<<interfaces-builtin-variables-viewportindex, code:ViewportIndex>>.

Each exclusive scissor rectangle is defined by a slink:VkRect2D.
These values are either set by the
slink:VkPipelineViewportExclusiveScissorStateCreateInfoNV structure during
pipeline creation, or dynamically by the flink:vkCmdSetExclusiveScissorNV
command.

A given sample is considered inside an exclusive scissor rectangle if
[eq]#x~f~# is in the range [eq]#[slink:VkRect2D::offset.x,
slink:VkRect2D::offset.x {plus} slink:VkRect2D::extent.x)#, and [eq]#y~f~#
is in the range [eq]#[slink:VkRect2D::offset.y, slink:VkRect2D::offset.y
{plus} slink:VkRect2D::extent.y)#.
Samples with coordinates inside the exclusive scissor rectangle at the
corresponding code:ViewportIndex will have their coverage set to `0`.

If no exclusive scissor rectangles are specified, the coverage mask is
unmodified by this operation.

[open,refpage='VkPipelineViewportExclusiveScissorStateCreateInfoNV',desc='Structure specifying parameters controlling exclusive scissor testing',type='structs']
--
The sname:VkPipelineViewportExclusiveScissorStateCreateInfoNV structure is
defined as:

include::{generated}/api/structs/VkPipelineViewportExclusiveScissorStateCreateInfoNV.txt[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:exclusiveScissorCount is the number of exclusive scissor
    rectangles.
  * pname:pExclusiveScissors is a pointer to an array of slink:VkRect2D
    structures defining exclusive scissor rectangles.

If the ename:VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV dynamic state is enabled
for a pipeline, the pname:pExclusiveScissors member is ignored.

When this structure is included in the pname:pNext chain of
slink:VkGraphicsPipelineCreateInfo, it defines parameters of the exclusive
scissor test.
If this structure is not included in the pname:pNext chain, it is equivalent
to specifying this structure with a pname:exclusiveScissorCount of `0`.

.Valid Usage
****
  * [[VUID-VkPipelineViewportExclusiveScissorStateCreateInfoNV-exclusiveScissorCount-02027]]
    If the <<features-multiViewport,multiple viewports>> feature is not
    enabled, pname:exclusiveScissorCount must: be `0` or `1`
  * [[VUID-VkPipelineViewportExclusiveScissorStateCreateInfoNV-exclusiveScissorCount-02028]]
    pname:exclusiveScissorCount must: be less than or equal to
    sname:VkPhysicalDeviceLimits::pname:maxViewports
  * [[VUID-VkPipelineViewportExclusiveScissorStateCreateInfoNV-exclusiveScissorCount-02029]]
    pname:exclusiveScissorCount must: be `0` or greater than or equal to the
    pname:viewportCount member of slink:VkPipelineViewportStateCreateInfo

****
include::{generated}/validity/structs/VkPipelineViewportExclusiveScissorStateCreateInfoNV.txt[]
--

[open,refpage='vkCmdSetExclusiveScissorNV',desc='Set the dynamic exclusive scissor rectangles on a command buffer',type='protos']
--
The exclusive scissor rectangles can: be set dynamically with the command:

include::{generated}/api/protos/vkCmdSetExclusiveScissorNV.txt[]

  * pname:commandBuffer is the command buffer into which the command will be
    recorded.
  * pname:firstExclusiveScissor is the index of the first exclusive scissor
    rectangle whose state is updated by the command.
  * pname:exclusiveScissorCount is the number of exclusive scissor
    rectangles updated by the command.
  * pname:pExclusiveScissors is a pointer to an array of slink:VkRect2D
    structures defining exclusive scissor rectangles.

The scissor rectangles taken from element [eq]#i# of
pname:pExclusiveScissors replace the current state for the scissor index
[eq]#pname:firstExclusiveScissor {plus} i#, for [eq]#i# in [eq]#[0,
pname:exclusiveScissorCount)#.

This command sets the state for a given draw when the graphics pipeline is
created with ename:VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV set in
slink:VkPipelineDynamicStateCreateInfo::pname:pDynamicStates.

.Valid Usage
****
  * [[VUID-vkCmdSetExclusiveScissorNV-None-02031]]
    The <<features-exclusiveScissor,exclusive scissor>> feature must: be
    enabled
  * [[VUID-vkCmdSetExclusiveScissorNV-firstExclusiveScissor-02034]]
    The sum of pname:firstExclusiveScissor and pname:exclusiveScissorCount
    must: be between `1` and
    sname:VkPhysicalDeviceLimits::pname:maxViewports, inclusive
  * [[VUID-vkCmdSetExclusiveScissorNV-firstExclusiveScissor-02035]]
    If the <<features-multiViewport,multiple viewports>> feature is not
    enabled, pname:firstExclusiveScissor must: be `0`
  * [[VUID-vkCmdSetExclusiveScissorNV-exclusiveScissorCount-02036]]
    If the <<features-multiViewport,multiple viewports>> feature is not
    enabled, pname:exclusiveScissorCount must: be `1`
  * [[VUID-vkCmdSetExclusiveScissorNV-x-02037]]
    The pname:x and pname:y members of pname:offset in each member of
    pname:pExclusiveScissors must: be greater than or equal to `0`
  * [[VUID-vkCmdSetExclusiveScissorNV-offset-02038]]
    Evaluation of [eq]#(pname:offset.x {plus} pname:extent.width)# for each
    member of pname:pExclusiveScissors must: not cause a signed integer
    addition overflow
  * [[VUID-vkCmdSetExclusiveScissorNV-offset-02039]]
    Evaluation of [eq]#(pname:offset.y {plus} pname:extent.height)# for each
    member of pname:pExclusiveScissors must: not cause a signed integer
    addition overflow
****

include::{generated}/validity/protos/vkCmdSetExclusiveScissorNV.txt[]
--
endif::VK_NV_scissor_exclusive[]


[[fragops-samplemask]]
== Sample Mask Test

The sample mask test compares the <<primsrast-multisampling-coverage-mask,
coverage mask>> for a fragment with the _sample mask_ defined by
slink:VkPipelineMultisampleStateCreateInfo::pname:pSampleMask.

Each bit of the coverage mask is associated with a sample index as described
in the <<primsrast-multisampling-coverage-mask, rasterization chapter>>.
If the bit in slink:VkPipelineMultisampleStateCreateInfo::pname:pSampleMask
which is associated with that same sample index is set to `0`, the coverage
mask bit is set to `0`.


[[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,
ifdef::VK_NV_sample_mask_override_coverage[]
but not code:OverrideCoverageNV,
endif::VK_NV_sample_mask_override_coverage[]
the coverage mask is code:ANDed with the bits of the code:SampleMask
built-in to generate a new coverage mask.
ifdef::VK_NV_sample_mask_override_coverage[]
If the code:SampleMask built-in is also decorated with
code:OverrideCoverageNV, the coverage mask is replaced with the mask bits
set in the shader.
endif::VK_NV_sample_mask_override_coverage[]
If <<primsrast-sampleshading,sample shading>> is enabled, bits written to
code:SampleMask corresponding to samples that are not being shaded by the
fragment shader invocation are ignored.
If no fragment shader is active, or if the active fragment shader does not
include code:SampleMask in its interface, the coverage mask is not modified.

Next, the fragment alpha value and coverage mask are modified based on the
ifdef::VK_EXT_line_rasterization[]
line coverage factor if the pname:lineRasterizationMode member of the
slink:VkPipelineRasterizationStateCreateInfo structure is
ename:VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT, and the
endif::VK_EXT_line_rasterization[]
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.

ifdef::VK_EXT_line_rasterization[]
If the pname:lineRasterizationMode member of the
slink:VkPipelineRasterizationStateCreateInfo structure is
ename:VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT and the fragment
came from a line segment, then the alpha value is replaced by multiplying it
by the coverage factor for the fragment computed during
<<primsrast-lines-smooth,smooth line rasterization>>.
endif::VK_EXT_line_rasterization[]

If pname:alphaToCoverageEnable is enabled, a temporary coverage mask is
generated where each bit is determined by the fragment's alpha value, which
is ANDed with the fragment coverage mask.

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 [eq]#[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]
.Note
====
Using different algorithms at different framebuffer coordinates may: help to
avoid artifacts caused by regular coverage sample locations.
====

Finally, 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.

[open,refpage='VkPipelineDepthStencilStateCreateInfo',desc='Structure specifying parameters of a newly created pipeline depth stencil state',type='structs']
--
The sname:VkPipelineDepthStencilStateCreateInfo structure is defined as:

include::{generated}/api/structs/VkPipelineDepthStencilStateCreateInfo.txt[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    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 when pname:depthTestEnable is ename:VK_TRUE.
    Depth writes are always disabled when pname:depthTestEnable is
    ename:VK_FALSE.
  * 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 is the minimum depth bound used in the
    <<fragops-dbt, depth bounds test>>.
  * pname:maxDepthBounds is the maximum depth bound used in the
    <<fragops-dbt, depth bounds test>>.

.Valid Usage
****
  * [[VUID-VkPipelineDepthStencilStateCreateInfo-depthBoundsTestEnable-00598]]
    If the <<features-depthBounds,depth bounds testing>> feature is not
    enabled, pname:depthBoundsTestEnable must: be ename:VK_FALSE
ifdef::VK_KHR_portability_subset[]
  * [[VUID-VkPipelineDepthStencilStateCreateInfo-separateStencilMaskRef-04453]]
    If the `<<VK_KHR_portability_subset>>` extension is enabled, and
    slink:VkPhysicalDevicePortabilitySubsetFeaturesKHR::pname:separateStencilMaskRef
    is ename:VK_FALSE, and the value of
    slink:VkPipelineDepthStencilStateCreateInfo::pname:stencilTestEnable is
    ename:VK_TRUE, and the value of
    slink:VkPipelineRasterizationStateCreateInfo::pname:cullMode is
    ename:VK_CULL_MODE_NONE, the value of pname:reference in each of the
    slink:VkStencilOpState structs in pname:front and pname:back must: be
    the same.
endif::VK_KHR_portability_subset[]
****

include::{generated}/validity/structs/VkPipelineDepthStencilStateCreateInfo.txt[]
--

[open,refpage='VkPipelineDepthStencilStateCreateFlags',desc='Reserved for future use',type='flags']
--
include::{generated}/api/flags/VkPipelineDepthStencilStateCreateFlags.txt[]

tname:VkPipelineDepthStencilStateCreateFlags is a bitmask type for setting a
mask, but is currently reserved for future use.
--


[[fragops-dbt]]
== Depth Bounds Test

The depth bounds test compares the depth value [eq]#z~a~# in the
depth/stencil attachment at each sample's framebuffer coordinates
[eq]#(x~f~,y~f~)# and <<primsrast-multisampling-coverage-mask, sample
index>> [eq]#i# against a set of _depth bounds_.

The depth bounds are determined by two floating point values defining a
minimum (pname:minDepthBounds) and maximum (pname:maxDepthBounds) depth
value.
These values are either set by the
slink:VkPipelineDepthStencilStateCreateInfo structure during pipeline
creation, or dynamically by
ifdef::VK_EXT_extended_dynamic_state[]
flink:vkCmdSetDepthBoundsTestEnableEXT and
endif::VK_EXT_extended_dynamic_state[]
flink:vkCmdSetDepthBounds.

A given sample is considered within the depth bounds if [eq]#z~a~# is in the
range [eq]#[pname:minDepthBounds,pname:maxDepthBounds]#.
Samples with depth attachment values outside of the depth bounds will have
their coverage set to `0`.

If the depth bounds test is disabled, or if there is no depth attachment,
the coverage mask is unmodified by this operation.

ifdef::VK_EXT_extended_dynamic_state[]

[open,refpage='vkCmdSetDepthBoundsTestEnableEXT',desc='Set the depth bounds test enable for a command buffer',type='protos']
--
To dynamically enable or disable the depth bounds test:

include::{generated}/api/protos/vkCmdSetDepthBoundsTestEnableEXT.txt[]

  * pname:commandBuffer is the command buffer into which the command will be
    recorded.
  * pname:depthBoundsTestEnable specifies if the depth bounds test is
    enabled.

This command sets the state for a given draw when the graphics pipeline is
created with ename:VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT set in
slink:VkPipelineDynamicStateCreateInfo::pname:pDynamicStates.

.Valid Usage
****
  * [[VUID-vkCmdSetDepthBoundsTestEnableEXT-None-03349]]
    The <<features-extendedDynamicState, extendedDynamicState>> feature
    must: be enabled
****

include::{generated}/validity/protos/vkCmdSetDepthBoundsTestEnableEXT.txt[]
--

endif::VK_EXT_extended_dynamic_state[]

[open,refpage='vkCmdSetDepthBounds',desc='Set the depth bounds test values for a command buffer',type='protos']
--
To dynamically set the depth bounds range values call:

include::{generated}/api/protos/vkCmdSetDepthBounds.txt[]

  * pname:commandBuffer is the command buffer into which the command will be
    recorded.
  * pname:minDepthBounds is the minimum depth bound.
  * pname:maxDepthBounds is the maximum depth bound.

This command sets the state for a given draw when the graphics pipeline is
created with ename:VK_DYNAMIC_STATE_DEPTH_BOUNDS set in
slink:VkPipelineDynamicStateCreateInfo::pname:pDynamicStates.

.Valid Usage
****
ifdef::VK_EXT_depth_range_unrestricted[]
  * [[VUID-vkCmdSetDepthBounds-minDepthBounds-00600]]
    Unless the `<<VK_EXT_depth_range_unrestricted>>` extension is enabled
    pname:minDepthBounds must: be between `0.0` and `1.0`, inclusive
endif::VK_EXT_depth_range_unrestricted[]
ifndef::VK_EXT_depth_range_unrestricted[]
  * [[VUID-vkCmdSetDepthBounds-minDepthBounds-02508]]
    pname:minDepthBounds must: be between `0.0` and `1.0`, inclusive
endif::VK_EXT_depth_range_unrestricted[]
ifdef::VK_EXT_depth_range_unrestricted[]
  * [[VUID-vkCmdSetDepthBounds-maxDepthBounds-00601]]
    Unless the `<<VK_EXT_depth_range_unrestricted>>` extension is enabled
    pname:maxDepthBounds must: be between `0.0` and `1.0`, inclusive
endif::VK_EXT_depth_range_unrestricted[]
ifndef::VK_EXT_depth_range_unrestricted[]
  * [[VUID-vkCmdSetDepthBounds-maxDepthBounds-02509]]
    pname:maxDepthBounds must: be between `0.0` and `1.0`, inclusive
endif::VK_EXT_depth_range_unrestricted[]
****

include::{generated}/validity/protos/vkCmdSetDepthBounds.txt[]
--


[[fragops-stencil]]
== Stencil Test

The stencil test compares the stencil attachment value [eq]#s~a~# in the
depth/stencil attachment at each sample's framebuffer coordinates
[eq]#(x~f~,y~f~)# and <<primsrast-multisampling-coverage-mask, sample
index>> [eq]#i# against a _stencil reference value_.

ifdef::VK_EXT_fragment_density_map[]
If the render pass has a fragment density map attachment and the fragment
covers multiple pixels, there is an implementation-dependent association of
coverage samples to stencil attachment samples within the fragment.
However, if all samples in the fragment are covered, and the stencil
attachment value is updated as a result of this test, all stencil attachment
samples will be updated.
endif::VK_EXT_fragment_density_map[]

If the stencil test is not enabled, as specified by
ifdef::VK_EXT_extended_dynamic_state[]
flink:vkCmdSetStencilTestEnableEXT or
endif::VK_EXT_extended_dynamic_state[]
slink:VkPipelineDepthStencilStateCreateInfo::pname:stencilTestEnable, or if
there is no stencil attachment, the coverage mask is unmodified by this
operation.

The stencil test is controlled by one of two sets of stencil-related state,
the front stencil state and the back stencil state.
Stencil tests and writes use the back stencil state when processing
fragments generated by <<primsrast-polygons-basic,back-facing>>
<<primsrast-polygons,polygons>>, and the front stencil state when processing
fragments generated by <<primsrast-polygons-basic,front-facing polygons>> or
any other primitives.

The comparison performed is based on the elink:VkCompareOp, compare mask
[eq]#s~c~# , and stencil reference value [eq]#s~r~# of the relevant state
set.
The compare mask and stencil reference value are set by either the
slink:VkPipelineDepthStencilStateCreateInfo structure during pipeline
creation, or by the flink:vkCmdSetStencilCompareMask and
flink:vkCmdSetStencilReference commands respectively.
The compare operation is set by slink:VkStencilOpState::pname:compareOp
during pipeline creation.

The stencil reference and attachment values [eq]#s~r~# and [eq]#s~a~# are
each independently combined with the compare mask [eq]#s~c~# using a logical
code:AND operation to create masked reference and attachment values
[eq]#s'~r~# and [eq]#s'~a~#.
[eq]#s'~r~# and [eq]#s'~a~# are used as [eq]#A# and [eq]#B#, respectively,
in the operation specified by elink:VkCompareOp.

If the comparison evaluates to false, the coverage for the sample is set to
`0`.

A new stencil value [eq]#s~g~# is generated according to a stencil operation
defined by elink:VkStencilOp parameters set by
ifdef::VK_EXT_extended_dynamic_state[]
flink:vkCmdSetStencilOpEXT or
endif::VK_EXT_extended_dynamic_state[]
slink:VkPipelineDepthStencilStateCreateInfo.
If the stencil test fails, pname:failOp defines the stencil operation used.
If the stencil test passes however, the stencil op used is based on the
<<fragops-depth, depth test>> - if it passes,
slink:VkPipelineDepthStencilStateCreateInfo::pname:passOp is used, otherwise
slink:VkPipelineDepthStencilStateCreateInfo::pname:depthFailOp is used.

The stencil attachment value [eq]#s~a~# is then updated with the generated
stencil value [eq]#s~g~# according to the write mask [eq]#s~w~# defined by
slink:VkPipelineDepthStencilStateCreateInfo::pname:writeMask as:

  {empty}:: [eq]#s~a~ = (s~a~ & ¬s~w~) | (s~g~ & s~w~)#

ifdef::VK_EXT_extended_dynamic_state[]

[open,refpage='vkCmdSetStencilTestEnableEXT',desc='Set the stencil test enable for the command buffer',type='protos']
--
To dynamically enable or disable the stencil test, call:

include::{generated}/api/protos/vkCmdSetStencilTestEnableEXT.txt[]

  * pname:commandBuffer is the command buffer into which the command will be
    recorded.
  * pname:stencilTestEnable specifies if the stencil test is enabled.

This command sets the state for a given draw when the graphics pipeline is
created with ename:VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT set in
slink:VkPipelineDynamicStateCreateInfo::pname:pDynamicStates.

.Valid Usage
****
  * [[VUID-vkCmdSetStencilTestEnableEXT-None-03350]]
    The <<features-extendedDynamicState, extendedDynamicState>> feature
    must: be enabled
****

include::{generated}/validity/protos/vkCmdSetStencilTestEnableEXT.txt[]
--

[open,refpage='vkCmdSetStencilOpEXT',desc='Set the stencil operation for the command buffer',type='protos']
--
To dynamically set the stencil operations, call:

include::{generated}/api/protos/vkCmdSetStencilOpEXT.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 stencil operation.
  * pname:failOp is a elink:VkStencilOp value specifying the action
    performed on samples that fail the stencil test.
  * pname:passOp is a elink:VkStencilOp value specifying the action
    performed on samples that pass both the depth and stencil tests.
  * pname:depthFailOp is a elink:VkStencilOp value specifying the action
    performed on samples that pass the stencil test and fail the depth test.
  * pname:compareOp is a elink:VkCompareOp value specifying the comparison
    operator used in the stencil test.

This command sets the state for a given draw when the graphics pipeline is
created with ename:VK_DYNAMIC_STATE_STENCIL_OP_EXT set in
slink:VkPipelineDynamicStateCreateInfo::pname:pDynamicStates.

.Valid Usage
****
  * [[VUID-vkCmdSetStencilOpEXT-None-03351]]
    The <<features-extendedDynamicState, extendedDynamicState>> feature
    must: be enabled
****

include::{generated}/validity/protos/vkCmdSetStencilOpEXT.txt[]
--

endif::VK_EXT_extended_dynamic_state[]

[open,refpage='VkStencilOpState',desc='Structure specifying stencil operation state',type='structs']
--
The sname:VkStencilOpState structure is defined as:

include::{generated}/api/structs/VkStencilOpState.txt[]

  * pname:failOp is a elink:VkStencilOp value specifying the action
    performed on samples that fail the stencil test.
  * pname:passOp is a elink:VkStencilOp value specifying the action
    performed on samples that pass both the depth and stencil tests.
  * pname:depthFailOp is a elink:VkStencilOp value specifying the action
    performed on samples that pass the stencil test and fail the depth test.
  * pname:compareOp is a elink:VkCompareOp value specifying 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::{generated}/validity/structs/VkStencilOpState.txt[]
--

[open,refpage='vkCmdSetStencilCompareMask',desc='Set the stencil compare mask dynamic state',type='protos']
--
To dynamically set the stencil compare mask call:

include::{generated}/api/protos/vkCmdSetStencilCompareMask.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 compare mask.
  * pname:compareMask is the new value to use as the stencil compare mask.

This command sets the state for a given draw when the graphics pipeline is
created with ename:VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK set in
slink:VkPipelineDynamicStateCreateInfo::pname:pDynamicStates.

include::{generated}/validity/protos/vkCmdSetStencilCompareMask.txt[]
--

[open,refpage='VkStencilFaceFlagBits',desc='Bitmask specifying sets of stencil state for which to update the compare mask',type='enums']
--
ename:VkStencilFaceFlagBits values are:

include::{generated}/api/enums/VkStencilFaceFlagBits.txt[]

  * ename:VK_STENCIL_FACE_FRONT_BIT specifies that only the front set of
    stencil state is updated.
  * ename:VK_STENCIL_FACE_BACK_BIT specifies that only the back set of
    stencil state is updated.
  * ename:VK_STENCIL_FACE_FRONT_AND_BACK is the combination of
    ename:VK_STENCIL_FACE_FRONT_BIT and ename:VK_STENCIL_FACE_BACK_BIT, and
    specifies that both sets of stencil state are updated.

--

[open,refpage='VkStencilFaceFlags',desc='Bitmask of VkStencilFaceFlagBits',type='flags']
--
include::{generated}/api/flags/VkStencilFaceFlags.txt[]

tname:VkStencilFaceFlags is a bitmask type for setting a mask of zero or
more elink:VkStencilFaceFlagBits.
--

[open,refpage='vkCmdSetStencilWriteMask',desc='Set the stencil write mask dynamic state',type='protos']
--
To dynamically set the stencil write mask call:

include::{generated}/api/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.

This command sets the state for a given draw when the graphics pipeline is
created with ename:VK_DYNAMIC_STATE_STENCIL_WRITE_MASK set in
slink:VkPipelineDynamicStateCreateInfo::pname:pDynamicStates.

include::{generated}/validity/protos/vkCmdSetStencilWriteMask.txt[]
--

[open,refpage='vkCmdSetStencilReference',desc='Set the stencil reference dynamic state',type='protos']
--
To dynamically set the stencil reference value call:

include::{generated}/api/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.

This command sets the state for a given draw when the graphics pipeline is
created with ename:VK_DYNAMIC_STATE_STENCIL_REFERENCE set in
slink:VkPipelineDynamicStateCreateInfo::pname:pDynamicStates.

include::{generated}/validity/protos/vkCmdSetStencilReference.txt[]
--

[open,refpage='VkCompareOp',desc='Stencil comparison function',type='enums']
--
Possible values of slink:VkStencilOpState::pname:compareOp, specifying the
stencil comparison function, are:

include::{generated}/api/enums/VkCompareOp.txt[]

  * ename:VK_COMPARE_OP_NEVER specifies that the test evaluates to false.
  * ename:VK_COMPARE_OP_LESS specifies that the test evaluates [eq]#A < B#.
  * ename:VK_COMPARE_OP_EQUAL specifies that the test evaluates [eq]#A = B#.
  * ename:VK_COMPARE_OP_LESS_OR_EQUAL specifies that the test evaluates
    [eq]#A {leq} B#.
  * ename:VK_COMPARE_OP_GREATER specifies that the test evaluates [eq]#A >
    B#.
  * ename:VK_COMPARE_OP_NOT_EQUAL specifies that the test evaluates [eq]#A
    {neq} B#.
  * ename:VK_COMPARE_OP_GREATER_OR_EQUAL specifies that the test evaluates
    [eq]#A {geq} B#.
  * ename:VK_COMPARE_OP_ALWAYS specifies that the test evaluates to true.
--

[open,refpage='VkStencilOp',desc='Stencil comparison function',type='enums']
--
Possible values of the pname:failOp, pname:passOp, and pname:depthFailOp
members of slink:VkStencilOpState, specifying what happens to the stored
stencil value if this or certain subsequent tests fail or pass, are:

include::{generated}/api/enums/VkStencilOp.txt[]

  * 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.
--


[[fragops-depth]]
== Depth Test

The depth test compares the depth value [eq]#z~a~# in the depth/stencil
attachment at each sample's framebuffer coordinates [eq]#(x~f~,y~f~)# and
<<primsrast-multisampling-coverage-mask, sample index>> [eq]#i# against the
sample's depth value [eq]#z~f~#.
If there is no depth attachment then the depth test is skipped.

ifdef::VK_EXT_fragment_density_map[]
If the render pass has a fragment density map attachment and the fragment
covers multiple pixels, there is an implementation-dependent association of
rasterization samples to depth attachment samples within the fragment.
However, if all samples in the fragment are covered, and the depth
attachment value is updated as a result of this test, all depth attachment
samples will be updated.
endif::VK_EXT_fragment_density_map[]

The depth test occurs in three stages, as detailed in the following
sections.

=== Depth Clamping and Range Adjustment

If slink:VkPipelineRasterizationStateCreateInfo::pname:depthClampEnable is
enabled, before the sample's [eq]#z~f~# is compared to [eq]#z~a~#,
[eq]#z~f~# is clamped to [eq]#[min(n,f),max(n,f)]#, where [eq]#n# and
[eq]#f# are the pname:minDepth and pname:maxDepth depth range values of the
viewport used by this fragment, respectively.

If depth clamping is not enabled and [eq]#z~f~# is not in the range [eq]#[0,
1]#
ifdef::VK_EXT_depth_range_unrestricted[]
and either VK_EXT_depth_range_unrestricted is not enabled, or the depth
attachment has a fixed-point format,
endif::VK_EXT_depth_range_unrestricted[]
then [eq]#z~f~# is undefined: following this step.


=== Depth Comparison

If the depth test is not enabled, as specified by
ifdef::VK_EXT_extended_dynamic_state[]
flink:vkCmdSetDepthTestEnableEXT or
endif::VK_EXT_extended_dynamic_state[]
slink:VkPipelineDepthStencilStateCreateInfo::pname:depthTestEnable, then
this step is skipped.

The comparison performed is based on the elink:VkCompareOp, set by
ifdef::VK_EXT_extended_dynamic_state[]
flink:vkCmdSetDepthCompareOpEXT or
endif::VK_EXT_extended_dynamic_state[]
slink:VkPipelineDepthStencilStateCreateInfo::pname:depthCompareOp during
pipeline creation.
[eq]#z~f~# and [eq]#z~a~# are used as [eq]#A# and [eq]#B#, respectively, in
the operation specified by the elink:VkCompareOp.

If the comparison evaluates to false, the coverage for the sample is set to
`0`.


[[fragops-depth-write]]
=== Depth Buffer Writes

If depth writes are enabled, as specified by
ifdef::VK_EXT_extended_dynamic_state[]
flink:vkCmdSetDepthWriteEnableEXT or
endif::VK_EXT_extended_dynamic_state[]
slink:VkPipelineDepthStencilStateCreateInfo::pname:depthWriteEnable, and the
comparison evaluated to true, the depth attachment value [eq]#z~a~# is set
to the sample's depth value [eq]#z~f~#.


ifdef::VK_EXT_extended_dynamic_state[]

[open,refpage='vkCmdSetDepthTestEnableEXT',desc='Set the depth test enable for a command buffer',type='protos']
--
To dynamically enable or disable the depth test, call:

include::{generated}/api/protos/vkCmdSetDepthTestEnableEXT.txt[]

  * pname:commandBuffer is the command buffer into which the command will be
    recorded.
  * pname:depthTestEnable specifies if the depth test is enabled.

This command sets the state for a given draw when the graphics pipeline is
created with ename:VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT set in
slink:VkPipelineDynamicStateCreateInfo::pname:pDynamicStates.

.Valid Usage
****
  * [[VUID-vkCmdSetDepthTestEnableEXT-None-03352]]
    The <<features-extendedDynamicState, extendedDynamicState>> feature
    must: be enabled
****

include::{generated}/validity/protos/vkCmdSetDepthTestEnableEXT.txt[]
--

[open,refpage='vkCmdSetDepthCompareOpEXT',desc='Set the depth comparison operator for the command buffer',type='protos']
--
To dynamically set the depth compare operations, call:

include::{generated}/api/protos/vkCmdSetDepthCompareOpEXT.txt[]

  * pname:commandBuffer is the command buffer into which the command will be
    recorded.
  * pname:depthCompareOp specifies the depth comparison operator.

This command sets the state for a given draw when the graphics pipeline is
created with ename:VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT set in
slink:VkPipelineDynamicStateCreateInfo::pname:pDynamicStates.

.Valid Usage
****
  * [[VUID-vkCmdSetDepthCompareOpEXT-None-03353]]
    The <<features-extendedDynamicState, extendedDynamicState>> feature
    must: be enabled
****

include::{generated}/validity/protos/vkCmdSetDepthCompareOpEXT.txt[]
--

[open,refpage='vkCmdSetDepthWriteEnableEXT',desc='Set the depth write enable for the command buffer',type='protos']
--
To dynamically enable or disable depth writes, call:

include::{generated}/api/protos/vkCmdSetDepthWriteEnableEXT.txt[]

  * pname:commandBuffer is the command buffer into which the command will be
    recorded.
  * pname:depthWriteEnable specifies if depth writes are enabled.

This command sets the state for a given draw when the graphics pipeline is
created with ename:VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT set in
slink:VkPipelineDynamicStateCreateInfo::pname:pDynamicStates.

.Valid Usage
****
  * [[VUID-vkCmdSetDepthWriteEnableEXT-None-03354]]
    The <<features-extendedDynamicState, extendedDynamicState>> feature
    must: be enabled
****

include::{generated}/validity/protos/vkCmdSetDepthWriteEnableEXT.txt[]
--

endif::VK_EXT_extended_dynamic_state[]


ifdef::VK_NV_representative_fragment_test[]
[[fragops-rep-frag-test]]
== 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.

[open,refpage='VkPipelineRepresentativeFragmentTestStateCreateInfoNV',desc='Structure specifying representative fragment test',type='structs']
--
If the pname:pNext chain of slink:VkGraphicsPipelineCreateInfo includes a
sname:VkPipelineRepresentativeFragmentTestStateCreateInfoNV structure, then
that structure includes parameters that control the representative fragment
test.

The sname:VkPipelineRepresentativeFragmentTestStateCreateInfoNV structure is
defined as:

include::{generated}/api/structs/VkPipelineRepresentativeFragmentTestStateCreateInfoNV.txt[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:representativeFragmentTestEnable controls whether the
    representative fragment test is enabled.

If this structure is not included in the pname:pNext chain,
pname:representativeFragmentTestEnable is considered to be ename:VK_FALSE,
and the representative fragment test is disabled.

If <<shaders-fragment-earlytest, early fragment tests>> are not enabled in
the active fragment shader, the representative fragment shader test has no
effect, even if enabled.

include::{generated}/validity/structs/VkPipelineRepresentativeFragmentTestStateCreateInfoNV.txt[]
--

endif::VK_NV_representative_fragment_test[]


[[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,
ifdef::VK_NV_scissor_exclusive[]
exclusive scissor,
endif::VK_NV_scissor_exclusive[]
sample mask, alpha to coverage, stencil, and depth tests.


ifdef::VK_NV_fragment_coverage_to_color[]
[[fragops-coverage-to-color]]
== Fragment Coverage To Color

[open,refpage='VkPipelineCoverageToColorStateCreateInfoNV',desc='Structure specifying whether fragment coverage replaces a color',type='structs']
--
The sname:VkPipelineCoverageToColorStateCreateInfoNV structure is defined
as:

include::{generated}/api/structs/VkPipelineCoverageToColorStateCreateInfoNV.txt[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:flags is reserved for future use.
  * pname:coverageToColorEnable controls whether the fragment coverage value
    replaces a fragment color output.
  * pname:coverageToColorLocation controls which fragment shader color
    output value is replaced.

If the pname:pNext chain of slink:VkPipelineMultisampleStateCreateInfo
includes a sname:VkPipelineCoverageToColorStateCreateInfoNV structure, then
that structure controls whether the fragment coverage is substituted for a
fragment color output and, if so, which output is replaced.

If pname:coverageToColorEnable is ename:VK_TRUE, the
<<primsrast-multisampling-coverage-mask, coverage mask>> replaces the first
component of the color value corresponding to the fragment shader output
location with code:Location equal to pname:coverageToColorLocation and
code:Index equal to zero.
If the color attachment format has fewer bits than the coverage mask, the
low bits of the sample coverage mask are taken without any clamping.
If the color attachment format has more bits than the coverage mask, the
high bits of the sample coverage mask are filled with zeros.

If pname:coverageToColorEnable is ename:VK_FALSE, these operations are
skipped.
If this structure is not included in the pname:pNext chain, it is as if
pname:coverageToColorEnable is ename:VK_FALSE.

.Valid Usage
****
  * [[VUID-VkPipelineCoverageToColorStateCreateInfoNV-coverageToColorEnable-01404]]
    If pname:coverageToColorEnable is ename:VK_TRUE, then the render pass
    subpass indicated by
    slink:VkGraphicsPipelineCreateInfo::pname:renderPass and
    slink:VkGraphicsPipelineCreateInfo::pname:subpass must: have a color
    attachment at the location selected by pname:coverageToColorLocation,
    with a elink:VkFormat of ename:VK_FORMAT_R8_UINT,
    ename:VK_FORMAT_R8_SINT, ename:VK_FORMAT_R16_UINT,
    ename:VK_FORMAT_R16_SINT, ename:VK_FORMAT_R32_UINT, or
    ename:VK_FORMAT_R32_SINT
****

include::{generated}/validity/structs/VkPipelineCoverageToColorStateCreateInfoNV.txt[]
--

[open,refpage='VkPipelineCoverageToColorStateCreateFlagsNV',desc='Reserved for future use',type='flags']
--
include::{generated}/api/flags/VkPipelineCoverageToColorStateCreateFlagsNV.txt[]

tname:VkPipelineCoverageToColorStateCreateFlagsNV is a bitmask type for
setting a mask, but is currently reserved for future use.
--
endif::VK_NV_fragment_coverage_to_color[]


[[fragops-coverage-reduction]]
== Coverage Reduction

Coverage reduction takes the coverage information for a fragment and
converts that to a boolean coverage value for each color sample in each
pixel covered by the fragment.


=== Pixel Coverage

Coverage for each pixel is first extracted from the total fragment coverage
mask.
This consists of pname:rasterizationSamples unique coverage samples for each
pixel in the fragment area, each with a unique
<<primsrast-multisampling-coverage-mask, sample index>>.
If the fragment only contains a single pixel, coverage for the pixel is
equivalent to the fragment coverage.

ifdef::VK_EXT_fragment_density_map[]
If the render pass has a fragment density map attachment and the fragment
covers multiple pixels, pixel coverage is generated in an
implementation-dependent manner.
If all samples in the fragment are covered, all samples will be covered in
each pixel coverage.
endif::VK_EXT_fragment_density_map[]

ifdef::VK_NV_shading_rate_image[]
If a <<primsrast-shading-rate-image,shading rate image>> is used, and the
fragment covers multiple pixels, each pixel's coverage consists of the
coverage samples corresponding to that pixel, and each sample retains its
unique <<primsrast-multisampling-coverage-mask, sample index [eq]#i#>>.
endif::VK_NV_shading_rate_image[]

ifdef::VK_KHR_fragment_shading_rate[]
If the <<primsrast-fragment-shading-rate, fragment shading rate>> is set,
and the fragment covers multiple pixels, each pixel's coverage consists of
the coverage samples with a <<primsrast-multisampling-coverage-mask-vrfs,
pixel index>> matching that pixel, and each sample retains its unique
<<primsrast-multisampling-coverage-mask, sample index [eq]#i#>>.
endif::VK_KHR_fragment_shading_rate[]

=== Color Sample Coverage

Once pixel coverage is determined, coverage for each individual color sample
corresponding to that pixel is determined.

ifdef::VK_AMD_mixed_attachment_samples,VK_NV_framebuffer_mixed_samples,VK_NV_coverage_reduction_mode[If the]
ifndef::VK_AMD_mixed_attachment_samples,VK_NV_framebuffer_mixed_samples,VK_NV_coverage_reduction_mode[The]
number of pname:rasterizationSamples is identical to the number of samples
in the color attachments.
A color sample is covered if the pixel coverage sample with the same
<<primsrast-multisampling-coverage-mask, sample index>> [eq]#i# is covered.

ifdef::VK_AMD_mixed_attachment_samples,VK_NV_framebuffer_mixed_samples,VK_NV_coverage_reduction_mode[]
Otherwise, the coverage for each color sample is computed from the pixel
coverage as follows.
endif::VK_AMD_mixed_attachment_samples,VK_NV_framebuffer_mixed_samples,VK_NV_coverage_reduction_mode[]

ifdef::VK_AMD_mixed_attachment_samples[]
If the `<<VK_AMD_mixed_attachment_samples>>` extension is enabled, for color
samples present in the color attachments, a color sample is covered if the
pixel coverage sample with the same <<primsrast-multisampling-coverage-mask,
sample index>> [eq]#i# is covered; additional pixel coverage samples are
discarded.
endif::VK_AMD_mixed_attachment_samples[]

ifdef::VK_NV_framebuffer_mixed_samples[]

ifndef::VK_NV_coverage_reduction_mode[]
When the `<<VK_NV_framebuffer_mixed_samples>>` extension is enabled, if the
pipeline's
slink:VkPipelineMultisampleStateCreateInfo::pname:rasterizationSamples is
greater than the slink:VkAttachmentDescription::pname:samples of the color
attachments in the subpass, each color sample will be associated with an
implementation-dependent subset of samples in the pixel coverage.
If any of those associated samples are covered, the color sample is covered.
endif::VK_NV_coverage_reduction_mode[]

ifdef::VK_NV_coverage_reduction_mode[]
When the `<<VK_NV_coverage_reduction_mode>>` extension is enabled, the
pipeline state controlling coverage reduction is specified through the
members of the sname:VkPipelineCoverageReductionStateCreateInfoNV structure.

[open,refpage='VkPipelineCoverageReductionStateCreateInfoNV',desc='Structure specifying parameters controlling coverage reduction',type='structs']
--
The sname:VkPipelineCoverageReductionStateCreateInfoNV structure is defined
as:

include::{generated}/api/structs/VkPipelineCoverageReductionStateCreateInfoNV.txt[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:flags is reserved for future use.
  * pname:coverageReductionMode is a elink:VkCoverageReductionModeNV value
    controlling how color sample coverage is generated from pixel coverage.

If this structure is not included in the pname:pNext chain, or if the
extension is not enabled, the default coverage reduction mode is inferred as
follows:

  * If the `<<VK_NV_framebuffer_mixed_samples>>` extension is enabled, then
    it is as if the pname:coverageReductionMode is
    ename:VK_COVERAGE_REDUCTION_MODE_MERGE_NV.
  * If the `<<VK_AMD_mixed_attachment_samples>>` extension is enabled, then
    it is as if the pname:coverageReductionMode is
    ename:VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV.
  * If both `<<VK_NV_framebuffer_mixed_samples>>` and
    `<<VK_AMD_mixed_attachment_samples>>` are enabled, then the default
    coverage reduction mode is implementation-dependent.

include::{generated}/validity/structs/VkPipelineCoverageReductionStateCreateInfoNV.txt[]
--

[open,refpage='VkPipelineCoverageReductionStateCreateFlagsNV',desc='Reserved for future use',type='flags']
--
include::{generated}/api/flags/VkPipelineCoverageReductionStateCreateFlagsNV.txt[]

tname:VkPipelineCoverageReductionStateCreateFlagsNV is a bitmask type for
setting a mask, but is currently reserved for future use.
--

[open,refpage='VkCoverageReductionModeNV',desc='Specify the coverage reduction mode',type='enums']
--
Possible values of
slink:VkPipelineCoverageReductionStateCreateInfoNV::pname:coverageReductionMode,
specifying how color sample coverage is generated from pixel coverage, are:

include::{generated}/api/enums/VkCoverageReductionModeNV.txt[]

  * ename:VK_COVERAGE_REDUCTION_MODE_MERGE_NV specifies that each color
    sample will be associated with an implementation-dependent subset of
    samples in the pixel coverage.
    If any of those associated samples are covered, the color sample is
    covered.
  * ename:VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV specifies that for color
    samples present in the color attachments, a color sample is covered if
    the pixel coverage sample with the same
    <<primsrast-multisampling-coverage-mask, sample index>> [eq]#i# is
    covered; other pixel coverage samples are discarded.
--

[open,refpage='vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV',desc='Query supported sample count combinations',type='protos']
--
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:

include::{generated}/api/protos/vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV.txt[]

  * pname:physicalDevice is the physical device from which to query the set
    of combinations.
  * pname:pCombinationCount is a pointer to an integer related to the number
    of combinations available or queried, as described below.
  * pname:pCombinations is either `NULL` or a pointer to an array of
    slink:VkFramebufferMixedSamplesCombinationNV values, indicating the
    supported combinations of coverage reduction mode, rasterization
    samples, and color, depth, stencil attachment sample counts.

If pname:pCombinations is `NULL`, then the number of supported combinations
for the given pname:physicalDevice is returned in pname:pCombinationCount.
Otherwise, pname:pCombinationCount must: point to a variable set by the user
to the number of elements in the pname:pCombinations array, and on return
the variable is overwritten with the number of values actually written to
pname:pCombinations.
If the value of pname:pCombinationCount is less than the number of
combinations supported for the given pname:physicalDevice, at most
pname:pCombinationCount values will be written to pname:pCombinations, and
ename:VK_INCOMPLETE will be returned instead of ename:VK_SUCCESS, to
indicate that not all the supported values were returned.

include::{generated}/validity/protos/vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV.txt[]
--

[open,refpage='VkFramebufferMixedSamplesCombinationNV',desc='Structure specifying a supported sample count combination',type='structs']
--
The sname:VkFramebufferMixedSamplesCombinationNV structure is defined as:

include::{generated}/api/structs/VkFramebufferMixedSamplesCombinationNV.txt[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:coverageReductionMode is a elink:VkCoverageReductionModeNV value
    specifying the coverage reduction mode.
  * pname:rasterizationSamples is a elink:VkSampleCountFlagBits specifying
    the number of rasterization samples in the supported combination.
  * pname:depthStencilSamples specifies 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.
  * pname:colorSamples specifies 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.

include::{generated}/validity/structs/VkFramebufferMixedSamplesCombinationNV.txt[]
--
endif::VK_NV_coverage_reduction_mode[]


[[fragops-coverage-modulation]]
=== Coverage Modulation

[open,refpage='VkPipelineCoverageModulationStateCreateInfoNV',desc='Structure specifying parameters controlling coverage modulation',type='structs']
--
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 sname:VkPipelineCoverageModulationStateCreateInfoNV
structure.

The sname:VkPipelineCoverageModulationStateCreateInfoNV structure is defined
as:

include::{generated}/api/structs/VkPipelineCoverageModulationStateCreateInfoNV.txt[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:flags is reserved for future use.
  * pname:coverageModulationMode is a elink:VkCoverageModulationModeNV value
    controlling which color components are modulated.
  * pname:coverageModulationTableEnable controls whether the modulation
    factor is looked up from a table in pname:pCoverageModulationTable.
  * pname:coverageModulationTableCount is the number of elements in
    pname:pCoverageModulationTable.
  * pname:pCoverageModulationTable is a table of modulation factors
    containing a value for each number of covered samples.

If pname:coverageModulationTableEnable is ename:VK_FALSE, then for each
color sample the associated bits of the pixel coverage are counted and
divided by the number of associated bits to produce a modulation factor
[eq]#R# in the range [eq]#(0,1]# (a value of zero would have been killed due
to a color coverage of 0).
Specifically:

  * [eq]#N# = value of pname:rasterizationSamples
  * [eq]#M# = value of slink:VkAttachmentDescription::pname:samples for any
    color attachments
  * [eq]#R = popcount(associated coverage bits) / (N / M)#

If pname:coverageModulationTableEnable is ename:VK_TRUE, the value [eq]#R#
is computed using a programmable lookup table.
The lookup table has [eq]#N / M# elements, and the element of the table is
selected by:

  * [eq]#R = pname:pCoverageModulationTable[popcount(associated coverage
    bits)-1]#

Note that the table does not have an entry for [eq]#popcount(associated
coverage bits) = 0#, because such samples would have been killed.

The values of pname:pCoverageModulationTable may: be rounded to an
implementation-dependent precision, which is at least as fine as [eq]#1 /
N#, and clamped to [eq]#[0,1]#.

For each color attachment with a floating point or normalized color format,
each fragment output color value is replicated to [eq]#M# values which can:
each be modulated (multiplied) by that color sample's associated value of
[eq]#R#.
Which components are modulated is controlled by
pname:coverageModulationMode.

If this structure is not included in the pname:pNext chain, it is as if
pname:coverageModulationMode is ename:VK_COVERAGE_MODULATION_MODE_NONE_NV.

ifdef::VK_NV_coverage_reduction_mode[]
If the <<fragops-coverage-reduction, coverage reduction mode>> is
ename:VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV, each color sample is
associated with only a single coverage sample.
In this case, it is as if pname:coverageModulationMode is
ename:VK_COVERAGE_MODULATION_MODE_NONE_NV.
endif::VK_NV_coverage_reduction_mode[]

.Valid Usage
****
  * [[VUID-VkPipelineCoverageModulationStateCreateInfoNV-coverageModulationTableEnable-01405]]
    If pname:coverageModulationTableEnable is ename:VK_TRUE,
    pname:coverageModulationTableCount must: be equal to the number of
    rasterization samples divided by the number of color samples in the
    subpass
****

include::{generated}/validity/structs/VkPipelineCoverageModulationStateCreateInfoNV.txt[]
--

[open,refpage='VkPipelineCoverageModulationStateCreateFlagsNV',desc='Reserved for future use',type='flags']
--
include::{generated}/api/flags/VkPipelineCoverageModulationStateCreateFlagsNV.txt[]

tname:VkPipelineCoverageModulationStateCreateFlagsNV is a bitmask type for
setting a mask, but is currently reserved for future use.
--

[open,refpage='VkCoverageModulationModeNV',desc='Specify the coverage modulation mode',type='enums']
--
Possible values of
slink:VkPipelineCoverageModulationStateCreateInfoNV::pname:coverageModulationMode,
specifying which color components are modulated, are:

include::{generated}/api/enums/VkCoverageModulationModeNV.txt[]

  * ename:VK_COVERAGE_MODULATION_MODE_NONE_NV specifies that no components
    are multiplied by the modulation factor.
  * ename:VK_COVERAGE_MODULATION_MODE_RGB_NV specifies that the red, green,
    and blue components are multiplied by the modulation factor.
  * ename:VK_COVERAGE_MODULATION_MODE_ALPHA_NV specifies that the alpha
    component is multiplied by the modulation factor.
  * ename:VK_COVERAGE_MODULATION_MODE_RGBA_NV specifies that all components
    are multiplied by the modulation factor.
--

endif::VK_NV_framebuffer_mixed_samples[]
