Skip to content

Commit f15f478

Browse files
Refactor PipelineStateVkImpl::ShaderStageInfo
Use internal struct Item to keep stage element data
1 parent 0ba141b commit f15f478

4 files changed

Lines changed: 64 additions & 54 deletions

File tree

Graphics/Archiver/src/Archiver_Vk.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2025 Diligent Graphics LLC
2+
* Copyright 2019-2026 Diligent Graphics LLC
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -128,9 +128,8 @@ void SerializedPipelineStateImpl::PatchShadersVk(const CreateInfoType& CreateInf
128128
{
129129
ShaderStageInfoVk& Src{ShaderStages[i]};
130130
PipelineStateVkImpl::ShaderStageInfo& Dst{ShaderStagesVk[i]};
131-
Dst.Type = Src.Type;
132-
Dst.Shaders = std::move(Src.Shaders);
133-
Dst.SPIRVs = std::move(Src.SPIRVs);
131+
Dst.Type = Src.Type;
132+
Dst.Items = std::move(Src.Items);
134133
}
135134

136135
IPipelineResourceSignature** ppSignatures = CreateInfo.ppResourceSignatures;
@@ -189,7 +188,7 @@ void SerializedPipelineStateImpl::PatchShadersVk(const CreateInfoType& CreateInf
189188
const PipelineStateVkImpl::ShaderStageInfo& Stage = ShaderStagesVk[j];
190189
for (size_t i = 0; i < Stage.Count(); ++i)
191190
{
192-
const std::vector<Uint32>& SPIRV = Stage.SPIRVs[i];
191+
const std::vector<Uint32>& SPIRV = Stage.Items[i].SPIRV;
193192
ShaderCreateInfo ShaderCI = ShaderStages[j].Serialized[i]->GetCreateInfo();
194193

195194
ShaderCI.Source = nullptr;

Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2025 Diligent Graphics LLC
2+
* Copyright 2019-2026 Diligent Graphics LLC
33
* Copyright 2015-2019 Egor Yusov
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -73,6 +73,7 @@ class PipelineStateVkImpl final : public PipelineStateBase<EngineVkImplTraits>
7373

7474
const PipelineLayoutVk& GetPipelineLayout() const { return m_PipelineLayout; }
7575

76+
using ShaderResourcesSharedPtr = std::shared_ptr<const SPIRVShaderResources>;
7677
struct ShaderStageInfo
7778
{
7879
ShaderStageInfo() {}
@@ -84,8 +85,14 @@ class PipelineStateVkImpl final : public PipelineStateBase<EngineVkImplTraits>
8485
// Shader stage type. All shaders in the stage must have the same type.
8586
SHADER_TYPE Type = SHADER_TYPE_UNKNOWN;
8687

87-
std::vector<const ShaderVkImpl*> Shaders;
88-
std::vector<std::vector<uint32_t>> SPIRVs;
88+
struct Item
89+
{
90+
const ShaderVkImpl* pShader = nullptr;
91+
std::vector<uint32_t> SPIRV;
92+
93+
explicit Item(const ShaderVkImpl* _pShader);
94+
};
95+
std::vector<Item> Items;
8996

9097
friend SHADER_TYPE GetShaderStageType(const ShaderStageInfo& Stage) { return Stage.Type; }
9198
};

Graphics/GraphicsEngineVulkan/include/ShaderVkImpl.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2025 Diligent Graphics LLC
2+
* Copyright 2019-2026 Diligent Graphics LLC
33
* Copyright 2015-2019 Egor Yusov
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -90,7 +90,8 @@ class ShaderVkImpl final : public ShaderBase<EngineVkImplTraits>
9090
return !IsCompiling() ? m_SPIRV : NullSPIRV;
9191
}
9292

93-
const std::shared_ptr<const SPIRVShaderResources>& GetShaderResources() const
93+
using ShaderResourcesSharedPtr = std::shared_ptr<const SPIRVShaderResources>;
94+
const ShaderResourcesSharedPtr& GetShaderResources() const
9495
{
9596
DEV_CHECK_ERR(!IsCompiling(), "Shader resources are not available until the shader is compiled. Use GetStatus() to check the shader status.");
9697
return m_pShaderResources;
@@ -115,7 +116,7 @@ class ShaderVkImpl final : public ShaderBase<EngineVkImplTraits>
115116
const CreateInfo& VkShaderCI) noexcept(false);
116117

117118
private:
118-
std::shared_ptr<const SPIRVShaderResources> m_pShaderResources;
119+
ShaderResourcesSharedPtr m_pShaderResources;
119120

120121
std::string m_EntryPoint;
121122
std::vector<uint32_t> m_SPIRV;

Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp

Lines changed: 46 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -56,33 +56,27 @@ namespace
5656
{
5757

5858
void InitPipelineShaderStages(const VulkanUtilities::LogicalDevice& LogicalDevice,
59-
PipelineStateVkImpl::TShaderStages& ShaderStages,
59+
const PipelineStateVkImpl::TShaderStages& ShaderStages,
6060
std::vector<VulkanUtilities::ShaderModuleWrapper>& ShaderModules,
6161
std::vector<VkPipelineShaderStageCreateInfo>& Stages)
6262
{
63-
for (size_t s = 0; s < ShaderStages.size(); ++s)
63+
for (const PipelineStateVkImpl::ShaderStageInfo& Stage : ShaderStages)
6464
{
65-
const std::vector<const ShaderVkImpl*>& Shaders = ShaderStages[s].Shaders;
66-
std::vector<std::vector<uint32_t>>& SPIRVs = ShaderStages[s].SPIRVs;
67-
const SHADER_TYPE ShaderType = ShaderStages[s].Type;
68-
69-
VERIFY_EXPR(Shaders.size() == SPIRVs.size());
70-
7165
VkPipelineShaderStageCreateInfo StageCI{};
7266
StageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
7367
StageCI.pNext = nullptr;
7468
StageCI.flags = 0; // reserved for future use
75-
StageCI.stage = ShaderTypeToVkShaderStageFlagBit(ShaderType);
69+
StageCI.stage = ShaderTypeToVkShaderStageFlagBit(Stage.Type);
7670

7771
VkShaderModuleCreateInfo ShaderModuleCI{};
7872
ShaderModuleCI.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
7973
ShaderModuleCI.pNext = nullptr;
8074
ShaderModuleCI.flags = 0;
8175

82-
for (size_t i = 0; i < Shaders.size(); ++i)
76+
for (const PipelineStateVkImpl::ShaderStageInfo::Item& StageItem : Stage.Items)
8377
{
84-
const ShaderVkImpl* pShader = Shaders[i];
85-
const std::vector<uint32_t> SPIRV = SPIRVs[i];
78+
const ShaderVkImpl* pShader = StageItem.pShader;
79+
const std::vector<uint32_t>& SPIRV = StageItem.SPIRV;
8680

8781
ShaderModuleCI.codeSize = SPIRV.size() * sizeof(uint32_t);
8882
ShaderModuleCI.pCode = SPIRV.data();
@@ -415,9 +409,9 @@ std::vector<VkRayTracingShaderGroupCreateInfoKHR> BuildRTShaderGroupDescription(
415409
{
416410
if (ShaderType == Stage.Type)
417411
{
418-
for (Uint32 i = 0; i < Stage.Shaders.size(); ++i, ++idx)
412+
for (Uint32 i = 0; i < Stage.Items.size(); ++i, ++idx)
419413
{
420-
if (Stage.Shaders[i] == pShaderVk)
414+
if (Stage.Items[i].pShader == pShaderVk)
421415
return idx;
422416
}
423417
UNEXPECTED("Unable to find shader '", pShaderVk->GetDesc().Name, "' in the shader stage. This should never happen and is a bug.");
@@ -554,22 +548,27 @@ void VerifyResourceMerge(const char* PSOName,
554548
} // namespace
555549

556550

551+
PipelineStateVkImpl::ShaderStageInfo::Item::Item(const ShaderVkImpl* _pShader) :
552+
pShader{_pShader},
553+
SPIRV{_pShader->GetSPIRV()}
554+
{
555+
}
556+
557557
PipelineStateVkImpl::ShaderStageInfo::ShaderStageInfo(const ShaderVkImpl* pShader) :
558558
Type{pShader->GetDesc().ShaderType},
559-
Shaders{pShader},
560-
SPIRVs{pShader->GetSPIRV()}
559+
Items{Item{pShader}}
561560
{}
562561

563562
void PipelineStateVkImpl::ShaderStageInfo::Append(const ShaderVkImpl* pShader)
564563
{
565564
VERIFY_EXPR(pShader != nullptr);
566-
VERIFY(std::find(Shaders.begin(), Shaders.end(), pShader) == Shaders.end(),
565+
VERIFY(std::find_if(Items.begin(), Items.end(), [pShader](const Item& I) { return I.pShader == pShader; }) == Items.end(),
567566
"Shader '", pShader->GetDesc().Name, "' already exists in the stage. Shaders must be deduplicated.");
568567

569568
const SHADER_TYPE NewShaderType = pShader->GetDesc().ShaderType;
570569
if (Type == SHADER_TYPE_UNKNOWN)
571570
{
572-
VERIFY_EXPR(Shaders.empty() && SPIRVs.empty());
571+
VERIFY_EXPR(Items.empty());
573572
Type = NewShaderType;
574573
}
575574
else
@@ -578,14 +577,12 @@ void PipelineStateVkImpl::ShaderStageInfo::Append(const ShaderVkImpl* pShader)
578577
") of shader '", pShader->GetDesc().Name, "' being added to the stage is inconsistent with the stage type (",
579578
GetShaderTypeLiteralName(Type), ").");
580579
}
581-
Shaders.push_back(pShader);
582-
SPIRVs.push_back(pShader->GetSPIRV());
580+
Items.emplace_back(pShader);
583581
}
584582

585583
size_t PipelineStateVkImpl::ShaderStageInfo::Count() const
586584
{
587-
VERIFY_EXPR(Shaders.size() == SPIRVs.size());
588-
return Shaders.size();
585+
return Items.size();
589586
}
590587

591588
PipelineResourceSignatureDescWrapper PipelineStateVkImpl::GetDefaultResourceSignatureDesc(
@@ -599,9 +596,9 @@ PipelineResourceSignatureDescWrapper PipelineStateVkImpl::GetDefaultResourceSign
599596
std::unordered_map<ShaderResourceHashKey, const SPIRVShaderResourceAttribs&, ShaderResourceHashKey::Hasher> UniqueResources;
600597
for (const ShaderStageInfo& Stage : ShaderStages)
601598
{
602-
for (const ShaderVkImpl* pShader : Stage.Shaders)
599+
for (const ShaderStageInfo::Item& StageItem : Stage.Items)
603600
{
604-
const SPIRVShaderResources& ShaderResources = *pShader->GetShaderResources();
601+
const SPIRVShaderResources& ShaderResources = *StageItem.pShader->GetShaderResources();
605602
ShaderResources.ProcessResources(
606603
[&](const SPIRVShaderResourceAttribs& Attribs, Uint32) //
607604
{
@@ -627,7 +624,7 @@ PipelineResourceSignatureDescWrapper PipelineStateVkImpl::GetDefaultResourceSign
627624
{
628625
if (Attribs.ArraySize == 0)
629626
{
630-
LOG_ERROR_AND_THROW("Resource '", Attribs.Name, "' in shader '", pShader->GetDesc().Name, "' is a runtime-sized array. ",
627+
LOG_ERROR_AND_THROW("Resource '", Attribs.Name, "' in shader '", ShaderResources.GetShaderName(), "' is a runtime-sized array. ",
631628
"You must use explicit resource signature to specify the array size.");
632629
}
633630

@@ -668,21 +665,21 @@ void PipelineStateVkImpl::RemapOrVerifyShaderResources(
668665

669666
// Verify that pipeline layout is compatible with shader resources and
670667
// remap resource bindings.
671-
for (size_t s = 0; s < ShaderStages.size(); ++s)
668+
for (ShaderStageInfo& Stage : ShaderStages)
672669
{
673-
const std::vector<const ShaderVkImpl*>& Shaders = ShaderStages[s].Shaders;
674-
std::vector<std::vector<uint32_t>>& SPIRVs = ShaderStages[s].SPIRVs;
675-
const SHADER_TYPE ShaderType = ShaderStages[s].Type;
670+
const SHADER_TYPE ShaderType = Stage.Type;
676671

677-
VERIFY_EXPR(Shaders.size() == SPIRVs.size());
678-
679-
for (size_t i = 0; i < Shaders.size(); ++i)
672+
for (ShaderStageInfo::Item& StageItem : Stage.Items)
680673
{
681-
const ShaderVkImpl* pShader = Shaders[i];
682-
std::vector<uint32_t>& SPIRV = SPIRVs[i];
674+
const char* const ShaderName = StageItem.pShader->GetDesc().Name;
675+
const ShaderResourcesSharedPtr& pShaderResources = StageItem.pShader->GetShaderResources();
676+
std::vector<uint32_t>& SPIRV = StageItem.SPIRV;
683677

684-
const auto& pShaderResources = pShader->GetShaderResources();
685-
VERIFY_EXPR(pShaderResources);
678+
if (!pShaderResources)
679+
{
680+
UNEXPECTED("Shader resources are not initialized for shader '", ShaderName, "'. This is a bug.");
681+
continue;
682+
}
686683

687684
if (pDvpShaderResources)
688685
pDvpShaderResources->emplace_back(pShaderResources);
@@ -693,7 +690,7 @@ void PipelineStateVkImpl::RemapOrVerifyShaderResources(
693690
const ResourceAttribution ResAttribution = GetResourceAttribution(SPIRVAttribs.Name, ShaderType, pSignatures, SignatureCount);
694691
if (!ResAttribution)
695692
{
696-
LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource '", SPIRVAttribs.Name,
693+
LOG_ERROR_AND_THROW("Shader '", ShaderName, "' contains resource '", SPIRVAttribs.Name,
697694
"' that is not present in any pipeline resource signature used to create pipeline state '",
698695
PipelineName, "'.");
699696
}
@@ -708,7 +705,7 @@ void PipelineStateVkImpl::RemapOrVerifyShaderResources(
708705
{
709706
const PipelineResourceDesc& ResDesc = ResAttribution.pSignature->GetResourceDesc(ResAttribution.ResourceIndex);
710707
ValidatePipelineResourceCompatibility(ResDesc, ResType, Flags, SPIRVAttribs.ArraySize,
711-
pShader->GetDesc().Name, SignDesc.Name);
708+
ShaderName, SignDesc.Name);
712709

713710
const PipelineResourceSignatureVkImpl::ResourceAttribs& ResAttribs{ResAttribution.pSignature->GetResourceAttribs(ResAttribution.ResourceIndex)};
714711
ResourceBinding = ResAttribs.BindingIndex;
@@ -718,7 +715,7 @@ void PipelineStateVkImpl::RemapOrVerifyShaderResources(
718715
{
719716
if (ResType != SHADER_RESOURCE_TYPE_SAMPLER)
720717
{
721-
LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", SPIRVAttribs.Name,
718+
LOG_ERROR_AND_THROW("Shader '", ShaderName, "' contains resource with name '", SPIRVAttribs.Name,
722719
"' and type '", GetShaderResourceTypeLiteralName(ResType),
723720
"' that is not compatible with immutable sampler defined in pipeline resource signature '",
724721
SignDesc.Name, "'.");
@@ -740,13 +737,13 @@ void PipelineStateVkImpl::RemapOrVerifyShaderResources(
740737
const Uint32 SpvDescrSet = SPIRV[SPIRVAttribs.DescriptorSetDecorationOffset];
741738
if (SpvBinding != ResourceBinding)
742739
{
743-
LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' maps resource '", SPIRVAttribs.Name,
740+
LOG_ERROR_AND_THROW("Shader '", ShaderName, "' maps resource '", SPIRVAttribs.Name,
744741
"' to binding ", SpvBinding, ", but the same resource in pipeline resource signature '",
745742
SignDesc.Name, "' is mapped to binding ", ResourceBinding, '.');
746743
}
747744
if (SpvDescrSet != DescriptorSet)
748745
{
749-
LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' maps resource '", SPIRVAttribs.Name,
746+
LOG_ERROR_AND_THROW("Shader '", ShaderName, "' maps resource '", SPIRVAttribs.Name,
750747
"' to descriptor set ", SpvDescrSet, ", but the same resource in pipeline resource signature '",
751748
SignDesc.Name, "' is mapped to set ", DescriptorSet, '.');
752749
}
@@ -777,7 +774,7 @@ void PipelineStateVkImpl::RemapOrVerifyShaderResources(
777774
if (!StrippedSPIRV.empty())
778775
SPIRV = std::move(StrippedSPIRV);
779776
else
780-
LOG_ERROR("Failed to strip reflection information from shader '", pShader->GetDesc().Name, "'. This may indicate a problem with the byte code.");
777+
LOG_ERROR("Failed to strip reflection information from shader '", ShaderName, "'. This may indicate a problem with the byte code.");
781778
#endif
782779
}
783780
}
@@ -899,7 +896,13 @@ void PipelineStateVkImpl::InitializePipeline(const RayTracingPipelineStateCreate
899896
// Used by TPipelineStateBase::Construct()
900897
inline std::vector<const ShaderVkImpl*> GetStageShaders(const PipelineStateVkImpl::ShaderStageInfo& Stage)
901898
{
902-
return Stage.Shaders;
899+
std::vector<const ShaderVkImpl*> StageShaders;
900+
StageShaders.reserve(Stage.Count());
901+
for (const PipelineStateVkImpl::ShaderStageInfo::Item& StageItem : Stage.Items)
902+
{
903+
StageShaders.push_back(StageItem.pShader);
904+
}
905+
return StageShaders;
903906
}
904907

905908
PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, const GraphicsPipelineStateCreateInfo& CreateInfo) :

0 commit comments

Comments
 (0)