Fix D3D12 descriptor set staging for shader tables
This commit is contained in:
@@ -348,10 +348,12 @@ void D3D12CommandList::SetGraphicsDescriptorSets(
|
||||
}
|
||||
|
||||
D3D12DescriptorHeap* heap = d3d12Set->GetHeap();
|
||||
if (heap == nullptr || !heap->IsShaderVisible()) {
|
||||
if (heap == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Descriptor sets are staged in CPU-visible heaps and copied into this
|
||||
// command list's shader-visible heaps immediately before binding.
|
||||
if (heap->GetType() == DescriptorHeapType::CBV_SRV_UAV) {
|
||||
const bool hasSrvTable = d3d12Layout->UsesSetLayouts()
|
||||
? d3d12Layout->HasShaderResourceTable(setIndex)
|
||||
@@ -581,10 +583,12 @@ void D3D12CommandList::SetComputeDescriptorSets(
|
||||
}
|
||||
|
||||
D3D12DescriptorHeap* heap = d3d12Set->GetHeap();
|
||||
if (heap == nullptr || !heap->IsShaderVisible()) {
|
||||
if (heap == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Descriptor sets are staged in CPU-visible heaps and copied into this
|
||||
// command list's shader-visible heaps immediately before binding.
|
||||
if (heap->GetType() == DescriptorHeapType::CBV_SRV_UAV) {
|
||||
const bool hasSrvTable = d3d12Layout->UsesSetLayouts()
|
||||
? d3d12Layout->HasShaderResourceTable(setIndex)
|
||||
|
||||
@@ -77,6 +77,9 @@ D3D12_CPU_DESCRIPTOR_HANDLE D3D12DescriptorHeap::GetCPUDescriptorHandleForHeapSt
|
||||
}
|
||||
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE D3D12DescriptorHeap::GetGPUDescriptorHandleForHeapStart() const {
|
||||
if (!m_shaderVisible || m_descriptorHeap == nullptr) {
|
||||
return D3D12_GPU_DESCRIPTOR_HANDLE{0};
|
||||
}
|
||||
return m_descriptorHeap->GetGPUDescriptorHandleForHeapStart();
|
||||
}
|
||||
|
||||
@@ -89,6 +92,10 @@ CPUDescriptorHandle D3D12DescriptorHeap::GetCPUDescriptorHandle(uint32_t index)
|
||||
}
|
||||
|
||||
GPUDescriptorHandle D3D12DescriptorHeap::GetGPUDescriptorHandle(uint32_t index) {
|
||||
if (!m_shaderVisible || m_descriptorHeap == nullptr) {
|
||||
return GPUDescriptorHandle{0};
|
||||
}
|
||||
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE handle = m_descriptorHeap->GetGPUDescriptorHandleForHeapStart();
|
||||
handle.ptr += index * m_descriptorSize;
|
||||
GPUDescriptorHandle result;
|
||||
|
||||
@@ -51,6 +51,10 @@ bool HasShaderPayload(const ShaderCompileDesc& desc) {
|
||||
return !desc.source.empty() || !desc.fileName.empty() || !desc.compiledBinary.empty();
|
||||
}
|
||||
|
||||
bool UsesTransientShaderVisibleDescriptorHeap(DescriptorHeapType type) {
|
||||
return type == DescriptorHeapType::CBV_SRV_UAV || type == DescriptorHeapType::Sampler;
|
||||
}
|
||||
|
||||
bool ShouldTraceVolumetricShaderCompile(const ShaderCompileDesc& desc) {
|
||||
const std::string fileName = NarrowAscii(desc.fileName);
|
||||
if (fileName.find("volumetric") != std::string::npos) {
|
||||
@@ -1279,6 +1283,11 @@ RHIDescriptorPool* D3D12Device::CreateDescriptorPool(const DescriptorPoolDesc& d
|
||||
auto* pool = new D3D12DescriptorHeap();
|
||||
DescriptorPoolDesc poolDesc = desc;
|
||||
poolDesc.device = m_device.Get();
|
||||
if (UsesTransientShaderVisibleDescriptorHeap(poolDesc.type)) {
|
||||
// Descriptor sets are staged in CPU-visible heaps and copied into the
|
||||
// command list's transient shader-visible heaps before each bind.
|
||||
poolDesc.shaderVisible = false;
|
||||
}
|
||||
if (pool->Initialize(poolDesc)) {
|
||||
return pool;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "fixtures/D3D12TestFixture.h"
|
||||
|
||||
#include "XCEngine/RHI/D3D12/D3D12DescriptorHeap.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12DescriptorSet.h"
|
||||
#include "XCEngine/RHI/D3D12/D3D12PipelineLayout.h"
|
||||
#include "XCEngine/RHI/RHIDescriptorPool.h"
|
||||
@@ -54,6 +55,64 @@ TEST_F(D3D12TestFixture, DescriptorSet_MixedBindings_AssignDescriptorIndicesByTy
|
||||
delete pool;
|
||||
}
|
||||
|
||||
TEST_F(D3D12TestFixture, DescriptorSet_TableBindingsUseCpuVisibleStagingHeaps) {
|
||||
DescriptorPoolDesc texturePoolDesc = {};
|
||||
texturePoolDesc.type = DescriptorHeapType::CBV_SRV_UAV;
|
||||
texturePoolDesc.descriptorCount = 2;
|
||||
texturePoolDesc.shaderVisible = true;
|
||||
|
||||
RHIDescriptorPool* texturePool = GetDevice()->CreateDescriptorPool(texturePoolDesc);
|
||||
ASSERT_NE(texturePool, nullptr);
|
||||
|
||||
DescriptorSetLayoutBinding textureBinding = {};
|
||||
textureBinding.binding = 0;
|
||||
textureBinding.type = static_cast<uint32_t>(DescriptorType::SRV);
|
||||
textureBinding.count = 1;
|
||||
|
||||
DescriptorSetLayoutDesc textureLayoutDesc = {};
|
||||
textureLayoutDesc.bindings = &textureBinding;
|
||||
textureLayoutDesc.bindingCount = 1;
|
||||
|
||||
RHIDescriptorSet* textureSet = texturePool->AllocateSet(textureLayoutDesc);
|
||||
ASSERT_NE(textureSet, nullptr);
|
||||
auto* textureD3D12Set = static_cast<D3D12DescriptorSet*>(textureSet);
|
||||
ASSERT_NE(textureD3D12Set->GetHeap(), nullptr);
|
||||
EXPECT_FALSE(textureD3D12Set->GetHeap()->IsShaderVisible());
|
||||
|
||||
DescriptorPoolDesc samplerPoolDesc = {};
|
||||
samplerPoolDesc.type = DescriptorHeapType::Sampler;
|
||||
samplerPoolDesc.descriptorCount = 1;
|
||||
samplerPoolDesc.shaderVisible = true;
|
||||
|
||||
RHIDescriptorPool* samplerPool = GetDevice()->CreateDescriptorPool(samplerPoolDesc);
|
||||
ASSERT_NE(samplerPool, nullptr);
|
||||
|
||||
DescriptorSetLayoutBinding samplerBinding = {};
|
||||
samplerBinding.binding = 0;
|
||||
samplerBinding.type = static_cast<uint32_t>(DescriptorType::Sampler);
|
||||
samplerBinding.count = 1;
|
||||
|
||||
DescriptorSetLayoutDesc samplerLayoutDesc = {};
|
||||
samplerLayoutDesc.bindings = &samplerBinding;
|
||||
samplerLayoutDesc.bindingCount = 1;
|
||||
|
||||
RHIDescriptorSet* samplerSet = samplerPool->AllocateSet(samplerLayoutDesc);
|
||||
ASSERT_NE(samplerSet, nullptr);
|
||||
auto* samplerD3D12Set = static_cast<D3D12DescriptorSet*>(samplerSet);
|
||||
ASSERT_NE(samplerD3D12Set->GetHeap(), nullptr);
|
||||
EXPECT_FALSE(samplerD3D12Set->GetHeap()->IsShaderVisible());
|
||||
|
||||
textureSet->Shutdown();
|
||||
delete textureSet;
|
||||
texturePool->Shutdown();
|
||||
delete texturePool;
|
||||
|
||||
samplerSet->Shutdown();
|
||||
delete samplerSet;
|
||||
samplerPool->Shutdown();
|
||||
delete samplerPool;
|
||||
}
|
||||
|
||||
TEST_F(D3D12TestFixture, DescriptorSet_MultipleConstantBuffersUploadIndependently) {
|
||||
DescriptorPoolDesc poolDesc = {};
|
||||
poolDesc.type = DescriptorHeapType::CBV_SRV_UAV;
|
||||
|
||||
Reference in New Issue
Block a user