DirectX-Specs

Conservative Rasterization

Version: 3.2

Date: 6/30/2015


Contents


Summary

Support Conservative Rasterization in Direct3D. Conservative Rasterization is mode of operation for the Rasterizer stage of the Direct3D Graphics Pipeline. It disables the standard sample-based rasterization, and will instead rasterize a pixel that is covered by any amount by a primitive. One important distinction is that, while any coverage at all produces a rasterized pixel, that coverage cannot be characterized by the hardware so coverage always appears binary to a Pixel Shader: either fully covered or not covered. It is left to the Pixel Shader code to analytically determine the actual coverage, if needed.


Overview

Conservative Rasterization in this context means that all pixels that are at least partially covered by a rendered primitive are rasterized, meaning the Pixel Shader is invoked. Behavior is not dependent on the sample point coverage that is used when Conservative Rasterization is not enabled: if any part of a primitive overlaps a pixel, then that pixel is considered covered and is then rasterized. When an edge or corner of a primitive falls along the edge or corner of a pixel, the application of the Top-Left Rule is implementation-specific (with the exception of implementations using the minimum uncertainty region). However, for implementations that support degenerate triangles, a degenerate triangle along an edge or corner must cover at least one pixel; so nothing falls through the cracks.

This type of rasterization is sometimes referred to as Overestimated Conservative Rasterization. There is also the concept of Underestimated Conservative Rasterization, which means that only pixels that are fully covered by a rendered primitive are rasterized. Underestimated Conservative Rasterization is only exposed via the new InnerCoverage System Generated Value, described later. The D3D Rasterizer’s Conservative Rasterization mode specified here is only Overestimated Conservative Rasterization.

Conservative Rasterization implementations are allowed to produce false positives, meaning they incorrectly decide that pixels are covered. This can happen due to implementation-specific details like primitive growing or snapping error inherent in the fixed-point vertex coordinates used in rasterization. The reason false positives (with respect to fixed point vertex coordinates) are valid is because some amount of false positives are needed to allow an implementation to do coverage evaluation against post-snapped vertices (i.e. vertex coordinates that have been converted from floating point to the 16.8 fixed-point used in the Rasterizer), but honor the coverage produced by the original floating point vertex coordinates. Beyond that, implementations are encouraged to reduce the number of false positives as much as possible. Limits on false positives are detailed in Rasterization Rules interaction.

Conservative Rasterization implementations must never produce false negatives with respect to the floating-point vertex coordinates for non-degenerate post-snap primitives: if any part of a primitive overlaps any part of a pixel, then that pixel must be rasterized.

Triangles that are degenerate (duplicate indices in an index buffer or collinear in 3D), or become degenerate after fixed-point conversion (collinear vertices in the Rasterizer), may or may not be culled; both are valid behaviors. However, Tier 2 and above require an implementation to never produce false negatives with respect to the floating-point vertex coordinates and therefore they must rasterize degenerates, with the exception that triangles with duplicate indices in an index buffer may be culled (some hardware automatically discards triangles with duplicate indices and this case is not considered useful enough to force a hardware change). Degenerate triangles must be considered back facing, so if a specific behavior is required by an application, it can use back-face culling or the IsFrontFace System Generated Value. Degenerate triangles must use the values assigned to Vertex 0 for all interpolated values.

Conservative Rasterization is an optional feature as of D3D11.3. (Note: check support DDI not detailed here). A WDDM 2.0+, D3D Feature Level 11.1+ capable driver and hardware is required.

Conservative Rasterization support will be defined by three Tiers, as described in the Tiered Support section.


Architectural Overview

Conservative Rasterization will only be supported on WDDM 2.0 or newer UMDs that support FL11.1+. A new capability bit will expose support on such systems.


Architecture Decisions

We will use a Tiered structure to split implementations across two differentiators: post-snap degenerate culling behavior, and inner input coverage.

(1) Tier 1:

(2) Tier 2:

(3) Tier 3:


Interactions with the Pipeline


Rasterization Rules interaction

In Conservative Rasterization mode, Rasterization Rules apply the same way as when Conservative Rasterization mode is not enabled with exceptions for the Top-Left Rule, as described previously, and [Pixel Coverage]{.underline}. 16.8 Fixed-Point Rasterizer precision must be used.

Pixels that would not be covered if hardware was using full floating point vertex coordinates may only be included if they are within an uncertainty region no larger half a pixel in the fixed point domain. Future hardware is expected to reach the tightened uncertainty region specified in Tier 2. Note that this requirement prevents sliver triangles from extending further than necessary.

A similar valid uncertainty region applies to InnerCoverage as well, but it is tighter since no implementations require a larger uncertainty region for this case. See InnerCoverage for more detail.

Inner and outer uncertainty regions must be greater than or equal to the size of half the subpixel grid, or 1/512 of a pixel, in the fixed point domain. This is the minimum valid uncertainty region. 1/512 comes from the 16.8 fixed point Rasterizer coordinate representation and the round-to-nearest rule that applies when converting floating point vertex coordinates to 16.8 fixed point coordinates. 1/512 can change if the Rasterizer precision changes. If an implementation implements this minimum uncertainty region, then they must follow the Top-Left Rule when an edge or corner of the uncertainty region falls along the edge or corner of a pixel. The clipped edges of the uncertainty region should be treated as the closest vertex, meaning that it counts as two edges: the two that join at the associated vertex. Top-Left Rule is required when the minimum uncertainty region is used because if it is not, then a Conservative Rasterization implementation would fail to rasterize pixels that could be covered when Conservative Rasterization mode is disabled.

The included diagram illustrates a valid outer uncertainty region produced by sweeping a square around the edges of the primitive in the fixed point domain (i.e. the vertices have been quantized by the 16.8 fixed point representation). The dimensions of this square are based on the valid outer uncertainty region size: for the 1/2 of a pixel, the square is 1 pixel in width and height, for 1/512 of a pixel, the square is 1/256 of a pixel in width and height. The green triangle represents a given primitive, the red dotted line represents the bound on Overestimated Conservative Rasterization, the solid black squares represent the square that is swept along the primitive edges, and the blue checkered area is the outer uncertainty region:

consras1


Multisampling interaction

Regardless of the number of samples in RenderTarget/DepthStencil surfaces (or whether ForcedSampleCount is being used or not), all samples are covered for pixels rasterized by Conservative Rasterization. Individual sample locations are not tested for whether they fall in the primitive or not.


SampleMask interaction

The SampleMask Rasterizer State applies the same way as when Conservative Rasterization is not enabled for InputCoverage, but does not affect InnerCoverage (i.e. it is not AND’ed into an input declared with InnerCoverage). This is because InnerCoverage is unrelated to whether MSAA samples are masked out: 0 InnerCoverage only means that the pixel is not guaranteed to be fully covered, not that no samples will be updated.


Depth/Stencil Test interaction

Depth/Stencil Testing proceeds for a conservatively rasterized pixel the same way as if all samples are covered when Conservative Rasterization is not enabled. Proceeding with all samples covered can cause Depth extrapolation, which is valid and must be clamped to the viewport as specified when Conservative Rasterization is not enabled. This is similar to when pixel-frequency interpolation modes are used on a RenderTarget with sample count > 1 (see section 3.5.5), although in the case of Conservative Rasterization, it is the depth value going into the fixed function depth test that can be extrapolated.

Use of early depth culling behavior in combination with conservative rasterization is undefined. This includes early depth culling where depth extrapolation occurs. This is because some Early Depth culling hardware cannot properly support extrapolated depth values. However, Early Depth culling behavior in the presence of Depth Extrapolation is problematic even with hardware that can support extrapolated depth values. This issue can be worked around by clamping the Pixel Shader input depth to the min and max depth values of the primitive being rasterized and writing that value to oDepth. Implementations are required to disable Early Depth culling in this case, due to the oDepth write.


Helper Pixel interaction

Helper Pixel rules apply the same way as when Conservative Rasterization is not enabled. As part of this, all pixels including Helper Pixels must report InputCoverage accurately as specified in the InputCoverage interaction section. So fully noncovered pixels report 0 coverage.


Output Coverage interaction

Output Coverage (oMask) behaves for a conservatively rasterized pixel as it does when Conservative Rasterization is not enabled with all samples covered.


InputCoverage interaction

In Conservative Rasterization mode, this input register is populated as if all samples are covered when Conservative Rasterization is not enabled for a given conservatively rasterized pixel. That is to say, all existing interactions apply (e.g. SampleMask is applied), and the first n bits in InputCoverage from the LSB are set to 1 for a conservatively rasterized pixel, given an n sample per pixel RenderTarget and/or Depth/Stencil buffer is bound at the Output Merger, or an n sample ForcedSampleCount. The rest of the bits are 0.

This input is available in a shader regardless of the use of Conservative Rasterization, though Conservative Rasterization changes its behavior to only show all samples covered (or none for Helper Pixels).


InnerCoverage

This feature is required by, and only available in, Tier 3. The runtime will fail shader creation for shaders that use this mode when an implementation supports a Tier less than Tier 3.

The Pixel Shader has a new 32-bit scalar integer System Generate Value available: InnerCoverage. This is a bitfield that has bit 0 from the LSB set to 1 for a given conservatively rasterized pixel, only when that pixel is guaranteed to be entirely inside the current primitive. All other input register bits must be set to 0 when bit 0 is not set, but are undefined when bit 0 is set to 1 (essentially, this bitfield represents a Boolean value where false must be exactly 0, but true can be any odd (i.e. bit 0 set) non-zero value). This input is used for underestimated Conservative Rasterization information. It informs the Pixel Shader whether the current pixel lies completely inside the geometry.

This must account for snapping error at resolutions greater than or equal to the resolution at which the current Draw is operating. There must not be false positives (setting InnerCoverage bits when the pixel is not fully covered for any snapping error at resolutions greater than or equal to the resolution at which the current Draw is operating), but false negatives are allowed. Said another way, the implementation must not incorrectly identify pixels as fully covered that would not be with full floating point vertex coordinates in the Rasterizer.

Pixels that would be fully covered if hardware was using full floating point vertex coordinates may only be omitted if they intersect the inner uncertainty region, which must be no larger than the size of the subpixel grid, or 1/256 of a pixel, in the fixed point domain. Said another way, pixels entirely within the inner boundary of the inner uncertainty region must be marked as fully covered. The inner boundary of the uncertainty region is illustrated in the diagram below by the bold black dotted line. 1/256 comes from the 16.8 fixed point Rasterizer coordinate representation, which can change if the Rasterizer precision changes. This uncertainty region is enough to account for snapping error caused by the conversion of floating point vertex coordinates to fixed point vertex coordinates in the Rasterizer.

The same 1/512 minimum uncertainty region requirements defined in Rasterization Rules interaction apply here as well.

The included diagram illustrates a valid inner uncertainty region produced by sweeping a square around the edges of the primitive in the fixed point domain (i.e. the vertices have been quantized by the 16.8 fixed point representation). The dimensions of this square are based on the valid inner uncertainty region size: for 1/256 of a pixel, the square is 1/128 of a pixel in width and height. The green triangle represents a given primitive, the bold black dotted line represents the boundary of the inner uncertainty region, the solid black squares represent the square that is swept along the primitive edges, and the orange checkered area is the inner uncertainty region:

consras2

The use of InnerCoverage does not affect whether a pixel is conservatively rasterized, i.e. using one of these InputCoverage modes does not affect which pixels are rasterized when Conservative Rasterization mode is enabled. Therefore, when InnerCoverage is used and the Pixel Shader is processing a pixel that is not completely covered by the geometry its value will be 0, but the Pixel Shader invocation will have samples updated. This is different from when InputCoverage is 0, meaning that no samples will be updated.

This input is mutually exclusive with InputCoverage: both cannot be used.

To access InnerCoverage, it must be declared as a single component out of one of the Pixel Shader input registers. The interpolation mode on the declaration must be constant (interpolation does not apply).

The InnnerCoverage bitfield is not affected by depth/stencil tests, nor is it ANDed with the SampleMask Rasterizer state.

This input is only valid in Conservative Rasterization mode. That is to say, when Conservative Rasterization is not enabled, InnerCoverage produces an undefined value.

Pixel Shader invocations caused by the need for Helper Pixels, but otherwise not covered by the primitive, must have the InnerCoverage register set to 0.


Attribute Interpolation interaction

Attribute interpolation modes are unchanged and proceed the same way as when Conservative Rasterization is not enabled, where the viewport-scaled and fixed-point-converted vertices are used. Because all samples in a conservatively rasterized pixel are considered covered, it is valid for values to be extrapolated, similar to when pixel-frequency interpolation modes are used on a RenderTarget with sample count > 1 (see section 3.5.5). Centroid interpolation modes produce results identical to the corresponding non-centroid interpolation mode; the notion of centroid is meaningless in this scenario – where sample coverage is only either full or 0.

Conservative Rasterization allows for degenerate triangles to produce Pixel Shader invocations, therefore, degenerate triangles must use the values assigned to Vertex 0 for all interpolated values.


Clipping interaction

When Conservative Rasterization mode is enabled and depth clip is disabled (i.e. DepthClipEnable Rasterizer State set to FALSE), there may be variances in attribute interpolation for segments of a primitive that fall outside the 0 <= z <= w range, depending on implementation: either constant values are used from a point where the primitive intersects the relevant plane (near or far), or attribute interpolation behaves as when Conservative Rasterization mode is disabled. However, the depth value behavior is the same regardless of Conservative Rasterization mode, i.e. primitives that fall outside of the depth range must still be given the value of the nearest limit of the viewport depth range. Attribute interpolation behavior inside the 0 <= z <= w range must remain unchanged.


Clip Distance interaction

Clip Distance is valid when Conservative Rasterization mode is enabled, and behaves for a conservatively rasterized pixel as it does when Conservative Rasterization is not enabled with all samples covered.

Note that Conservative Rasterization can cause extrapolation of the W vertex coordinate, which may cause W <= 0. This could cause per-pixel Clip Distance implementations to operate on a Clip Distance that has been Perspective Divided by an invalid W value. Clip Distance implementations must guard against invoking rasterization for pixels where vertex coordinate W <= 0 (e.g. due to extrapolation when in Conservative Rasterization mode).


Target Independent Rasterization interaction

Conservative Rasterization mode is compatible with TIR. TIR rules and restrictions apply, behaving for a conservatively rasterized pixel as if all samples are covered.


IA Primitive Topology interaction

Conservative Rasterization is not defined for line or point primitives. Therefore, Primitive Topologies that specify points or lines produce undefined behavior if they are fed to the rasterizer unit when Conservative Rasterization is enabled.

Note: there will be debug layer validation to verify applications do not use these Primitive Topologies.


Query interaction

For a conservatively rasterized pixel, D3D11 Queries must behave as they do when Conservative Rasterization is not enabled when all samples are covered. E.g. For a conservatively rasterized pixel, D3D11_QUERY_OCCLUSION and D3D11_QUERY_DATA_PIPELINE_STATISTICS must behave as they would when Conservative Rasterization is not enabled when all samples are covered.

For example, Pixel Shader invocations should increment for every conservatively rasterized pixel in Conservative Rasterization mode.


Cull State interaction

All Cull States are valid in Conservative Rasterization mode and follow the same rules as when Conservative Rasterization is not enabled.

Note: When comparing Conservative Rasterization across resolutions to itself or without Conservative Rasterization enabled, there is the possibility that some primitives may have mismatched facedness (i.e. one back facing, the other front facing). Applications can avoid this uncertainty by using D3D11_CULL_NONE and not using the IsFrontFace System Generated Value.


IsFrontFace interaction

The IsFrontFace System Generated Value is valid to use in Conservative Rasterization mode, and follows the behavior defined when Conservative Rasterization is not enabled.

Note: see cull state interaction.


Fill Modes interaction

The only valid Fill Mode for Conservative Rasterization is D3D11_FILL_SOLID, any other Fill Mode is an invalid parameter for the Rasterizer State.

This is because D3D11 functional specification specifies that wireframe Fill Mode should convert triangle edges to lines and follow the line rasterization rules and conservative line rasterization behavior has not been defined. If conservative line rasterization behavior is defined in the future, this restriction can be lifted.


Tiered Support

We expect future implementations to converge on support for Tier 3.


Tier 1

This tier captures use cases that don’t rely on degenerates being rasterized or inner coverage.

Conservative Rasterization behaves as specified previously in this document.


Tier 2

This tier captures use cases that rely on degenerates being rasterized, such as voxelization.

Conservative Rasterization behaves as specified previously in this document, with the following new requirements:


Degenerate Triangle Culling

Conservative Rasterization must not fail to rasterize pixels that would be rasterized with full floating point vertex coordinates in the Rasterizer (note that (especially post-snap) degenerate culling prevents this from being true).

Therefore, degenerate triangles must not be culled, with the exception that triangles with duplicate indices may be culled. This simplifies the distinction between Standard and Conservative Rasterization: standard always has degenerate culling, conservative does not.

Note that degenerate triangles must be back-facing, so if a specific behavior is required by an application, it can use back-face culling or the IsFrontFace System Generated Value.


Smaller Outer Uncertainty Region

Pixels that would not be covered if hardware was using floating point vertex coordinates must only be included if they are within an outer uncertainty region no larger than the size the subpixel grid, or 1/256 of a pixel as the Rasterizer exists today, in the fixed point domain. 1/256 comes from the 16.8 fixed point Rasterizer coordinate representation, which can change if the Rasterizer precision changes. This uncertainty region is enough to account for snapping error caused by the conversion of floating point vertex coordinates to fixed point vertex coordinates in the Rasterizer. Note that this requirement prevents sliver triangles from extending further than necessary.

The previously included outer uncertainty region diagram illustrates this smaller valid outer uncertainty region when the swept square measures 1/128 of a pixel in width and height.


Tier 3

This tier captures use cases that require inner input coverage, such as occlusion culling.

Conservative Rasterization behaves as specified previously in this document (including previous tier requirements), with the following new requirements:


Inner-Conservative Coverage System Generated Value

InnerCoverage System Generate Value is required.



API Changes


D3D11

A new Rasterizer Desc struct will be required at the API.

API Struct:

typedef struct D3D11_RASTERIZER_DESC2
{
    /* Previous members */
    D3D11_CONSERVATIVE_RASTER_MODE ConservativeRaster;
} D3D11_RASTERIZER_DESC2;

```C++
typedef enum D3D11_CONSERVATIVE_RASTERIZER_MODE
{
    D3D11_CONSERVATIVE_RASTER_MODE_OFF = 0; // Default
    D3D11_CONSERVATIVE_RASTER_MODE_ON = 1;
} D3D11_CONSERVATIVE_RASTERIZER_MODE;

This needs an associated CD3D11_RASTERIZER_DESC2 utility class.

A new ID3D11Device* function will be added to the latest ID3D11Device*
interface (e.g. ID3D11Device3) that takes the new desc:

```C++
HRESULT CreateRasterizerState2(
    [annotation(\"_In_\")[ const D3D11_RASTERIZER_DESC2* pRasterizerDesc,
    [annotation(\"_Out_opt_\")[ ID3D11RasterizerState2** ppRasterizerState );

A new Rasterizer State interface will be required to support a new GetDesc:

interface ID3D11RasterizerState2 : ID3D11RasterizerState1
{
    void GetDesc2( [annotation(\"_Out_\")[ D3D11_RASTERIZER_DESC2* pDesc );
};

RS[Set/Get[State() APIs do not require changes.


D3D12

D3D12 uses the same (or similar) types and interfaces, so essentially the same D3D11 changes can be made to D3D12. There is a possibility that we rename the rasterizer state interface to ID3D12RasterizerState, or that we get rid of separate pipeline objects all together and only have PSOs, but that work is being considered as part of the 11on12 effort.


HLSL

A new Input Coverage System Generated Value is defined that must work in D3D11 and D3D12:

SV_InnerCoverage

A 32-bit scalar integer that can be specified on input of a pixel shader. Requires ps_5_0 or higher.

Represents underestimated conservative rasterization information (i.e. whether a pixel is guaranteed-to-be-fully covered).

This System Generated Value is required for Tier 3 support, and is only available in that Tier. Therefore, a new Shader Feature flag must be added to the SShaderFeatureInfo FeatureFlags in order for runtime to properly validate. This is typically performed as part of the HLSL compiler work, see SHADER_FEATURE_TILED_RESOURCES as an example.

SV_InnerCoverage is mutually exclusive with SV_Coverage: both cannot be used.

To access SV_InnerCoverage, it must be declared as a single component out of one of the Pixel Shader input registers. The interpolation mode on the declaration must be constant (interpolation does not apply).


DDI Design

Conservative Rasterization will be supported by D3D11 and D3D12. D3D11 DDI is specified here, but there will be D3D12 equivalents.

D3D Feature Level 11.1+ hardware and WDDM 2.0+ UMD is required.


GetCaps

A new D3D10_2DDICAPS_TYPE will be added to communicate Tier, for example:

typedef enum D3D10_2DDICAPS_TYPE
{
    /* other caps */
    D3DWDDM2_0DDICAPS_D3D11_OPTIONS2 = 140,
} D3D10_2DDICAPS_TYPE;

And an associated struct for the driver to fill out:

// D3DWDDM2_0DDICAPS_D3D11_OPTIONS2
typedef struct D3DWDDM2_0DDICAPS_D3D11_OPTIONS2_DATA
{
    /* other caps */
    D3DWDDM2_0DDI_CONSERVATIVE_RASTERIZATION_TIER
    ConservativeRasterizationTier;
} D3DWDDM2_0DDICAPS_D3D11_OPTIONS2_DATA;

And an associated enum type:

typedef enum D3DWDDM2_0DDI_CONSERVATIVE_RASTERIZATION_TIER
{
    D3DWDDM2_0DDI_CONSERVATIVE_RASTERIZATION_NOT_SUPPORTED = 0,
    D3DWDDM2_0DDI_CONSERVATIVE_RASTERIZATION_TIER_1 = 1,
    D3DWDDM2_0DDI_CONSERVATIVE_RASTERIZATION_TIER_2 = 2,
    D3DWDDM2_0DDI_CONSERVATIVE_RASTERIZATION_TIER_3 = 3,
} D3DWDDM2_0DDI_CONSERVATIVE_RASTERIZATION_TIER;

Rasterizer State Additions

A new Conservative Rasterization mode Rasterizer State will be added, for example:

typedef struct D3DWDDM2_0DDI_RASTERIZER_DESC
{
    /* other state */
    D3DWDDM2_0DDI_CONSERVATIVE_RASTERIZATION_MODE ConservativeRaster;
} D3DWDDM2_0DDI_RASTERIZER_DESC;

typedef enum D3DWDDM2_0DDI_CONSERVATIVE_RASTERIZATION_MODE
{
    D3DWDDM2_0DDI_CONSERVATIVE_RASTERIZATION_OFF = 0, // Default
    D3DWDDM2_0DDI_CONSERVATIVE_RASTERIZATION_ON = 1,
} D3DWDDM2_0DDI_CONSERVATIVE_RASTERIZATION_MODE;

This necessitates revisions of the DDIs that have Rasterizer State parameters (CalcPrivateSize and CreateRasterizerState):

typedef SIZE_T ( APIENTRY* PFND3D12DDI_CALCPRIVATERASTERIZERSTATESIZE)(
    D3D12DDI_HDEVICE, _In_ CONST D3DWDDM2_0DDI_RASTERIZER_DESC * );

typedef VOID ( APIENTRY* PFND3DWDDM2_0DDI_CREATERASTERIZERSTATE )(
    D3D12DDI_HDEVICE, _In_ CONST D3DWDDM2_0DDI_RASTERIZER_DESC *,
    D3D12DDI_HRASTERIZERSTATE, D3D12DDI_HRTRASTERIZERSTATE );

Runtime Changes


D3D11

CRasterizerState in both the runtime and SDKLayers needs to implement the new ID3D11RasterizerState2. Uses of ID3D11RasterizerState1 should be updated to ID3D11RasterizerState2 where they make sense as well, e.g. C10and11DeviceChildForVisibleClasses<>, ChildTypeFromIFace<>, CDeviceChild<>. GetDesc will be updated to have a GetDesc_Worker that provides the shared code implementation, taking a CFunctionSentinel from the callers (see CreateRasterizerStatePostValidation for an example of CFunctionSentinel passing).

CDevice in both the runtime and SDKLayers needs to implement the new Create API added to the latest ID3D11Device* interface.

SmallRasterizerStateDesc must also be updated to handle the new API and DDI structs. This utility class is used in many of the functions identified in this section to access API state and DDI state objects.

To support layered creation, a new layered creation args that inherits from SD3D11_1LayeredRasterizerStateCreationArgs is required (e.g. SD3D11_3LayeredRasterizerStateCreationArgs). This necessitates changes to the CDevice::GetLayeredChildSize, CDevice::CreateLayeredChild, CDevice::CreateRasterizerState* functions, CDevice::EnsureRSDual, and CRasterizerState::TConstructorArgs.

DDI call sites in CDevice::GetLayeredChildSize and CRasterizerState::CLS::FinalConstruct must be updated to call the latest DDI.

Device Removed stubs for D3D11’s handling of Device Removed UMD insulation and Software Deferred Context stubs are required for the new DDIs as well.

SwitchToRef.* can be safely ignored because the precedent was set to do so with the addition of D3D11_RASTERIZER_DESC1.


Validation

CCreateRasterizerStateValidator::Validate must be updated to take a D3D11_RASTERIZER_DESC2. Any Create-time validation of Conservative Rasterization must be added here. Create validation consists of the following checks:

Draw-time validation of Conservative Rasterization will be placed in CContext::ValidateDraw, and a new default Rasterizer State Desc will be added (i.e. a new version of c_DefaultRasterizerDesc1). Draw-time validation consists of the following checks:

Pixel Shader creation validation will be placed in CCreatePixelShaderValidator::ValidateShader. Validation consists of the following checks:


D3D12

Most changes specified in D3D11 apply here, with a few additions:

We specify “most changes” because D3D12 is currently in the process of removing now-out-dated 11 APIs. For example, CreateRasterizerState will not have so many variants in D3D12.

Any chance to share code between D3D12 and D3D11 should be taken. To do so, the easiest way is to add a new <filename>_SharedTo11.<fileext> file that contains the shared code and is included in both D3D12 and D3D11 versions of <filename>. Let the preprocessor do the work! However, we must be mindful of changes to the DDI in D3D12 that could require the shared code to be unshared, so don’t waste work! A good candidate for sharing is the pre and post validation functions.


Functional / Unit Tests

The functional unit tests will be written in TAEF. Because negatives must be tested, we need D3D11 and D3D12 API tests. We must also ensure D3D11on12 works for positives. D3DDriver will be used for D3D11 DDI call verification, DDIFilter and WARP will be used for D3D12 and D3D11on12.

Functional unit tests will cover the following:

CreateRasterizerState2 and RS[Set/Get[State are the only ones required to unblock partners.

Note that is probably makes sense to combine many of these tests so, for example, successful creates can be used for later validation.

IHV-Bring-up Test

The unit test to unblock IHV development is written to rasterize a triangle that falls in between the center sample positions of a 2x2 Render Target. Enabling Conservative Rasterization must produce rasterized pixels, while disabling Conservative Rasterization must NOT rasterize pixels. The vertex coordinates should be <-1,0>,<1,0>,<0,0.5> in NDC, with a Viewport top-left of <0,0> and <2,2> width and height.

This test leverages 11on12 to get D3D12 coverage.

Conformance Tests

The following functionality is HCK (conformance) tested:

consras3

consras4

consras5

consras6

consras7

All tests specified here can be verified by reading the Render Target contents (via copy-to-staging + map), or writing to a UAV.


Questions

Some Conservative Rasterization implementations are not capable of only rasterizing guaranteed-to-be-fully-covered pixels. To support the most hardware, this mode of rasterization behavior is not yet available, but the same information can be conveyed by using the InnerCoverage System Generated Value.

That feature wasn’t tightly related to Conservative Rasterization, although it can help certain use cases where Conservative Rasterization is used to render a low-resolution proxy. Conservative Rasterization should not rely on configuring the fractional precision in the rasterizer because that limits its usefulness. This feature is still interesting, and can be introduced in a future spec.