From 53c53efd2b6be579c6ccd23afb4addc3c8a1b1e6 Mon Sep 17 00:00:00 2001 From: assiduous Date: Fri, 6 Oct 2023 14:43:44 -0700 Subject: [PATCH] Refactoring PBR renderer to make it more flexible --- Hydrogent/include/HnRendererImpl.hpp | 4 +- Hydrogent/src/HnRendererImpl.cpp | 25 +- PBR/interface/GLTF_PBR_Renderer.hpp | 8 +- PBR/interface/PBR_Renderer.hpp | 107 ++++---- PBR/interface/USD_Renderer.hpp | 6 +- PBR/src/GLTF_PBR_Renderer.cpp | 40 ++- PBR/src/PBR_Renderer.cpp | 361 +++++++++++++++++---------- PBR/src/USD_Renderer.cpp | 49 +++- Shaders/PBR/private/RenderPBR.vsh | 65 ++--- shaders_inc/RenderPBR.vsh.h | 65 ++--- 10 files changed, 424 insertions(+), 306 deletions(-) diff --git a/Hydrogent/include/HnRendererImpl.hpp b/Hydrogent/include/HnRendererImpl.hpp index 88b0b053..5ccb21bc 100644 --- a/Hydrogent/include/HnRendererImpl.hpp +++ b/Hydrogent/include/HnRendererImpl.hpp @@ -36,6 +36,7 @@ #include "BasicMath.hpp" #include "ObjectBase.hpp" #include "GPUCompletionAwaitQueue.hpp" +#include "USD_Renderer.hpp" #include "pxr/usd/usd/stage.h" #include "pxr/imaging/hd/tokens.h" @@ -47,7 +48,6 @@ namespace Diligent { -class USD_Renderer; class EnvMapRenderer; namespace USD @@ -109,6 +109,8 @@ class HnRendererImpl final : public ObjectBase RefCntAutoPtr m_DepthBuffer; GPUCompletionAwaitQueue> m_MeshIdReadBackQueue; + + PBR_Renderer::PSO_FLAGS m_PSOFlags = PBR_Renderer::PSO_FLAG_NONE; }; } // namespace USD diff --git a/Hydrogent/src/HnRendererImpl.cpp b/Hydrogent/src/HnRendererImpl.cpp index 40dde52a..8e4e74ca 100644 --- a/Hydrogent/src/HnRendererImpl.cpp +++ b/Hydrogent/src/HnRendererImpl.cpp @@ -124,6 +124,23 @@ HnRendererImpl::HnRendererImpl(IReferenceCounters* pRefCounters, }(CI, pDevice))}, m_MeshIdReadBackQueue{pDevice} { + m_PSOFlags |= + PBR_Renderer::PSO_FLAG_USE_VERTEX_NORMALS | + PBR_Renderer::PSO_FLAG_USE_TEXCOORD0 | + PBR_Renderer::PSO_FLAG_USE_TEXCOORD1 | + PBR_Renderer::PSO_FLAG_USE_DIFFUSE_MAP | + PBR_Renderer::PSO_FLAG_USE_NORMAL_MAP | + PBR_Renderer::PSO_FLAG_USE_METALLIC_MAP | + PBR_Renderer::PSO_FLAG_USE_ROUGHNESS_MAP; + + m_PSOFlags |= + PBR_Renderer::PSO_FLAG_USE_AO_MAP | + PBR_Renderer::PSO_FLAG_USE_EMISSIVE_MAP | + PBR_Renderer::PSO_FLAG_USE_IBL | + PBR_Renderer::PSO_FLAG_ALLOW_DEBUG_VIEW; + + if (CI.ConvertOutputToSRGB) + m_PSOFlags |= PBR_Renderer::PSO_FLAG_CONVERT_TO_SRGB; } HnRendererImpl::~HnRendererImpl() @@ -228,9 +245,9 @@ void HnRendererImpl::Draw(IDeviceContext* pCtx, const HnDrawAttribs& Attribs) for (auto AlphaMode : {USD_Renderer::ALPHA_MODE_OPAQUE, USD_Renderer::ALPHA_MODE_MASK, USD_Renderer::ALPHA_MODE_BLEND}) { if (Attribs.RenderMode == HN_RENDER_MODE_MESH_EDGES) - pCtx->SetPipelineState(m_USDRenderer->GetMeshEdgesPSO()); + pCtx->SetPipelineState(m_USDRenderer->GetMeshEdgesPSO({m_PSOFlags, USD_Renderer::ALPHA_MODE_OPAQUE, /*DoubleSided = */ false}, true)); else - pCtx->SetPipelineState(m_USDRenderer->GetPSO({AlphaMode, /*DoubleSided = */ false})); + pCtx->SetPipelineState(m_USDRenderer->GetPSO({m_PSOFlags, AlphaMode, /*DoubleSided = */ false}, true)); for (auto mesh_it : Meshes) { @@ -335,7 +352,7 @@ void HnRendererImpl::RenderMesh(IDeviceContext* pCtx, const HnMesh& Mesh, const void HnRendererImpl::SetEnvironmentMap(IDeviceContext* pCtx, ITextureView* pEnvironmentMapSRV) { - m_USDRenderer->PrecomputeCubemaps(m_Device, m_Device, pCtx, pEnvironmentMapSRV); + m_USDRenderer->PrecomputeCubemaps(pCtx, pEnvironmentMapSRV); } const char* HnRendererImpl::QueryPrimId(IDeviceContext* pCtx, Uint32 X, Uint32 Y) @@ -437,7 +454,7 @@ void HnRendererImpl::RenderPrimId(IDeviceContext* pContext, ITextureView* pDepth if (Meshes.empty()) return; - auto* pMeshIdPSO = m_USDRenderer->GetMeshIdPSO(false); + auto* pMeshIdPSO = m_USDRenderer->GetMeshIdPSO({m_PSOFlags, USD_Renderer::ALPHA_MODE_OPAQUE, /*DoubleSided = */ false}, true); if (pMeshIdPSO == nullptr) return; diff --git a/PBR/interface/GLTF_PBR_Renderer.hpp b/PBR/interface/GLTF_PBR_Renderer.hpp index 30d3db8b..60076368 100644 --- a/PBR/interface/GLTF_PBR_Renderer.hpp +++ b/PBR/interface/GLTF_PBR_Renderer.hpp @@ -192,8 +192,6 @@ class GLTF_PBR_Renderer : public PBR_Renderer /// \param [in] CacheUseInfo - GLTF resource cache usage information. /// \param [in] pCameraAttribs - Camera attributes constant buffer to set in the SRB. /// \param [in] pLightAttribs - Light attributes constant buffer to set in the SRB. - /// \param [in] pPSO - Optional PSO object to use to create the SRB instead of the - /// default PSO. Can be null /// \param [out] ppCacheSRB - Pointer to memory location where the pointer to the SRB object /// will be written. void CreateResourceCacheSRB(IRenderDevice* pDevice, @@ -201,7 +199,6 @@ class GLTF_PBR_Renderer : public PBR_Renderer ResourceCacheUseInfo& CacheUseInfo, IBuffer* pCameraAttribs, IBuffer* pLightAttribs, - IPipelineState* pPSO, IShaderResourceBinding** ppCacheSRB); /// Prepares the renderer for rendering objects. @@ -217,13 +214,14 @@ class GLTF_PBR_Renderer : public PBR_Renderer ResourceCacheUseInfo& CacheUseInfo, ResourceCacheBindings& Bindings, IBuffer* pCameraAttribs, - IBuffer* pLightAttribs, - IPipelineState* pPSO = nullptr); + IBuffer* pLightAttribs); private: static ALPHA_MODE GltfAlphaModeToAlphaMode(GLTF::Material::ALPHA_MODE GltfAlphaMode); RenderInfo m_RenderParams; + + PSO_FLAGS m_PSOFlags = PSO_FLAG_NONE; }; 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 cd41963e..9378fde4 100644 --- a/PBR/interface/PBR_Renderer.hpp +++ b/PBR/interface/PBR_Renderer.hpp @@ -26,16 +26,17 @@ #pragma once -#include -#include +#include +#include #include "../../../DiligentCore/Platforms/Basic/interface/DebugUtilities.hpp" #include "../../../DiligentCore/Graphics/GraphicsEngine/interface/DeviceContext.h" #include "../../../DiligentCore/Graphics/GraphicsEngine/interface/RenderDevice.h" #include "../../../DiligentCore/Graphics/GraphicsEngine/interface/GraphicsTypesX.hpp" -#include "../../../DiligentCore/Graphics/GraphicsTools/interface/RenderStateCache.h" +#include "../../../DiligentCore/Graphics/GraphicsTools/interface/RenderStateCache.hpp" #include "../../../DiligentCore/Graphics/GraphicsTools/interface/ShaderMacroHelper.hpp" #include "../../../DiligentCore/Common/interface/RefCntAutoPtr.hpp" +#include "../../../DiligentCore/Common/interface/HashUtils.hpp" namespace Diligent { @@ -198,80 +199,97 @@ class PBR_Renderer // clang-format on /// Precompute cubemaps used by IBL. - void PrecomputeCubemaps(IRenderDevice* pDevice, - IRenderStateCache* pStateCache, - IDeviceContext* pCtx, - ITextureView* pEnvironmentMap, - Uint32 NumPhiSamples = 64, - Uint32 NumThetaSamples = 32, - bool OptimizeSamples = true); + void PrecomputeCubemaps(IDeviceContext* pCtx, + ITextureView* pEnvironmentMap, + Uint32 NumPhiSamples = 64, + Uint32 NumThetaSamples = 32, + bool OptimizeSamples = true); void CreateResourceBinding(IShaderResourceBinding** ppSRB); + enum PSO_FLAGS : Uint32 + { + PSO_FLAG_NONE = 0u, + PSO_FLAG_USE_VERTEX_COLORS = 1u << 0u, + PSO_FLAG_USE_VERTEX_NORMALS = 1u << 1u, + PSO_FLAG_USE_TEXCOORD0 = 1u << 2u, + PSO_FLAG_USE_TEXCOORD1 = 1u << 3u, + PSO_FLAG_USE_JOINTS = 1u << 4u, + + PSO_FLAG_USE_DIFFUSE_MAP = 1u << 5u, + PSO_FLAG_USE_NORMAL_MAP = 1u << 6u, + PSO_FLAG_USE_METALLIC_MAP = 1u << 7u, + PSO_FLAG_USE_ROUGHNESS_MAP = 1u << 8u, + PSO_FLAG_USE_PHYS_DESC_MAP = 1u << 9u, + PSO_FLAG_USE_AO_MAP = 1u << 10u, + PSO_FLAG_USE_EMISSIVE_MAP = 1u << 11u, + PSO_FLAG_USE_IBL = 1u << 12u, + + PSO_FLAG_FRONT_CCW = 1u << 13u, + PSO_FLAG_ALLOW_DEBUG_VIEW = 1u << 14u, + PSO_FLAG_USE_TEXTURE_ATLAS = 1u << 15u, + PSO_FLAG_CONVERT_TO_SRGB = 1u << 16u, + }; + struct PSOKey { PSOKey() noexcept {}; - PSOKey(ALPHA_MODE _AlphaMode, bool _DoubleSided) : + PSOKey(PSO_FLAGS _Flags, ALPHA_MODE _AlphaMode, bool _DoubleSided) noexcept : + Flags{_Flags}, AlphaMode{_AlphaMode}, DoubleSided{_DoubleSided} {} bool operator==(const PSOKey& rhs) const noexcept { - return AlphaMode == rhs.AlphaMode && DoubleSided == rhs.DoubleSided; + return Flags == rhs.Flags && AlphaMode == rhs.AlphaMode && DoubleSided == rhs.DoubleSided; } bool operator!=(const PSOKey& rhs) const noexcept { - return AlphaMode != rhs.AlphaMode || DoubleSided != rhs.DoubleSided; + return Flags != rhs.Flags || AlphaMode != rhs.AlphaMode || DoubleSided != rhs.DoubleSided; } + PSO_FLAGS Flags = PSO_FLAG_NONE; ALPHA_MODE AlphaMode = ALPHA_MODE_OPAQUE; bool DoubleSided = false; - }; - IPipelineState* GetPSO(const PSOKey& Key) const - { - auto Idx = GetPSOIdx(Key); - VERIFY_EXPR(Idx < m_PSOCache.size()); - return Idx < m_PSOCache.size() ? m_PSOCache[Idx].RawPtr() : nullptr; - } + struct Hasher + { + size_t operator()(const PSOKey& Key) const noexcept + { + return ComputeHash(Key.Flags, Key.AlphaMode, Key.DoubleSided); + } + }; + }; - IPipelineState* GetMeshIdPSO(bool DoubleSided) const - { - return m_MeshIdPSO[DoubleSided ? 1 : 0]; - } + IPipelineState* GetPSO(const PSOKey& Key, bool CreateIfNull); + IPipelineState* GetMeshIdPSO(const PSOKey& Key, bool CreateIfNull); void InitCommonSRBVars(IShaderResourceBinding* pSRB, IBuffer* pCameraAttribs, IBuffer* pLightAttribs); protected: - ShaderMacroHelper DefineMacros() const; - InputLayoutDescX GetInputLayout() const; + ShaderMacroHelper DefineMacros(PSO_FLAGS PSOFlags) const; - static size_t GetPSOIdx(const PSOKey& Key) - { - size_t PSOIdx; + void GetVSInputStructAndLayout(PSO_FLAGS PSOFlags, std::string& VSInputStruct, InputLayoutDescX& InputLayout) const; - PSOIdx = Key.AlphaMode == ALPHA_MODE_BLEND ? 1 : 0; - PSOIdx = PSOIdx * 2 + (Key.DoubleSided ? 1 : 0); - return PSOIdx; - } + using PSOCacheType = std::unordered_map, PSOKey::Hasher>; - void AddPSO(const PSOKey& Key, RefCntAutoPtr pPSO); + static IPipelineState* GetPSO(PSOCacheType& PSOCache, const PSOKey& Key, std::function CreatePSO); private: - void PrecomputeBRDF(IRenderDevice* pDevice, - IRenderStateCache* pStateCache, - IDeviceContext* pCtx, - Uint32 NumBRDFSamples = 512); + void PrecomputeBRDF(IDeviceContext* pCtx, + Uint32 NumBRDFSamples = 512); - void CreatePSO(IRenderDevice* pDevice, IRenderStateCache* pStateCache); - void CreateSignature(IRenderDevice* pDevice, IRenderStateCache* pStateCache); + void CreatePSO(PSO_FLAGS PSOFlags, TEXTURE_FORMAT RTVFmt, TEXTURE_FORMAT DSVFmt); + void CreateSignature(); protected: const CreateInfo m_Settings; + RenderDeviceWithCache_N m_Device; + static constexpr Uint32 BRDF_LUT_Dim = 512; RefCntAutoPtr m_pBRDF_LUT_SRV; @@ -298,9 +316,12 @@ class PBR_Renderer RefCntAutoPtr m_PrecomputeEnvMapAttribsCB; RefCntAutoPtr m_JointsBuffer; - RefCntAutoPtr m_ResourceSignature; - std::vector> m_PSOCache; - std::array, 2> m_MeshIdPSO; + RefCntAutoPtr m_ResourceSignature; + + PSOCacheType m_PSOs; + PSOCacheType m_MeshIdPSOs; }; +DEFINE_FLAG_ENUM_OPERATORS(PBR_Renderer::PSO_FLAGS) + } // namespace Diligent diff --git a/PBR/interface/USD_Renderer.hpp b/PBR/interface/USD_Renderer.hpp index ffdf4d0e..9f264e56 100644 --- a/PBR/interface/USD_Renderer.hpp +++ b/PBR/interface/USD_Renderer.hpp @@ -41,13 +41,13 @@ class USD_Renderer : public PBR_Renderer IDeviceContext* pCtx, const CreateInfo& CI); - IPipelineState* GetMeshEdgesPSO() const { return m_MeshEdgesPSO; } + IPipelineState* GetMeshEdgesPSO(const PSOKey& Key, bool CreateIfNull); private: - void CreatMeshEdgesPSO(IRenderDevice* pDevice, IRenderStateCache* pStateCache); + void CreateMeshEdgesPSO(PSO_FLAGS PSOFlags, TEXTURE_FORMAT RTVFmt, TEXTURE_FORMAT DSVFmt); private: - RefCntAutoPtr m_MeshEdgesPSO; + PSOCacheType m_MeshEdgesPSOs; }; } // namespace Diligent diff --git a/PBR/src/GLTF_PBR_Renderer.cpp b/PBR/src/GLTF_PBR_Renderer.cpp index 3a3fa447..d8dc91d5 100644 --- a/PBR/src/GLTF_PBR_Renderer.cpp +++ b/PBR/src/GLTF_PBR_Renderer.cpp @@ -63,6 +63,26 @@ GLTF_PBR_Renderer::GLTF_PBR_Renderer(IRenderDevice* pDevice, const CreateInfo& CI) : PBR_Renderer{pDevice, pStateCache, pCtx, CI} { + m_PSOFlags |= + PSO_FLAG_USE_VERTEX_NORMALS | + PSO_FLAG_USE_TEXCOORD0 | + PSO_FLAG_USE_TEXCOORD1 | + PSO_FLAG_USE_JOINTS | + PSO_FLAG_USE_DIFFUSE_MAP | + PSO_FLAG_USE_NORMAL_MAP | + PSO_FLAG_USE_PHYS_DESC_MAP; + if (CI.UseAO) + m_PSOFlags |= PSO_FLAG_USE_AO_MAP; + if (CI.UseEmissive) + m_PSOFlags |= PSO_FLAG_USE_EMISSIVE_MAP; + if (CI.UseIBL) + m_PSOFlags |= PSO_FLAG_USE_IBL; + if (CI.AllowDebugView) + m_PSOFlags |= PSO_FLAG_ALLOW_DEBUG_VIEW; + if (CI.UseTextureAtlas) + m_PSOFlags |= PSO_FLAG_USE_TEXTURE_ATLAS; + if (CI.ConvertOutputToSRGB) + m_PSOFlags |= PSO_FLAG_CONVERT_TO_SRGB; } void GLTF_PBR_Renderer::InitMaterialSRB(GLTF::Model& Model, @@ -133,12 +153,11 @@ void GLTF_PBR_Renderer::CreateResourceCacheSRB(IRenderDevice* pDevice, ResourceCacheUseInfo& CacheUseInfo, IBuffer* pCameraAttribs, IBuffer* pLightAttribs, - IPipelineState* pPSO, IShaderResourceBinding** ppCacheSRB) { DEV_CHECK_ERR(CacheUseInfo.pResourceMgr != nullptr, "Resource manager must not be null"); - pPSO->CreateShaderResourceBinding(ppCacheSRB, true); + m_ResourceSignature->CreateShaderResourceBinding(ppCacheSRB, true); IShaderResourceBinding* const pSRB = *ppCacheSRB; if (pSRB == nullptr) { @@ -202,22 +221,18 @@ void GLTF_PBR_Renderer::Begin(IRenderDevice* pDevice, ResourceCacheUseInfo& CacheUseInfo, ResourceCacheBindings& Bindings, IBuffer* pCameraAttribs, - IBuffer* pLightAttribs, - IPipelineState* pPSO) + IBuffer* pLightAttribs) { VERIFY(CacheUseInfo.pResourceMgr != nullptr, "Resource manager must not be null."); VERIFY(CacheUseInfo.VtxLayoutKey != GLTF::ResourceManager::VertexLayoutKey{}, "Vertex layout key must not be null."); Begin(pCtx); - if (pPSO == nullptr) - pPSO = GetPSO(PSOKey{}); - auto TextureVersion = CacheUseInfo.pResourceMgr->GetTextureVersion(); if (!Bindings.pSRB || Bindings.Version != TextureVersion) { Bindings.pSRB.Release(); - CreateResourceCacheSRB(pDevice, pCtx, CacheUseInfo, pCameraAttribs, pLightAttribs, pPSO, &Bindings.pSRB); + CreateResourceCacheSRB(pDevice, pCtx, CacheUseInfo, pCameraAttribs, pLightAttribs, &Bindings.pSRB); if (!Bindings.pSRB) { LOG_ERROR_MESSAGE("Failed to create an SRB for GLTF resource cache"); @@ -226,7 +241,8 @@ void GLTF_PBR_Renderer::Begin(IRenderDevice* pDevice, Bindings.Version = TextureVersion; } - pCtx->TransitionShaderResources(pPSO, Bindings.pSRB); + if (auto pPSO = GetPSO(PSOKey{m_PSOFlags, PBR_Renderer::ALPHA_MODE_OPAQUE, false}, true)) + pCtx->TransitionShaderResources(pPSO, Bindings.pSRB); if (auto* pVertexPool = CacheUseInfo.pResourceMgr->GetVertexPool(CacheUseInfo.VtxLayoutKey)) { @@ -323,7 +339,7 @@ void GLTF_PBR_Renderer::Render(IDeviceContext* pCtx, if (material.Attribs.AlphaMode != AlphaMode) continue; - const PSOKey Key{GltfAlphaModeToAlphaMode(AlphaMode), material.DoubleSided}; + const PSOKey Key{m_PSOFlags, GltfAlphaModeToAlphaMode(AlphaMode), material.DoubleSided}; if (Key != CurrPSOKey) { @@ -332,14 +348,14 @@ void GLTF_PBR_Renderer::Render(IDeviceContext* pCtx, } if (pCurrPSO == nullptr) { - pCurrPSO = GetPSO(CurrPSOKey); + pCurrPSO = GetPSO(CurrPSOKey, true); VERIFY_EXPR(pCurrPSO != nullptr); pCtx->SetPipelineState(pCurrPSO); pCurrSRB = nullptr; } else { - VERIFY_EXPR(pCurrPSO == GetPSO(PSOKey{GltfAlphaModeToAlphaMode(AlphaMode), material.DoubleSided})); + VERIFY_EXPR(pCurrPSO == GetPSO(PSOKey{m_PSOFlags, GltfAlphaModeToAlphaMode(AlphaMode), material.DoubleSided}, false)); } if (pModelBindings != nullptr) diff --git a/PBR/src/PBR_Renderer.cpp b/PBR/src/PBR_Renderer.cpp index 08ec9df0..994f44f4 100644 --- a/PBR/src/PBR_Renderer.cpp +++ b/PBR/src/PBR_Renderer.cpp @@ -34,7 +34,9 @@ #include "CommonlyUsedStates.h" #include "BasicMath.hpp" #include "MapHelper.hpp" +#include "GraphicsAccessories.hpp" #include "../../../Utilities/include/DiligentFXShaderSourceStreamFactory.hpp" +#include "ShaderSourceFactoryUtils.h" namespace Diligent { @@ -57,11 +59,12 @@ PBR_Renderer::PBR_Renderer(IRenderDevice* pDevice, IRenderStateCache* pStateCache, IDeviceContext* pCtx, const CreateInfo& CI) : - m_Settings{CI} + m_Settings{CI}, + m_Device{pDevice, pStateCache} { if (m_Settings.UseIBL) { - PrecomputeBRDF(pDevice, pStateCache, pCtx, m_Settings.NumBRDFSamples); + PrecomputeBRDF(pCtx, m_Settings.NumBRDFSamples); TextureDesc TexDesc; TexDesc.Name = "Irradiance cube map for PBR renderer"; @@ -74,17 +77,16 @@ PBR_Renderer::PBR_Renderer(IRenderDevice* pDevice, TexDesc.ArraySize = 6; TexDesc.MipLevels = 0; - RefCntAutoPtr IrradainceCubeTex; - pDevice->CreateTexture(TexDesc, nullptr, &IrradainceCubeTex); - m_pIrradianceCubeSRV = IrradainceCubeTex->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE); + auto IrradainceCubeTex = m_Device.CreateTexture(TexDesc); + m_pIrradianceCubeSRV = IrradainceCubeTex->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE); TexDesc.Name = "Prefiltered environment map for PBR renderer"; TexDesc.Width = PrefilteredEnvMapDim; TexDesc.Height = PrefilteredEnvMapDim; TexDesc.Format = PrefilteredEnvMapFmt; - RefCntAutoPtr PrefilteredEnvMapTex; - pDevice->CreateTexture(TexDesc, nullptr, &PrefilteredEnvMapTex); - m_pPrefilteredEnvMapSRV = PrefilteredEnvMapTex->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE); + + auto PrefilteredEnvMapTex = m_Device.CreateTexture(TexDesc); + m_pPrefilteredEnvMapSRV = PrefilteredEnvMapTex->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE); } { @@ -99,29 +101,26 @@ PBR_Renderer::PBR_Renderer(IRenderDevice* pDevice, TexDesc.Height = TexDim; TexDesc.Format = TEX_FORMAT_RGBA8_UNORM; TexDesc.MipLevels = 1; - std::vector Data(TexDim * TexDim, 0xFFFFFFFF); - TextureSubResData Level0Data{Data.data(), TexDim * 4}; - TextureData InitData{&Level0Data, 1}; - RefCntAutoPtr pWhiteTex; - pDevice->CreateTexture(TexDesc, &InitData, &pWhiteTex); + std::vector Data(TexDim * TexDim, 0xFFFFFFFF); + TextureSubResData Level0Data{Data.data(), TexDim * 4}; + TextureData InitData{&Level0Data, 1}; + + auto pWhiteTex = m_Device.CreateTexture(TexDesc, &InitData); m_pWhiteTexSRV = pWhiteTex->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE); TexDesc.Name = "Black texture for PBR renderer"; for (auto& c : Data) c = 0; - RefCntAutoPtr pBlackTex; - pDevice->CreateTexture(TexDesc, &InitData, &pBlackTex); + auto pBlackTex = m_Device.CreateTexture(TexDesc, &InitData); m_pBlackTexSRV = pBlackTex->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE); TexDesc.Name = "Default normal map for PBR renderer"; for (auto& c : Data) c = 0x00FF7F7F; - RefCntAutoPtr pDefaultNormalMap; - pDevice->CreateTexture(TexDesc, &InitData, &pDefaultNormalMap); + auto pDefaultNormalMap = m_Device.CreateTexture(TexDesc, &InitData); m_pDefaultNormalMapSRV = pDefaultNormalMap->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE); TexDesc.Name = "Default physical description map for PBR renderer"; for (auto& c : Data) c = 0x0000FF00; - RefCntAutoPtr pDefaultPhysDesc; - pDevice->CreateTexture(TexDesc, &InitData, &pDefaultPhysDesc); + auto pDefaultPhysDesc = m_Device.CreateTexture(TexDesc, &InitData); m_pDefaultPhysDescSRV = pDefaultPhysDesc->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE); // clang-format off @@ -135,8 +134,7 @@ PBR_Renderer::PBR_Renderer(IRenderDevice* pDevice, // clang-format on pCtx->TransitionResourceStates(_countof(Barriers), Barriers); - RefCntAutoPtr pDefaultSampler; - pDevice->CreateSampler(Sam_LinearClamp, &pDefaultSampler); + auto pDefaultSampler = m_Device.CreateSampler(Sam_LinearClamp); m_pWhiteTexSRV->SetSampler(pDefaultSampler); m_pBlackTexSRV->SetSampler(pDefaultSampler); m_pDefaultNormalMapSRV->SetSampler(pDefaultSampler); @@ -156,25 +154,16 @@ PBR_Renderer::PBR_Renderer(IRenderDevice* pDevice, pCtx->TransitionResourceStates(static_cast(Barriers.size()), Barriers.data()); } - CreateSignature(pDevice, pStateCache); - - if (CI.RTVFmt != TEX_FORMAT_UNKNOWN || CI.DSVFmt != TEX_FORMAT_UNKNOWN) - { - CreatePSO(pDevice, pStateCache); - } + CreateSignature(); } PBR_Renderer::~PBR_Renderer() { } -void PBR_Renderer::PrecomputeBRDF(IRenderDevice* pDevice, - IRenderStateCache* pStateCache, - IDeviceContext* pCtx, - Uint32 NumBRDFSamples) +void PBR_Renderer::PrecomputeBRDF(IDeviceContext* pCtx, + Uint32 NumBRDFSamples) { - RenderDeviceWithCache Device{pDevice, pStateCache}; - TextureDesc TexDesc; TexDesc.Name = "BRDF Look-up texture"; TexDesc.Type = RESOURCE_DIM_TEX_2D; @@ -184,7 +173,7 @@ void PBR_Renderer::PrecomputeBRDF(IRenderDevice* pDevice, TexDesc.Height = BRDF_LUT_Dim; TexDesc.Format = TEX_FORMAT_RG16_FLOAT; TexDesc.MipLevels = 1; - auto pBRDF_LUT = Device.CreateTexture(TexDesc); + auto pBRDF_LUT = m_Device.CreateTexture(TexDesc); m_pBRDF_LUT_SRV = pBRDF_LUT->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE); RefCntAutoPtr PrecomputeBRDF_PSO; @@ -216,7 +205,7 @@ void PBR_Renderer::PrecomputeBRDF(IRenderDevice* pDevice, ShaderCI.EntryPoint = "FullScreenTriangleVS"; ShaderCI.FilePath = "FullScreenTriangleVS.fx"; - pVS = Device.CreateShader(ShaderCI); + pVS = m_Device.CreateShader(ShaderCI); } // Create pixel shader @@ -226,13 +215,13 @@ void PBR_Renderer::PrecomputeBRDF(IRenderDevice* pDevice, ShaderCI.EntryPoint = "PrecomputeBRDF_PS"; ShaderCI.FilePath = "PrecomputeBRDF.psh"; - pPS = Device.CreateShader(ShaderCI); + pPS = m_Device.CreateShader(ShaderCI); } // Finally, create the pipeline state PSOCreateInfo.pVS = pVS; PSOCreateInfo.pPS = pPS; - PrecomputeBRDF_PSO = Device.CreateGraphicsPipelineState(PSOCreateInfo); + PrecomputeBRDF_PSO = m_Device.CreateGraphicsPipelineState(PSOCreateInfo); } pCtx->SetPipelineState(PrecomputeBRDF_PSO); @@ -250,13 +239,11 @@ void PBR_Renderer::PrecomputeBRDF(IRenderDevice* pDevice, pCtx->TransitionResourceStates(_countof(Barriers), Barriers); } -void PBR_Renderer::PrecomputeCubemaps(IRenderDevice* pDevice, - IRenderStateCache* pStateCache, - IDeviceContext* pCtx, - ITextureView* pEnvironmentMap, - Uint32 NumPhiSamples, - Uint32 NumThetaSamples, - bool OptimizeSamples) +void PBR_Renderer::PrecomputeCubemaps(IDeviceContext* pCtx, + ITextureView* pEnvironmentMap, + Uint32 NumPhiSamples, + Uint32 NumThetaSamples, + bool OptimizeSamples) { if (!m_Settings.UseIBL) { @@ -264,8 +251,6 @@ void PBR_Renderer::PrecomputeCubemaps(IRenderDevice* pDevice, return; } - RenderDeviceWithCache Device{pDevice, pStateCache}; - struct PrecomputeEnvMapAttribs { float4x4 Rotation; @@ -278,7 +263,7 @@ void PBR_Renderer::PrecomputeCubemaps(IRenderDevice* pDevice, if (!m_PrecomputeEnvMapAttribsCB) { - CreateUniformBuffer(pDevice, sizeof(PrecomputeEnvMapAttribs), "Precompute env map attribs CB", &m_PrecomputeEnvMapAttribsCB); + CreateUniformBuffer(m_Device, sizeof(PrecomputeEnvMapAttribs), "Precompute env map attribs CB", &m_PrecomputeEnvMapAttribsCB); } if (!m_pPrecomputeIrradianceCubePSO) @@ -297,7 +282,7 @@ void PBR_Renderer::PrecomputeCubemaps(IRenderDevice* pDevice, ShaderCI.EntryPoint = "main"; ShaderCI.FilePath = "CubemapFace.vsh"; - pVS = Device.CreateShader(ShaderCI); + pVS = m_Device.CreateShader(ShaderCI); } // Create pixel shader @@ -307,7 +292,7 @@ void PBR_Renderer::PrecomputeCubemaps(IRenderDevice* pDevice, ShaderCI.EntryPoint = "main"; ShaderCI.FilePath = "ComputeIrradianceMap.psh"; - pPS = Device.CreateShader(ShaderCI); + pPS = m_Device.CreateShader(ShaderCI); } GraphicsPipelineStateCreateInfo PSOCreateInfo; @@ -333,7 +318,7 @@ void PBR_Renderer::PrecomputeCubemaps(IRenderDevice* pDevice, .AddImmutableSampler(SHADER_TYPE_PIXEL, "g_EnvironmentMap", Sam_LinearClamp); PSODesc.ResourceLayout = ResourceLayout; - m_pPrecomputeIrradianceCubePSO = Device.CreateGraphicsPipelineState(PSOCreateInfo); + m_pPrecomputeIrradianceCubePSO = m_Device.CreateGraphicsPipelineState(PSOCreateInfo); m_pPrecomputeIrradianceCubePSO->GetStaticVariableByName(SHADER_TYPE_VERTEX, "cbTransform")->Set(m_PrecomputeEnvMapAttribsCB); m_pPrecomputeIrradianceCubePSO->CreateShaderResourceBinding(&m_pPrecomputeIrradianceCubeSRB, true); } @@ -354,7 +339,7 @@ void PBR_Renderer::PrecomputeCubemaps(IRenderDevice* pDevice, ShaderCI.EntryPoint = "main"; ShaderCI.FilePath = "CubemapFace.vsh"; - pVS = Device.CreateShader(ShaderCI); + pVS = m_Device.CreateShader(ShaderCI); } // Create pixel shader @@ -364,7 +349,7 @@ void PBR_Renderer::PrecomputeCubemaps(IRenderDevice* pDevice, ShaderCI.EntryPoint = "main"; ShaderCI.FilePath = "PrefilterEnvMap.psh"; - pPS = Device.CreateShader(ShaderCI); + pPS = m_Device.CreateShader(ShaderCI); } GraphicsPipelineStateCreateInfo PSOCreateInfo; @@ -390,7 +375,7 @@ void PBR_Renderer::PrecomputeCubemaps(IRenderDevice* pDevice, .AddImmutableSampler(SHADER_TYPE_PIXEL, "g_EnvironmentMap", Sam_LinearClamp); PSODesc.ResourceLayout = ResourceLayout; - m_pPrefilterEnvMapPSO = Device.CreateGraphicsPipelineState(PSOCreateInfo); + m_pPrefilterEnvMapPSO = m_Device.CreateGraphicsPipelineState(PSOCreateInfo); m_pPrefilterEnvMapPSO->GetStaticVariableByName(SHADER_TYPE_VERTEX, "cbTransform")->Set(m_PrecomputeEnvMapAttribsCB); m_pPrefilterEnvMapPSO->GetStaticVariableByName(SHADER_TYPE_PIXEL, "FilterAttribs")->Set(m_PrecomputeEnvMapAttribsCB); m_pPrefilterEnvMapPSO->CreateShaderResourceBinding(&m_pPrefilterEnvMapSRB, true); @@ -508,10 +493,8 @@ void PBR_Renderer::InitCommonSRBVars(IShaderResourceBinding* pSRB, } } -void PBR_Renderer::CreateSignature(IRenderDevice* pDevice, IRenderStateCache* pStateCache) +void PBR_Renderer::CreateSignature() { - RenderDeviceWithCache Device{pDevice, pStateCache}; - PipelineResourceSignatureDescX SignatureDesc{"PBR Renderer Resource Signature"}; SignatureDesc .SetUseCombinedTextureSamplers(true) @@ -570,7 +553,7 @@ void PBR_Renderer::CreateSignature(IRenderDevice* pDevice, IRenderStateCache* pS .AddImmutableSampler(SHADER_TYPE_PIXEL, "g_PrefilteredEnvMap", Sam_LinearClamp); } - m_ResourceSignature = Device.CreatePipelineResourceSignature(SignatureDesc); + m_ResourceSignature = m_Device.CreatePipelineResourceSignature(SignatureDesc); if (m_Settings.UseIBL) { @@ -583,7 +566,7 @@ void PBR_Renderer::CreateSignature(IRenderDevice* pDevice, IRenderStateCache* pS } } -ShaderMacroHelper PBR_Renderer::DefineMacros() const +ShaderMacroHelper PBR_Renderer::DefineMacros(PSO_FLAGS PSOFlags) const { ShaderMacroHelper Macros; Macros.Add("MAX_JOINT_COUNT", static_cast(m_Settings.MaxJointCount)); @@ -624,6 +607,28 @@ ShaderMacroHelper PBR_Renderer::DefineMacros() const Macros.Add("DEBUG_VIEW_SPECULAR_IBL", static_cast(DebugViewType::SpecularIBL)); // clang-format on +#define ADD_PSO_FLAG_MACRO(Flag) Macros.Add(#Flag, (PSOFlags & PSO_FLAG_##Flag) != PSO_FLAG_NONE) + ADD_PSO_FLAG_MACRO(USE_VERTEX_COLORS); + ADD_PSO_FLAG_MACRO(USE_VERTEX_NORMALS); + ADD_PSO_FLAG_MACRO(USE_TEXCOORD0); + ADD_PSO_FLAG_MACRO(USE_TEXCOORD1); + ADD_PSO_FLAG_MACRO(USE_JOINTS); + + ADD_PSO_FLAG_MACRO(USE_DIFFUSE_MAP); + ADD_PSO_FLAG_MACRO(USE_NORMAL_MAP); + ADD_PSO_FLAG_MACRO(USE_METALLIC_MAP); + ADD_PSO_FLAG_MACRO(USE_ROUGHNESS_MAP); + ADD_PSO_FLAG_MACRO(USE_PHYS_DESC_MAP); + ADD_PSO_FLAG_MACRO(USE_AO_MAP); + ADD_PSO_FLAG_MACRO(USE_EMISSIVE_MAP); + ADD_PSO_FLAG_MACRO(USE_IBL); + + //ADD_PSO_FLAG_MACRO(FRONT_CCW); + //ADD_PSO_FLAG_MACRO(ALLOW_DEBUG_VIEW); + //ADD_PSO_FLAG_MACRO(USE_TEXTURE_ATLAS); + //ADD_PSO_FLAG_MACRO(CONVERT_TO_SRGB); +#undef ADD_PSO_FLAG_MACRO + Macros.Add("TEX_COLOR_CONVERSION_MODE_NONE", CreateInfo::TEX_COLOR_CONVERSION_MODE_NONE); Macros.Add("TEX_COLOR_CONVERSION_MODE_SRGB_TO_LINEAR", CreateInfo::TEX_COLOR_CONVERSION_MODE_SRGB_TO_LINEAR); Macros.Add("TEX_COLOR_CONVERSION_MODE", m_Settings.TexColorConversionMode); @@ -631,63 +636,137 @@ ShaderMacroHelper PBR_Renderer::DefineMacros() const return Macros; } -InputLayoutDescX PBR_Renderer::GetInputLayout() const +void PBR_Renderer::GetVSInputStructAndLayout(PSO_FLAGS PSOFlags, + std::string& VSInputStruct, + InputLayoutDescX& InputLayout) const { - InputLayoutDescX InputLayout; + //struct VSInput + //{ + // float3 Pos : ATTRIB0; + // float3 Normal : ATTRIB1; + // float2 UV0 : ATTRIB2; + // float2 UV1 : ATTRIB3; + // float4 Joint0 : ATTRIB4; + // float4 Weight0 : ATTRIB5; + // float4 Color : ATTRIB6; + //}; + if (m_Settings.InputLayout.NumElements != 0) { InputLayout = m_Settings.InputLayout; } else { + InputLayout.Clear(); InputLayout .Add(0u, 0u, 3u, VT_FLOAT32) //float3 Pos : ATTRIB0; .Add(1u, 0u, 3u, VT_FLOAT32) //float3 Normal : ATTRIB1; .Add(2u, 0u, 2u, VT_FLOAT32) //float2 UV0 : ATTRIB2; - .Add(3u, 0u, 2u, VT_FLOAT32); //float2 UV1 : ATTRIB3; - if (m_Settings.MaxJointCount > 0) + .Add(3u, 0u, 2u, VT_FLOAT32) //float2 UV1 : ATTRIB3; + .Add(4u, 1u, 4u, VT_FLOAT32) //float4 Joint0 : ATTRIB4; + .Add(5u, 1u, 4u, VT_FLOAT32) //float4 Weight0 : ATTRIB5; + .Add(6u, 2u, 4u, VT_FLOAT32); //float4 Color : ATTRIB6; + + // TODO: need to compute offsets and strides + } + + std::stringstream ss; + ss << "struct VSInput" << std::endl + << "{" << std::endl; + + auto ProccessAttrib = [&](const char* Type, Uint32 NumComponents, const char* Name, Uint32 Index, PSO_FLAGS Flag) // + { + if (Flag == PSO_FLAG_NONE || (PSOFlags & Flag) != 0) { - InputLayout - .Add(4u, 1u, 4u, VT_FLOAT32) //float4 Joint0 : ATTRIB4; - .Add(5u, 1u, 4u, VT_FLOAT32); //float4 Weight0 : ATTRIB5; + ss << " " << std::setw(7) << Type << NumComponents << std::setw(9) << Name << ": ATTRIB" << Index << ";" << std::endl; +#ifdef DILIGENT_DEVELOPMENT + { + bool AttribFound = false; + for (Uint32 i = 0; i < InputLayout.GetNumElements(); ++i) + { + const auto& Elem = InputLayout[i]; + if (Elem.InputIndex == Index) + { + AttribFound = true; + DEV_CHECK_ERR(Elem.NumComponents == NumComponents, "Input layout element '", Name, "' (index ", Index, ") has ", Elem.NumComponents, " components, but shader expects ", NumComponents); + DEV_CHECK_ERR(Elem.ValueType == VT_FLOAT32, "Input layout element '", Name, "' (index ", Index, ") has value type ", GetValueTypeString(Elem.ValueType), ", but shader expects float"); + break; + } + } + DEV_CHECK_ERR(AttribFound, "Input layout does not contain attribute '", Name, "' (index ", Index, ")"); + } +#endif } - } + else + { + // Remove attribute from layout + for (Uint32 i = 0; i < InputLayout.GetNumElements(); ++i) + { + const auto& Elem = InputLayout[i]; + if (Elem.InputIndex == Index) + { + InputLayout.Remove(i); + break; + } + } + } + }; + + // clang-format off + ProccessAttrib("float", 3, "Pos", 0, PSO_FLAG_NONE); + ProccessAttrib("float", 3, "Normal", 1, PSO_FLAG_USE_VERTEX_NORMALS); + ProccessAttrib("float", 2, "UV0", 2, PSO_FLAG_USE_TEXCOORD0); + ProccessAttrib("float", 2, "UV1", 3, PSO_FLAG_USE_TEXCOORD1); + ProccessAttrib("float", 4, "Joint0", 4, PSO_FLAG_USE_JOINTS); + ProccessAttrib("float", 4, "Weight0", 5, PSO_FLAG_USE_JOINTS); + ProccessAttrib("float", 4, "Color", 6, PSO_FLAG_USE_VERTEX_COLORS); + // clang-format on + + ss << "};" << std::endl; - return InputLayout; + VSInputStruct = ss.str(); } -void PBR_Renderer::CreatePSO(IRenderDevice* pDevice, IRenderStateCache* pStateCache) +void PBR_Renderer::CreatePSO(PSO_FLAGS PSOFlags, TEXTURE_FORMAT RTVFmt, TEXTURE_FORMAT DSVFmt) { - RenderDeviceWithCache Device{pDevice, pStateCache}; - GraphicsPipelineStateCreateInfo PSOCreateInfo; PipelineStateDesc& PSODesc = PSOCreateInfo.PSODesc; GraphicsPipelineDesc& GraphicsPipeline = PSOCreateInfo.GraphicsPipeline; - PSODesc.Name = "Render PBR PSO"; - PSODesc.PipelineType = PIPELINE_TYPE_GRAPHICS; - GraphicsPipeline.NumRenderTargets = 1; - GraphicsPipeline.RTVFormats[0] = m_Settings.RTVFmt; - GraphicsPipeline.DSVFormat = m_Settings.DSVFmt; + GraphicsPipeline.RTVFormats[0] = RTVFmt; + GraphicsPipeline.DSVFormat = DSVFmt; GraphicsPipeline.PrimitiveTopology = PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - GraphicsPipeline.RasterizerDesc.CullMode = CULL_MODE_BACK; GraphicsPipeline.RasterizerDesc.FrontCounterClockwise = m_Settings.FrontCCW; + InputLayoutDescX InputLayout; + std::string VSInputStruct; + GetVSInputStructAndLayout(PSOFlags, VSInputStruct, InputLayout); + + MemoryShaderSourceFileInfo VSInputStructSource{"VSInputStruct.generated", VSInputStruct}; + MemoryShaderSourceFactoryCreateInfo MemorySourceFactoryCI{&VSInputStructSource, 1}; + RefCntAutoPtr pMemorySourceFactory; + CreateMemoryShaderSourceFactory(MemorySourceFactoryCI, &pMemorySourceFactory); + + IShaderSourceInputStreamFactory* ppShaderSourceFactories[] = {&DiligentFXShaderSourceStreamFactory::GetInstance(), pMemorySourceFactory}; + CompoundShaderSourceFactoryCreateInfo CompoundSourceFactoryCI{ppShaderSourceFactories, _countof(ppShaderSourceFactories)}; + RefCntAutoPtr pCompoundSourceFactory; + CreateCompoundShaderSourceFactory(CompoundSourceFactoryCI, &pCompoundSourceFactory); + ShaderCreateInfo ShaderCI; ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL; - ShaderCI.pShaderSourceStreamFactory = &DiligentFXShaderSourceStreamFactory::GetInstance(); + ShaderCI.pShaderSourceStreamFactory = pCompoundSourceFactory; - const auto Macros = DefineMacros(); + const auto Macros = DefineMacros(PSOFlags); ShaderCI.Macros = Macros; RefCntAutoPtr pVS; { ShaderCI.Desc = {"PBR VS", SHADER_TYPE_VERTEX, true}; - ShaderCI.EntryPoint = m_Settings.MaxJointCount > 0 ? "VSMainSkinned" : "VSMain"; + ShaderCI.EntryPoint = "main"; ShaderCI.FilePath = "RenderPBR.vsh"; - pVS = Device.CreateShader(ShaderCI); + pVS = m_Device.CreateShader(ShaderCI); } // Create pixel shader @@ -697,10 +776,9 @@ void PBR_Renderer::CreatePSO(IRenderDevice* pDevice, IRenderStateCache* pStateCa ShaderCI.EntryPoint = "main"; ShaderCI.FilePath = "RenderPBR.psh"; - pPS = Device.CreateShader(ShaderCI); + pPS = m_Device.CreateShader(ShaderCI); } - const auto InputLayout = GetInputLayout(); PSOCreateInfo.GraphicsPipeline.InputLayout = InputLayout; IPipelineResourceSignature* ppSignatures[] = {m_ResourceSignature}; @@ -710,53 +788,50 @@ void PBR_Renderer::CreatePSO(IRenderDevice* pDevice, IRenderStateCache* pStateCa PSOCreateInfo.pVS = pVS; PSOCreateInfo.pPS = pPS; + for (auto AlphaMode : {ALPHA_MODE_OPAQUE, ALPHA_MODE_BLEND}) { - PSOKey Key{ALPHA_MODE_OPAQUE, false}; - - auto pSingleSidedOpaquePSO = Device.CreateGraphicsPipelineState(PSOCreateInfo); - AddPSO(Key, std::move(pSingleSidedOpaquePSO)); - - PSOCreateInfo.GraphicsPipeline.RasterizerDesc.CullMode = CULL_MODE_NONE; - - Key.DoubleSided = true; - - auto pDobleSidedOpaquePSO = Device.CreateGraphicsPipelineState(PSOCreateInfo); - AddPSO(Key, std::move(pDobleSidedOpaquePSO)); - } - - PSOCreateInfo.GraphicsPipeline.RasterizerDesc.CullMode = CULL_MODE_BACK; - - auto& RT0 = PSOCreateInfo.GraphicsPipeline.BlendDesc.RenderTargets[0]; - RT0.BlendEnable = true; - RT0.SrcBlend = BLEND_FACTOR_SRC_ALPHA; - RT0.DestBlend = BLEND_FACTOR_INV_SRC_ALPHA; - RT0.BlendOp = BLEND_OPERATION_ADD; - RT0.SrcBlendAlpha = BLEND_FACTOR_ONE; - RT0.DestBlendAlpha = BLEND_FACTOR_INV_SRC_ALPHA; - RT0.BlendOpAlpha = BLEND_OPERATION_ADD; - - { - PSOKey Key{ALPHA_MODE_BLEND, false}; - - auto pSingleSidedBlendPSO = Device.CreateGraphicsPipelineState(PSOCreateInfo); - AddPSO(Key, std::move(pSingleSidedBlendPSO)); - - PSOCreateInfo.GraphicsPipeline.RasterizerDesc.CullMode = CULL_MODE_NONE; - - Key.DoubleSided = true; + if (AlphaMode == ALPHA_MODE_OPAQUE) + { + PSOCreateInfo.GraphicsPipeline.BlendDesc = BS_Default; + } + else + { + auto& RT0 = GraphicsPipeline.BlendDesc.RenderTargets[0]; + RT0.BlendEnable = true; + RT0.SrcBlend = BLEND_FACTOR_SRC_ALPHA; + RT0.DestBlend = BLEND_FACTOR_INV_SRC_ALPHA; + RT0.BlendOp = BLEND_OPERATION_ADD; + RT0.SrcBlendAlpha = BLEND_FACTOR_ONE; + RT0.DestBlendAlpha = BLEND_FACTOR_INV_SRC_ALPHA; + RT0.BlendOpAlpha = BLEND_OPERATION_ADD; + } - auto pDoubleSidedBlendPSO = Device.CreateGraphicsPipelineState(PSOCreateInfo); - AddPSO(Key, std::move(pDoubleSidedBlendPSO)); + for (auto CullMode : {CULL_MODE_BACK, CULL_MODE_NONE}) + { + std::string PSOName{"PBR PSO"}; + PSOName += (AlphaMode == ALPHA_MODE_OPAQUE ? " - opaque" : " - blend"); + 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_PSOs[{PSOFlags, AlphaMode, DoubleSided}] = PSO; + if (AlphaMode == ALPHA_MODE_BLEND) + { + // Mask and blend use the same PSO + m_PSOs[{PSOFlags, ALPHA_MODE_MASK, DoubleSided}] = PSO; + } + } } - if (m_Settings.EnableMeshIdRendering) { PSOCreateInfo.PSODesc.Name = "Render Mesh Id PSO"; - PSOCreateInfo.GraphicsPipeline.DepthStencilDesc.DepthFunc = COMPARISON_FUNC_LESS_EQUAL; - PSOCreateInfo.GraphicsPipeline.BlendDesc = BS_Default; - PSOCreateInfo.GraphicsPipeline.RTVFormats[0] = MeshIdFmt; + GraphicsPipeline.DepthStencilDesc.DepthFunc = COMPARISON_FUNC_LESS_EQUAL; + GraphicsPipeline.BlendDesc = BS_Default; + GraphicsPipeline.RTVFormats[0] = MeshIdFmt; RefCntAutoPtr pMeshIdPS; { @@ -764,32 +839,50 @@ void PBR_Renderer::CreatePSO(IRenderDevice* pDevice, IRenderStateCache* pStateCa ShaderCI.EntryPoint = "main"; ShaderCI.FilePath = "RenderMeshId.psh"; - pMeshIdPS = Device.CreateShader(ShaderCI); + pMeshIdPS = m_Device.CreateShader(ShaderCI); } PSOCreateInfo.pPS = pMeshIdPS; - PSOCreateInfo.GraphicsPipeline.RasterizerDesc.CullMode = CULL_MODE_BACK; + for (auto CullMode : {CULL_MODE_BACK, CULL_MODE_NONE}) + { + GraphicsPipeline.RasterizerDesc.CullMode = CullMode; + const auto DoubleSided = CullMode == CULL_MODE_NONE; - m_MeshIdPSO[0] = Device.CreateGraphicsPipelineState(PSOCreateInfo); + m_MeshIdPSOs[{PSOFlags, ALPHA_MODE_OPAQUE, DoubleSided}] = m_Device.CreateGraphicsPipelineState(PSOCreateInfo); + } + } +} + +void PBR_Renderer::CreateResourceBinding(IShaderResourceBinding** ppSRB) +{ + m_ResourceSignature->CreateShaderResourceBinding(ppSRB, true); +} - PSOCreateInfo.GraphicsPipeline.RasterizerDesc.CullMode = CULL_MODE_NONE; +IPipelineState* PBR_Renderer::GetPSO(PSOCacheType& PSOCache, const PSOKey& Key, std::function CreatePSO) +{ + auto it = PSOCache.find(Key); + if (it == PSOCache.end() && CreatePSO != nullptr) + { + CreatePSO(); - m_MeshIdPSO[1] = Device.CreateGraphicsPipelineState(PSOCreateInfo); + it = PSOCache.find(Key); + VERIFY_EXPR(it != PSOCache.end()); } + + return it != PSOCache.end() ? it->second.RawPtr() : nullptr; } -void PBR_Renderer::AddPSO(const PSOKey& Key, RefCntAutoPtr pPSO) +IPipelineState* PBR_Renderer::GetPSO(const PSOKey& Key, bool CreateIfNull) { - auto Idx = GetPSOIdx(Key); - if (Idx >= m_PSOCache.size()) - m_PSOCache.resize(Idx + 1); - VERIFY_EXPR(!m_PSOCache[Idx]); - m_PSOCache[Idx] = std::move(pPSO); + return GetPSO(m_PSOs, Key, [&]() { CreatePSO(Key.Flags, m_Settings.RTVFmt, m_Settings.DSVFmt); }); } -void PBR_Renderer::CreateResourceBinding(IShaderResourceBinding** ppSRB) +IPipelineState* PBR_Renderer::GetMeshIdPSO(const PSOKey& _Key, bool CreateIfNull) { - m_ResourceSignature->CreateShaderResourceBinding(ppSRB, true); + auto Key = _Key; + Key.AlphaMode = ALPHA_MODE_OPAQUE; + + return GetPSO(m_MeshIdPSOs, Key, [&]() { CreatePSO(Key.Flags, MeshIdFmt, m_Settings.DSVFmt); }); } } // namespace Diligent diff --git a/PBR/src/USD_Renderer.cpp b/PBR/src/USD_Renderer.cpp index af05e192..0e8c576c 100644 --- a/PBR/src/USD_Renderer.cpp +++ b/PBR/src/USD_Renderer.cpp @@ -28,6 +28,7 @@ #include "RenderStateCache.hpp" #include "../../../Utilities/include/DiligentFXShaderSourceStreamFactory.hpp" +#include "ShaderSourceFactoryUtils.h" namespace Diligent { @@ -38,13 +39,10 @@ USD_Renderer::USD_Renderer(IRenderDevice* pDevice, const CreateInfo& CI) : PBR_Renderer{pDevice, pStateCache, pCtx, CI} { - CreatMeshEdgesPSO(pDevice, pStateCache); } -void USD_Renderer::CreatMeshEdgesPSO(IRenderDevice* pDevice, IRenderStateCache* pStateCache) +void USD_Renderer::CreateMeshEdgesPSO(PSO_FLAGS PSOFlags, TEXTURE_FORMAT RTVFmt, TEXTURE_FORMAT DSVFmt) { - RenderDeviceWithCache Device{pDevice, pStateCache}; - GraphicsPipelineStateCreateInfo PSOCreateInfo; PipelineStateDesc& PSODesc = PSOCreateInfo.PSODesc; GraphicsPipelineDesc& GraphicsPipeline = PSOCreateInfo.GraphicsPipeline; @@ -53,15 +51,29 @@ void USD_Renderer::CreatMeshEdgesPSO(IRenderDevice* pDevice, IRenderStateCache* PSODesc.PipelineType = PIPELINE_TYPE_GRAPHICS; GraphicsPipeline.NumRenderTargets = 1; - GraphicsPipeline.RTVFormats[0] = m_Settings.RTVFmt; - GraphicsPipeline.DSVFormat = m_Settings.DSVFmt; + GraphicsPipeline.RTVFormats[0] = RTVFmt; + GraphicsPipeline.DSVFormat = DSVFmt; GraphicsPipeline.PrimitiveTopology = PRIMITIVE_TOPOLOGY_LINE_LIST; + InputLayoutDescX InputLayout; + std::string VSInputStruct; + GetVSInputStructAndLayout(PSOFlags, VSInputStruct, InputLayout); + + MemoryShaderSourceFileInfo VSInputStructSource{"VSInputStruct.generated", VSInputStruct}; + MemoryShaderSourceFactoryCreateInfo MemorySourceFactoryCI{&VSInputStructSource, 1}; + RefCntAutoPtr pMemorySourceFactory; + CreateMemoryShaderSourceFactory(MemorySourceFactoryCI, &pMemorySourceFactory); + + IShaderSourceInputStreamFactory* ppShaderSourceFactories[] = {&DiligentFXShaderSourceStreamFactory::GetInstance(), pMemorySourceFactory}; + CompoundShaderSourceFactoryCreateInfo CompoundSourceFactoryCI{ppShaderSourceFactories, _countof(ppShaderSourceFactories)}; + RefCntAutoPtr pCompoundSourceFactory; + CreateCompoundShaderSourceFactory(CompoundSourceFactoryCI, &pCompoundSourceFactory); + ShaderCreateInfo ShaderCI; ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL; - ShaderCI.pShaderSourceStreamFactory = &DiligentFXShaderSourceStreamFactory::GetInstance(); + ShaderCI.pShaderSourceStreamFactory = pCompoundSourceFactory; - const auto Macros = DefineMacros(); + const auto Macros = DefineMacros(PSO_FLAG_NONE); ShaderCI.Macros = Macros; RefCntAutoPtr pVS; @@ -70,7 +82,7 @@ void USD_Renderer::CreatMeshEdgesPSO(IRenderDevice* pDevice, IRenderStateCache* ShaderCI.EntryPoint = m_Settings.MaxJointCount > 0 ? "VSMainSkinned" : "VSMain"; ShaderCI.FilePath = "RenderPBR.vsh"; - pVS = Device.CreateShader(ShaderCI); + pVS = m_Device.CreateShader(ShaderCI); } // Create pixel shader @@ -80,10 +92,9 @@ void USD_Renderer::CreatMeshEdgesPSO(IRenderDevice* pDevice, IRenderStateCache* ShaderCI.EntryPoint = "main"; ShaderCI.FilePath = "RenderWireframe.psh"; - pPS = Device.CreateShader(ShaderCI); + pPS = m_Device.CreateShader(ShaderCI); } - const auto InputLayout = GetInputLayout(); PSOCreateInfo.GraphicsPipeline.InputLayout = InputLayout; IPipelineResourceSignature* ppSignatures[] = {m_ResourceSignature}; @@ -93,7 +104,21 @@ void USD_Renderer::CreatMeshEdgesPSO(IRenderDevice* pDevice, IRenderStateCache* PSOCreateInfo.pVS = pVS; PSOCreateInfo.pPS = pPS; - m_MeshEdgesPSO = Device.CreateGraphicsPipelineState(PSOCreateInfo); + for (auto CullMode : {CULL_MODE_BACK, CULL_MODE_NONE}) + { + GraphicsPipeline.RasterizerDesc.CullMode = CullMode; + const auto DoubleSided = CullMode == CULL_MODE_NONE; + + m_MeshEdgesPSOs[{PSOFlags, ALPHA_MODE_OPAQUE, DoubleSided}] = m_Device.CreateGraphicsPipelineState(PSOCreateInfo); + } +} + +IPipelineState* USD_Renderer::GetMeshEdgesPSO(const PSOKey& _Key, bool CreateIfNull) +{ + auto Key = _Key; + Key.AlphaMode = ALPHA_MODE_OPAQUE; + + return GetPSO(m_MeshEdgesPSOs, Key, [&]() { CreateMeshEdgesPSO(Key.Flags, m_Settings.RTVFmt, m_Settings.DSVFmt); }); } } // namespace Diligent diff --git a/Shaders/PBR/private/RenderPBR.vsh b/Shaders/PBR/private/RenderPBR.vsh index 87e09718..5d468db2 100644 --- a/Shaders/PBR/private/RenderPBR.vsh +++ b/Shaders/PBR/private/RenderPBR.vsh @@ -2,26 +2,21 @@ #include "VertexProcessing.fxh" #include "PBR_Structures.fxh" #include "RenderPBRCommon.fxh" +#include "VSInputStruct.generated" #ifndef MAX_JOINT_COUNT # define MAX_JOINT_COUNT 64 #endif -struct VertexAttribs -{ - float3 Pos : ATTRIB0; - float3 Normal : ATTRIB1; - float2 UV0 : ATTRIB2; - float2 UV1 : ATTRIB3; -}; - -#if MAX_JOINT_COUNT > 0 -struct SkinningAttribs -{ - float4 Joint0 : ATTRIB4; - float4 Weight0 : ATTRIB5; -}; -#endif +//struct VSInput +//{ +// float3 Pos : ATTRIB0; +// float3 Normal : ATTRIB1; +// float2 UV0 : ATTRIB2; +// float2 UV1 : ATTRIB3; +// float4 Joint0 : ATTRIB4; +// float4 Weight0 : ATTRIB5; +//}; cbuffer cbCameraAttribs { @@ -40,11 +35,8 @@ cbuffer cbJointTransforms } #endif -void VSMainInternal(in VertexAttribs Vert, -#if MAX_JOINT_COUNT > 0 - in SkinningAttribs Skinning, -#endif - out PbrVsOutput VSOut) +void main(in VSInput VSIn, + out PbrVsOutput VSOut) { // Warning: moving this block into GLTF_TransformVertex() function causes huge // performance degradation on Vulkan because glslang/SPIRV-Tools are apparently not able @@ -56,38 +48,19 @@ void VSMainInternal(in VertexAttribs Vert, { // Mesh is skinned float4x4 SkinMat = - Skinning.Weight0.x * g_Joints[int(Skinning.Joint0.x)] + - Skinning.Weight0.y * g_Joints[int(Skinning.Joint0.y)] + - Skinning.Weight0.z * g_Joints[int(Skinning.Joint0.z)] + - Skinning.Weight0.w * g_Joints[int(Skinning.Joint0.w)]; + VSIn.Weight0.x * g_Joints[int(VSIn.Joint0.x)] + + VSIn.Weight0.y * g_Joints[int(VSIn.Joint0.y)] + + VSIn.Weight0.z * g_Joints[int(VSIn.Joint0.z)] + + VSIn.Weight0.w * g_Joints[int(VSIn.Joint0.w)]; Transform = mul(Transform, SkinMat); } #endif - GLTF_TransformedVertex TransformedVert = GLTF_TransformVertex(Vert.Pos, Vert.Normal, Transform); + GLTF_TransformedVertex TransformedVert = GLTF_TransformVertex(VSIn.Pos, VSIn.Normal, Transform); VSOut.ClipPos = mul(float4(TransformedVert.WorldPos, 1.0), g_CameraAttribs.mViewProj); VSOut.WorldPos = TransformedVert.WorldPos; VSOut.Normal = TransformedVert.Normal; - VSOut.UV0 = Vert.UV0; - VSOut.UV1 = Vert.UV1; -} - -#if MAX_JOINT_COUNT > 0 - -void VSMainSkinned(in VertexAttribs Vert, - in SkinningAttribs Skinning, - out PbrVsOutput VSOut) -{ - VSMainInternal(Vert, Skinning, VSOut); + VSOut.UV0 = VSIn.UV0; + VSOut.UV1 = VSIn.UV1; } - -#else - -void VSMain(in VertexAttribs Vert, - out PbrVsOutput VSOut) -{ - VSMainInternal(Vert, VSOut); -} - -#endif diff --git a/shaders_inc/RenderPBR.vsh.h b/shaders_inc/RenderPBR.vsh.h index 17a11a36..b5275889 100644 --- a/shaders_inc/RenderPBR.vsh.h +++ b/shaders_inc/RenderPBR.vsh.h @@ -2,26 +2,21 @@ "#include \"VertexProcessing.fxh\"\n" "#include \"PBR_Structures.fxh\"\n" "#include \"RenderPBRCommon.fxh\"\n" +"#include \"VSInputStruct.generated\"\n" "\n" "#ifndef MAX_JOINT_COUNT\n" "# define MAX_JOINT_COUNT 64\n" "#endif\n" "\n" -"struct VertexAttribs\n" -"{\n" -" float3 Pos : ATTRIB0;\n" -" float3 Normal : ATTRIB1;\n" -" float2 UV0 : ATTRIB2;\n" -" float2 UV1 : ATTRIB3;\n" -"};\n" -"\n" -"#if MAX_JOINT_COUNT > 0\n" -"struct SkinningAttribs\n" -"{\n" -" float4 Joint0 : ATTRIB4;\n" -" float4 Weight0 : ATTRIB5;\n" -"};\n" -"#endif\n" +"//struct VSInput\n" +"//{\n" +"// float3 Pos : ATTRIB0;\n" +"// float3 Normal : ATTRIB1;\n" +"// float2 UV0 : ATTRIB2;\n" +"// float2 UV1 : ATTRIB3;\n" +"// float4 Joint0 : ATTRIB4;\n" +"// float4 Weight0 : ATTRIB5;\n" +"//};\n" "\n" "cbuffer cbCameraAttribs\n" "{\n" @@ -40,11 +35,8 @@ "}\n" "#endif\n" "\n" -"void VSMainInternal(in VertexAttribs Vert,\n" -"#if MAX_JOINT_COUNT > 0\n" -" in SkinningAttribs Skinning,\n" -"#endif\n" -" out PbrVsOutput VSOut)\n" +"void main(in VSInput VSIn,\n" +" out PbrVsOutput VSOut)\n" "{\n" " // Warning: moving this block into GLTF_TransformVertex() function causes huge\n" " // performance degradation on Vulkan because glslang/SPIRV-Tools are apparently not able\n" @@ -56,38 +48,19 @@ " {\n" " // Mesh is skinned\n" " float4x4 SkinMat =\n" -" Skinning.Weight0.x * g_Joints[int(Skinning.Joint0.x)] +\n" -" Skinning.Weight0.y * g_Joints[int(Skinning.Joint0.y)] +\n" -" Skinning.Weight0.z * g_Joints[int(Skinning.Joint0.z)] +\n" -" Skinning.Weight0.w * g_Joints[int(Skinning.Joint0.w)];\n" +" VSIn.Weight0.x * g_Joints[int(VSIn.Joint0.x)] +\n" +" VSIn.Weight0.y * g_Joints[int(VSIn.Joint0.y)] +\n" +" VSIn.Weight0.z * g_Joints[int(VSIn.Joint0.z)] +\n" +" VSIn.Weight0.w * g_Joints[int(VSIn.Joint0.w)];\n" " Transform = mul(Transform, SkinMat);\n" " }\n" "#endif\n" "\n" -" GLTF_TransformedVertex TransformedVert = GLTF_TransformVertex(Vert.Pos, Vert.Normal, Transform);\n" +" GLTF_TransformedVertex TransformedVert = GLTF_TransformVertex(VSIn.Pos, VSIn.Normal, Transform);\n" "\n" " VSOut.ClipPos = mul(float4(TransformedVert.WorldPos, 1.0), g_CameraAttribs.mViewProj);\n" " VSOut.WorldPos = TransformedVert.WorldPos;\n" " VSOut.Normal = TransformedVert.Normal;\n" -" VSOut.UV0 = Vert.UV0;\n" -" VSOut.UV1 = Vert.UV1;\n" -"}\n" -"\n" -"#if MAX_JOINT_COUNT > 0\n" -"\n" -"void VSMainSkinned(in VertexAttribs Vert,\n" -" in SkinningAttribs Skinning,\n" -" out PbrVsOutput VSOut)\n" -"{\n" -" VSMainInternal(Vert, Skinning, VSOut);\n" +" VSOut.UV0 = VSIn.UV0;\n" +" VSOut.UV1 = VSIn.UV1;\n" "}\n" -"\n" -"#else\n" -"\n" -"void VSMain(in VertexAttribs Vert,\n" -" out PbrVsOutput VSOut)\n" -"{\n" -" VSMainInternal(Vert, VSOut);\n" -"}\n" -"\n" -"#endif\n"