Skip to content

Commit 70b0382

Browse files
authored
Merge branch 'inline_constants' into inline_constants_multiple_shader_stages
2 parents d2f62ea + aa7539a commit 70b0382

1 file changed

Lines changed: 63 additions & 5 deletions

File tree

Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,51 @@ void VerifyResourceMerge(const char* PSOName,
545545
#undef LOG_RESOURCE_MERGE_ERROR_AND_THROW
546546
}
547547

548+
struct MergedPushConstantInfo
549+
{
550+
SHADER_TYPE Stages = SHADER_TYPE_UNKNOWN;
551+
Uint32 Size = 0;
552+
};
553+
554+
using MergedPushConstantMapType = std::unordered_map<std::string_view, MergedPushConstantInfo>;
555+
MergedPushConstantMapType MergePushConstants(const PipelineStateVkImpl::TShaderStages& ShaderStages,
556+
const char* PSOName) noexcept(false)
557+
{
558+
MergedPushConstantMapType MergedPushConstants;
559+
for (const PipelineStateVkImpl::ShaderStageInfo& Stage : ShaderStages)
560+
{
561+
for (const PipelineStateVkImpl::ShaderStageInfo::Item& StageItem : Stage.Items)
562+
{
563+
const SPIRVShaderResources& ShaderResources = *StageItem.pShader->GetShaderResources();
564+
for (Uint32 i = 0; i < ShaderResources.GetNumPushConstants(); ++i)
565+
{
566+
const SPIRVShaderResourceAttribs& PCAttribs = ShaderResources.GetPushConstant(i);
567+
MergedPushConstantInfo& MergedPC = MergedPushConstants[PCAttribs.Name];
568+
const Uint32 BufferSize = PCAttribs.GetConstantBufferSize();
569+
if (MergedPC.Stages == SHADER_TYPE_UNKNOWN)
570+
{
571+
MergedPC.Stages = Stage.Type;
572+
MergedPC.Size = BufferSize;
573+
}
574+
else if (MergedPC.Size == BufferSize)
575+
{
576+
MergedPC.Stages |= Stage.Type;
577+
}
578+
else
579+
{
580+
LOG_ERROR_AND_THROW("Push constant '", PCAttribs.Name,
581+
"' is shared between multiple shaders in pipeline '", (PSOName ? PSOName : ""),
582+
"', but its size varies (",
583+
MergedPC.Size, " vs ", BufferSize,
584+
"). A push constant shared between multiple shaders must have the same size in all shaders.");
585+
}
586+
}
587+
}
588+
}
589+
590+
return MergedPushConstants;
591+
}
592+
548593
} // namespace
549594

550595

@@ -640,7 +685,7 @@ PipelineResourceSignatureDescWrapper PipelineStateVkImpl::GetDefaultResourceSign
640685
{
641686
PipelineResourceSignatureDescWrapper SignDesc{PSOName, ResourceLayout, SRBAllocationGranularity};
642687

643-
PipelineStateVkImpl::SPIRVPushConstantInfo PCInfo = GetSPIRVPushConstantInfo(ShaderStages);
688+
MergedPushConstantMapType MergedPushConstants;
644689

645690
std::unordered_map<ShaderResourceHashKey, const SPIRVShaderResourceAttribs&, ShaderResourceHashKey::Hasher> UniqueResources;
646691
for (const ShaderStageInfo& Stage : ShaderStages)
@@ -667,11 +712,24 @@ PipelineResourceSignatureDescWrapper PipelineStateVkImpl::GetDefaultResourceSign
667712
nullptr;
668713

669714
ShaderResourceVariableDesc VarDesc = FindPipelineResourceLayoutVariable(ResourceLayout, Attribs.Name, Stage.Type, SamplerSuffix);
670-
671-
if (PCInfo && PCInfo.Name == Attribs.Name)
715+
if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::PushConstant)
672716
{
673-
//Use merged ShaderStages for PushConstants
674-
VarDesc.ShaderStages = PCInfo.ShaderStages;
717+
if (MergedPushConstants.empty())
718+
{
719+
// First time we found a push constant - build the merged map
720+
MergedPushConstants = MergePushConstants(ShaderStages, PSOName);
721+
}
722+
723+
auto it = MergedPushConstants.find(VarDesc.Name);
724+
if (it != MergedPushConstants.end())
725+
{
726+
VERIFY_EXPR(Attribs.GetConstantBufferSize() == it->second.Size);
727+
VarDesc.ShaderStages = it->second.Stages;
728+
}
729+
else
730+
{
731+
UNEXPECTED("Push constant '", VarDesc.Name, "' not found in merged push constant stages map. This is a bug.");
732+
}
675733
}
676734

677735
// Note that Attribs.Name != VarDesc.Name for combined samplers

0 commit comments

Comments
 (0)