Share builtin pass layout assembly utilities
This commit is contained in:
@@ -274,24 +274,33 @@ bool BuiltinObjectIdPass::CreateResources(const RenderContext& context) {
|
||||
m_perObjectBinding = bindingPlan.perObject;
|
||||
m_firstDescriptorSet = bindingPlan.firstDescriptorSet;
|
||||
|
||||
std::vector<std::vector<RHI::DescriptorSetLayoutBinding>> setBindingStorage(
|
||||
static_cast<size_t>(bindingPlan.maxSetIndex) + 1u);
|
||||
RHI::DescriptorSetLayoutBinding constantBinding = {};
|
||||
constantBinding.binding = m_perObjectBinding.binding;
|
||||
constantBinding.type = static_cast<uint32_t>(RHI::DescriptorType::CBV);
|
||||
constantBinding.count = 1;
|
||||
setBindingStorage[m_perObjectBinding.set].push_back(constantBinding);
|
||||
std::vector<BuiltinPassSetLayoutMetadata> setLayouts;
|
||||
Containers::String setLayoutError;
|
||||
if (!TryBuildBuiltinPassSetLayouts(bindingPlan, setLayouts, &setLayoutError)) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
(Containers::String("BuiltinObjectIdPass failed to build descriptor set layouts: ") + setLayoutError).CStr());
|
||||
DestroyResources();
|
||||
return false;
|
||||
}
|
||||
if (m_perObjectBinding.set >= setLayouts.size()) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
"BuiltinObjectIdPass produced an invalid PerObject descriptor set index");
|
||||
DestroyResources();
|
||||
return false;
|
||||
}
|
||||
m_perObjectSetLayout = setLayouts[m_perObjectBinding.set];
|
||||
RefreshBuiltinPassSetLayoutMetadata(m_perObjectSetLayout);
|
||||
|
||||
std::vector<RHI::DescriptorSetLayoutDesc> setLayouts(setBindingStorage.size());
|
||||
for (size_t setIndex = 0; setIndex < setBindingStorage.size(); ++setIndex) {
|
||||
setLayouts[setIndex].bindings =
|
||||
setBindingStorage[setIndex].empty() ? nullptr : setBindingStorage[setIndex].data();
|
||||
setLayouts[setIndex].bindingCount = static_cast<uint32_t>(setBindingStorage[setIndex].size());
|
||||
std::vector<RHI::DescriptorSetLayoutDesc> nativeSetLayouts(setLayouts.size());
|
||||
for (size_t setIndex = 0; setIndex < setLayouts.size(); ++setIndex) {
|
||||
nativeSetLayouts[setIndex] = setLayouts[setIndex].layout;
|
||||
}
|
||||
|
||||
RHI::RHIPipelineLayoutDesc pipelineLayoutDesc = {};
|
||||
pipelineLayoutDesc.setLayouts = setLayouts.empty() ? nullptr : setLayouts.data();
|
||||
pipelineLayoutDesc.setLayoutCount = static_cast<uint32_t>(setLayouts.size());
|
||||
pipelineLayoutDesc.setLayouts = nativeSetLayouts.empty() ? nullptr : nativeSetLayouts.data();
|
||||
pipelineLayoutDesc.setLayoutCount = static_cast<uint32_t>(nativeSetLayouts.size());
|
||||
m_pipelineLayout = m_device->CreatePipelineLayout(pipelineLayoutDesc);
|
||||
if (m_pipelineLayout == nullptr) {
|
||||
DestroyResources();
|
||||
@@ -340,12 +349,14 @@ void BuiltinObjectIdPass::DestroyResources() {
|
||||
m_device = nullptr;
|
||||
m_backendType = RHI::RHIType::D3D12;
|
||||
m_perObjectBinding = {};
|
||||
m_perObjectSetLayout = {};
|
||||
m_firstDescriptorSet = 0;
|
||||
m_builtinObjectIdShader.Reset();
|
||||
}
|
||||
|
||||
RHI::RHIDescriptorSet* BuiltinObjectIdPass::GetOrCreatePerObjectSet(uint64_t objectId) {
|
||||
if (m_perObjectBinding.IsValid() == false) {
|
||||
if (m_perObjectBinding.IsValid() == false ||
|
||||
m_perObjectSetLayout.layout.bindingCount == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -355,9 +366,10 @@ RHI::RHIDescriptorSet* BuiltinObjectIdPass::GetOrCreatePerObjectSet(uint64_t obj
|
||||
}
|
||||
|
||||
RHI::DescriptorPoolDesc poolDesc = {};
|
||||
poolDesc.type = RHI::DescriptorHeapType::CBV_SRV_UAV;
|
||||
poolDesc.descriptorCount = 1;
|
||||
poolDesc.shaderVisible = false;
|
||||
poolDesc.type = m_perObjectSetLayout.heapType;
|
||||
poolDesc.descriptorCount =
|
||||
CountBuiltinPassHeapDescriptors(m_perObjectSetLayout.heapType, m_perObjectSetLayout.bindings);
|
||||
poolDesc.shaderVisible = m_perObjectSetLayout.shaderVisible;
|
||||
|
||||
OwnedDescriptorSet descriptorSet = {};
|
||||
descriptorSet.pool = m_device->CreateDescriptorPool(poolDesc);
|
||||
@@ -365,15 +377,7 @@ RHI::RHIDescriptorSet* BuiltinObjectIdPass::GetOrCreatePerObjectSet(uint64_t obj
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHI::DescriptorSetLayoutBinding binding = {};
|
||||
binding.binding = m_perObjectBinding.binding;
|
||||
binding.type = static_cast<uint32_t>(RHI::DescriptorType::CBV);
|
||||
binding.count = 1;
|
||||
|
||||
RHI::DescriptorSetLayoutDesc layout = {};
|
||||
layout.bindings = &binding;
|
||||
layout.bindingCount = 1;
|
||||
descriptorSet.set = descriptorSet.pool->AllocateSet(layout);
|
||||
descriptorSet.set = descriptorSet.pool->AllocateSet(m_perObjectSetLayout.layout);
|
||||
if (descriptorSet.set == nullptr) {
|
||||
DestroyOwnedDescriptorSet(descriptorSet);
|
||||
return nullptr;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user