State Objects

With shader models 6.3 and later, applications have the convenience and flexibility of being able to define DXR state objects directly in HLSL shader code in addition to using Direct3D 12 APIs.

In HLSL, state objects are declared with this syntax:

Type Name = 
{ 
    Field1,
    Field2,
    ...
};
Item Description
Type
Identifies the type of subobject. Must be one of the supported HLSL subobject types.
Name
An ASCII string that uniquely identifies the variable name.
Field[1, 2, ...]
Fields of the subobject. Specific fields for each type of subobject are described below.

List of subobject types:

StateObjectConfig

The StateObjectConfig subobject type corresponds to a D3D12_STATE_OBJECT_CONFIG structure.

It has one field, a bitwise flag, which is one or both of

  • STATE_OBJECT_FLAGS_ALLOW_LOCAL_DEPENDENCIES_ON_EXTERNAL_DEFINITONS
  • STATE_OBJECT_FLAGS_ALLOW_EXTERNAL_DEPENDENCIES_ON_LOCAL_DEFINITIONS

or, zero for neither of them.

Example:

StateObjectConfig MyStateObjectConfig = 
{ 
    STATE_OBJECT_FLAGS_ALLOW_LOCAL_DEPENDENCIES_ON_EXTERNAL_DEFINITONS
};

GlobalRootSignature

A GlobalRootSignature corresponds to a D3D12_GLOBAL_ROOT_SIGNATURE structure.

The fields consist of some number of strings describing the parts of the root signature. For reference on this, see Specifying Root Signatures in HLSL.

Example:

GlobalRootSignature MyGlobalRootSignature =
{
    "DescriptorTable(UAV(u0)),"                     // Output texture
    "SRV(t0),"                                      // Acceleration structure
    "CBV(b0),"                                      // Scene constants
    "DescriptorTable(SRV(t1, numDescriptors = 2))"  // Static index and vertex buffers.
};

LocalRootSignature

A LocalRootSignature corresponds to a D3D12_LOCAL_ROOT_SIGNATURE structure.

Just like the global root signature subobject, the fields consist of some number of strings describing the parts of the root signature. For reference on this, see Specifying Root Signatures in HLSL.

Example:

LocalRootSignature MyLocalRootSignature = 
{
    "RootConstants(num32BitConstants = 4, b1)"  // Cube constants 
};

SubobjectToExportsAssocation

By default, a subobject merely declared in the same library as an export is able to apply to that export. However, applications have the ability to override that and get specific about what subobject goes with which export. In HLSL, this "explicit association" is done using SubobjectToExportsAssocation.

A SubobjectToExportsAssocation corresponds to a D3D12_DXIL_SUBOBJECT_TO_EXPORTS_ASSOCIATION structure.

This subobject is declared with the syntax

SubobjectToExportsAssocation Name = 
{ 
    SubobjectName,
    Exports
};
Item Description
Name
An ASCII string that uniquely identifies the variable name.
SubobjectName
String which identifies an exported subobject.
Exports
String containing a semicolon-delimited list of exports.

Example:

SubobjectToExportsAssociation MyLocalRootSignatureAssociation =
{
    "MyLocalRootSignature",    // Subobject name
    "MyHitGroup;MyMissShader"  // Exports association 
};

Note that both fields use exported names. An exported name may be different from the original name in HLSL, if the application chooses to do export-renaming.

RaytracingShaderConfig

A RaytracingShaderConfig corresponds to a D3D12_RAYTRACING_SHADER_CONFIG structure.

This subobject is declared with the syntax

RaytracingShaderConfig Name = 
{ 
    MaxPayloadSize,
    MaxAttributeSize
};
Item Description
Name
An ASCII string that uniquely identifies the variable name.
MaxPayloadSize
Numerical value for the maximum storage for scalars (counted as 4 bytes each) in ray payloads for associated raytracing shaders.
MaxAttributeSize
Numerical value for the maximum number of scalars (counted as 4 bytes each) that can be used for attributes in associated raytracing shaders. The value cannot exceed D3D12_RAYTRACING_MAX_ATTRIBUTE_SIZE_IN_BYTES.

Example:

RaytracingShaderConfig MyShaderConfig =
{
    16,  // Max payload size
    8    // Max attribute size
};

RaytracingPipelineConfig

A RaytracingPipelineConfig corresponds to a D3D12_RAYTRACING_PIPELINE_CONFIG structure.

This subobject is declared with the syntax

RaytracingPipelineConfig Name = 
{ 
    MaxTraceRecursionDepth
};
Item Description
Name
An ASCII string that uniquely identifies the variable name.
MaxTraceRecursionDepth
Numerical limit to use for ray recursion in the raytracing pipeline. It is a number between 0 and 31, inclusive.

Example:

RaytracingPipelineConfig MyPipelineConfig =
{
    1  // Max trace recursion depth
};

Since there is a performance cost to raytracing recursion, applications should use the lowest recursion depth needed for the desired results.

If shader invocations haven't yet reached the maximum recursion depth, they can call TraceRay any number of times. But if they reach or exceed the maximum recursion depth, calling TraceRay puts the device into removed state. Therefore, raytracing shaders should take care to stop calling TraceRay if they've met or exceeded the maximum recursion depth.

TriangleHitGroup

A TriangleHitGroup corresponds to a D3D12_HIT_GROUP_DESC structure whose Type field is set to D3D12_HIT_GROUP_TYPE_TRIANGLES.

This subobject is declared with the syntax

TriangleHitGroup Name = 
{ 
    AnyHitShader,
    ClosestHitShader
};
Item Description
Name
An ASCII string that uniquely identifies the variable name.
AnyHitShader
String name of the anyhit shader for the hit group, or an empty string.
ClosestHitShader
String name of the closest hit shader for the hit group, or an empty string.

Example:

TriangleHitGroup MyHitGroup =
{
    "",                    // AnyHit
    "MyClosestHitShader",  // ClosestHit
};

Note that both fields use exported names. An exported name may be different from the original name in HLSL, if the application chooses to do export-renaming.

ProceduralPrimitiveHitGroup

A ProceduralPrimitiveHitGroup corresponds to a D3D12_HIT_GROUP_DESC structure whose Type field is set to D3D12_HIT_GROUP_TYPE_PROCEDURAL_PRIMITIVE.

This subobject is declared with the syntax

ProceduralPrimitiveHitGroup Name = 
{ 
    AnyHitShader,
    ClosestHitShader,
    IntersectionShader
};
Item Description
Name
An ASCII string that uniquely identifies the variable name.
AnyHitShader
String name of the anyhit shader for the hit group, or an empty string.
ClosestHitShader
String name of the closest hit shader for the hit group, or an empty string.
IntersectionShader
String name of the intersection shader for the hit group, or an empty string.

Example:

ProceduralPrimitiveHitGroup MyProceduralHitGroup
{
    "MyAnyHit",       // AnyHit
    "MyClosestHit",   // ClosestHit
    "MyIntersection"  // Intersection
};

Note that the three fields use exported names. An exported name may be different from the original name in HLSL, if the application chooses to do export-renaming.

Remarks

Subobjects have the notion of "association", or "which subobject goes with which export".

When specifying subobjects through shader code, the choice of "which subobject goes with which export" follows the rules as outlined in the DXR specification. In particular, suppose an application has some export. If an application associates that export with root signature A through shader-code and root signature B through application code, B is the one that gets used. The design of "use B" instead of "produce an error" gives applications the ability to conveniently override DXIL associations using application code, rather than be forced to recompile shaders to resolve mismatching things.

DirectX Developer Blog post "New in D3D12 – DirectX Raytracing (DXR) now supports library subobjects"

DirectX Raytracing (DXR) Functional Spec

Sample: D3D12RaytracingLibrarySubobjects