DirectX-Specs

Problem definition

The state object compiler is a tool based off of the D3D codebase which provides similar affordances for feature capability querying, and API -> DDI translation for complex structures like state objects, but without the full D3D12 runtime or kernel dependencies. It does that without creating a D3D12 device, and is expected to work without a driver being available. It is meant to work with an IHV compiler plugin separate from the driver.

The current runtime API/DDI design is dependent on driver handles. To help the compiler work without those dependencies some change are needed for the way we express PSO/SO API and DDI structs.

For the PSO creation struct the root signature subobject expects type ID3D12RootSignature which is dependent on ID3D12DeviceChild as shown below:

[ uuid( c54a6b66-72df-4ee8-8be5-a946a1429214 ), object, local, pointer_default( unique ) ]
interface ID3D12RootSignature
    : ID3D12DeviceChild
{
}

Root signature creation usually looks like:

CComPtr<ID3D12RootSignature> rootSignature;

CD3DX12_ROOT_SIGNATURE_DESC descRootSignature;
descRootSignature.Init(0, nullptr, 0, nullptr, flags);

CComPtr<ID3DBlob> signature;
CComPtr<ID3DBlob> error;
VERIFY_SUCCEEDED(D3D12SerializeRootSignature(&descRootSignature, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error));
VERIFY_SUCCEEDED(Device->CreateRootSignature(0 /*node mask*/, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&rootSignature)));

The compiler host doesn’t create a device as a result can’t use the existing ID3D12RootSignature structure that can be used with D3D12_PIPELINE_STATE_STREAM_DESC which is passed in to the compiler host CompilePipelineState API.

 HRESULT CompilePipelineState(
        [in] const D3D12_COMPILER_CACHE_SESSION_GROUP_KEY* pKey,
        D3D12_COMPILER_VALUE_TYPE_FLAGS ValueTypeFlags,
        [in] const D3D12_PIPELINE_STATE_STREAM_DESC* pDesc
        );

What are the options to fix this issue:

For simplicity solution 1 is the choice, there is no confusion on the root signature pointer type needed to be used for runtime vs compiler host and the change is limited to the PSO/SO desc.

Solution

For the compiler host to be able to compile PSO/SO from the SODB, we need to be able to save the root signature as a desc and then pass it in to the IHV compiler where the root signature will be used for PSO/SO compilation. A new subobject type is introduced for PSO stream which is D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SERIALIZED_ROOT_SIGNATURE and for SOs it is D3D12_STATE_SUBOBJECT_TYPE_SERIALIZED_ROOT_SIGNATURE. The compiler host uses a new DDI struct to pass the new subobject desc to the driver which is described in the compiler host spec.

To keep things consitent for the runtime and the compiler the new subobject type will be supported in the runtime for creating a PSO/SO. The runtime will create the root signature object pointer on behalf of the app and pass it on to the driver.

Runtime support for the new subobject type

###Changes to subobject types

typedef enum D3D12_PIPELINE_STATE_SUBOBJECT_TYPE
{
    .....
    D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SERIALIZED_ROOT_SIGNATURE, // D3D12_SERIALIZED_ROOT_SIGNATURE_DESC
}

Changes to D3D12_STATE_SUBOBJECT_TYPE

typedef enum D3D12_STATE_SUBOBJECT_TYPE
{
    .....
    D3D12_STATE_SUBOBJECT_TYPE_SERIALIZED_ROOT_SIGNATURE, // D3D12_SERIALIZED_ROOT_SIGNATURE_DESC
}

D3D12_SERIALIZED_ROOT_SIGNATURE_DESC

typedef struct D3D12_SERIALIZED_ROOT_SIGNATURE_DESC
{
_Field_size_bytes_full_(SerializedBlobSizeInBytes)  const void *pSerializedBlob;
SIZE_T SerializedBlobSizeInBytes;
} 	D3D12_SERIALIZED_ROOT_SIGNATURE_DESC;

The new way to define it will be:


CD3DX12_ROOT_SIGNATURE_DESC descRootSignature;
descRootSignature.Init(0, nullptr, 0, nullptr, flags);

 struct MyPSOStream
 {
     CD3DX12_PIPELINE_STATE_STREAM_VS VS{D3D12_SHADER_BYTECODE{g_vs_fullscreenquad, sizeof(g_vs_fullscreenquad)}};
     CD3DX12_PIPELINE_STATE_STREAM_PRIMITIVE_TOPOLOGY Topology{D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE};
     D3D12_SERIALIZED_VERSIONED_ROOT_SIGNATURE_DESC RootSigDesc;

    MyPSOStream(CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC* pRS) {
        CComPtr<ID3DBlob> signature;
        CComPtr<ID3DBlob> error;
        VERIFY_SUCCEEDED(D3D12SerializeRootSignature(pRS, pRS->Version, &signature, &error));

        RootSigDesc.pSerializedBlob = signature.p;
        RootSigDesc.Version = pRS->Version;
    }
 } PSODesc(descRootSignature);

How to handle having multiple root signature subobjects in the PSO/SO

If the PSO/SO definition has both an ID3D12RootSignature and a D3D12_SERIALIZED_ROOT_SIGNATURE_DESC it will be considered an error. Root signature definition using D3D12_SERIALIZED_ROOT_SIGNATURE_DESC is equivalent to using ID3D12RootSignature; which means it is treated with the same precedent when resolving which root signature is getting used for a PSO/SO.

Root signature getters

To make the use of the new subobject make more sense, new APIs will be get the root signature for a given PSO or for a state object program or ray tracing state object.The root signature can then be used when setting the command list or when creating other PSO/SO.

These are pending for a future revision of the API

Pipeline state object getter

Below is the function signature that will be added to the new d3d12 pipeline state interface:

ID3D12PipelineState1 : public ID3D12PipelineState
{
public:
    virtual HRESULT STDMETHODCALLTYPE GetRootSignature( 
        REFIID riid,
        _COM_Outptr_  void **ppvRootSignature) = 0;
    
};

State object root signature getters

Below are the function signatures that will be added to the new d3d12 state object properties interface:

ID3D12StateObjectProperties2 : public ID3D12StateObjectProperties1
{
public:
    virtual HRESULT STDMETHODCALLTYPE GetGlobalRootSignatureForProgram( 
        LPCWSTR pProgramName,
        REFIID riid,
        _COM_Outptr_  void **ppvRootSignature) = 0;
    
    virtual HRESULT STDMETHODCALLTYPE GetGlobalRootSignatureForShader( 
        LPCWSTR pExportName,
        REFIID riid,
        _COM_Outptr_  void **ppvRootSignature) = 0;
    
};