Depth stencil state determines how data is written to and read from the depth/stencil buffer.
`DepthTestEnable` determines whether the depth buffer will be used at all when determining whether to render a particular pixel. If you turn it off, the pixel will always be written no matter what is in the depth buffer.
`DepthWriteEnable` determines whether the depth buffer will be written to. This enables you to, for example, perform a depth test but not update the depth buffer with the results.
`CompareOp` determines how the depth buffer will be checked when determining whether to write a pixel. For example, if you use `CompareOp.LessOrEqual`, the new pixel will be checked for a depth value less than or equal. If it is, then the pixel will be written. Otherwise it will be discarded.
`DepthBoundsTestEnable` determines whether bounds will be checked. `MinDepthBounds` determines the minimum, and `MaxDepthBounds` the maximum. If a pixel's depth is outside of this range it will be ignored. If `DepthBoundsTestEnable`, pixels will not be ignored on the basis of their depth value.
`StencilTestEnable` enables or disables the stencil test. Obviously this should be `false` for pipelines that don't use a stencil buffer, and `true` for pipelines that do.
Next there are two kinds of `StencilOpState`s. Stencil tests and writes use the back stencil state when handling back-facing polygons and use the front stencil state when handling front-facing polygons. We'll get into this distinction later when we talk about rasterizer state.
If you want to understand why and how to use stencil testing you should [read this handy explanation](https://learnopengl.com/Advanced-OpenGL/Stencil-testing). For now I'll just detail how to set up stencil state.
The `StencilOpState` fields are as follows:
`FailOp` specifies the action performed on samples that fail the stencil test.
`PassOp` specifies the action performed on samples that pass both the depth and stencil tests.
`DepthFailOp` specifies the action performed on samples that pass the stencil test and fail the depth test.
`CompareOp` specifies the comparison operator used in the stencil test.
`CompareMask` selects the bits of the stencil values participating in the stencil test.
`WriteMask` selects the bits of the stencil values updated by the stencil test in the stencil buffer.
`Reference` is an integer reference value that is used in the unsigned stencil comparison.
Let's put it all together.
```cs
var myDepthStencilState = new DepthStencilState
{
DepthTestEnable = true,
DepthWriteEnable = true,
CompareOp = CompareOp.LessOrEqual,
DepthBoundsTestEnable = false,
StencilTestEnable = false
};
```
The above depth stencil state will write to and read from the depth buffer, letting through pixels that are at a lower or equal depth value to the current depth value.
Sorry for the relatively basic example state, but if you get to the point where you need something more complex you'll probably understand all this stuff pretty well anyway. Let's move on.