如何修复CREATEGRAPHICSPIPELINESTATE_VS_ROOT_SIGNATURE_MISMATCH错误?
问题分析
错误CREATEGRAPHICSPIPELINESTATE_VS_ROOT_SIGNATURE_MISMATCH的核心原因是:根签名定义与顶点着色器的资源需求不匹配。顶点着色器期望绑定寄存器b0(空间0)的CBV,但你的根签名没有正确暴露该资源。
查看代码会发现,根参数设置存在矛盾:你将ParameterType设为D3D12_ROOT_PARAMETER_TYPE_CBV(根CBV),却同时给DescriptorTable字段赋值。根参数的类型与配置字段必须一一对应——要么是直接的根CBV(仅使用Descriptor字段),要么是描述符表(仅使用DescriptorTable字段,此时ParameterType需设为D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE),不能混用。
解决方案
根据需求提供两种正确实现方式:
方式一:使用根CBV(直接将CBV放入根签名)
适合单个常量缓冲区场景,无需额外描述符堆,修改代码如下:
D3D12_ROOT_PARAMETER rootParameters[1] = {}; // 配置根CBV参数 D3D12_ROOT_PARAMETER& vertexConstantParameter = rootParameters[0]; vertexConstantParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; vertexConstantParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX; // 仅设置Descriptor字段,不要赋值DescriptorTable vertexConstantParameter.Descriptor.RegisterSpace = 0; vertexConstantParameter.Descriptor.ShaderRegister = 0; // 根签名描述保持不变 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 | 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);
方式二:使用描述符表CBV(将CBV放入描述符堆)
适合需要多个CBV或其他资源(如SRV/UAV)的场景,修改代码如下:
D3D12_DESCRIPTOR_RANGE descriptorRange[1]; descriptorRange->RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV; descriptorRange->NumDescriptors = 1; descriptorRange->BaseShaderRegister = 0; descriptorRange->RegisterSpace = 0; descriptorRange->OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; D3D12_ROOT_DESCRIPTOR_TABLE descriptorTable; descriptorTable.NumDescriptorRanges = _countof(descriptorRange); descriptorTable.pDescriptorRanges = descriptorRange; D3D12_ROOT_PARAMETER rootParameters[1] = {}; D3D12_ROOT_PARAMETER& vertexConstantParameter = rootParameters[0]; // 参数类型改为描述符表 vertexConstantParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; vertexConstantParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX; // 仅设置DescriptorTable字段,不要赋值Descriptor 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 | 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);
额外检查点
- 确认顶点着色器代码中,常量缓冲区确实绑定在
register(b0, space0),示例HLSL代码如下:cbuffer ConstantBuffer : register(b0) { float4x4 worldViewProj; }; - 若尝试空根签名仍报错,说明顶点着色器确实依赖该CBV,必须在根签名中正确声明,无法省略。
内容的提问来源于stack exchange,提问作者I101I
相关产品推荐
相关产品推荐

