refactor(rhi): let pipeline layouts own set metadata

This commit is contained in:
2026-03-26 12:40:49 +08:00
parent 36d2f479cd
commit 476a56724f
6 changed files with 270 additions and 26 deletions

View File

@@ -4,6 +4,32 @@
namespace XCEngine {
namespace RHI {
namespace {
void AccumulateDescriptorCounts(const DescriptorSetLayoutDesc& setLayout, RHIPipelineLayoutDesc& desc) {
for (uint32_t bindingIndex = 0; bindingIndex < setLayout.bindingCount; ++bindingIndex) {
const DescriptorSetLayoutBinding& binding = setLayout.bindings[bindingIndex];
switch (static_cast<DescriptorType>(binding.type)) {
case DescriptorType::CBV:
desc.constantBufferCount += binding.count;
break;
case DescriptorType::SRV:
desc.textureCount += binding.count;
break;
case DescriptorType::UAV:
desc.uavCount += binding.count;
break;
case DescriptorType::Sampler:
desc.samplerCount += binding.count;
break;
default:
break;
}
}
}
} // namespace
D3D12PipelineLayout::D3D12PipelineLayout()
: m_device(nullptr) {
}
@@ -23,6 +49,38 @@ bool D3D12PipelineLayout::InitializeInternal(D3D12Device* device, const RHIPipel
m_device = device;
m_desc = desc;
m_setLayouts.clear();
m_setLayoutBindings.clear();
if (desc.setLayoutCount > 0 && desc.setLayouts != nullptr) {
m_desc.constantBufferCount = 0;
m_desc.textureCount = 0;
m_desc.samplerCount = 0;
m_desc.uavCount = 0;
m_setLayouts.resize(desc.setLayoutCount);
m_setLayoutBindings.resize(desc.setLayoutCount);
for (uint32_t setIndex = 0; setIndex < desc.setLayoutCount; ++setIndex) {
const DescriptorSetLayoutDesc& srcSetLayout = desc.setLayouts[setIndex];
auto& dstBindings = m_setLayoutBindings[setIndex];
if (srcSetLayout.bindingCount > 0 && srcSetLayout.bindings != nullptr) {
dstBindings.assign(
srcSetLayout.bindings,
srcSetLayout.bindings + srcSetLayout.bindingCount);
}
DescriptorSetLayoutDesc dstSetLayout = {};
dstSetLayout.bindingCount = srcSetLayout.bindingCount;
dstSetLayout.bindings = dstBindings.empty() ? nullptr : dstBindings.data();
m_setLayouts[setIndex] = dstSetLayout;
AccumulateDescriptorCounts(dstSetLayout, m_desc);
}
m_desc.setLayouts = m_setLayouts.data();
m_desc.setLayoutCount = static_cast<uint32_t>(m_setLayouts.size());
}
m_rootParameters.clear();
m_descriptorRanges.clear();
@@ -31,31 +89,33 @@ bool D3D12PipelineLayout::InitializeInternal(D3D12Device* device, const RHIPipel
m_unorderedAccessTableRootIndex = UINT32_MAX;
m_samplerTableRootIndex = UINT32_MAX;
const RHIPipelineLayoutDesc& normalizedDesc = m_desc;
const uint32_t rootParameterCount =
desc.constantBufferCount +
(desc.textureCount > 0 ? 1u : 0u) +
(desc.uavCount > 0 ? 1u : 0u) +
(desc.samplerCount > 0 ? 1u : 0u);
normalizedDesc.constantBufferCount +
(normalizedDesc.textureCount > 0 ? 1u : 0u) +
(normalizedDesc.uavCount > 0 ? 1u : 0u) +
(normalizedDesc.samplerCount > 0 ? 1u : 0u);
const uint32_t descriptorRangeCount =
(desc.textureCount > 0 ? 1u : 0u) +
(desc.uavCount > 0 ? 1u : 0u) +
(desc.samplerCount > 0 ? 1u : 0u);
(normalizedDesc.textureCount > 0 ? 1u : 0u) +
(normalizedDesc.uavCount > 0 ? 1u : 0u) +
(normalizedDesc.samplerCount > 0 ? 1u : 0u);
m_rootParameters.reserve(rootParameterCount);
m_descriptorRanges.reserve(descriptorRangeCount);
uint32_t rootIndex = 0;
for (uint32_t i = 0; i < desc.constantBufferCount; ++i) {
for (uint32_t i = 0; i < normalizedDesc.constantBufferCount; ++i) {
D3D12_ROOT_PARAMETER param = D3D12RootSignature::CreateCBV(i, ShaderVisibility::All, 0);
m_rootParameters.push_back(param);
m_constantBufferRootIndices[i] = rootIndex;
rootIndex++;
}
if (desc.textureCount > 0) {
if (normalizedDesc.textureCount > 0) {
m_descriptorRanges.push_back(D3D12RootSignature::CreateDescriptorRange(
D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, desc.textureCount, 0));
D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, normalizedDesc.textureCount, 0));
D3D12_ROOT_PARAMETER param = D3D12RootSignature::CreateDescriptorTable(
1, &m_descriptorRanges.back(), ShaderVisibility::All);
m_rootParameters.push_back(param);
@@ -63,9 +123,9 @@ bool D3D12PipelineLayout::InitializeInternal(D3D12Device* device, const RHIPipel
rootIndex++;
}
if (desc.uavCount > 0) {
if (normalizedDesc.uavCount > 0) {
m_descriptorRanges.push_back(D3D12RootSignature::CreateDescriptorRange(
D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, desc.uavCount, 0));
D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, normalizedDesc.uavCount, 0));
D3D12_ROOT_PARAMETER param = D3D12RootSignature::CreateDescriptorTable(
1, &m_descriptorRanges.back(), ShaderVisibility::All);
m_rootParameters.push_back(param);
@@ -73,9 +133,9 @@ bool D3D12PipelineLayout::InitializeInternal(D3D12Device* device, const RHIPipel
rootIndex++;
}
if (desc.samplerCount > 0) {
if (normalizedDesc.samplerCount > 0) {
m_descriptorRanges.push_back(D3D12RootSignature::CreateDescriptorRange(
D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 0, desc.samplerCount, 0));
D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 0, normalizedDesc.samplerCount, 0));
D3D12_ROOT_PARAMETER param = D3D12RootSignature::CreateDescriptorTable(
1, &m_descriptorRanges.back(), ShaderVisibility::All);
m_rootParameters.push_back(param);
@@ -124,6 +184,8 @@ void D3D12PipelineLayout::Shutdown() {
m_shaderResourceTableRootIndex = UINT32_MAX;
m_unorderedAccessTableRootIndex = UINT32_MAX;
m_samplerTableRootIndex = UINT32_MAX;
m_setLayouts.clear();
m_setLayoutBindings.clear();
m_device = nullptr;
}

View File

@@ -3,14 +3,75 @@
namespace XCEngine {
namespace RHI {
namespace {
void AccumulateDescriptorCounts(const DescriptorSetLayoutDesc& setLayout, RHIPipelineLayoutDesc& desc) {
for (uint32_t bindingIndex = 0; bindingIndex < setLayout.bindingCount; ++bindingIndex) {
const DescriptorSetLayoutBinding& binding = setLayout.bindings[bindingIndex];
switch (static_cast<DescriptorType>(binding.type)) {
case DescriptorType::CBV:
desc.constantBufferCount += binding.count;
break;
case DescriptorType::SRV:
desc.textureCount += binding.count;
break;
case DescriptorType::UAV:
desc.uavCount += binding.count;
break;
case DescriptorType::Sampler:
desc.samplerCount += binding.count;
break;
default:
break;
}
}
}
} // namespace
bool OpenGLPipelineLayout::Initialize(const RHIPipelineLayoutDesc& desc) {
m_desc = desc;
m_setLayouts.clear();
m_setLayoutBindings.clear();
if (desc.setLayoutCount > 0 && desc.setLayouts != nullptr) {
m_desc.constantBufferCount = 0;
m_desc.textureCount = 0;
m_desc.samplerCount = 0;
m_desc.uavCount = 0;
m_setLayouts.resize(desc.setLayoutCount);
m_setLayoutBindings.resize(desc.setLayoutCount);
for (uint32_t setIndex = 0; setIndex < desc.setLayoutCount; ++setIndex) {
const DescriptorSetLayoutDesc& srcSetLayout = desc.setLayouts[setIndex];
auto& dstBindings = m_setLayoutBindings[setIndex];
if (srcSetLayout.bindingCount > 0 && srcSetLayout.bindings != nullptr) {
dstBindings.assign(
srcSetLayout.bindings,
srcSetLayout.bindings + srcSetLayout.bindingCount);
}
DescriptorSetLayoutDesc dstSetLayout = {};
dstSetLayout.bindingCount = srcSetLayout.bindingCount;
dstSetLayout.bindings = dstBindings.empty() ? nullptr : dstBindings.data();
m_setLayouts[setIndex] = dstSetLayout;
AccumulateDescriptorCounts(dstSetLayout, m_desc);
}
m_desc.setLayouts = m_setLayouts.data();
m_desc.setLayoutCount = static_cast<uint32_t>(m_setLayouts.size());
}
m_initialized = true;
return true;
}
void OpenGLPipelineLayout::Shutdown() {
m_desc = {};
m_setLayouts.clear();
m_setLayoutBindings.clear();
m_initialized = false;
}