@@ -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