diff --git a/Hydrogent/include/HnRendererImpl.hpp b/Hydrogent/include/HnRendererImpl.hpp index 16468be0..3d782f67 100644 --- a/Hydrogent/include/HnRendererImpl.hpp +++ b/Hydrogent/include/HnRendererImpl.hpp @@ -103,6 +103,10 @@ class HnRendererImpl final : public ObjectBase std::shared_ptr m_USDRenderer; std::unique_ptr m_EnvMapRenderer; + USD_Renderer::PbrPsoCacheAccessor m_PbrPSOCache; + USD_Renderer::WireframePsoCacheAccessor m_WireframePSOCache; + USD_Renderer::MeshIdPsoCacheAccessor m_MeshIdPSOCache; + std::unique_ptr m_RenderDelegate; pxr::UsdStageRefPtr m_Stage; diff --git a/Hydrogent/src/HnRendererImpl.cpp b/Hydrogent/src/HnRendererImpl.cpp index 3f53bb2b..381e6097 100644 --- a/Hydrogent/src/HnRendererImpl.cpp +++ b/Hydrogent/src/HnRendererImpl.cpp @@ -77,8 +77,6 @@ HnRendererImpl::HnRendererImpl(IReferenceCounters* pRefCounters, pContext, [](const HnRendererCreateInfo& CI) { USD_Renderer::CreateInfo USDRendererCI; - USDRendererCI.RTVFmt = CI.RTVFormat; - USDRendererCI.DSVFmt = CI.DSVFormat; // Use samplers from texture views USDRendererCI.UseImmutableSamplers = false; @@ -115,8 +113,28 @@ HnRendererImpl::HnRendererImpl(IReferenceCounters* pRefCounters, }(CI, pDevice))}, m_MeshIdReadBackQueue{pDevice} { - if (CI.FrontCCW) - m_DefaultPSOFlags |= PBR_Renderer::PSO_FLAG_FRONT_CCW; + GraphicsPipelineDesc GraphicsDesc; + GraphicsDesc.NumRenderTargets = 1; + GraphicsDesc.RTVFormats[0] = CI.RTVFormat; + GraphicsDesc.DSVFormat = CI.DSVFormat; + GraphicsDesc.PrimitiveTopology = PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + GraphicsDesc.RasterizerDesc.FrontCounterClockwise = CI.FrontCCW; + + m_PbrPSOCache = m_USDRenderer->GetPbrPsoCacheAccessor(GraphicsDesc); + VERIFY_EXPR(m_PbrPSOCache); + + GraphicsDesc.PrimitiveTopology = PRIMITIVE_TOPOLOGY_LINE_LIST; + + m_WireframePSOCache = m_USDRenderer->GetWireframePsoCacheAccessor(GraphicsDesc); + VERIFY_EXPR(m_WireframePSOCache); + + GraphicsDesc.NumRenderTargets = 1; + GraphicsDesc.RTVFormats[0] = TEX_FORMAT_RGBA8_UINT; + GraphicsDesc.PrimitiveTopology = PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + GraphicsDesc.DepthStencilDesc.DepthFunc = COMPARISON_FUNC_LESS_EQUAL; + + m_MeshIdPSOCache = m_USDRenderer->GetMeshIdPsoCacheAccessor(GraphicsDesc); + VERIFY_EXPR(m_MeshIdPSOCache); if (CI.ConvertOutputToSRGB) m_DefaultPSOFlags |= PBR_Renderer::PSO_FLAG_CONVERT_OUTPUT_TO_SRGB; @@ -317,15 +335,15 @@ void HnRendererImpl::RenderMesh(IDeviceContext* pCtx, PBR_Renderer::PSO_FLAG_USE_IBL | PBR_Renderer::PSO_FLAG_ENABLE_DEBUG_VIEW; - pPSO = m_USDRenderer->GetPbrPSO({PSOFlags, AlphaMode, /*DoubleSided = */ false}, true); + pPSO = m_PbrPSOCache.Get({PSOFlags, AlphaMode, /*DoubleSided = */ false}, true); } else if (Attribs.RenderMode == HN_RENDER_MODE_MESH_EDGES) { - pPSO = m_USDRenderer->GetWireframePSO({m_DefaultPSOFlags, PRIMITIVE_TOPOLOGY_LINE_LIST, /*DoubleSided = */ false}, true); + pPSO = m_WireframePSOCache.Get({m_DefaultPSOFlags, /*DoubleSided = */ false}, true); } else { - pPSO = m_USDRenderer->GetMeshIdPSO({m_DefaultPSOFlags, /*DoubleSided = */ false}, true); + pPSO = m_MeshIdPSOCache.Get({m_DefaultPSOFlags, /*DoubleSided = */ false}, true); } pCtx->SetPipelineState(pPSO); diff --git a/PBR/interface/GLTF_PBR_Renderer.hpp b/PBR/interface/GLTF_PBR_Renderer.hpp index f780507c..fcbb1d66 100644 --- a/PBR/interface/GLTF_PBR_Renderer.hpp +++ b/PBR/interface/GLTF_PBR_Renderer.hpp @@ -41,6 +41,17 @@ namespace Diligent class GLTF_PBR_Renderer : public PBR_Renderer { public: + struct CreateInfo : public PBR_Renderer::CreateInfo + { + /// Render target format. + TEXTURE_FORMAT RTVFmt = TEX_FORMAT_UNKNOWN; + + /// Depth-buffer format. + TEXTURE_FORMAT DSVFmt = TEX_FORMAT_UNKNOWN; + + bool FrontCounterClockwise = false; + }; + /// Initializes the renderer GLTF_PBR_Renderer(IRenderDevice* pDevice, IRenderStateCache* pStateCache, @@ -243,6 +254,9 @@ class GLTF_PBR_Renderer : public PBR_Renderer {} }; std::array, GLTF::Material::ALPHA_MODE_NUM_MODES> m_RenderLists; + + PbrPsoCacheAccessor m_PbrPSOCache; + WireframePsoCacheAccessor m_WireframePSOCache; }; DEFINE_FLAG_ENUM_OPERATORS(GLTF_PBR_Renderer::RenderInfo::ALPHA_MODE_FLAGS) diff --git a/PBR/interface/PBR_Renderer.hpp b/PBR/interface/PBR_Renderer.hpp index 9d8a0207..991ce1e0 100644 --- a/PBR/interface/PBR_Renderer.hpp +++ b/PBR/interface/PBR_Renderer.hpp @@ -47,17 +47,6 @@ class PBR_Renderer /// Renderer create info struct CreateInfo { - /// Render target format. - TEXTURE_FORMAT RTVFmt = TEX_FORMAT_UNKNOWN; - - /// Depth-buffer format. - - /// \note If both RTV and DSV formats are TEX_FORMAT_UNKNOWN, - /// the renderer will not initialize PSO, uniform buffers and other - /// resources. It is expected that an application will use custom - /// render callback function. - TEXTURE_FORMAT DSVFmt = TEX_FORMAT_UNKNOWN; - /// Indicates whether to enable IBL. /// A pipeline state can use IBL only if this flag is set to true. bool EnableIBL = true; @@ -226,10 +215,9 @@ class PBR_Renderer PSO_FLAG_USE_EMISSIVE_MAP = 1u << 11u, PSO_FLAG_USE_IBL = 1u << 12u, - PSO_FLAG_FRONT_CCW = 1u << 13u, - PSO_FLAG_ENABLE_DEBUG_VIEW = 1u << 14u, - PSO_FLAG_USE_TEXTURE_ATLAS = 1u << 15u, - PSO_FLAG_CONVERT_OUTPUT_TO_SRGB = 1u << 16u, + PSO_FLAG_ENABLE_DEBUG_VIEW = 1u << 13u, + PSO_FLAG_USE_TEXTURE_ATLAS = 1u << 14u, + PSO_FLAG_CONVERT_OUTPUT_TO_SRGB = 1u << 15u, PSO_FLAG_LAST = PSO_FLAG_CONVERT_OUTPUT_TO_SRGB, @@ -247,8 +235,7 @@ class PBR_Renderer PSO_FLAG_USE_PHYS_DESC_MAP | PSO_FLAG_USE_AO_MAP | PSO_FLAG_USE_EMISSIVE_MAP | - PSO_FLAG_USE_IBL | - PSO_FLAG_FRONT_CCW, + PSO_FLAG_USE_IBL, PSO_FLAG_ALL = PSO_FLAG_LAST * 2u - 1u, }; @@ -309,48 +296,79 @@ class PBR_Renderer } }; }; - IPipelineState* GetPbrPSO(const PbrPSOKey& Key, bool CreateIfNull); struct WireframePSOKey : PSOKey { static const PSO_FLAGS SupportedFlags; - PRIMITIVE_TOPOLOGY Topology = PRIMITIVE_TOPOLOGY_UNDEFINED; - WireframePSOKey() noexcept {}; - WireframePSOKey(PSO_FLAGS _Flags, PRIMITIVE_TOPOLOGY _Topology, bool _DoubleSided) noexcept; + WireframePSOKey(PSO_FLAGS _Flags, bool _DoubleSided) noexcept; + }; - bool operator==(const WireframePSOKey& rhs) const noexcept - { - return PSOKey::operator==(rhs) && Topology == rhs.Topology; - } + struct MeshIdPSOKey : PSOKey + { + static const PSO_FLAGS SupportedFlags; - bool operator!=(const WireframePSOKey& rhs) const noexcept + MeshIdPSOKey() noexcept {}; + MeshIdPSOKey(PSO_FLAGS _Flags, bool _DoubleSided) noexcept; + }; + + + template + class PsoCacheAccessor + { + public: + PsoCacheAccessor() noexcept + {} + + PsoCacheAccessor(const PsoCacheAccessor&) = default; + PsoCacheAccessor(PsoCacheAccessor&&) = default; + PsoCacheAccessor& operator=(const PsoCacheAccessor&) = default; + PsoCacheAccessor& operator=(PsoCacheAccessor&&) = default; + + explicit operator bool() const noexcept { - return PSOKey::operator!=(rhs) || Topology != rhs.Topology; + return m_pRenderer != nullptr && m_pPsoHashMap != nullptr && m_pGraphicsDesc != nullptr; } - struct Hasher + IPipelineState* Get(const PsoKeyType& Key, bool CreateIfNull) const { - size_t operator()(const WireframePSOKey& Key) const noexcept + if (!*this) { - size_t Hash = PSOKey::Hasher{}(Key); - HashCombine(Hash, Key.Topology); - return Hash; + UNEXPECTED("Accessor is not initialized"); + return nullptr; } - }; - }; - IPipelineState* GetWireframePSO(const WireframePSOKey& Key, bool CreateIfNull); + return m_pRenderer->GetPSO(*m_pPsoHashMap, *m_pGraphicsDesc, Key, CreateIfNull); + } - struct MeshIdPSOKey : PSOKey - { - static const PSO_FLAGS SupportedFlags; + private: + friend PBR_Renderer; + PsoCacheAccessor(PBR_Renderer& Renderer, + PsoHashMapType& PsoHashMap, + const GraphicsPipelineDesc& GraphicsDesc) noexcept : + m_pRenderer{&Renderer}, + m_pPsoHashMap{&PsoHashMap}, + m_pGraphicsDesc{&GraphicsDesc} + {} - MeshIdPSOKey() noexcept {}; - MeshIdPSOKey(PSO_FLAGS _Flags, bool _DoubleSided) noexcept; + private: + PBR_Renderer* m_pRenderer = nullptr; + PsoHashMapType* m_pPsoHashMap = nullptr; + const GraphicsPipelineDesc* m_pGraphicsDesc = nullptr; }; - IPipelineState* GetMeshIdPSO(const MeshIdPSOKey& Key, bool CreateIfNull); + + using PbrPsoHashMapType = std::unordered_map, PbrPSOKey::Hasher>; + using MeshIdPsoHashMapType = std::unordered_map, MeshIdPSOKey::Hasher>; + using WireframePsoHashMapType = std::unordered_map, WireframePSOKey::Hasher>; + + using PbrPsoCacheAccessor = PsoCacheAccessor; + using MeshIdPsoCacheAccessor = PsoCacheAccessor; + using WireframePsoCacheAccessor = PsoCacheAccessor; + + PbrPsoCacheAccessor GetPbrPsoCacheAccessor(const GraphicsPipelineDesc& GraphicsDesc); + MeshIdPsoCacheAccessor GetMeshIdPsoCacheAccessor(const GraphicsPipelineDesc& GraphicsDesc); + WireframePsoCacheAccessor GetWireframePsoCacheAccessor(const GraphicsPipelineDesc& GraphicsDesc); void InitCommonSRBVars(IShaderResourceBinding* pSRB, IBuffer* pCameraAttribs, @@ -361,11 +379,14 @@ class PBR_Renderer void GetVSInputStructAndLayout(PSO_FLAGS PSOFlags, std::string& VSInputStruct, InputLayoutDescX& InputLayout) const; - template + template + struct GetPSOHelper; + + template IPipelineState* GetPSO(std::unordered_map, typename KeyType::Hasher>& PSOCache, + const GraphicsPipelineDesc& GraphicsDesc, KeyType Key, - bool CreateIfNull, - CreatePSOType&& CreatePSO); + bool CreateIfNull); static std::string GetVSOutputStruct(PSO_FLAGS PSOFlags); @@ -382,9 +403,9 @@ class PBR_Renderer void PrecomputeBRDF(IDeviceContext* pCtx, Uint32 NumBRDFSamples = 512); - void CreatePbrPSO(const PbrPSOKey& Key); - void CreateWireframePSO(const WireframePSOKey& Key); - void CreateMeshIdPSO(const MeshIdPSOKey& Key); + void CreatePbrPSO(PbrPsoHashMapType& PbrPSOs, const GraphicsPipelineDesc& GraphicsDesc, const PbrPSOKey& Key); + void CreateWireframePSO(WireframePsoHashMapType& WireframePSOs, const GraphicsPipelineDesc& GraphicsDesc, const WireframePSOKey& Key); + void CreateMeshIdPSO(MeshIdPsoHashMapType& MeshIdPSOs, const GraphicsPipelineDesc& GraphicsDesc, const MeshIdPSOKey& Key); void CreateSignature(); protected: @@ -403,7 +424,6 @@ class PBR_Renderer static constexpr TEXTURE_FORMAT IrradianceCubeFmt = TEX_FORMAT_RGBA32_FLOAT; static constexpr TEXTURE_FORMAT PrefilteredEnvMapFmt = TEX_FORMAT_RGBA16_FLOAT; - static constexpr TEXTURE_FORMAT MeshIdFmt = TEX_FORMAT_RGBA8_UINT; static constexpr Uint32 IrradianceCubeDim = 64; static constexpr Uint32 PrefilteredEnvMapDim = 256; @@ -420,9 +440,9 @@ class PBR_Renderer RefCntAutoPtr m_ResourceSignature; - std::unordered_map, PbrPSOKey::Hasher> m_PbrPSOs; - std::unordered_map, MeshIdPSOKey::Hasher> m_MeshIdPSOs; - std::unordered_map, WireframePSOKey::Hasher> m_WireframePSOs; + std::unordered_map m_PbrPSOs; + std::unordered_map m_MeshIdPSOs; + std::unordered_map m_WireframePSOs; }; DEFINE_FLAG_ENUM_OPERATORS(PBR_Renderer::PSO_FLAGS) @@ -434,11 +454,9 @@ inline PBR_Renderer::PbrPSOKey::PbrPSOKey(PSO_FLAGS _Flags, AlphaMode{_AlphaMode} {} -inline PBR_Renderer::WireframePSOKey::WireframePSOKey(PSO_FLAGS _Flags, - PRIMITIVE_TOPOLOGY _Topology, - bool _DoubleSided) noexcept : - PSOKey{_Flags & SupportedFlags, _DoubleSided}, - Topology{_Topology} +inline PBR_Renderer::WireframePSOKey::WireframePSOKey(PSO_FLAGS _Flags, + bool _DoubleSided) noexcept : + PSOKey{_Flags & SupportedFlags, _DoubleSided} {} inline PBR_Renderer::MeshIdPSOKey::MeshIdPSOKey(PSO_FLAGS _Flags, @@ -446,11 +464,29 @@ inline PBR_Renderer::MeshIdPSOKey::MeshIdPSOKey(PSO_FLAGS _Flags, PSOKey{_Flags & SupportedFlags, _DoubleSided} {} -template +template <> +struct PBR_Renderer::GetPSOHelper +{ + static constexpr decltype(&PBR_Renderer::CreatePbrPSO) CreatePSO = &PBR_Renderer::CreatePbrPSO; +}; + +template <> +struct PBR_Renderer::GetPSOHelper +{ + static constexpr decltype(&PBR_Renderer::CreateWireframePSO) CreatePSO = &PBR_Renderer::CreateWireframePSO; +}; + +template <> +struct PBR_Renderer::GetPSOHelper +{ + static constexpr decltype(&PBR_Renderer::CreateMeshIdPSO) CreatePSO = &PBR_Renderer::CreateMeshIdPSO; +}; + +template IPipelineState* PBR_Renderer::GetPSO(std::unordered_map, typename KeyType::Hasher>& PSOCache, + const GraphicsPipelineDesc& GraphicsDesc, KeyType Key, - bool CreateIfNull, - CreatePSOType&& CreatePSO) + bool CreateIfNull) { Key.Flags &= KeyType::SupportedFlags; @@ -484,7 +520,7 @@ IPipelineState* PBR_Renderer::GetPSO(std::unordered_map*GetPSOHelper::CreatePSO)(PSOCache, GraphicsDesc, Key); it = PSOCache.find(Key); VERIFY_EXPR(it != PSOCache.end()); } diff --git a/PBR/src/GLTF_PBR_Renderer.cpp b/PBR/src/GLTF_PBR_Renderer.cpp index 5caf31e3..c9826790 100644 --- a/PBR/src/GLTF_PBR_Renderer.cpp +++ b/PBR/src/GLTF_PBR_Renderer.cpp @@ -107,10 +107,24 @@ GLTF_PBR_Renderer::GLTF_PBR_Renderer(IRenderDevice* pDevice, m_SupportedPSOFlags |= PSO_FLAG_USE_IBL; m_SupportedPSOFlags |= - PSO_FLAG_FRONT_CCW | PSO_FLAG_ENABLE_DEBUG_VIEW | PSO_FLAG_USE_TEXTURE_ATLAS | PSO_FLAG_CONVERT_OUTPUT_TO_SRGB; + + { + GraphicsPipelineDesc GraphicsDesc; + GraphicsDesc.NumRenderTargets = 1; + GraphicsDesc.RTVFormats[0] = CI.RTVFmt; + GraphicsDesc.DSVFormat = CI.DSVFmt; + GraphicsDesc.PrimitiveTopology = PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + GraphicsDesc.RasterizerDesc.FrontCounterClockwise = CI.FrontCounterClockwise; + + m_PbrPSOCache = GetPbrPsoCacheAccessor(GraphicsDesc); + + GraphicsDesc.RasterizerDesc.FillMode = FILL_MODE_WIREFRAME; + + m_WireframePSOCache = GetWireframePsoCacheAccessor(GraphicsDesc); + } } void GLTF_PBR_Renderer::InitMaterialSRB(GLTF::Model& Model, @@ -401,7 +415,7 @@ void GLTF_PBR_Renderer::Render(IDeviceContext* pCtx, const auto& material = GLTFModel.Materials[primitive.MaterialId]; const auto& NodeGlobalMatrix = Transforms.NodeGlobalMatrices[Node.Index]; - auto UpdatePSO = [this, pCtx, &pCurrPSO](const auto& NewKey, auto& CurrKey, auto&& GetPSO) { + auto UpdatePSO = [this, pCtx, &pCurrPSO](const auto& NewKey, auto& CurrKey, auto& PSOCache) { if (NewKey != CurrKey) { CurrKey = NewKey; @@ -410,26 +424,26 @@ void GLTF_PBR_Renderer::Render(IDeviceContext* pCtx, if (pCurrPSO == nullptr) { - pCurrPSO = GetPSO(this, NewKey, true); + pCurrPSO = PSOCache.Get(NewKey, true); VERIFY_EXPR(pCurrPSO != nullptr); pCtx->SetPipelineState(pCurrPSO); } else { - VERIFY_EXPR(pCurrPSO == GetPSO(this, NewKey, false)); + VERIFY_EXPR(pCurrPSO == PSOCache.Get(NewKey, false)); } }; if (RenderParams.Wireframe) { - UpdatePSO(WireframePSOKey{PSOFlags, PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, material.DoubleSided}, + UpdatePSO(WireframePSOKey{PSOFlags, material.DoubleSided}, CurrWireframePsoKey, - std::mem_fn(&GLTF_PBR_Renderer::GetWireframePSO)); + m_WireframePSOCache); } else { UpdatePSO(PbrPSOKey{PSOFlags, GltfAlphaModeToAlphaMode(AlphaMode), material.DoubleSided}, CurrPbrPsoKey, - std::mem_fn(&GLTF_PBR_Renderer::GetPbrPSO)); + m_PbrPSOCache); } if (pModelBindings != nullptr) diff --git a/PBR/src/PBR_Renderer.cpp b/PBR/src/PBR_Renderer.cpp index 5bb834a5..594b777e 100644 --- a/PBR/src/PBR_Renderer.cpp +++ b/PBR/src/PBR_Renderer.cpp @@ -43,15 +43,9 @@ namespace Diligent const SamplerDesc PBR_Renderer::CreateInfo::DefaultSampler = Sam_LinearWrap; -const PBR_Renderer::PSO_FLAGS PBR_Renderer::PbrPSOKey::SupportedFlags = PSO_FLAG_ALL; - -const PBR_Renderer::PSO_FLAGS PBR_Renderer::WireframePSOKey::SupportedFlags = - PSO_FLAG_USE_JOINTS | - PSO_FLAG_FRONT_CCW; - -const PBR_Renderer::PSO_FLAGS PBR_Renderer::MeshIdPSOKey::SupportedFlags = - PSO_FLAG_USE_JOINTS | - PSO_FLAG_FRONT_CCW; +const PBR_Renderer::PSO_FLAGS PBR_Renderer::PbrPSOKey::SupportedFlags = PSO_FLAG_ALL; +const PBR_Renderer::PSO_FLAGS PBR_Renderer::WireframePSOKey::SupportedFlags = PSO_FLAG_USE_JOINTS; +const PBR_Renderer::PSO_FLAGS PBR_Renderer::MeshIdPSOKey::SupportedFlags = PSO_FLAG_USE_JOINTS; namespace { @@ -824,24 +818,19 @@ void PBR_Renderer::CreateShaders(PSO_FLAGS PSOFlags, } -void PBR_Renderer::CreatePbrPSO(const PbrPSOKey& Key) +void PBR_Renderer::CreatePbrPSO(PbrPsoHashMapType& PbrPSOs, const GraphicsPipelineDesc& GraphicsDesc, const PbrPSOKey& Key) { GraphicsPipelineStateCreateInfo PSOCreateInfo; PipelineStateDesc& PSODesc = PSOCreateInfo.PSODesc; GraphicsPipelineDesc& GraphicsPipeline = PSOCreateInfo.GraphicsPipeline; - GraphicsPipeline.NumRenderTargets = 1; - GraphicsPipeline.RTVFormats[0] = m_Settings.RTVFmt; - GraphicsPipeline.DSVFormat = m_Settings.DSVFmt; - GraphicsPipeline.PrimitiveTopology = PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - GraphicsPipeline.RasterizerDesc.FrontCounterClockwise = (Key.Flags & PSO_FLAG_FRONT_CCW) != 0; - InputLayoutDescX InputLayout; RefCntAutoPtr pVS; RefCntAutoPtr pPS; CreateShaders(Key.Flags, "RenderPBR.vsh", "PBR VS", "RenderPBR.psh", "PBR PS", pVS, pPS, InputLayout); - PSOCreateInfo.GraphicsPipeline.InputLayout = InputLayout; + GraphicsPipeline = GraphicsDesc; + GraphicsPipeline.InputLayout = InputLayout; IPipelineResourceSignature* ppSignatures[] = {m_ResourceSignature}; PSOCreateInfo.ppResourceSignatures = ppSignatures; @@ -875,38 +864,32 @@ void PBR_Renderer::CreatePbrPSO(const PbrPSOKey& Key) PSOName += (CullMode == CULL_MODE_BACK ? " - backface culling" : " - no culling"); PSODesc.Name = PSOName.c_str(); - GraphicsPipeline.RasterizerDesc.CullMode = CullMode; - const auto DoubleSided = CullMode == CULL_MODE_NONE; - auto PSO = m_Device.CreateGraphicsPipelineState(PSOCreateInfo); - m_PbrPSOs[{Key.Flags, AlphaMode, DoubleSided}] = PSO; + GraphicsPipeline.RasterizerDesc.CullMode = CullMode; + const auto DoubleSided = CullMode == CULL_MODE_NONE; + auto PSO = m_Device.CreateGraphicsPipelineState(PSOCreateInfo); + PbrPSOs[{Key.Flags, AlphaMode, DoubleSided}] = PSO; if (AlphaMode == ALPHA_MODE_BLEND) { // Mask and blend use the same PSO - m_PbrPSOs[{Key.Flags, ALPHA_MODE_MASK, DoubleSided}] = PSO; + PbrPSOs[{Key.Flags, ALPHA_MODE_MASK, DoubleSided}] = PSO; } } } } -void PBR_Renderer::CreateMeshIdPSO(const MeshIdPSOKey& Key) +void PBR_Renderer::CreateMeshIdPSO(MeshIdPsoHashMapType& MeshIdPSOs, const GraphicsPipelineDesc& GraphicsDesc, const MeshIdPSOKey& Key) { GraphicsPipelineStateCreateInfo PSOCreateInfo; PipelineStateDesc& PSODesc = PSOCreateInfo.PSODesc; GraphicsPipelineDesc& GraphicsPipeline = PSOCreateInfo.GraphicsPipeline; - GraphicsPipeline.NumRenderTargets = 1; - GraphicsPipeline.RTVFormats[0] = MeshIdFmt; - GraphicsPipeline.DSVFormat = m_Settings.DSVFmt; - GraphicsPipeline.PrimitiveTopology = PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - GraphicsPipeline.RasterizerDesc.FrontCounterClockwise = (Key.Flags & PSO_FLAG_FRONT_CCW) != 0; - GraphicsPipeline.DepthStencilDesc.DepthFunc = COMPARISON_FUNC_LESS_EQUAL; - InputLayoutDescX InputLayout; RefCntAutoPtr pVS; RefCntAutoPtr pPS; CreateShaders(Key.Flags, "RenderPBR.vsh", "Mesh ID VS", "RenderMeshId.psh", "Mesh ID PS", pVS, pPS, InputLayout); - PSOCreateInfo.GraphicsPipeline.InputLayout = InputLayout; + GraphicsPipeline = GraphicsDesc; + GraphicsPipeline.InputLayout = InputLayout; IPipelineResourceSignature* ppSignatures[] = {m_ResourceSignature}; PSOCreateInfo.ppResourceSignatures = ppSignatures; @@ -924,31 +907,23 @@ void PBR_Renderer::CreateMeshIdPSO(const MeshIdPSOKey& Key) GraphicsPipeline.RasterizerDesc.CullMode = CullMode; const auto DoubleSided = CullMode == CULL_MODE_NONE; - m_MeshIdPSOs[{Key.Flags, DoubleSided}] = m_Device.CreateGraphicsPipelineState(PSOCreateInfo); + MeshIdPSOs[{Key.Flags, DoubleSided}] = m_Device.CreateGraphicsPipelineState(PSOCreateInfo); } } -void PBR_Renderer::CreateWireframePSO(const WireframePSOKey& Key) +void PBR_Renderer::CreateWireframePSO(WireframePsoHashMapType& WireframePSOs, const GraphicsPipelineDesc& GraphicsDesc, const WireframePSOKey& Key) { GraphicsPipelineStateCreateInfo PSOCreateInfo; PipelineStateDesc& PSODesc = PSOCreateInfo.PSODesc; GraphicsPipelineDesc& GraphicsPipeline = PSOCreateInfo.GraphicsPipeline; - GraphicsPipeline.NumRenderTargets = 1; - GraphicsPipeline.RTVFormats[0] = m_Settings.RTVFmt; - GraphicsPipeline.DSVFormat = m_Settings.DSVFmt; - GraphicsPipeline.PrimitiveTopology = Key.Topology; - if (Key.Topology != PRIMITIVE_TOPOLOGY_LINE_LIST && Key.Topology != PRIMITIVE_TOPOLOGY_LINE_STRIP && - Key.Topology != PRIMITIVE_TOPOLOGY_LINE_LIST_ADJ && Key.Topology != PRIMITIVE_TOPOLOGY_LINE_STRIP_ADJ) - GraphicsPipeline.RasterizerDesc.FillMode = FILL_MODE_WIREFRAME; - GraphicsPipeline.RasterizerDesc.FrontCounterClockwise = (Key.Flags & PSO_FLAG_FRONT_CCW) != 0; - InputLayoutDescX InputLayout; RefCntAutoPtr pVS; RefCntAutoPtr pPS; CreateShaders(Key.Flags, "RenderPBR.vsh", "Wireframe VS", "RenderWireframe.psh", "Wireframe PS", pVS, pPS, InputLayout); - PSOCreateInfo.GraphicsPipeline.InputLayout = InputLayout; + GraphicsPipeline = GraphicsDesc; + GraphicsPipeline.InputLayout = InputLayout; IPipelineResourceSignature* ppSignatures[] = {m_ResourceSignature}; PSOCreateInfo.ppResourceSignatures = ppSignatures; @@ -966,7 +941,7 @@ void PBR_Renderer::CreateWireframePSO(const WireframePSOKey& Key) GraphicsPipeline.RasterizerDesc.CullMode = CullMode; const auto DoubleSided = CullMode == CULL_MODE_NONE; - m_WireframePSOs[{Key.Flags, Key.Topology, DoubleSided}] = m_Device.CreateGraphicsPipelineState(PSOCreateInfo); + WireframePSOs[{Key.Flags, DoubleSided}] = m_Device.CreateGraphicsPipelineState(PSOCreateInfo); } } @@ -975,19 +950,28 @@ void PBR_Renderer::CreateResourceBinding(IShaderResourceBinding** ppSRB) m_ResourceSignature->CreateShaderResourceBinding(ppSRB, true); } -IPipelineState* PBR_Renderer::GetPbrPSO(const PbrPSOKey& Key, bool CreateIfNull) +PBR_Renderer::PbrPsoCacheAccessor PBR_Renderer::GetPbrPsoCacheAccessor(const GraphicsPipelineDesc& GraphicsDesc) { - return GetPSO(m_PbrPSOs, Key, CreateIfNull, std::mem_fn(&PBR_Renderer::CreatePbrPSO)); + auto it = m_PbrPSOs.find(GraphicsDesc); + if (it == m_PbrPSOs.end()) + it = m_PbrPSOs.emplace(GraphicsDesc, PbrPsoHashMapType{}).first; + return {*this, it->second, it->first}; } -IPipelineState* PBR_Renderer::GetMeshIdPSO(const MeshIdPSOKey& Key, bool CreateIfNull) +PBR_Renderer::MeshIdPsoCacheAccessor PBR_Renderer::GetMeshIdPsoCacheAccessor(const GraphicsPipelineDesc& GraphicsDesc) { - return GetPSO(m_MeshIdPSOs, Key, CreateIfNull, std::mem_fn(&PBR_Renderer::CreateMeshIdPSO)); + auto it = m_MeshIdPSOs.find(GraphicsDesc); + if (it == m_MeshIdPSOs.end()) + it = m_MeshIdPSOs.emplace(GraphicsDesc, MeshIdPsoHashMapType{}).first; + return {*this, it->second, it->first}; } -IPipelineState* PBR_Renderer::GetWireframePSO(const WireframePSOKey& Key, bool CreateIfNull) +PBR_Renderer::WireframePsoCacheAccessor PBR_Renderer::GetWireframePsoCacheAccessor(const GraphicsPipelineDesc& GraphicsDesc) { - return GetPSO(m_WireframePSOs, Key, CreateIfNull, std::mem_fn(&PBR_Renderer::CreateWireframePSO)); + auto it = m_WireframePSOs.find(GraphicsDesc); + if (it == m_WireframePSOs.end()) + it = m_WireframePSOs.emplace(GraphicsDesc, WireframePsoHashMapType{}).first; + return {*this, it->second, it->first}; } } // namespace Diligent