Share builtin pass layout assembly utilities

This commit is contained in:
2026-04-04 13:48:13 +08:00
parent 0ebd2d4979
commit a3ba08bb99
7 changed files with 328 additions and 180 deletions

View File

@@ -52,72 +52,6 @@ private:
namespace {
RHI::DescriptorType ToDescriptorType(Resources::ShaderResourceType type) {
switch (type) {
case Resources::ShaderResourceType::ConstantBuffer:
return RHI::DescriptorType::CBV;
case Resources::ShaderResourceType::Texture2D:
case Resources::ShaderResourceType::TextureCube:
return RHI::DescriptorType::SRV;
case Resources::ShaderResourceType::Sampler:
return RHI::DescriptorType::Sampler;
default:
return RHI::DescriptorType::CBV;
}
}
RHI::DescriptorHeapType ResolveDescriptorHeapType(Resources::ShaderResourceType type) {
return type == Resources::ShaderResourceType::Sampler
? RHI::DescriptorHeapType::Sampler
: RHI::DescriptorHeapType::CBV_SRV_UAV;
}
bool IsShaderVisibleSet(const std::vector<RHI::DescriptorSetLayoutBinding>& bindings) {
for (const RHI::DescriptorSetLayoutBinding& binding : bindings) {
const RHI::DescriptorType descriptorType = static_cast<RHI::DescriptorType>(binding.type);
if (descriptorType == RHI::DescriptorType::SRV ||
descriptorType == RHI::DescriptorType::UAV ||
descriptorType == RHI::DescriptorType::Sampler) {
return true;
}
}
return false;
}
uint32_t CountHeapDescriptors(
RHI::DescriptorHeapType heapType,
const std::vector<RHI::DescriptorSetLayoutBinding>& bindings) {
uint32_t descriptorCount = 0;
for (const RHI::DescriptorSetLayoutBinding& binding : bindings) {
const RHI::DescriptorType descriptorType = static_cast<RHI::DescriptorType>(binding.type);
if (heapType == RHI::DescriptorHeapType::Sampler) {
if (descriptorType == RHI::DescriptorType::Sampler) {
descriptorCount += binding.count > 0 ? binding.count : 1u;
}
continue;
}
if (descriptorType != RHI::DescriptorType::Sampler) {
descriptorCount += binding.count > 0 ? binding.count : 1u;
}
}
return descriptorCount > 0 ? descriptorCount : 1u;
}
bool BindingNumberExists(
const std::vector<RHI::DescriptorSetLayoutBinding>& bindings,
uint32_t bindingNumber) {
for (const RHI::DescriptorSetLayoutBinding& binding : bindings) {
if (binding.binding == bindingNumber) {
return true;
}
}
return false;
}
bool TryResolveSurfacePassType(
const Resources::Material* material,
BuiltinMaterialPass& outPass) {
@@ -582,7 +516,10 @@ BuiltinForwardPipeline::PassResourceLayout* BuiltinForwardPipeline::GetOrCreateP
const bool hasAnyResource = !bindingPlan.bindings.Empty();
if (hasAnyResource) {
passLayout.setLayouts.resize(static_cast<size_t>(bindingPlan.maxSetIndex) + 1u);
Containers::String setLayoutError;
if (!TryBuildBuiltinPassSetLayouts(bindingPlan, passLayout.setLayouts, &setLayoutError)) {
return failLayout(setLayoutError.CStr());
}
passLayout.staticDescriptorSets.resize(passLayout.setLayouts.size());
passLayout.firstDescriptorSet = bindingPlan.firstDescriptorSet;
passLayout.descriptorSetCount = bindingPlan.descriptorSetCount;
@@ -593,51 +530,6 @@ BuiltinForwardPipeline::PassResourceLayout* BuiltinForwardPipeline::GetOrCreateP
passLayout.baseColorTexture = bindingPlan.baseColorTexture;
passLayout.linearClampSampler = bindingPlan.linearClampSampler;
for (const BuiltinPassResourceBindingDesc& binding : bindingPlan.bindings) {
if (binding.location.set >= passLayout.setLayouts.size()) {
return failLayout("BuiltinForwardPipeline encountered an invalid forward shader resource set");
}
const RHI::DescriptorType descriptorType = ToDescriptorType(binding.resourceType);
const RHI::DescriptorHeapType heapType = ResolveDescriptorHeapType(binding.resourceType);
PassSetLayoutMetadata& setLayout = passLayout.setLayouts[binding.location.set];
if (!setLayout.bindings.empty() && setLayout.heapType != heapType) {
return failLayout("BuiltinForwardPipeline does not support mixing sampler and non-sampler bindings in one set");
}
if (BindingNumberExists(setLayout.bindings, binding.location.binding)) {
return failLayout("BuiltinForwardPipeline encountered duplicate bindings inside one descriptor set");
}
if (setLayout.bindings.empty()) {
setLayout.heapType = heapType;
}
RHI::DescriptorSetLayoutBinding layoutBinding = {};
layoutBinding.binding = binding.location.binding;
layoutBinding.type = static_cast<uint32_t>(descriptorType);
layoutBinding.count = 1;
setLayout.bindings.push_back(layoutBinding);
switch (binding.semantic) {
case BuiltinPassResourceSemantic::PerObject:
setLayout.usesPerObject = true;
break;
case BuiltinPassResourceSemantic::Material:
setLayout.usesMaterial = true;
break;
case BuiltinPassResourceSemantic::BaseColorTexture:
setLayout.usesTexture = true;
break;
case BuiltinPassResourceSemantic::LinearClampSampler:
setLayout.usesSampler = true;
break;
default:
return failLayout("BuiltinForwardPipeline encountered an unsupported forward shader resource semantic");
}
}
if (!passLayout.perObject.IsValid()) {
return failLayout("BuiltinForwardPipeline requires a PerObject resource binding");
}
@@ -646,7 +538,7 @@ BuiltinForwardPipeline::PassResourceLayout* BuiltinForwardPipeline::GetOrCreateP
passLayout.firstDescriptorSet > 0 &&
!passLayout.setLayouts.empty() &&
passLayout.setLayouts[0].bindings.empty()) {
PassSetLayoutMetadata& compatibilitySet = passLayout.setLayouts[0];
BuiltinPassSetLayoutMetadata& compatibilitySet = passLayout.setLayouts[0];
if (bindingPlan.usesConstantBuffers) {
compatibilitySet.bindings.push_back({
0,
@@ -671,20 +563,7 @@ BuiltinForwardPipeline::PassResourceLayout* BuiltinForwardPipeline::GetOrCreateP
0
});
}
compatibilitySet.shaderVisible = true;
}
for (Core::uint32 setIndex = 0; setIndex < passLayout.setLayouts.size(); ++setIndex) {
PassSetLayoutMetadata& setLayout = passLayout.setLayouts[setIndex];
std::sort(
setLayout.bindings.begin(),
setLayout.bindings.end(),
[](const RHI::DescriptorSetLayoutBinding& left, const RHI::DescriptorSetLayoutBinding& right) {
return left.binding < right.binding;
});
setLayout.shaderVisible = IsShaderVisibleSet(setLayout.bindings);
setLayout.layout.bindings = setLayout.bindings.empty() ? nullptr : setLayout.bindings.data();
setLayout.layout.bindingCount = static_cast<uint32_t>(setLayout.bindings.size());
RefreshBuiltinPassSetLayoutMetadata(compatibilitySet);
}
std::vector<RHI::DescriptorSetLayoutDesc> nativeSetLayouts(passLayout.setLayouts.size());
@@ -702,10 +581,7 @@ BuiltinForwardPipeline::PassResourceLayout* BuiltinForwardPipeline::GetOrCreateP
const auto result = m_passResourceLayouts.emplace(passLayoutKey, passLayout);
PassResourceLayout& storedPassLayout = result.first->second;
for (PassSetLayoutMetadata& setLayout : storedPassLayout.setLayouts) {
setLayout.layout.bindings = setLayout.bindings.empty() ? nullptr : setLayout.bindings.data();
setLayout.layout.bindingCount = static_cast<uint32_t>(setLayout.bindings.size());
}
RefreshBuiltinPassSetLayouts(storedPassLayout.setLayouts);
return &storedPassLayout;
}
@@ -760,11 +636,11 @@ RHI::RHIPipelineState* BuiltinForwardPipeline::GetOrCreatePipelineState(
}
bool BuiltinForwardPipeline::CreateOwnedDescriptorSet(
const PassSetLayoutMetadata& setLayout,
const BuiltinPassSetLayoutMetadata& setLayout,
OwnedDescriptorSet& descriptorSet) {
RHI::DescriptorPoolDesc poolDesc = {};
poolDesc.type = setLayout.heapType;
poolDesc.descriptorCount = CountHeapDescriptors(setLayout.heapType, setLayout.bindings);
poolDesc.descriptorCount = CountBuiltinPassHeapDescriptors(setLayout.heapType, setLayout.bindings);
poolDesc.shaderVisible = setLayout.shaderVisible;
descriptorSet.pool = m_device->CreateDescriptorPool(poolDesc);
@@ -813,7 +689,7 @@ RHI::RHIDescriptorSet* BuiltinForwardPipeline::GetOrCreateStaticDescriptorSet(
BuiltinForwardPipeline::CachedDescriptorSet* BuiltinForwardPipeline::GetOrCreateDynamicDescriptorSet(
const PassLayoutKey& passLayoutKey,
const PassResourceLayout& passLayout,
const PassSetLayoutMetadata& setLayout,
const BuiltinPassSetLayoutMetadata& setLayout,
Core::uint32 setIndex,
Core::uint64 objectId,
const Resources::Material* material,
@@ -1008,7 +884,7 @@ bool BuiltinForwardPipeline::DrawVisibleItem(
return false;
}
const PassSetLayoutMetadata& setLayout = passLayout->setLayouts[setIndex];
const BuiltinPassSetLayoutMetadata& setLayout = passLayout->setLayouts[setIndex];
RHI::RHIDescriptorSet* descriptorSet = nullptr;
if (setLayout.usesPerObject || setLayout.usesMaterial || setLayout.usesTexture) {