summaryrefslogtreecommitdiffstats
path: root/Graphics
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2021-03-06 22:06:26 +0000
committerassiduous <assiduous@diligentgraphics.com>2021-03-19 00:38:16 +0000
commit30a65df99cfc678a431a89b0cff02a515416c78a (patch)
tree2d3ed68bf8ec028879e22ff6d1ec386df723677e /Graphics
parentMoved GetResourceAttribution() function to PipelineStateBase to eliminate dup... (diff)
downloadDiligentCore-30a65df99cfc678a431a89b0cff02a515416c78a.tar.gz
DiligentCore-30a65df99cfc678a431a89b0cff02a515416c78a.zip
Unified resource signature handling by pipeline state in D3D12, Vk and GL
Diffstat (limited to 'Graphics')
-rw-r--r--Graphics/GraphicsEngine/include/PipelineResourceSignatureBase.hpp60
-rw-r--r--Graphics/GraphicsEngine/include/PipelineStateBase.hpp133
-rw-r--r--Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp13
-rw-r--r--Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp47
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp25
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp67
-rw-r--r--Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp57
-rw-r--r--Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp22
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp27
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp91
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp142
-rw-r--r--Graphics/GraphicsEngineVulkan/src/RenderPassCache.cpp2
12 files changed, 286 insertions, 400 deletions
diff --git a/Graphics/GraphicsEngine/include/PipelineResourceSignatureBase.hpp b/Graphics/GraphicsEngine/include/PipelineResourceSignatureBase.hpp
index 68d4aa8a..0942ffcf 100644
--- a/Graphics/GraphicsEngine/include/PipelineResourceSignatureBase.hpp
+++ b/Graphics/GraphicsEngine/include/PipelineResourceSignatureBase.hpp
@@ -231,58 +231,22 @@ public:
return this->m_Desc.ImmutableSamplers[SampIndex];
}
- static Uint32 CalcMaxSignatureBindIndex(const Uint32 SignatureCount,
- IPipelineResourceSignature* ppResourceSignatures[])
+ static bool SignaturesCompatible(const PipelineResourceSignatureImplType* pSign0,
+ const PipelineResourceSignatureImplType* pSign1)
{
- Uint32 MaxSignatureBindingIndex = 0;
- for (Uint32 i = 0; i < SignatureCount; ++i)
- {
- const auto* pSignature = ppResourceSignatures[i];
- VERIFY(pSignature != nullptr, "Pipeline resource signature at index ", i, " is null. This error should've been caught by ValidatePipelineResourceSignatures.");
- MaxSignatureBindingIndex = std::max(MaxSignatureBindingIndex, Uint32{pSignature->GetDesc().BindingIndex});
- }
- return MaxSignatureBindingIndex;
- }
+ if (pSign0 == pSign1)
+ return true;
- template <typename TPipelineResourceSignature>
- static Uint32 CopyResourceSignatures(PIPELINE_TYPE PipelineType,
- const Uint32 SignatureCount,
- IPipelineResourceSignature* ppResourceSignatures[],
- RefCntAutoPtr<TPipelineResourceSignature> DstSignatures[],
- const size_t MaxDstSignatureCount)
- {
- Uint32 MaxSignatureBindIndex = 0;
- for (Uint32 i = 0; i < SignatureCount; ++i)
- {
- auto* pSignature = ValidatedCast<TPipelineResourceSignature>(ppResourceSignatures[i]);
- VERIFY(pSignature != nullptr, "Pipeline resource signature at index ", i, " is null. This error should've been caught by ValidatePipelineResourceSignatures.");
-
- const Uint8 Index = pSignature->GetDesc().BindingIndex;
+ bool IsNull0 = pSign0 == nullptr || (pSign0->GetTotalResourceCount() == 0 && pSign0->GetImmutableSamplerCount() == 0);
+ bool IsNull1 = pSign1 == nullptr || (pSign1->GetTotalResourceCount() == 0 && pSign1->GetImmutableSamplerCount() == 0);
+ if (IsNull0 && IsNull1)
+ return true;
-#ifdef DILIGENT_DEBUG
- VERIFY(Index < MaxDstSignatureCount,
- "Pipeline resource signature specifies binding index ", Uint32{Index}, " that exceeds the limit (", MaxDstSignatureCount - 1,
- "). This error should've been caught by ValidatePipelineResourceSignatureDesc.");
+ if (IsNull0 != IsNull1)
+ return false;
- VERIFY(DstSignatures[Index] == nullptr,
- "Pipeline resource signature '", pSignature->GetDesc().Name, "' at index ", Uint32{Index},
- " conflicts with another resource signature '", DstSignatures[Index]->GetDesc().Name,
- "' that uses the same index. This error should've been caught by ValidatePipelineResourceSignatures.");
-
- for (Uint32 s = 0, StageCount = pSignature->GetNumActiveShaderStages(); s < StageCount; ++s)
- {
- const auto ShaderType = pSignature->GetActiveShaderStageType(s);
- VERIFY(IsConsistentShaderType(ShaderType, PipelineType),
- "Pipeline resource signature '", pSignature->GetDesc().Name, "' at index ", Uint32{Index},
- " has shader stage '", GetShaderTypeLiteralName(ShaderType), "' that is not compatible with pipeline type '",
- GetPipelineTypeString(PipelineType), "'.");
- }
-#endif
-
- MaxSignatureBindIndex = std::max<Uint32>(MaxSignatureBindIndex, Index);
- DstSignatures[Index] = pSignature;
- }
- return MaxSignatureBindIndex;
+ VERIFY_EXPR(pSign0 != nullptr && pSign1 != nullptr);
+ return pSign0->IsCompatibleWith(pSign1);
}
protected:
diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp
index f831f4ea..dcdd82d9 100644
--- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp
+++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp
@@ -231,6 +231,13 @@ public:
m_pRayTracingPipelineData->~RayTracingPipelineData();
}
+ if (m_Signatures != nullptr)
+ {
+ for (Uint32 i = 0; i < m_SignatureCount; ++i)
+ m_Signatures[i].~SignatureAutoPtrType();
+ m_Signatures = nullptr;
+ }
+
if (m_pPipelineDataRawMem)
{
GetRawAllocator().Free(m_pPipelineDataRawMem);
@@ -404,6 +411,45 @@ public:
return this->GetResourceSignature(0)->InitializeStaticSRBResources(pSRB);
}
+ /// Implementation of IPipelineState::GetResourceSignatureCount().
+ virtual Uint32 DILIGENT_CALL_TYPE GetResourceSignatureCount() const override final
+ {
+ return m_SignatureCount;
+ }
+
+ /// Implementation of IPipelineState::GetResourceSignature().
+ virtual PipelineResourceSignatureImplType* DILIGENT_CALL_TYPE GetResourceSignature(Uint32 Index) const override final
+ {
+ VERIFY_EXPR(Index < m_SignatureCount);
+ return m_Signatures[Index];
+ }
+
+ /// Implementation of IPipelineState::IsCompatibleWith().
+ virtual bool DILIGENT_CALL_TYPE IsCompatibleWith(const IPipelineState* pPSO) const override // May be overriden
+ {
+ DEV_CHECK_ERR(pPSO != nullptr, "pPSO must not be null");
+
+ if (pPSO == this)
+ return true;
+
+ const auto& lhs = *static_cast<const PipelineStateImplType*>(this);
+ const auto& rhs = *ValidatedCast<const PipelineStateImplType>(pPSO);
+
+ const auto SignCount = lhs.GetResourceSignatureCount();
+ if (SignCount != rhs.GetResourceSignatureCount())
+ return false;
+
+ for (Uint32 s = 0; s < SignCount; ++s)
+ {
+ const auto* pLhsSign = GetResourceSignature(s);
+ const auto* pRhsSign = rhs.GetResourceSignature(s);
+ if (!PipelineResourceSignatureImplType::SignaturesCompatible(pLhsSign, pRhsSign))
+ return false;
+ }
+
+ return true;
+ }
+
protected:
using TNameToGroupIndexMap = std::unordered_map<HashMapStringKey, Uint32, HashMapStringKey::Hasher>;
@@ -412,6 +458,7 @@ protected:
{
MemPool.AddSpace<GraphicsPipelineData>();
ReserveResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool);
+ ReserveResourceSignatures(CreateInfo, MemPool);
const auto& InputLayout = CreateInfo.GraphicsPipeline.InputLayout;
Uint32 BufferSlotsUsed = 0;
@@ -429,13 +476,14 @@ protected:
}
void ReserveSpaceForPipelineDesc(const ComputePipelineStateCreateInfo& CreateInfo,
- FixedLinearAllocator& MemPool) const noexcept
+ FixedLinearAllocator& MemPool) noexcept
{
ReserveResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool);
+ ReserveResourceSignatures(CreateInfo, MemPool);
}
void ReserveSpaceForPipelineDesc(const RayTracingPipelineStateCreateInfo& CreateInfo,
- FixedLinearAllocator& MemPool) const noexcept
+ FixedLinearAllocator& MemPool) noexcept
{
size_t RTDataSize = sizeof(RayTracingPipelineData);
// Reserve space for shader handles
@@ -459,6 +507,7 @@ protected:
}
ReserveResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool);
+ ReserveResourceSignatures(CreateInfo, MemPool);
}
@@ -604,6 +653,7 @@ protected:
CorrectGraphicsPipelineDesc(GraphicsPipeline);
CopyResourceLayout(CreateInfo.PSODesc.ResourceLayout, this->m_Desc.ResourceLayout, MemPool);
+ CopyResourceSignatures(CreateInfo, MemPool);
pRenderPass = GraphicsPipeline.pRenderPass;
if (pRenderPass)
@@ -730,6 +780,7 @@ protected:
m_pPipelineDataRawMem = MemPool.ReleaseOwnership();
CopyResourceLayout(CreateInfo.PSODesc.ResourceLayout, this->m_Desc.ResourceLayout, MemPool);
+ CopyResourceSignatures(CreateInfo, MemPool);
}
void InitializePipelineDesc(const RayTracingPipelineStateCreateInfo& CreateInfo,
@@ -756,6 +807,7 @@ protected:
CopyRTShaderGroupNames(NameToGroupIndex, CreateInfo, MemPool);
CopyResourceLayout(CreateInfo.PSODesc.ResourceLayout, this->m_Desc.ResourceLayout, MemPool);
+ CopyResourceSignatures(CreateInfo, MemPool);
}
@@ -890,6 +942,73 @@ private:
}
}
+ void ReserveResourceSignatures(const PipelineStateCreateInfo& CreateInfo, FixedLinearAllocator& MemPool)
+ {
+ if (m_UsingImplicitSignature)
+ {
+ VERIFY_EXPR(CreateInfo.ResourceSignaturesCount == 0 || CreateInfo.ppResourceSignatures == nullptr);
+ m_SignatureCount = 1;
+ }
+ else
+ {
+ VERIFY_EXPR(CreateInfo.ResourceSignaturesCount > 0 && CreateInfo.ppResourceSignatures != nullptr);
+ Uint32 MaxSignatureBindingIndex = 0;
+ for (Uint32 i = 0; i < CreateInfo.ResourceSignaturesCount; ++i)
+ {
+ const auto* pSignature = ValidatedCast<PipelineResourceSignatureImplType>(CreateInfo.ppResourceSignatures[i]);
+ VERIFY(pSignature != nullptr, "Pipeline resource signature at index ", i, " is null. This error should've been caught by ValidatePipelineResourceSignatures.");
+
+ Uint32 Index = pSignature->GetDesc().BindingIndex;
+ VERIFY(Index < MAX_RESOURCE_SIGNATURES,
+ "Pipeline resource signature specifies binding index ", Uint32{Index}, " that exceeds the limit (", MAX_RESOURCE_SIGNATURES - 1,
+ "). This error should've been caught by ValidatePipelineResourceSignatureDesc.");
+
+ MaxSignatureBindingIndex = std::max(MaxSignatureBindingIndex, Uint32{Index});
+ }
+ VERIFY_EXPR(MaxSignatureBindingIndex < MAX_RESOURCE_SIGNATURES);
+ m_SignatureCount = static_cast<decltype(m_SignatureCount)>(MaxSignatureBindingIndex + 1);
+ VERIFY_EXPR(m_SignatureCount == MaxSignatureBindingIndex + 1);
+ }
+
+ MemPool.AddSpace<SignatureAutoPtrType>(m_SignatureCount);
+ }
+
+ void CopyResourceSignatures(const PipelineStateCreateInfo& CreateInfo, FixedLinearAllocator& MemPool)
+ {
+ m_Signatures = MemPool.ConstructArray<SignatureAutoPtrType>(m_SignatureCount);
+ if (!m_UsingImplicitSignature)
+ {
+ VERIFY_EXPR(CreateInfo.ResourceSignaturesCount != 0 && CreateInfo.ppResourceSignatures != nullptr);
+ for (Uint32 i = 0; i < CreateInfo.ResourceSignaturesCount; ++i)
+ {
+ auto* pSignature = ValidatedCast<PipelineResourceSignatureImplType>(CreateInfo.ppResourceSignatures[i]);
+ VERIFY_EXPR(pSignature != nullptr);
+
+ const Uint32 Index = pSignature->GetDesc().BindingIndex;
+
+#ifdef DILIGENT_DEBUG
+ VERIFY_EXPR(Index < m_SignatureCount);
+
+ VERIFY(m_Signatures[Index] == nullptr,
+ "Pipeline resource signature '", pSignature->GetDesc().Name, "' at index ", Uint32{Index},
+ " conflicts with another resource signature '", m_Signatures[Index]->GetDesc().Name,
+ "' that uses the same index. This error should've been caught by ValidatePipelineResourceSignatures.");
+
+ for (Uint32 s = 0, StageCount = pSignature->GetNumActiveShaderStages(); s < StageCount; ++s)
+ {
+ const auto ShaderType = pSignature->GetActiveShaderStageType(s);
+ VERIFY(IsConsistentShaderType(ShaderType, CreateInfo.PSODesc.PipelineType),
+ "Pipeline resource signature '", pSignature->GetDesc().Name, "' at index ", Uint32{Index},
+ " has shader stage '", GetShaderTypeLiteralName(ShaderType), "' that is not compatible with pipeline type '",
+ GetPipelineTypeString(CreateInfo.PSODesc.PipelineType), "'.");
+ }
+#endif
+
+ m_Signatures[Index] = pSignature;
+ }
+ }
+ }
+
protected:
/// Shader stages that are active in this PSO.
SHADER_TYPE m_ActiveShaderStages = SHADER_TYPE_UNKNOWN;
@@ -897,6 +1016,16 @@ protected:
/// True if the pipeline was created using implicit root signature.
const bool m_UsingImplicitSignature;
+ /// The number of signatures in m_Signatures array.
+ /// Note that this is not necessarily the same as the number of signatures
+ /// that were used to create the pipeline, because signatures are arranged
+ /// by their binding index.
+ Uint8 m_SignatureCount = 0;
+
+ /// Resource signatures arranged by their binding indices
+ using SignatureAutoPtrType = RefCntAutoPtr<PipelineResourceSignatureImplType>;
+ SignatureAutoPtrType* m_Signatures = nullptr; // [m_SignatureCount]
+
struct GraphicsPipelineData
{
GraphicsPipelineDesc Desc;
diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp
index 4c0f954b..c8f35d36 100644
--- a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp
@@ -60,16 +60,6 @@ public:
/// Implementation of IPipelineState::IsCompatibleWith() in Direct3D12 backend.
virtual bool DILIGENT_CALL_TYPE IsCompatibleWith(const IPipelineState* pPSO) const override final;
- /// Implementation of IPipelineState::GetResourceSignatureCount() in Direct3D12 backend.
- virtual Uint32 DILIGENT_CALL_TYPE GetResourceSignatureCount() const override final { return m_RootSig->GetSignatureCount(); }
-
- /// Implementation of IPipelineState::GetResourceSignature() in Direct3D12 backend.
- virtual PipelineResourceSignatureD3D12Impl* DILIGENT_CALL_TYPE GetResourceSignature(Uint32 Index) const override final
- {
- VERIFY_EXPR(Index < GetResourceSignatureCount());
- return m_ResourceSignatures[Index];
- }
-
/// Implementation of IPipelineStateD3D12::GetD3D12PipelineState().
virtual ID3D12PipelineState* DILIGENT_CALL_TYPE GetD3D12PipelineState() const override final { return static_cast<ID3D12PipelineState*>(m_pd3d12PSO.p); }
@@ -111,7 +101,7 @@ private:
TShaderStages& ShaderStages,
LocalRootSignatureD3D12* pLocalRootSig);
- static RefCntAutoPtr<IPipelineResourceSignature> CreateDefaultResourceSignature(
+ static RefCntAutoPtr<PipelineResourceSignatureD3D12Impl> CreateDefaultResourceSignature(
RenderDeviceD3D12Impl* pDevice,
const PipelineStateCreateInfo& CreateInfo,
TShaderStages& ShaderStages,
@@ -128,7 +118,6 @@ private:
// NB: Pipeline resource signatures used to create the PSO may NOT be the same as
// pipeline resource signatures in m_RootSig, because the latter may be used from the
// cache. While the two signatures may be compatible, they resource names may not be identical.
- std::unique_ptr<RefCntAutoPtr<PipelineResourceSignatureD3D12Impl>[]> m_ResourceSignatures;
#ifdef DILIGENT_DEVELOPMENT
// Shader resources for all shaders in all shader stages in the pipeline.
diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp
index f27d39dc..94e8b8b4 100644
--- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp
@@ -414,7 +414,7 @@ size_t PipelineStateD3D12Impl::ShaderStageInfo::Count() const
}
-RefCntAutoPtr<IPipelineResourceSignature> PipelineStateD3D12Impl::CreateDefaultResourceSignature(
+RefCntAutoPtr<PipelineResourceSignatureD3D12Impl> PipelineStateD3D12Impl::CreateDefaultResourceSignature(
RenderDeviceD3D12Impl* pDevice,
const PipelineStateCreateInfo& CreateInfo,
TShaderStages& ShaderStages,
@@ -513,7 +513,7 @@ RefCntAutoPtr<IPipelineResourceSignature> PipelineStateD3D12Impl::CreateDefaultR
}
}
- RefCntAutoPtr<IPipelineResourceSignature> pImplicitSignature;
+ RefCntAutoPtr<PipelineResourceSignatureD3D12Impl> pImplicitSignature;
if (Resources.size())
{
PipelineResourceSignatureDesc ResSignDesc;
@@ -526,7 +526,11 @@ RefCntAutoPtr<IPipelineResourceSignature> PipelineStateD3D12Impl::CreateDefaultR
ResSignDesc.UseCombinedTextureSamplers = pCombinedSamplerSuffix != nullptr;
ResSignDesc.CombinedSamplerSuffix = pCombinedSamplerSuffix;
- pDevice->CreatePipelineResourceSignature(ResSignDesc, &pImplicitSignature, true);
+ // Always initialize default resource signature as internal device object.
+ // This is necessary to avoud cyclic references from GenerateMips.
+ // This may never be a problem as the PSO keeps the reference to the device if necessary.
+ constexpr bool bIsDeviceInternal = true;
+ pDevice->CreatePipelineResourceSignature(ResSignDesc, pImplicitSignature.DblPtr<IPipelineResourceSignature>(), bIsDeviceInternal);
if (!pImplicitSignature)
LOG_ERROR_AND_THROW("Failed to create implicit resource signature for pipeline state '", (CreateInfo.PSODesc.Name ? CreateInfo.PSODesc.Name : ""), "'.");
@@ -539,31 +543,14 @@ void PipelineStateD3D12Impl::InitRootSignature(const PipelineStateCreateInfo& Cr
TShaderStages& ShaderStages,
LocalRootSignatureD3D12* pLocalRootSig)
{
- Uint32 SignatureCount = 0;
- if (CreateInfo.ResourceSignaturesCount == 0 || CreateInfo.ppResourceSignatures == nullptr)
+ if (m_UsingImplicitSignature)
{
- auto pImplicitSignature = CreateDefaultResourceSignature(GetDevice(), CreateInfo, ShaderStages, pLocalRootSig);
- if (pImplicitSignature)
- {
- VERIFY_EXPR(pImplicitSignature->GetDesc().BindingIndex == 0);
- SignatureCount = 1;
- m_ResourceSignatures.reset(new RefCntAutoPtr<PipelineResourceSignatureD3D12Impl>[SignatureCount]);
- m_ResourceSignatures[0] = pImplicitSignature.RawPtr<PipelineResourceSignatureD3D12Impl>();
- }
- }
- else
- {
- Uint32 MaxSignatureBindingIndex = PipelineResourceSignatureD3D12Impl::CalcMaxSignatureBindIndex(CreateInfo.ResourceSignaturesCount, CreateInfo.ppResourceSignatures);
- SignatureCount = MaxSignatureBindingIndex + 1;
- m_ResourceSignatures.reset(new RefCntAutoPtr<PipelineResourceSignatureD3D12Impl>[SignatureCount]);
-
- auto DbgMaxSignatureBindingIndex =
- PipelineResourceSignatureD3D12Impl::CopyResourceSignatures(CreateInfo.PSODesc.PipelineType, CreateInfo.ResourceSignaturesCount,
- CreateInfo.ppResourceSignatures, m_ResourceSignatures.get(), SignatureCount);
- VERIFY_EXPR(DbgMaxSignatureBindingIndex == MaxSignatureBindingIndex);
+ VERIFY_EXPR(m_SignatureCount == 1);
+ m_Signatures[0] = CreateDefaultResourceSignature(GetDevice(), CreateInfo, ShaderStages, pLocalRootSig);
+ VERIFY_EXPR(!m_Signatures[0] || m_Signatures[0]->GetDesc().BindingIndex == 0);
}
- m_RootSig = GetDevice()->GetRootSignatureCache().GetRootSig(m_ResourceSignatures.get(), SignatureCount);
+ m_RootSig = GetDevice()->GetRootSignatureCache().GetRootSig(m_Signatures, m_SignatureCount);
if (!m_RootSig)
LOG_ERROR_AND_THROW("Failed to create root signature for pipeline '", m_Desc.Name, "'.");
@@ -587,9 +574,9 @@ void PipelineStateD3D12Impl::InitRootSignature(const PipelineStateCreateInfo& Cr
ResourceBinding::TMap ResourceMap;
// Note that we must use signatures from m_ResourceSignatures for resource binding map,
// because signatures from m_RootSig may have resources with different names.
- for (Uint32 sign = 0; sign < SignatureCount; ++sign)
+ for (Uint32 sign = 0; sign < m_SignatureCount; ++sign)
{
- const PipelineResourceSignatureD3D12Impl* const pSignature = m_ResourceSignatures[sign];
+ const PipelineResourceSignatureD3D12Impl* const pSignature = m_Signatures[sign];
if (pSignature == nullptr)
continue;
@@ -1118,12 +1105,14 @@ void PipelineStateD3D12Impl::Destruct()
bool PipelineStateD3D12Impl::IsCompatibleWith(const IPipelineState* pPSO) const
{
- VERIFY_EXPR(pPSO != nullptr);
+ DEV_CHECK_ERR(pPSO != nullptr, "pPSO must not be null");
if (pPSO == this)
return true;
- return (m_RootSig == ValidatedCast<const PipelineStateD3D12Impl>(pPSO)->m_RootSig);
+ bool IsCompatible = (m_RootSig == ValidatedCast<const PipelineStateD3D12Impl>(pPSO)->m_RootSig);
+ VERIFY_EXPR(IsCompatible == TPipelineStateBase::IsCompatibleWith(pPSO));
+ return IsCompatible;
}
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp
index 20f1965a..37fef0ba 100644
--- a/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp
+++ b/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp
@@ -60,19 +60,6 @@ public:
/// Queries the specific interface, see IObject::QueryInterface() for details
virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override;
- /// Implementation of IPipelineState::GetResourceSignatureCount() in OpenGL backend.
- virtual Uint32 DILIGENT_CALL_TYPE GetResourceSignatureCount() const override final { return m_SignatureCount; }
-
- /// Implementation of IPipelineState::GetResourceSignature() in OpenGL backend.
- virtual PipelineResourceSignatureGLImpl* DILIGENT_CALL_TYPE GetResourceSignature(Uint32 Index) const override final
- {
- VERIFY_EXPR(Index < m_SignatureCount);
- return m_Signatures[Index].RawPtr<PipelineResourceSignatureGLImpl>();
- }
-
- /// Implementation of IPipelineState::IsCompatibleWith() in OpenGL backend.
- virtual bool DILIGENT_CALL_TYPE IsCompatibleWith(const IPipelineState* pPSO) const override final;
-
void CommitProgram(GLContextState& State);
#ifdef DILIGENT_DEVELOPMENT
@@ -92,10 +79,10 @@ private:
const TShaderStages& ShaderStages,
SHADER_TYPE ActiveStages);
- void CreateDefaultSignature(const PipelineStateCreateInfo& CreateInfo,
- const TShaderStages& ShaderStages,
- SHADER_TYPE ActiveStages,
- IPipelineResourceSignature** ppSignature);
+ RefCntAutoPtr<PipelineResourceSignatureGLImpl> CreateDefaultSignature(
+ const PipelineStateCreateInfo& CreateInfo,
+ const TShaderStages& ShaderStages,
+ SHADER_TYPE ActiveStages);
void Destruct();
@@ -115,10 +102,6 @@ private:
std::vector<std::pair<GLContext::NativeGLContextType, GLObjectWrappers::GLPipelineObj>> m_GLProgPipelines;
- using SignatureArrayType = std::array<RefCntAutoPtr<PipelineResourceSignatureGLImpl>, MAX_RESOURCE_SIGNATURES>;
- SignatureArrayType m_Signatures = {};
- Uint8 m_SignatureCount = 0;
-
Uint8 m_NumPrograms = 0;
bool m_IsProgramPipelineSupported = false;
std::array<SHADER_TYPE, 5> m_ShaderTypes = {};
diff --git a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp
index 693c0d1a..334b20d7 100644
--- a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp
+++ b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp
@@ -41,10 +41,10 @@
namespace Diligent
{
-void PipelineStateGLImpl::CreateDefaultSignature(const PipelineStateCreateInfo& CreateInfo,
- const TShaderStages& ShaderStages,
- SHADER_TYPE ActiveStages,
- IPipelineResourceSignature** ppSignature)
+RefCntAutoPtr<PipelineResourceSignatureGLImpl> PipelineStateGLImpl::CreateDefaultSignature(
+ const PipelineStateCreateInfo& CreateInfo,
+ const TShaderStages& ShaderStages,
+ SHADER_TYPE ActiveStages)
{
std::vector<PipelineResourceDesc> Resources;
@@ -152,6 +152,7 @@ void PipelineStateGLImpl::CreateDefaultSignature(const PipelineStateCreateInfo&
ProgramResources.ProcessConstResources(HandleUB, HandleTexture, HandleImage, HandleSB);
}
+ RefCntAutoPtr<PipelineResourceSignatureGLImpl> pSignature;
if (Resources.size())
{
String SignName = String{"Implicit signature for PSO '"} + m_Desc.Name + '\'';
@@ -167,37 +168,28 @@ void PipelineStateGLImpl::CreateDefaultSignature(const PipelineStateCreateInfo&
ResSignDesc.SRBAllocationGranularity = CreateInfo.PSODesc.SRBAllocationGranularity;
ResSignDesc.UseCombinedTextureSamplers = true;
- GetDevice()->CreatePipelineResourceSignature(ResSignDesc, ppSignature, true);
+ // Always initialize default resource signature as internal device object.
+ // This is necessary to avoud cyclic references from TexRegionRenderer.
+ // This may never be a problem as the PSO keeps the reference to the device if necessary.
+ constexpr bool bIsDeviceInternal = true;
+ GetDevice()->CreatePipelineResourceSignature(ResSignDesc, pSignature.DblPtr<IPipelineResourceSignature>(), bIsDeviceInternal);
- if (*ppSignature == nullptr)
+ if (!pSignature)
LOG_ERROR_AND_THROW("Failed to create resource signature for pipeline state");
}
+
+ return pSignature;
}
void PipelineStateGLImpl::InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo,
const TShaderStages& ShaderStages,
SHADER_TYPE ActiveStages)
{
- const Uint32 SignatureCount = CreateInfo.ResourceSignaturesCount;
- RefCntAutoPtr<IPipelineResourceSignature> pImplicitSignature;
-
- if (SignatureCount == 0 || CreateInfo.ppResourceSignatures == nullptr)
- {
- CreateDefaultSignature(CreateInfo, ShaderStages, ActiveStages, &pImplicitSignature);
- if (pImplicitSignature != nullptr)
- {
- VERIFY_EXPR(pImplicitSignature->GetDesc().BindingIndex == 0);
- m_Signatures[0] = ValidatedCast<PipelineResourceSignatureGLImpl>(pImplicitSignature.RawPtr());
- m_SignatureCount = 1;
- }
- }
- else
+ if (m_UsingImplicitSignature)
{
- const auto MaxBindingIndex =
- PipelineResourceSignatureGLImpl::CopyResourceSignatures(CreateInfo.PSODesc.PipelineType, SignatureCount, CreateInfo.ppResourceSignatures,
- m_Signatures.data(), m_Signatures.size());
- m_SignatureCount = static_cast<decltype(m_SignatureCount)>(MaxBindingIndex + 1);
- VERIFY_EXPR(m_SignatureCount == MaxBindingIndex + 1);
+ VERIFY_EXPR(m_SignatureCount == 1);
+ m_Signatures[0] = CreateDefaultSignature(CreateInfo, ShaderStages, ActiveStages);
+ VERIFY_EXPR(!m_Signatures[0] || m_Signatures[0]->GetDesc().BindingIndex == 0);
}
// Apply resource bindings to programs.
@@ -393,10 +385,7 @@ void PipelineStateGLImpl::Destruct()
m_GLPrograms = nullptr;
}
- m_Signatures.fill({});
-
- m_SignatureCount = 0;
- m_NumPrograms = 0;
+ m_NumPrograms = 0;
TPipelineStateBase::Destruct();
}
@@ -409,26 +398,6 @@ SHADER_TYPE PipelineStateGLImpl::GetShaderStageType(Uint32 Index) const
return m_ShaderTypes[Index];
}
-bool PipelineStateGLImpl::IsCompatibleWith(const IPipelineState* pPSO) const
-{
- VERIFY_EXPR(pPSO != nullptr);
-
- if (pPSO == this)
- return true;
-
- const auto& lhs = *this;
- const auto& rhs = *ValidatedCast<const PipelineStateGLImpl>(pPSO);
-
- if (lhs.GetResourceSignatureCount() != rhs.GetResourceSignatureCount())
- return false;
-
- for (Uint32 s = 0, SigCount = lhs.GetResourceSignatureCount(); s < SigCount; ++s)
- {
- if (!lhs.GetResourceSignature(s)->IsCompatibleWith(*rhs.GetResourceSignature(s)))
- return false;
- }
- return true;
-}
void PipelineStateGLImpl::CommitProgram(GLContextState& State)
{
diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp
index 25bbcb6b..3ef58d49 100644
--- a/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp
@@ -29,15 +29,16 @@
/// \file
/// Declaration of Diligent::PipelineLayoutVk class
+
#include <array>
-#include "PipelineResourceSignatureVkImpl.hpp"
#include "VulkanUtilities/VulkanObjectWrappers.hpp"
namespace Diligent
{
-class ShaderResourceCacheVk;
+class RenderDeviceVkImpl;
+class PipelineResourceSignatureVkImpl;
/// Implementation of the Diligent::PipelineLayoutVk class
class PipelineLayoutVk
@@ -46,68 +47,32 @@ public:
PipelineLayoutVk();
~PipelineLayoutVk();
- void Create(RenderDeviceVkImpl* pDeviceVk, PIPELINE_TYPE PipelineType, IPipelineResourceSignature** ppSignatures, Uint32 SignatureCount);
+ void Create(RenderDeviceVkImpl* pDeviceVk, RefCntAutoPtr<PipelineResourceSignatureVkImpl> ppSignatures[], Uint32 SignatureCount);
void Release(RenderDeviceVkImpl* pDeviceVkImpl, Uint64 CommandQueueMask);
- size_t GetHash() const;
-
VkPipelineLayout GetVkPipelineLayout() const { return m_VkPipelineLayout; }
- Uint32 GetSignatureCount() const { return m_SignatureCount; }
- PipelineResourceSignatureVkImpl* GetSignature(Uint32 index) const
+ // Returns the index of the first descriptor set used by the resource signature at the given bind index
+ Uint32 GetFirstDescrSetIndex(Uint32 Index) const
{
- VERIFY_EXPR(index < m_SignatureCount);
- return m_Signatures[index].RawPtr<PipelineResourceSignatureVkImpl>();
- }
-
- // Returns the index of the first descriptor set used by the given resource signature
- Uint32 GetFirstDescrSetIndex(const PipelineResourceSignatureVkImpl* pPRS) const
- {
- VERIFY_EXPR(pPRS != nullptr);
- Uint32 Index = pPRS->GetDesc().BindingIndex;
-
- VERIFY_EXPR(Index < m_SignatureCount);
- VERIFY_EXPR(m_Signatures[Index] != nullptr);
- VERIFY_EXPR(!m_Signatures[Index]->IsIncompatibleWith(*pPRS));
-
+ VERIFY_EXPR(Index <= m_DbgMaxBindIndex);
return m_FirstDescrSetIndex[Index];
}
- struct ResourceInfo
- {
- PipelineResourceSignatureVkImpl* Signature = nullptr;
- SHADER_RESOURCE_TYPE Type = SHADER_RESOURCE_TYPE_UNKNOWN;
- // Index in m_Desc.Resources for a resource, or ~0U for an immutable sampler.
- Uint32 ResIndex = ~0U;
- Uint32 DescrSetIndex = ~0U;
- Uint32 BindingIndex = ~0U;
-
- explicit operator bool() const
- {
- return Signature != nullptr && Type != SHADER_RESOURCE_TYPE_UNKNOWN;
- }
- };
- ResourceInfo GetResourceInfo(const char* Name, SHADER_TYPE Stage) const;
- ResourceInfo GetImmutableSamplerInfo(const char* Name, SHADER_TYPE Stage) const;
-
private:
- using SignatureArray = std::array<RefCntAutoPtr<PipelineResourceSignatureVkImpl>, MAX_RESOURCE_SIGNATURES>;
- using FirstDescrSetIndexArrayType = std::array<Uint8, MAX_RESOURCE_SIGNATURES>;
-
VulkanUtilities::PipelineLayoutWrapper m_VkPipelineLayout;
+ using FirstDescrSetIndexArrayType = std::array<Uint8, MAX_RESOURCE_SIGNATURES>;
// Index of the first descriptor set, for every resource signature.
FirstDescrSetIndexArrayType m_FirstDescrSetIndex = {};
- // The number of resource signatures used by this pipeline layout
- // (Maximum is MAX_RESOURCE_SIGNATURES)
- Uint8 m_SignatureCount = 0;
-
// The total number of descriptor sets used by this pipeline layout
// (Maximum is MAX_RESOURCE_SIGNATURES * 2)
Uint8 m_DescrSetCount = 0;
- SignatureArray m_Signatures;
+#ifdef DILIGENT_DEBUG
+ Uint32 m_DbgMaxBindIndex = 0;
+#endif
};
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp
index d2f289af..f36611df 100644
--- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp
@@ -44,6 +44,7 @@
#include "VulkanUtilities/VulkanCommandBuffer.hpp"
#include "RenderDeviceVkImpl.hpp"
#include "PipelineLayoutVk.hpp"
+#include "PipelineResourceSignatureVkImpl.hpp"
namespace Diligent
{
@@ -66,21 +67,12 @@ public:
IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_PipelineStateVk, TPipelineStateBase)
- /// Implementation of IPipelineState::IsCompatibleWith() in Vulkan backend.
- virtual bool DILIGENT_CALL_TYPE IsCompatibleWith(const IPipelineState* pPSO) const override final;
-
/// Implementation of IPipelineStateVk::GetRenderPass().
virtual IRenderPassVk* DILIGENT_CALL_TYPE GetRenderPass() const override final { return GetRenderPassPtr().RawPtr<IRenderPassVk>(); }
/// Implementation of IPipelineStateVk::GetVkPipeline().
virtual VkPipeline DILIGENT_CALL_TYPE GetVkPipeline() const override final { return m_Pipeline; }
- /// Implementation of IPipelineState::GetResourceSignatureCount() in Vulkan backend.
- virtual Uint32 DILIGENT_CALL_TYPE GetResourceSignatureCount() const override final { return m_PipelineLayout.GetSignatureCount(); }
-
- /// Implementation of IPipelineState::GetResourceSignature() in Vulkan backend.
- virtual IPipelineResourceSignature* DILIGENT_CALL_TYPE GetResourceSignature(Uint32 Index) const override final { return m_PipelineLayout.GetSignature(Index); }
-
const PipelineLayoutVk& GetPipelineLayout() const { return m_PipelineLayout; }
static RenderPassDesc GetImplicitRenderPassDesc(Uint32 NumRenderTargets,
@@ -115,7 +107,7 @@ public:
// Performs validation of SRB resource parameters that are not possible to validate
// when resource is bound.
using SRBArray = std::array<ShaderResourceBindingVkImpl*, MAX_RESOURCE_SIGNATURES>;
- void DvpVerifySRBResources(SRBArray& SRBs) const;
+ void DvpVerifySRBResources(const SRBArray& SRBs) const;
#endif
private:
@@ -127,9 +119,9 @@ private:
void InitPipelineLayout(const PipelineStateCreateInfo& CreateInfo,
TShaderStages& ShaderStages);
- void CreateDefaultSignature(const PipelineStateCreateInfo& CreateInfo,
- const TShaderStages& ShaderStages,
- IPipelineResourceSignature** ppSignature);
+ RefCntAutoPtr<PipelineResourceSignatureVkImpl> CreateDefaultSignature(
+ const PipelineStateCreateInfo& CreateInfo,
+ const TShaderStages& ShaderStages);
void Destruct();
@@ -139,8 +131,8 @@ private:
#ifdef DILIGENT_DEVELOPMENT
// Shader resources for all shaders in all shader stages
std::vector<std::shared_ptr<const SPIRVShaderResources>> m_ShaderResources;
- // Resource info for every resource in m_ShaderResources, in the same order
- std::vector<PipelineLayoutVk::ResourceInfo> m_ResInfo;
+ // Resource attributions for every resource in m_ShaderResources, in the same order
+ std::vector<ResourceAttribution> m_ResourceAttibutions;
#endif
};
diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
index 878cf9a9..0ac9c0fb 100644
--- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
@@ -318,14 +318,14 @@ void DeviceContextVkImpl::SetPipelineState(IPipelineState* pPipelineState)
const auto& Layout = pPipelineStateVk->GetPipelineLayout();
auto& BindInfo = GetDescriptorSetBindInfo(PSODesc.PipelineType);
- const auto SignCount = Layout.GetSignatureCount();
+ const auto SignCount = pPipelineStateVk->GetResourceSignatureCount();
BindInfo.vkPipelineLayout = Layout.GetVkPipelineLayout();
BindInfo.ActiveSRBMask = 0;
for (Uint32 i = 0; i < SignCount; ++i)
{
- auto* pSignature = Layout.GetSignature(i);
+ auto* pSignature = pPipelineStateVk->GetResourceSignature(i);
if (pSignature == nullptr || pSignature->GetNumDescriptorSets() == 0)
continue;
@@ -333,7 +333,7 @@ void DeviceContextVkImpl::SetPipelineState(IPipelineState* pPipelineState)
auto& ResInfo = BindInfo.Resources[i];
- ResInfo.DescriptorSetBaseInd = Layout.GetFirstDescrSetIndex(pSignature);
+ ResInfo.DescriptorSetBaseInd = Layout.GetFirstDescrSetIndex(pSignature->GetDesc().BindingIndex);
ResInfo.DynamicOffsetCount = pSignature->GetDynamicOffsetCount();
}
@@ -349,7 +349,7 @@ void DeviceContextVkImpl::SetPipelineState(IPipelineState* pPipelineState)
Uint32 sign = 0;
for (; sign < SignCount; ++sign)
{
- const auto* pLayoutSign = Layout.GetSignature(sign);
+ const auto* pLayoutSign = pPipelineStateVk->GetResourceSignature(sign);
const auto* pSRBSign = BindInfo.SRBs[sign] != nullptr ? BindInfo.SRBs[sign]->GetSignature() : nullptr;
if ((pLayoutSign == nullptr || pLayoutSign->GetNumDescriptorSets() == 0) != (pSRBSign == nullptr || pSRBSign->GetNumDescriptorSets() == 0))
@@ -414,7 +414,7 @@ void DeviceContextVkImpl::CommitDescriptorSets(DescriptorSetBindInfo& BindInfo)
while (StaleSRBFlags != 0)
{
Uint32 sign = PlatformMisc::GetLSB(StaleSRBFlags);
- VERIFY_EXPR(sign < m_pPipelineState->GetPipelineLayout().GetSignatureCount());
+ VERIFY_EXPR(sign < m_pPipelineState->GetResourceSignatureCount());
StaleSRBFlags &= ~(Uint32{1} << sign);
auto& ResInfo = BindInfo.Resources[sign];
@@ -461,17 +461,16 @@ void DeviceContextVkImpl::DvpValidateCommittedShaderResources()
if (m_State.CommittedResourcesValidated)
return;
- const auto& Layout = m_pPipelineState->GetPipelineLayout();
- auto& BindInfo = GetDescriptorSetBindInfo(m_pPipelineState->GetDesc().PipelineType);
- const auto SignCount = Layout.GetSignatureCount();
+ const auto& BindInfo = GetDescriptorSetBindInfo(m_pPipelineState->GetDesc().PipelineType);
+ const auto SignCount = m_pPipelineState->GetResourceSignatureCount();
for (Uint32 i = 0; i < SignCount; ++i)
{
- auto* pLayoutSign = Layout.GetSignature(i);
- if (pLayoutSign == nullptr)
+ const auto* pSign = m_pPipelineState->GetResourceSignature(i);
+ if (pSign == nullptr)
continue;
- if (pLayoutSign->GetNumDescriptorSets() == 0)
+ if (pSign->GetNumDescriptorSets() == 0)
{
// Skip signatures without any resources
continue;
@@ -487,7 +486,7 @@ void DeviceContextVkImpl::DvpValidateCommittedShaderResources()
const auto* pSRBSign = pSRB->GetSignature();
DEV_CHECK_ERR(pSRBSign != nullptr, "SRB must not be null");
- if (!pLayoutSign->IsCompatibleWith(*pSRBSign))
+ if (!pSign->IsCompatibleWith(*pSRBSign))
{
LOG_ERROR_MESSAGE("Shader resource binding at index ", i, " with signature '", pSRBSign->GetDesc().Name,
"' is not compatible with pipeline layout in current pipeline '", m_pPipelineState->GetDesc().Name, "'.");
@@ -496,12 +495,12 @@ void DeviceContextVkImpl::DvpValidateCommittedShaderResources()
DEV_CHECK_ERR((BindInfo.StaleSRBMask & BindInfo.ActiveSRBMask) == 0, "CommitDescriptorSets() must be called before validation.");
const auto& ResInfo = BindInfo.Resources[i];
- const auto DSCount = pLayoutSign->GetNumDescriptorSets();
+ const auto DSCount = pSign->GetNumDescriptorSets();
for (Uint32 s = 0; s < DSCount; ++s)
{
DEV_CHECK_ERR(ResInfo.vkSets[s] != VK_NULL_HANDLE,
"descriptor set with index ", s, " is not bound for resource signature '",
- pLayoutSign->GetDesc().Name, "', binding index ", i, ".");
+ pSign->GetDesc().Name, "', binding index ", i, ".");
}
DEV_CHECK_ERR(ResInfo.LastBoundDSBaseInd == ResInfo.DescriptorSetBaseInd,
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp
index f8fae8ee..14183e97 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp
@@ -34,6 +34,7 @@
#include "RenderDeviceVkImpl.hpp"
#include "VulkanTypeConversions.hpp"
#include "StringTools.hpp"
+#include "PipelineResourceSignatureVkImpl.hpp"
namespace Diligent
{
@@ -56,16 +57,9 @@ void PipelineLayoutVk::Release(RenderDeviceVkImpl* pDeviceVk, Uint64 CommandQueu
}
}
-void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, PIPELINE_TYPE PipelineType, IPipelineResourceSignature** ppSignatures, Uint32 SignatureCount)
+void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, RefCntAutoPtr<PipelineResourceSignatureVkImpl> ppSignatures[], Uint32 SignatureCount)
{
- VERIFY(m_SignatureCount == 0 && m_DescrSetCount == 0 && !m_VkPipelineLayout,
- "This pipeline layout is already initialized");
-
- auto MaxSignatureBindIndex =
- PipelineResourceSignatureVkImpl::CopyResourceSignatures(PipelineType, SignatureCount, ppSignatures,
- m_Signatures.data(), m_Signatures.size());
- m_SignatureCount = static_cast<Uint8>(MaxSignatureBindIndex + 1);
- VERIFY_EXPR(m_SignatureCount == MaxSignatureBindIndex + 1);
+ VERIFY(m_DescrSetCount == 0 && !m_VkPipelineLayout, "This pipeline layout is already initialized");
std::array<VkDescriptorSetLayout, MAX_RESOURCE_SIGNATURES * PipelineResourceSignatureVkImpl::MAX_DESCRIPTOR_SETS> DescSetLayouts;
@@ -73,9 +67,9 @@ void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, PIPELINE_TYPE Pipel
Uint32 DynamicUniformBufferCount = 0;
Uint32 DynamicStorageBufferCount = 0;
- for (Uint32 i = 0; i < m_SignatureCount; ++i)
+ for (Uint32 i = 0; i < SignatureCount; ++i)
{
- const auto& pSignature = m_Signatures[i];
+ const auto& pSignature = ppSignatures[i];
if (pSignature == nullptr)
continue;
@@ -91,6 +85,9 @@ void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, PIPELINE_TYPE Pipel
DynamicUniformBufferCount += pSignature->GetDynamicUniformBufferCount();
DynamicStorageBufferCount += pSignature->GetDynamicStorageBufferCount();
+#ifdef DILIGENT_DEBUG
+ m_DbgMaxBindIndex = std::max(m_DbgMaxBindIndex, Uint32{pSignature->GetDesc().BindingIndex});
+#endif
}
VERIFY_EXPR(DescSetLayoutCount <= MAX_RESOURCE_SIGNATURES * 2);
@@ -130,76 +127,4 @@ void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, PIPELINE_TYPE Pipel
m_DescrSetCount = static_cast<Uint8>(DescSetLayoutCount);
}
-size_t PipelineLayoutVk::GetHash() const
-{
- if (m_SignatureCount == 0)
- return 0;
-
- size_t hash = 0;
- HashCombine(hash, m_SignatureCount);
- for (Uint32 i = 0; i < m_SignatureCount; ++i)
- {
- if (m_Signatures[i] != nullptr)
- HashCombine(hash, m_Signatures[i]->GetHash());
- else
- HashCombine(hash, 0);
- }
- return hash;
-}
-
-PipelineLayoutVk::ResourceInfo PipelineLayoutVk::GetResourceInfo(const char* Name, SHADER_TYPE Stage) const
-{
- ResourceInfo Info;
- for (Uint32 sign = 0, SignCount = GetSignatureCount(); sign < SignCount && !Info; ++sign)
- {
- auto* const pSignature = GetSignature(sign);
- if (pSignature == nullptr)
- continue;
-
- for (Uint32 r = 0, ResCount = pSignature->GetTotalResourceCount(); r < ResCount; ++r)
- {
- const auto& ResDesc = pSignature->GetResourceDesc(r);
- const auto& Attr = pSignature->GetResourceAttribs(r);
-
- if ((ResDesc.ShaderStages & Stage) != 0 && strcmp(ResDesc.Name, Name) == 0)
- {
- Info.Signature = pSignature;
- Info.Type = ResDesc.ResourceType;
- Info.ResIndex = r;
- Info.BindingIndex = Attr.BindingIndex;
- Info.DescrSetIndex = m_FirstDescrSetIndex[sign] + Attr.DescrSet;
- break;
- }
- }
- }
- return Info;
-}
-
-PipelineLayoutVk::ResourceInfo PipelineLayoutVk::GetImmutableSamplerInfo(const char* Name, SHADER_TYPE Stage) const
-{
- ResourceInfo Info;
- for (Uint32 sign = 0, SignCount = GetSignatureCount(); sign < SignCount && !Info; ++sign)
- {
- auto* const pSignature = GetSignature(sign);
- if (pSignature == nullptr)
- continue;
-
- for (Uint32 s = 0, SampCount = pSignature->GetImmutableSamplerCount(); s < SampCount; ++s)
- {
- const auto& Desc = pSignature->GetImmutableSamplerDesc(s);
- const auto& Attr = pSignature->GetImmutableSamplerAttribs(s);
-
- if (Attr.Ptr && (Desc.ShaderStages & Stage) != 0 && StreqSuff(Name, Desc.SamplerOrTextureName, pSignature->GetCombinedSamplerSuffix()))
- {
- Info.Signature = pSignature;
- Info.Type = SHADER_RESOURCE_TYPE_SAMPLER;
- Info.BindingIndex = Attr.BindingIndex;
- Info.DescrSetIndex = m_FirstDescrSetIndex[sign] + Attr.DescrSet;
- break;
- }
- }
- }
- return Info;
-}
-
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
index 3a3f8092..364d6f1b 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
@@ -735,9 +735,9 @@ RenderPassDesc PipelineStateVkImpl::GetImplicitRenderPassDesc(
return RPDesc;
}
-void PipelineStateVkImpl::CreateDefaultSignature(const PipelineStateCreateInfo& CreateInfo,
- const TShaderStages& ShaderStages,
- IPipelineResourceSignature** ppSignature)
+RefCntAutoPtr<PipelineResourceSignatureVkImpl> PipelineStateVkImpl::CreateDefaultSignature(
+ const PipelineStateCreateInfo& CreateInfo,
+ const TShaderStages& ShaderStages)
{
struct UniqueResource
{
@@ -837,6 +837,7 @@ void PipelineStateVkImpl::CreateDefaultSignature(const PipelineStateCreateInfo&
}
}
+ RefCntAutoPtr<PipelineResourceSignatureVkImpl> pSignature;
if (Resources.size())
{
String SignName = String{"Implicit signature for PSO '"} + m_Desc.Name + '\'';
@@ -852,38 +853,30 @@ void PipelineStateVkImpl::CreateDefaultSignature(const PipelineStateCreateInfo&
ResSignDesc.UseCombinedTextureSamplers = pCombinedSamplerSuffix != nullptr;
ResSignDesc.CombinedSamplerSuffix = pCombinedSamplerSuffix;
- GetDevice()->CreatePipelineResourceSignature(ResSignDesc, ppSignature, true);
+ // Always initialize default resource signature as internal device object.
+ // This is necessary to avoud cyclic references.
+ // This may never be a problem as the PSO keeps the reference to the device if necessary.
+ constexpr bool bIsDeviceInternal = true;
+ GetDevice()->CreatePipelineResourceSignature(ResSignDesc, pSignature.DblPtr<IPipelineResourceSignature>(), bIsDeviceInternal);
- if (*ppSignature == nullptr)
+ if (pSignature == nullptr)
LOG_ERROR_AND_THROW("Failed to create resource signature for pipeline state");
}
+
+ return pSignature;
}
void PipelineStateVkImpl::InitPipelineLayout(const PipelineStateCreateInfo& CreateInfo,
TShaderStages& ShaderStages)
{
- std::array<IPipelineResourceSignature*, MAX_RESOURCE_SIGNATURES> Signatures = {};
- RefCntAutoPtr<IPipelineResourceSignature> pImplicitSignature;
-
- Uint32 SignatureCount = CreateInfo.ResourceSignaturesCount;
-
- for (Uint32 i = 0; i < SignatureCount; ++i)
- {
- Signatures[i] = CreateInfo.ppResourceSignatures[i];
- }
-
- if (SignatureCount == 0 || CreateInfo.ppResourceSignatures == nullptr)
+ if (m_UsingImplicitSignature)
{
- CreateDefaultSignature(CreateInfo, ShaderStages, &pImplicitSignature);
- if (pImplicitSignature != nullptr)
- {
- VERIFY_EXPR(pImplicitSignature->GetDesc().BindingIndex == 0);
- Signatures[0] = pImplicitSignature;
- SignatureCount = 1;
- }
+ VERIFY_EXPR(m_SignatureCount == 1);
+ m_Signatures[0] = CreateDefaultSignature(CreateInfo, ShaderStages);
+ VERIFY_EXPR(!m_Signatures[0] || m_Signatures[0]->GetDesc().BindingIndex == 0);
}
- m_PipelineLayout.Create(GetDevice(), CreateInfo.PSODesc.PipelineType, Signatures.data(), SignatureCount);
+ m_PipelineLayout.Create(GetDevice(), m_Signatures, m_SignatureCount);
// Verify that pipeline layout is compatible with shader resources and
// remap resource bindings.
@@ -908,46 +901,56 @@ void PipelineStateVkImpl::InitPipelineLayout(const PipelineStateCreateInfo& Crea
pShaderResources->ProcessResources(
[&](const SPIRVShaderResourceAttribs& SPIRVAttribs, Uint32) //
{
- auto Info = m_PipelineLayout.GetResourceInfo(SPIRVAttribs.Name, ShaderType);
- if (!Info && SPIRVAttribs.Type == SPIRVShaderResourceAttribs::SeparateSampler)
- {
- DEV_CHECK_ERR(SPIRVAttribs.ArraySize == 1, "Immutable sampler arrays must also be added to resource list");
- Info = m_PipelineLayout.GetImmutableSamplerInfo(SPIRVAttribs.Name, ShaderType);
- if (Info)
- {
- VERIFY(Info.BindingIndex != ~0u && Info.DescrSetIndex != ~0u,
- "Binding index and/or descriptor set index are not initialized. This indicates that the immutable sampler "
- "is also present in the list of resources, so it should've been found by GetResourceInfo().");
- }
- }
- if (!Info)
+ auto ResAttribution = GetResourceAttribution(SPIRVAttribs.Name, ShaderType);
+ if (!ResAttribution)
{
LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource '", SPIRVAttribs.Name,
"' that is not present in any pipeline resource signature used to create pipeline state '",
m_Desc.Name, "'.");
}
+ const auto& SignDesc = ResAttribution.pSignature->GetDesc();
+
SHADER_RESOURCE_TYPE Type;
PIPELINE_RESOURCE_FLAGS Flags;
GetShaderResourceTypeAndFlags(SPIRVAttribs.Type, Type, Flags);
- if (Type != Info.Type)
- {
- LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", SPIRVAttribs.Name,
- "' and type '", GetShaderResourceTypeLiteralName(Type), "' that is not compatible with type '",
- GetShaderResourceTypeLiteralName(Info.Type), "' specified in pipeline resource signature '", Info.Signature->GetDesc().Name, "'.");
- }
- if (Info.ResIndex != ~0u)
+ Uint32 ResourceBinding = ~0u;
+ Uint32 DescriptorSet = ~0u;
+ if (ResAttribution.ResourceIndex != ResourceAttribution::InvalidResourceIndex)
{
- const auto& ResDesc = Info.Signature->GetResourceDesc(Info.ResIndex);
+ const auto& ResDesc = ResAttribution.pSignature->GetResourceDesc(ResAttribution.ResourceIndex);
ValidatePipelineResourceCompatibility(ResDesc, Type, Flags, SPIRVAttribs.ArraySize,
- pShader->GetDesc().Name, Info.Signature->GetDesc().Name);
+ pShader->GetDesc().Name, SignDesc.Name);
+
+ const auto& ResAttribs{ResAttribution.pSignature->GetResourceAttribs(ResAttribution.ResourceIndex)};
+ ResourceBinding = ResAttribs.BindingIndex;
+ DescriptorSet = ResAttribs.DescrSet;
+ }
+ else if (ResAttribution.ImmutableSamplerIndex != ResourceAttribution::InvalidResourceIndex)
+ {
+ if (Type != SHADER_RESOURCE_TYPE_SAMPLER)
+ {
+ LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", SPIRVAttribs.Name,
+ "' and type '", GetShaderResourceTypeLiteralName(Type),
+ "' that is not compatible with immutable sampler defined in pipeline resource signature '",
+ SignDesc.Name, "'.");
+ }
+ const auto& SamAttribs{ResAttribution.pSignature->GetImmutableSamplerAttribs(ResAttribution.ImmutableSamplerIndex)};
+ ResourceBinding = SamAttribs.BindingIndex;
+ DescriptorSet = SamAttribs.DescrSet;
+ }
+ else
+ {
+ UNEXPECTED("Either immutable sampler or resource index should be valid");
}
- SPIRV[SPIRVAttribs.BindingDecorationOffset] = Info.BindingIndex;
- SPIRV[SPIRVAttribs.DescriptorSetDecorationOffset] = Info.DescrSetIndex;
+
+ VERIFY_EXPR(ResourceBinding != ~0u && DescriptorSet != ~0u);
+ SPIRV[SPIRVAttribs.BindingDecorationOffset] = ResourceBinding;
+ SPIRV[SPIRVAttribs.DescriptorSetDecorationOffset] = m_PipelineLayout.GetFirstDescrSetIndex(SignDesc.BindingIndex) + DescriptorSet;
#ifdef DILIGENT_DEVELOPMENT
- m_ResInfo.emplace_back(Info);
+ m_ResourceAttibutions.emplace_back(ResAttribution);
#endif
});
}
@@ -963,8 +966,6 @@ PipelineStateVkImpl::TShaderStages PipelineStateVkImpl::InitInternalObjects(
TShaderStages ShaderStages;
ExtractShaders<ShaderVkImpl>(CreateInfo, ShaderStages);
- InitPipelineLayout(CreateInfo, ShaderStages);
-
FixedLinearAllocator MemPool{GetRawAllocator()};
ReserveSpaceForPipelineDesc(CreateInfo, MemPool);
@@ -975,6 +976,8 @@ PipelineStateVkImpl::TShaderStages PipelineStateVkImpl::InitInternalObjects(
InitializePipelineDesc(CreateInfo, MemPool);
+ InitPipelineLayout(CreateInfo, ShaderStages);
+
// Create shader modules and initialize shader stages
InitPipelineShaderStages(LogicalDevice, ShaderStages, ShaderModules, vkShaderStages);
@@ -1062,45 +1065,24 @@ void PipelineStateVkImpl::Destruct()
TPipelineStateBase::Destruct();
}
-bool PipelineStateVkImpl::IsCompatibleWith(const IPipelineState* pPSO) const
-{
- VERIFY_EXPR(pPSO != nullptr);
-
- if (pPSO == this)
- return true;
-
- const auto& lhs = m_PipelineLayout;
- const auto& rhs = ValidatedCast<const PipelineStateVkImpl>(pPSO)->m_PipelineLayout;
-
- if (lhs.GetSignatureCount() != rhs.GetSignatureCount())
- return false;
-
- for (Uint32 s = 0, SigCount = lhs.GetSignatureCount(); s < SigCount; ++s)
- {
- if (!lhs.GetSignature(s)->IsCompatibleWith(*rhs.GetSignature(s)))
- return false;
- }
- return true;
-}
-
#ifdef DILIGENT_DEVELOPMENT
-void PipelineStateVkImpl::DvpVerifySRBResources(SRBArray& SRBs) const
+void PipelineStateVkImpl::DvpVerifySRBResources(const SRBArray& SRBs) const
{
- auto res_info = m_ResInfo.begin();
+ auto res_info = m_ResourceAttibutions.begin();
for (const auto& pResources : m_ShaderResources)
{
pResources->ProcessResources(
[&](const SPIRVShaderResourceAttribs& ResAttribs, Uint32) //
{
- if (res_info->ResIndex != ~0u) // There are also immutable samplers in the list
+ if (!res_info->IsImmutableSampler()) // There are also immutable samplers in the list
{
- VERIFY_EXPR(res_info->Signature != nullptr);
- const auto& SignDesc = res_info->Signature->GetDesc();
+ VERIFY_EXPR(res_info->pSignature != nullptr);
+ const auto& SignDesc = res_info->pSignature->GetDesc();
const auto SignBindIndex = SignDesc.BindingIndex;
if (auto* pSRB = SRBs[SignBindIndex])
{
- res_info->Signature->DvpValidateCommittedResource(ResAttribs, res_info->ResIndex, pSRB->GetResourceCache(),
- pResources->GetShaderName(), m_Desc.Name);
+ res_info->pSignature->DvpValidateCommittedResource(ResAttribs, res_info->ResourceIndex, pSRB->GetResourceCache(),
+ pResources->GetShaderName(), m_Desc.Name);
}
else
{
@@ -1111,7 +1093,7 @@ void PipelineStateVkImpl::DvpVerifySRBResources(SRBArray& SRBs) const
} //
);
}
- VERIFY_EXPR(res_info == m_ResInfo.end());
+ VERIFY_EXPR(res_info == m_ResourceAttibutions.end());
}
#endif
diff --git a/Graphics/GraphicsEngineVulkan/src/RenderPassCache.cpp b/Graphics/GraphicsEngineVulkan/src/RenderPassCache.cpp
index e6d053ee..3becabff 100644
--- a/Graphics/GraphicsEngineVulkan/src/RenderPassCache.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/RenderPassCache.cpp
@@ -87,7 +87,7 @@ RenderPassVkImpl* RenderPassCache::GetRenderPass(const RenderPassCacheKey& Key)
}
RefCntAutoPtr<RenderPassVkImpl> pRenderPass;
- m_DeviceVkImpl.CreateRenderPass(RPDesc, pRenderPass.GetRawDblPtr<IRenderPass>(), /* IsDeviceInternal = */ true);
+ m_DeviceVkImpl.CreateRenderPass(RPDesc, pRenderPass.RawDblPtr<IRenderPass>(), /* IsDeviceInternal = */ true);
VERIFY_EXPR(pRenderPass != nullptr);
it = m_Cache.emplace(Key, std::move(pRenderPass)).first;
}