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
- GlobalRootSignature
- LocalRootSignature
- SubobjectToExportsAssocation
- RaytracingShaderConfig
- RaytracingPipelineConfig
- TriangleHitGroup
- ProceduralPrimitiveHitGroup
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.