From 8a176f30d6c0ee19af6240ad48c2128222ad653c Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Sun, 11 Mar 2018 14:20:21 -0700 Subject: Implemented PSO compatibility in D3D12 --- .../GraphicsEngineD3D12/include/RootSignature.h | 113 +++++++++++++++++++++ .../src/PipelineStateD3D12Impl.cpp | 52 +++++++++- Graphics/GraphicsEngineD3D12/src/RootSignature.cpp | 37 +++++++ .../src/ShaderResourceBindingD3D12Impl.cpp | 4 +- 4 files changed, 200 insertions(+), 6 deletions(-) (limited to 'Graphics/GraphicsEngineD3D12') diff --git a/Graphics/GraphicsEngineD3D12/include/RootSignature.h b/Graphics/GraphicsEngineD3D12/include/RootSignature.h index 1244f0bf..46e4fc1c 100644 --- a/Graphics/GraphicsEngineD3D12/include/RootSignature.h +++ b/Graphics/GraphicsEngineD3D12/include/RootSignature.h @@ -146,6 +146,107 @@ public: Uint32 GetRootIndex()const{return m_RootIndex;} operator const D3D12_ROOT_PARAMETER&()const{return m_RootParam;} + + bool operator == (const RootParameter&rhs)const + { + if (m_ShaderVarType != rhs.m_ShaderVarType || + m_DescriptorTableSize != rhs.m_DescriptorTableSize || + m_RootIndex != rhs.m_RootIndex) + return false; + + if (m_RootParam.ParameterType != rhs.m_RootParam.ParameterType || + m_RootParam.ShaderVisibility != rhs.m_RootParam.ShaderVisibility) + return false; + + switch(m_RootParam.ParameterType) + { + case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE: + { + const auto &tbl0 = m_RootParam.DescriptorTable; + const auto &tbl1 = rhs.m_RootParam.DescriptorTable; + if(tbl0.NumDescriptorRanges != tbl1.NumDescriptorRanges) + return false; + for(UINT r=0; r < tbl0.NumDescriptorRanges; ++r) + { + const auto &rng0 = tbl0.pDescriptorRanges[r]; + const auto &rng1 = tbl1.pDescriptorRanges[r]; + if( memcmp(&rng0, &rng1, sizeof(rng0)) != 0) + return false; + } + } + break; + + case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS: + { + const auto &cnst0 = m_RootParam.Constants; + const auto &cnst1 = rhs.m_RootParam.Constants; + if (memcmp(&cnst0, &cnst1, sizeof(cnst0)) != 0) + return false; + } + break; + + case D3D12_ROOT_PARAMETER_TYPE_CBV: + case D3D12_ROOT_PARAMETER_TYPE_SRV: + case D3D12_ROOT_PARAMETER_TYPE_UAV: + { + const auto &dscr0 = m_RootParam.Descriptor; + const auto &dscr1 = rhs.m_RootParam.Descriptor; + if (memcmp(&dscr0, &dscr1, sizeof(dscr0)) != 0) + return false; + } + break; + + default: UNEXPECTED("Unexpected root parameter type"); + } + + return true; + } + + bool operator != (const RootParameter&rhs)const + { + return !(*this == rhs); + } + + size_t GetHash()const + { + size_t hash = ComputeHash(m_ShaderVarType, m_DescriptorTableSize, m_RootIndex); + HashCombine(hash, m_RootParam.ParameterType, m_RootParam.ShaderVisibility); + + switch (m_RootParam.ParameterType) + { + case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE: + { + const auto &tbl = m_RootParam.DescriptorTable; + HashCombine(hash, tbl.NumDescriptorRanges); + for (UINT r = 0; r < tbl.NumDescriptorRanges; ++r) + { + const auto &rng = tbl.pDescriptorRanges[r]; + HashCombine(hash, rng.BaseShaderRegister, rng.NumDescriptors, rng.OffsetInDescriptorsFromTableStart, rng.RangeType, rng.RegisterSpace); + } + } + break; + + case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS: + { + const auto &cnst = m_RootParam.Constants; + HashCombine(hash, cnst.Num32BitValues, cnst.RegisterSpace, cnst.ShaderRegister); + } + break; + + case D3D12_ROOT_PARAMETER_TYPE_CBV: + case D3D12_ROOT_PARAMETER_TYPE_SRV: + case D3D12_ROOT_PARAMETER_TYPE_UAV: + { + const auto &dscr = m_RootParam.Descriptor; + HashCombine(hash, dscr.RegisterSpace, dscr.ShaderRegister); + } + break; + + default: UNEXPECTED("Unexpected root parameter type"); + } + + return hash; + } private: @@ -204,6 +305,15 @@ public: return m_TotalSamplerSlots[VarType]; } + bool IsSameAs(const RootSignature& RS)const + { + return m_RootParams == RS.m_RootParams; + } + size_t GetHash()const + { + return m_RootParams.GetHash(); + } + private: #ifdef _DEBUG void dbgVerifyRootParameters()const; @@ -258,6 +368,9 @@ private: template void ProcessRootTables(TOperation)const; + bool operator == (const RootParamsManager& RootParams)const; + size_t GetHash()const; + private: size_t GetRequiredMemorySize(Uint32 NumExtraRootTables, Uint32 NumExtraRootViews, Uint32 NumExtraDescriptorRanges)const; D3D12_DESCRIPTOR_RANGE* Extend(Uint32 NumExtraRootTables, Uint32 NumExtraRootViews, Uint32 NumExtraDescriptorRanges, Uint32 RootTableToAddRanges = static_cast(-1)); diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp index 7fe35e92..de4648c4 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp @@ -220,6 +220,8 @@ PipelineStateD3D12Impl :: PipelineStateD3D12Impl(IReferenceCounters *pRefCounter auto &SRBAllocator = pDeviceD3D12->GetSRBAllocator(); // Default shader resource binding must be initialized after resource layouts are parsed! m_pDefaultShaderResBinding.reset( NEW_RC_OBJ(SRBAllocator, "ShaderResourceBindingD3D12Impl instance", ShaderResourceBindingD3D12Impl, this)(this, true) ); + + m_ShaderResourceLayoutHash = m_RootSig.GetHash(); } PipelineStateD3D12Impl::~PipelineStateD3D12Impl() @@ -267,8 +269,50 @@ void PipelineStateD3D12Impl::CreateShaderResourceBinding(IShaderResourceBinding bool PipelineStateD3D12Impl::IsCompatibleWith(const IPipelineState *pPSO)const { - UNSUPPORTED("Not yet implemented"); - return false; + VERIFY_EXPR(pPSO != nullptr); + + if (pPSO == this) + return true; + + const PipelineStateD3D12Impl *pPSOD3D12 = ValidatedCast(pPSO); + if (m_ShaderResourceLayoutHash != pPSOD3D12->m_ShaderResourceLayoutHash) + return false; + + auto IsSameRootSignature = m_RootSig.IsSameAs(pPSOD3D12->m_RootSig); + +#ifdef _DEBUG + { + bool IsCompatibleShaders = true; + if (m_NumShaders != pPSOD3D12->m_NumShaders) + IsCompatibleShaders = false; + + if(IsCompatibleShaders) + { + for (Uint32 s = 0; s < m_NumShaders; ++s) + { + auto *pShader0 = ValidatedCast(m_ppShaders[s]); + auto *pShader1 = ValidatedCast(pPSOD3D12->m_ppShaders[s]); + if (pShader0->GetDesc().ShaderType != pShader1->GetDesc().ShaderType) + { + IsCompatibleShaders = false; + break; + } + const ShaderResourcesD3D12 *pRes0 = pShader0->GetShaderResources().get(); + const ShaderResourcesD3D12 *pRes1 = pShader1->GetShaderResources().get(); + if (!pRes0->IsCompatibleWith(*pRes1)) + { + IsCompatibleShaders = false; + break; + } + } + } + + if(IsCompatibleShaders) + VERIFY(IsSameRootSignature, "Compatible shaders must have same root signatures"); + } +#endif + + return IsSameRootSignature; } const ShaderResourceLayoutD3D12& PipelineStateD3D12Impl::GetShaderResLayout(SHADER_TYPE ShaderType)const @@ -299,9 +343,9 @@ ShaderResourceCacheD3D12* PipelineStateD3D12Impl::CommitAndTransitionShaderResou #ifdef VERIFY_SHADER_BINDINGS { auto *pRefPSO = pResBindingD3D12Impl->GetPipelineState(); - if (pRefPSO != this) + if ( IsIncompatibleWith(pRefPSO) ) { - LOG_ERROR_MESSAGE("Shader resource binding does not match the pipeline state \"", m_Desc.Name, "\". Operation will be ignored."); + LOG_ERROR_MESSAGE("Shader resource binding is incompatible with the pipeline state \"", m_Desc.Name, "\". Operation will be ignored."); return nullptr; } } diff --git a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp index 1adcede1..2011bebe 100644 --- a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp @@ -32,6 +32,7 @@ #include "TextureD3D12Impl.h" #include "BufferD3D12Impl.h" #include "D3D12TypeConversions.h" +#include "HashUtils.h" namespace Diligent { @@ -111,6 +112,42 @@ void RootSignature::RootParamsManager::AddDescriptorRanges(Uint32 RootTableInd, VERIFY_EXPR( (char*)pRangePtr == (char*)m_pMemory.get() + GetRequiredMemorySize(0, 0, 0)); } +bool RootSignature::RootParamsManager::operator == (const RootParamsManager& RootParams)const +{ + if (m_NumRootTables != RootParams.m_NumRootTables || + m_NumRootViews != RootParams.m_NumRootViews) + return false; + + for (Uint32 rv = 0; rv < m_NumRootViews; ++rv) + { + const auto &RV0 = GetRootView(rv); + const auto &RV1 = RootParams.GetRootView(rv); + if (RV0 != RV1) + return false; + } + + for (Uint32 rv = 0; rv < m_NumRootTables; ++rv) + { + const auto &RT0 = GetRootTable(rv); + const auto &RT1 = RootParams.GetRootTable(rv); + if (RT0 != RT1) + return false; + } + + return true; +} + +size_t RootSignature::RootParamsManager::GetHash()const +{ + size_t hash = ComputeHash(m_NumRootTables, m_NumRootViews); + for (Uint32 rv = 0; rv < m_NumRootViews; ++rv) + HashCombine(hash, GetRootView(rv).GetHash()); + + for (Uint32 rv = 0; rv < m_NumRootTables; ++rv) + HashCombine(hash, GetRootTable(rv).GetHash()); + + return hash; +} RootSignature::RootSignature() : m_RootParams(GetRawAllocator()), diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp index 8af3d7a2..63552f93 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp @@ -105,9 +105,9 @@ IShaderVariable *ShaderResourceBindingD3D12Impl::GetVariable(SHADER_TYPE ShaderT void ShaderResourceBindingD3D12Impl::dbgVerifyResourceBindings(const PipelineStateD3D12Impl *pPSO) { auto *pRefPSO = GetPipelineState(); - if (pRefPSO != pPSO) + if (pPSO->IsIncompatibleWith(pRefPSO)) { - LOG_ERROR("Shader resource binding does not match the pipeline state \"", pPSO->GetDesc().Name, '\"'); + LOG_ERROR("Shader resource binding is incompatible with the pipeline state \"", pPSO->GetDesc().Name, '\"'); return; } for(Uint32 l = 0; l < m_NumShaders; ++l) -- cgit v1.2.3