D3D12中UAV/SRV描述符Pix显示无效但功能正常无调试警告
所有功能运行正常,但PIX工具显示UAV/SRV描述符无效,且未收到任何D3D12调试层警告。相关资源及视图创建代码如下:
auto& [res, srv, uav] = pingpongs[i]; { auto desc = CD3DX12_RESOURCE_DESC::Buffer(PINGPONG_BYTES, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS); device->CreateCommittedResource( &heap_default, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_COMMON, nullptr, IID_PPV_ARGS(res.put())); res->SetName(std::format(L"ComputeEngine::m_fft_ping_pong{}", i).c_str()); } { auto [cpu, gpu] = allocator.Allocate(); D3D12_SHADER_RESOURCE_VIEW_DESC desc{}; #if 1 desc.Format = DXGI_FORMAT_R32G32_FLOAT; desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; desc.Buffer.NumElements = PINGPONG_ELEMENTS; #else desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; desc.Buffer.NumElements = PINGPONG_ELEMENTS; desc.Buffer.StructureByteStride = 8U; #endif device->CreateShaderResourceView(res.get(), &desc, cpu); srv = gpu; } { auto [cpu, gpu] = allocator.Allocate(); D3D12_UNORDERED_ACCESS_VIEW_DESC desc{}; #if 1 desc.Format = DXGI_FORMAT_R32G32_FLOAT; desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; desc.Buffer.NumElements = PINGPONG_ELEMENTS; #else desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; desc.Buffer.NumElements = PINGPONG_ELEMENTS; desc.Buffer.StructureByteStride = 8U; #endif device->CreateUnorderedAccessView(res.get(), nullptr, &desc, cpu); uav = gpu; }
问题排查与解决方案
校验资源尺寸与视图参数匹配
确保PINGPONG_BYTES的数值等于PINGPONG_ELEMENTS * sizeof(float2)(即PINGPONG_ELEMENTS * 8)。如果两者不匹配,视图描述符的元素数量会和实际资源大小不符,PIX会判定描述符无效,即使功能暂时正常。规范结构化缓冲区视图配置(#else分支)
当使用结构化缓冲区模式(设置StructureByteStride)时,需要显式将视图的Format设为DXGI_FORMAT_UNKNOWN——D3D12中结构化缓冲区的视图不需要指定格式,虽然代码默认会初始化为0(对应DXGI_FORMAT_UNKNOWN),显式设置可以避免PIX的误判。修改后的代码片段如下:// SRV #else分支 desc.Format = DXGI_FORMAT_UNKNOWN; desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; desc.Buffer.NumElements = PINGPONG_ELEMENTS; desc.Buffer.StructureByteStride = 8U; // UAV #else分支 desc.Format = DXGI_FORMAT_UNKNOWN; desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; desc.Buffer.NumElements = PINGPONG_ELEMENTS; desc.Buffer.StructureByteStride = 8U;明确Typed缓冲区视图的默认参数(#if 1分支)
对于Typed缓冲区模式(指定Format),可以显式补充Buffer.FirstElement = 0和Buffer.ByteOffset = 0参数。虽然这些参数默认值就是0,但显式设置能让PIX更准确识别视图的合法性:// SRV #if 1分支 desc.Format = DXGI_FORMAT_R32G32_FLOAT; desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; desc.Buffer.NumElements = PINGPONG_ELEMENTS; desc.Buffer.FirstElement = 0; desc.Buffer.ByteOffset = 0; // UAV #if 1分支 desc.Format = DXGI_FORMAT_R32G32_FLOAT; desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; desc.Buffer.NumElements = PINGPONG_ELEMENTS; desc.Buffer.FirstElement = 0;检查描述符堆配置
确认分配描述符的allocator对应的是D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV类型的堆,且堆创建时设置了D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE标志——虽然功能正常说明堆配置大概率正确,但PIX可能会对非Shader可见的堆标记描述符无效。PIX假阳性可能性
如果上述调整后PIX仍提示无效,且功能完全正常,可能是PIX的误判。可以尝试更新PIX到最新版本,或者忽略该警告(只要调试层无报错、功能正常,就说明描述符实际是合法的)。
内容的提问来源于stack exchange,提问作者Tom Huntington

