D3D12多纹理绑定至像素着色器失败,求助解决方法
问题场景
像素着色器声明了两个Texture2D资源,使用Load(int3)方法访问像素,无需采样器:
Texture2D<uint> u_texture : register(t0); Texture2D u_palette : register(t1);
当前实现代码
1. SRV堆创建
D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {}; srvHeapDesc.NumDescriptors = 1; srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; ThrowIfFailed(g_device->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&i_srvHeap)));
2. SRV创建(单个纹理)
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; srvDesc.Format = DXGI_FORMAT_R8_UINT; srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; srvDesc.Texture2D.MipLevels = 1; g_device->CreateShaderResourceView(t->texture.Get(), &srvDesc, i_srvHeap->GetCPUDescriptorHandleForHeapStart());
(另一个纹理使用不同纹素格式,未完成SRV写入堆的操作)
3. 渲染命令绑定
i_commandList->SetPipelineState(p->pipelineState); i_commandList->SetGraphicsRootSignature(p->signature); i_commandList->SetGraphicsRootDescriptorTable(0, i_srvHeap->GetGPUDescriptorHandleForHeapStart()); i_commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); i_commandList->IASetVertexBuffers(0, 1, &v->view); i_commandList->DrawInstanced(count, 1, 0, 0);
错误信息
D3D12 ERROR: CGraphicsCommandList::SetGraphicsRootDescriptorTable: Specified GPU Descriptor Handle (ptr = 0x8000019dcfe14d3d at 0 offsetInDescriptorsFromDescriptorHeapStart) of type SRV, for Root Signature (0x0000019E56769000:'Unnamed ID3D12RootSignature Object')'s Descriptor Table (at Parameter Index [0])'s Descriptor Range (at Range Index [0] of type D3D12_DESCRIPTOR_RANGE_TYPE_CBV) have mismatching types. All descriptors of descriptor ranges declared STATIC (not-DESCRIPTORS_VOLATILE) in a root signature must be initialized prior to being set on the command list. [ EXECUTION ERROR #646: INVALID_DESCRIPTOR_HANDLE]
解决思路
- 修正根签名资源类型匹配:错误明确根签名中参数索引0的描述符范围类型为
D3D12_DESCRIPTOR_RANGE_TYPE_CBV,但绑定的是SRV类型资源。需修改根签名创建代码,将对应描述符范围类型设为D3D12_DESCRIPTOR_RANGE_TYPE_SRV,同时设置范围大小为2,对应t0和t1两个寄存器。 - 扩展SRV堆容量:当前SRV堆仅申请1个描述符空间,无法容纳两个纹理的SRV,需将
srvHeapDesc.NumDescriptors改为2。 - 正确写入第二个纹理的SRV:第一个纹理的SRV写入堆起始位置后,第二个纹理需写入堆的下一个描述符位置。通过设备接口获取描述符步长,计算目标句柄:
UINT srvIncrement = g_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); D3D12_CPU_DESCRIPTOR_HANDLE secondSrvHandle = i_srvHeap->GetCPUDescriptorHandleForHeapStart(); secondSrvHandle.ptr += srvIncrement; // 调用CreateShaderResourceView将第二个纹理的SRV写入secondSrvHandle - 验证根签名布局:确保根签名中描述符表的
BaseShaderRegister设为0,NumDescriptors设为2,与着色器中的t0、t1寄存器绑定完全对应。
内容的提问来源于stack exchange,提问作者Gunnar

