代码之家  ›  专栏  ›  技术社区  ›  Carsten

如何将常量缓冲区视图“完全绑定”到描述符范围?

  •  0
  • Carsten  · 技术社区  · 3 年前

    我目前正在学习DirectX 12并尝试运行演示应用程序。我目前一直在使用根签名创建管道状态对象。我正在使用 要编译顶点着色器,请执行以下操作:

    ./dxc -T vs_6_3 -E main -Fo "basic.vert.dxi" -D DXIL "basic.vert"
    

    我的着色器如下所示:

    #pragma pack_matrix(row_major)
    
    struct VertexData 
    {
        float4 Position : SV_POSITION;
        float4 Color : COLOR;
    }; 
    
    struct VertexInput
    {
        float3 Position : POSITION;
        float4 Color : COLOR;
    };
    
    struct CameraData
    {
        float4x4 ViewProjection;
    };
    
    ConstantBuffer<CameraData> camera : register(b0, space0);
    
    VertexData main(in VertexInput input)
    {
        VertexData vertex;
        
        vertex.Position = mul(float4(input.Position, 1.0), camera.ViewProjection);
        vertex.Color = input.Color;
     
        return vertex;
    }
    

    现在我想为我的着色器定义一个根签名。定义如下:

    CD3DX12_DESCRIPTOR_RANGE1 descriptorRange;
    descriptorRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0, 0, D3D12_DESCRIPTOR_RANGE_FLAG_DATA_STATIC, D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND);
    
    CD3DX12_ROOT_PARAMETER1 rootParameter;
    rootParameter.InitAsDescriptorTable(1, &descriptorRange, D3D12_SHADER_VISIBILITY_VERTEX);
    
    ComPtr<ID3DBlob> signature, error;
    CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC rootSignatureDesc;
    rootSignatureDesc.Init_1_1(1, &rootParameter, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
    ::D3D12SerializeVersionedRootSignature(&rootSignatureDesc, &signature, &error);
    
    ComPtr<ID3D12RootSignature> rootSignature;
    device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&rootSignature));
    

    最后,我将根签名与其他状态变量一起传递给管道状态对象:

    D3D12_GRAPHICS_PIPELINE_STATE_DESC pipelineStateDescription = {};
    // ...
    pipelineStateDescription.pRootSignature = rootSignature.Get();
    
    ComPtr<ID3D12PipelineState> pipelineState;
    device->CreateGraphicsPipelineState(&pipelineStateDescription, IID_PPV_ARGS(&pipelineState));
    

    [STATE_创建错误#688:CREATEGRAPHICSPIPELINESTATE_VS_ROOT_SIGNATURE_不匹配]

    D3D12: 中断 为上一条消息启用,该消息为:[错误状态_创建#688:CREATEGRAPHICSPIPELINESTATE\u VS_ROOT\u SIGNATURE\u不匹配]

    我对这个错误试图告诉我什么感到困惑,因为我显然有一个常数缓冲区绑定到 register(b0, space0) . 或者这是否意味着我必须在创建管道状态对象之前从堆中分配描述符?

    我还尝试在着色器本身中定义根签名:

    #define ShaderRootSignature \
        "RootFlags( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT ), " \
                  "DescriptorTable( CBV(b0, space = 0, numDescriptors = 1, flags = DATA_STATIC ) ), "
    

    ... 并使用 [RootSignature(ShaderRootSignature)] ,或指定 -rootsig-define "ShaderRootSignature" 用于dxc。然后我试着按建议加载签名 here 但是,这两种方法都失败了,因为无法从着色器字节码中读取根签名。

    如果能澄清如何解释错误消息,我将不胜感激,因为我真的不知道 根签名中的绑定 在本文中是指。提前感谢!

    0 回复  |  直到 3 年前
        1
  •  0
  •   Carsten    3 年前

    长话短说:DX12中的着色器可见性不是像中那样的位场 Vulkan ,因此将可见性设置为 D3D12_SHADER_VISIBILITY_VERTEX | D3D12_SHADER_VISIBILITY_PIXEL 导致参数仅对像素着色器可见。将其设置为 D3D12_SHADER_VISIBILITY_ALL 解决了我的问题。