c++directx

how to fix CREATEGRAPHICSPIPELINESTATE_VS_ROOT_SIGNATURE_MISMATCH?


I'm trying to create an ID3D12PipelineState but CreateGraphicsPipelineState() is throwing an error

D3D12 ERROR: ID3D12Device::CreateGraphicsPipelineState: Root Signature doesn't match Vertex Shader: Shader CBV descriptor range (BaseShaderRegister=0, NumDescriptors=1, RegisterSpace=0) is not fully bound in root signature
 [ STATE_CREATION ERROR #688: CREATEGRAPHICSPIPELINESTATE_VS_ROOT_SIGNATURE_MISMATCH]

ID3D12PipelineState creation code:

D3D12_DESCRIPTOR_RANGE descrioptorRange[1];
descrioptorRange->RangeType=D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
descrioptorRange->NumDescriptors=1;
descrioptorRange->BaseShaderRegister=0;
descrioptorRange->RegisterSpace = 0; // space 0. can usually be zero
descrioptorRange->OffsetInDescriptorsFromTableStart=D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND ;
D3D12_ROOT_DESCRIPTOR_TABLE descriptorTable;
descriptorTable.NumDescriptorRanges=_countof(descrioptorRange);
descriptorTable.pDescriptorRanges=descrioptorRange;

D3D12_ROOT_PARAMETER rootParameters[1]={};

D3D12_ROOT_PARAMETER& vertexConstantParameter = rootParameters[0];
vertexConstantParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
vertexConstantParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
vertexConstantParameter.Descriptor.RegisterSpace = 0; // Пространство регистрации
vertexConstantParameter.Descriptor.ShaderRegister = 0; // Регистр шейдера для константного буфера
vertexConstantParameter.DescriptorTable=descriptorTable;

D3D12_ROOT_SIGNATURE_DESC desc;
desc.NumParameters=_countof(rootParameters);
desc.pParameters=rootParameters;
desc.NumStaticSamplers=0;
desc.pStaticSamplers=nullptr;
desc.Flags=D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | // we can deny shader stages here for better performance
    D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS |
    D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS |
    D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS |
    D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS;

ThrowF(D3D12SerializeRootSignature(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &DX12.PipeLine.serializedRootSignature, nullptr), ERROR_CREATEPIPELINE);
ThrowFEX(DX12.d3dDevice->CreateRootSignature(0, DX12.PipeLine.serializedRootSignature->GetBufferPointer(),DX12.PipeLine.serializedRootSignature->GetBufferSize(), IID_PPV_ARGS(&DX12.PipeLine.rootSignature)), ERROR_CREATEPIPELINE, DX12.d3dDevice);


// Формат вершины
D3D12_INPUT_ELEMENT_DESC inputElementDescs[] =
{
    { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, offsetof(vertex,position), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
    { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(vertex,color), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
};


D3D12_SHADER_BYTECODE vShader={};
vShader.BytecodeLength=DX12.vShader->GetBufferSize();
vShader.pShaderBytecode=DX12.vShader->GetBufferPointer();

D3D12_SHADER_BYTECODE cShader={};
cShader.BytecodeLength=DX12.cShader->GetBufferSize();
cShader.pShaderBytecode=DX12.cShader->GetBufferPointer();

D3D12_GRAPHICS_PIPELINE_STATE_DESC pipeLineDesc={};
pipeLineDesc.InputLayout={inputElementDescs,_countof(inputElementDescs)};
pipeLineDesc.pRootSignature=DX12.PipeLine.rootSignature;
pipeLineDesc.VS=vShader;
pipeLineDesc.PS=cShader;
pipeLineDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
pipeLineDesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
pipeLineDesc.PrimitiveTopologyType=D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
pipeLineDesc.NumRenderTargets = 1; 
pipeLineDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; 
pipeLineDesc.DSVFormat = DXGI_FORMAT_D32_FLOAT; 
pipeLineDesc.SampleDesc.Count = 1; 
pipeLineDesc.SampleDesc.Quality = 0; 
pipeLineDesc.SampleMask=0xffffffff;
pipeLineDesc.BlendState=CD3DX12_BLEND_DESC(D3D12_DEFAULT);
pipeLineDesc.DepthStencilState.DepthEnable = false;
pipeLineDesc.DepthStencilState.StencilEnable = false;
pipeLineDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);

ThrowF(DX12.d3dDevice->CreateGraphicsPipelineState(&pipeLineDesc, IID_PPV_ARGS(&DX12.PipeLine.pPipelineState)), ERROR_CREATEPIPELINE);

I checked all the parameters several times. I tried to disable the creation of the representation of constant buffers of the vertex shader. I tried to use instead of D3D12_RESOURCE_DESC

CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc;
     rootSignatureDesc.Init(0, nullptr, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);

I handle all exceptions, no method before CreateGraphicsPipelineState throws an error. I don't understand what constant buffer CreateGraphicsPipelineState expects and why.


Solution

  • Usage D3D12_ROOT_PARAMETER_TYPE::D3D12_ROOT_PARAMETER_TYPE_CBV cannot be used with D3D12_ROOT_PARAMETER::DescriptorTable. This inevitably results in an error because it assumes that you are using a single representation of a constant buffer.

    If you need to define multiple constant buffers, you should use D3D12_ROOT_PARAMETER_TYPE::D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE and write the representation of the buffers to ID3D12DescriptorHeap. Then use SetGraphicsRootDescriptorTable(). Alternatively, create multiple D3D12_ROOT_PARAMETER structures and use SetGraphicsRootConstantBufferView() (although I haven't tested this).