Skip to content

Commit

Permalink
PBR Renderer: optimized PSO initialization
Browse files Browse the repository at this point in the history
  • Loading branch information
TheMostDiligent committed Oct 8, 2023
1 parent 14ba20e commit feee396
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 56 deletions.
23 changes: 17 additions & 6 deletions PBR/interface/PBR_Renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,11 @@ class PBR_Renderer
void GetVSInputStructAndLayout(PSO_FLAGS PSOFlags, std::string& VSInputStruct, InputLayoutDescX& InputLayout) const;

template <typename KeyType, class CreatePSOType>
IPipelineState* GetPSO(std::unordered_map<KeyType, RefCntAutoPtr<IPipelineState>, typename KeyType::Hasher>& PSOCache, KeyType Key, CreatePSOType&& CreatePSO);
IPipelineState* GetPSO(std::unordered_map<KeyType, RefCntAutoPtr<IPipelineState>, typename KeyType::Hasher>& PSOCache,
KeyType Key,
PSO_FLAGS SupportedFlags,
bool CreateIfNull,
CreatePSOType&& CreatePSO);

static std::string GetVSOutputStruct(PSO_FLAGS PSOFlags);

Expand All @@ -365,9 +369,9 @@ class PBR_Renderer
void PrecomputeBRDF(IDeviceContext* pCtx,
Uint32 NumBRDFSamples = 512);

void CreatePbrPSO(PSO_FLAGS PSOFlags, TEXTURE_FORMAT RTVFmt, TEXTURE_FORMAT DSVFmt);
void CreateWireframePSO(PSO_FLAGS PSOFlags, TEXTURE_FORMAT RTVFmt, TEXTURE_FORMAT DSVFmt, PRIMITIVE_TOPOLOGY Topology);
void CreateMeshIdPSO(PSO_FLAGS PSOFlags, TEXTURE_FORMAT RTVFmt, TEXTURE_FORMAT DSVFmt);
void CreatePbrPSO(const PbrPSOKey& Key);
void CreateWireframePSO(const WireframePSOKey& Key);
void CreateMeshIdPSO(const MeshIdPSOKey& Key);
void CreateSignature();

protected:
Expand Down Expand Up @@ -410,8 +414,14 @@ class PBR_Renderer
DEFINE_FLAG_ENUM_OPERATORS(PBR_Renderer::PSO_FLAGS)

template <typename KeyType, class CreatePSOType>
IPipelineState* PBR_Renderer::GetPSO(std::unordered_map<KeyType, RefCntAutoPtr<IPipelineState>, typename KeyType::Hasher>& PSOCache, KeyType Key, CreatePSOType&& CreatePSO)
IPipelineState* PBR_Renderer::GetPSO(std::unordered_map<KeyType, RefCntAutoPtr<IPipelineState>, typename KeyType::Hasher>& PSOCache,
KeyType Key,
PSO_FLAGS SupportedFlags,
bool CreateIfNull,
CreatePSOType&& CreatePSO)
{
Key.Flags &= SupportedFlags;

if (!m_Settings.EnableIBL)
{
Key.Flags &= ~PSO_FLAG_USE_IBL;
Expand Down Expand Up @@ -440,8 +450,9 @@ IPipelineState* PBR_Renderer::GetPSO(std::unordered_map<KeyType, RefCntAutoPtr<I
auto it = PSOCache.find(Key);
if (it == PSOCache.end())
{
if (CreatePSO())
if (CreateIfNull)
{
CreatePSO(this, Key);
it = PSOCache.find(Key);
VERIFY_EXPR(it != PSOCache.end());
}
Expand Down
77 changes: 27 additions & 50 deletions PBR/src/PBR_Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -812,22 +812,22 @@ void PBR_Renderer::CreateShaders(PSO_FLAGS PSOFlags,
}


void PBR_Renderer::CreatePbrPSO(PSO_FLAGS PSOFlags, TEXTURE_FORMAT RTVFmt, TEXTURE_FORMAT DSVFmt)
void PBR_Renderer::CreatePbrPSO(const PbrPSOKey& Key)
{
GraphicsPipelineStateCreateInfo PSOCreateInfo;
PipelineStateDesc& PSODesc = PSOCreateInfo.PSODesc;
GraphicsPipelineDesc& GraphicsPipeline = PSOCreateInfo.GraphicsPipeline;

GraphicsPipeline.NumRenderTargets = 1;
GraphicsPipeline.RTVFormats[0] = RTVFmt;
GraphicsPipeline.DSVFormat = DSVFmt;
GraphicsPipeline.RTVFormats[0] = m_Settings.RTVFmt;
GraphicsPipeline.DSVFormat = m_Settings.DSVFmt;
GraphicsPipeline.PrimitiveTopology = PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
GraphicsPipeline.RasterizerDesc.FrontCounterClockwise = (PSOFlags & PSO_FLAG_FRONT_CCW) != 0;
GraphicsPipeline.RasterizerDesc.FrontCounterClockwise = (Key.Flags & PSO_FLAG_FRONT_CCW) != 0;

InputLayoutDescX InputLayout;
RefCntAutoPtr<IShader> pVS;
RefCntAutoPtr<IShader> pPS;
CreateShaders(PSOFlags, "RenderPBR.vsh", "PBR VS", "RenderPBR.psh", "PBR PS", pVS, pPS, InputLayout);
CreateShaders(Key.Flags, "RenderPBR.vsh", "PBR VS", "RenderPBR.psh", "PBR PS", pVS, pPS, InputLayout);

PSOCreateInfo.GraphicsPipeline.InputLayout = InputLayout;

Expand Down Expand Up @@ -863,36 +863,36 @@ void PBR_Renderer::CreatePbrPSO(PSO_FLAGS PSOFlags, TEXTURE_FORMAT RTVFmt, TEXTU
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[{PSOFlags, AlphaMode, DoubleSided}] = PSO;
GraphicsPipeline.RasterizerDesc.CullMode = CullMode;
const auto DoubleSided = CullMode == CULL_MODE_NONE;
auto PSO = m_Device.CreateGraphicsPipelineState(PSOCreateInfo);
m_PbrPSOs[{Key.Flags, AlphaMode, DoubleSided}] = PSO;
if (AlphaMode == ALPHA_MODE_BLEND)
{
// Mask and blend use the same PSO
m_PbrPSOs[{PSOFlags, ALPHA_MODE_MASK, DoubleSided}] = PSO;
m_PbrPSOs[{Key.Flags, ALPHA_MODE_MASK, DoubleSided}] = PSO;
}
}
}
}

void PBR_Renderer::CreateMeshIdPSO(PSO_FLAGS PSOFlags, TEXTURE_FORMAT RTVFmt, TEXTURE_FORMAT DSVFmt)
void PBR_Renderer::CreateMeshIdPSO(const MeshIdPSOKey& Key)
{
GraphicsPipelineStateCreateInfo PSOCreateInfo;
PipelineStateDesc& PSODesc = PSOCreateInfo.PSODesc;
GraphicsPipelineDesc& GraphicsPipeline = PSOCreateInfo.GraphicsPipeline;

GraphicsPipeline.NumRenderTargets = 1;
GraphicsPipeline.RTVFormats[0] = MeshIdFmt;
GraphicsPipeline.DSVFormat = DSVFmt;
GraphicsPipeline.DSVFormat = m_Settings.DSVFmt;
GraphicsPipeline.PrimitiveTopology = PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
GraphicsPipeline.RasterizerDesc.FrontCounterClockwise = (PSOFlags & PSO_FLAG_FRONT_CCW) != 0;
GraphicsPipeline.RasterizerDesc.FrontCounterClockwise = (Key.Flags & PSO_FLAG_FRONT_CCW) != 0;
GraphicsPipeline.DepthStencilDesc.DepthFunc = COMPARISON_FUNC_LESS_EQUAL;

InputLayoutDescX InputLayout;
RefCntAutoPtr<IShader> pVS;
RefCntAutoPtr<IShader> pPS;
CreateShaders(PSOFlags, "RenderPBR.vsh", "Mesh ID VS", "RenderMeshId.psh", "Mesh ID PS", pVS, pPS, InputLayout);
CreateShaders(Key.Flags, "RenderPBR.vsh", "Mesh ID VS", "RenderMeshId.psh", "Mesh ID PS", pVS, pPS, InputLayout);

PSOCreateInfo.GraphicsPipeline.InputLayout = InputLayout;

Expand All @@ -912,27 +912,27 @@ void PBR_Renderer::CreateMeshIdPSO(PSO_FLAGS PSOFlags, TEXTURE_FORMAT RTVFmt, TE
GraphicsPipeline.RasterizerDesc.CullMode = CullMode;
const auto DoubleSided = CullMode == CULL_MODE_NONE;

m_MeshIdPSOs[{PSOFlags, DoubleSided}] = m_Device.CreateGraphicsPipelineState(PSOCreateInfo);
m_MeshIdPSOs[{Key.Flags, DoubleSided}] = m_Device.CreateGraphicsPipelineState(PSOCreateInfo);
}
}

void PBR_Renderer::CreateWireframePSO(PSO_FLAGS PSOFlags, TEXTURE_FORMAT RTVFmt, TEXTURE_FORMAT DSVFmt, PRIMITIVE_TOPOLOGY Topology)
void PBR_Renderer::CreateWireframePSO(const WireframePSOKey& Key)
{
GraphicsPipelineStateCreateInfo PSOCreateInfo;
PipelineStateDesc& PSODesc = PSOCreateInfo.PSODesc;
GraphicsPipelineDesc& GraphicsPipeline = PSOCreateInfo.GraphicsPipeline;

GraphicsPipeline.NumRenderTargets = 1;
GraphicsPipeline.RTVFormats[0] = RTVFmt;
GraphicsPipeline.DSVFormat = DSVFmt;
GraphicsPipeline.PrimitiveTopology = Topology;
GraphicsPipeline.RTVFormats[0] = m_Settings.RTVFmt;
GraphicsPipeline.DSVFormat = m_Settings.DSVFmt;
GraphicsPipeline.PrimitiveTopology = Key.Topology;
GraphicsPipeline.RasterizerDesc.FillMode = FILL_MODE_WIREFRAME;
GraphicsPipeline.RasterizerDesc.FrontCounterClockwise = (PSOFlags & PSO_FLAG_FRONT_CCW) != 0;
GraphicsPipeline.RasterizerDesc.FrontCounterClockwise = (Key.Flags & PSO_FLAG_FRONT_CCW) != 0;

InputLayoutDescX InputLayout;
RefCntAutoPtr<IShader> pVS;
RefCntAutoPtr<IShader> pPS;
CreateShaders(PSOFlags, "RenderPBR.vsh", "Wireframe VS", "RenderWireframe.psh", "Wireframe PS", pVS, pPS, InputLayout);
CreateShaders(Key.Flags, "RenderPBR.vsh", "Wireframe VS", "RenderWireframe.psh", "Wireframe PS", pVS, pPS, InputLayout);

PSOCreateInfo.GraphicsPipeline.InputLayout = InputLayout;

Expand All @@ -952,7 +952,7 @@ void PBR_Renderer::CreateWireframePSO(PSO_FLAGS PSOFlags, TEXTURE_FORMAT RTVFmt,
GraphicsPipeline.RasterizerDesc.CullMode = CullMode;
const auto DoubleSided = CullMode == CULL_MODE_NONE;

m_WireframePSOs[{PSOFlags, Topology, DoubleSided}] = m_Device.CreateGraphicsPipelineState(PSOCreateInfo);
m_WireframePSOs[{Key.Flags, Key.Topology, DoubleSided}] = m_Device.CreateGraphicsPipelineState(PSOCreateInfo);
}
}

Expand All @@ -963,46 +963,23 @@ void PBR_Renderer::CreateResourceBinding(IShaderResourceBinding** ppSRB)

IPipelineState* PBR_Renderer::GetPbrPSO(const PbrPSOKey& Key, bool CreateIfNull)
{
return GetPSO(m_PbrPSOs, Key,
[&]() {
if (CreateIfNull)
CreatePbrPSO(Key.Flags, m_Settings.RTVFmt, m_Settings.DSVFmt);
return CreateIfNull;
});
return GetPSO(m_PbrPSOs, Key, PSO_FLAG_ALL, CreateIfNull, std::mem_fn(&PBR_Renderer::CreatePbrPSO));
}

IPipelineState* PBR_Renderer::GetMeshIdPSO(const MeshIdPSOKey& _Key, bool CreateIfNull)
IPipelineState* PBR_Renderer::GetMeshIdPSO(const MeshIdPSOKey& Key, bool CreateIfNull)
{
constexpr auto MeshIdPsoFlags =
PSO_FLAG_USE_JOINTS |
PSO_FLAG_FRONT_CCW;

auto Key = _Key;
Key.Flags &= MeshIdPsoFlags;

return GetPSO(m_MeshIdPSOs, Key,
[&]() {
if (CreateIfNull)
CreateMeshIdPSO(Key.Flags, m_Settings.RTVFmt, m_Settings.DSVFmt);
return CreateIfNull;
});
return GetPSO(m_MeshIdPSOs, Key, MeshIdPsoFlags, CreateIfNull, std::mem_fn(&PBR_Renderer::CreateMeshIdPSO));
}

IPipelineState* PBR_Renderer::GetWireframePSO(const WireframePSOKey& _Key, bool CreateIfNull)
IPipelineState* PBR_Renderer::GetWireframePSO(const WireframePSOKey& Key, bool CreateIfNull)
{
constexpr auto WireframePsoFlags =
PSO_FLAG_USE_JOINTS |
PSO_FLAG_FRONT_CCW;

auto Key = _Key;
Key.Flags &= WireframePsoFlags;

return GetPSO(m_WireframePSOs, Key,
[&]() {
if (CreateIfNull)
CreateWireframePSO(Key.Flags, m_Settings.RTVFmt, m_Settings.DSVFmt, Key.Topology);
return CreateIfNull;
});
return GetPSO(m_WireframePSOs, Key, WireframePsoFlags, CreateIfNull, std::mem_fn(&PBR_Renderer::CreateWireframePSO));
}

} // namespace Diligent

0 comments on commit feee396

Please sign in to comment.