Skip to content

Commit

Permalink
Reworked PBR renderer to allow specifying graphics pipeline desc when…
Browse files Browse the repository at this point in the history
… querying PSO
  • Loading branch information
TheMostDiligent committed Oct 17, 2023
1 parent 826938a commit daa0829
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 124 deletions.
4 changes: 4 additions & 0 deletions Hydrogent/include/HnRendererImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ class HnRendererImpl final : public ObjectBase<IHnRenderer>
std::shared_ptr<USD_Renderer> m_USDRenderer;
std::unique_ptr<EnvMapRenderer> m_EnvMapRenderer;

USD_Renderer::PbrPsoCacheAccessor m_PbrPSOCache;
USD_Renderer::WireframePsoCacheAccessor m_WireframePSOCache;
USD_Renderer::MeshIdPsoCacheAccessor m_MeshIdPSOCache;

std::unique_ptr<HnRenderDelegate> m_RenderDelegate;

pxr::UsdStageRefPtr m_Stage;
Expand Down
32 changes: 25 additions & 7 deletions Hydrogent/src/HnRendererImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down
14 changes: 14 additions & 0 deletions PBR/interface/GLTF_PBR_Renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -243,6 +254,9 @@ class GLTF_PBR_Renderer : public PBR_Renderer
{}
};
std::array<std::vector<PrimitiveRenderInfo>, 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)
Expand Down
156 changes: 96 additions & 60 deletions PBR/interface/PBR_Renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,

Expand All @@ -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,
};
Expand Down Expand Up @@ -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 <typename PsoHashMapType, typename PsoKeyType>
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, RefCntAutoPtr<IPipelineState>, PbrPSOKey::Hasher>;
using MeshIdPsoHashMapType = std::unordered_map<MeshIdPSOKey, RefCntAutoPtr<IPipelineState>, MeshIdPSOKey::Hasher>;
using WireframePsoHashMapType = std::unordered_map<WireframePSOKey, RefCntAutoPtr<IPipelineState>, WireframePSOKey::Hasher>;

using PbrPsoCacheAccessor = PsoCacheAccessor<PbrPsoHashMapType, PbrPSOKey>;
using MeshIdPsoCacheAccessor = PsoCacheAccessor<MeshIdPsoHashMapType, MeshIdPSOKey>;
using WireframePsoCacheAccessor = PsoCacheAccessor<WireframePsoHashMapType, WireframePSOKey>;

PbrPsoCacheAccessor GetPbrPsoCacheAccessor(const GraphicsPipelineDesc& GraphicsDesc);
MeshIdPsoCacheAccessor GetMeshIdPsoCacheAccessor(const GraphicsPipelineDesc& GraphicsDesc);
WireframePsoCacheAccessor GetWireframePsoCacheAccessor(const GraphicsPipelineDesc& GraphicsDesc);

void InitCommonSRBVars(IShaderResourceBinding* pSRB,
IBuffer* pCameraAttribs,
Expand All @@ -361,11 +379,14 @@ class PBR_Renderer

void GetVSInputStructAndLayout(PSO_FLAGS PSOFlags, std::string& VSInputStruct, InputLayoutDescX& InputLayout) const;

template <typename KeyType, class CreatePSOType>
template <typename KeyType>
struct GetPSOHelper;

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

static std::string GetVSOutputStruct(PSO_FLAGS PSOFlags);

Expand All @@ -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:
Expand All @@ -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;

Expand All @@ -420,9 +440,9 @@ class PBR_Renderer

RefCntAutoPtr<IPipelineResourceSignature> m_ResourceSignature;

std::unordered_map<PbrPSOKey, RefCntAutoPtr<IPipelineState>, PbrPSOKey::Hasher> m_PbrPSOs;
std::unordered_map<MeshIdPSOKey, RefCntAutoPtr<IPipelineState>, MeshIdPSOKey::Hasher> m_MeshIdPSOs;
std::unordered_map<WireframePSOKey, RefCntAutoPtr<IPipelineState>, WireframePSOKey::Hasher> m_WireframePSOs;
std::unordered_map<GraphicsPipelineDesc, PbrPsoHashMapType> m_PbrPSOs;
std::unordered_map<GraphicsPipelineDesc, MeshIdPsoHashMapType> m_MeshIdPSOs;
std::unordered_map<GraphicsPipelineDesc, WireframePsoHashMapType> m_WireframePSOs;
};

DEFINE_FLAG_ENUM_OPERATORS(PBR_Renderer::PSO_FLAGS)
Expand All @@ -434,23 +454,39 @@ 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,
bool _DoubleSided) noexcept :
PSOKey{_Flags & SupportedFlags, _DoubleSided}
{}

template <typename KeyType, class CreatePSOType>
template <>
struct PBR_Renderer::GetPSOHelper<PBR_Renderer::PbrPSOKey>
{
static constexpr decltype(&PBR_Renderer::CreatePbrPSO) CreatePSO = &PBR_Renderer::CreatePbrPSO;
};

template <>
struct PBR_Renderer::GetPSOHelper<PBR_Renderer::WireframePSOKey>
{
static constexpr decltype(&PBR_Renderer::CreateWireframePSO) CreatePSO = &PBR_Renderer::CreateWireframePSO;
};

template <>
struct PBR_Renderer::GetPSOHelper<PBR_Renderer::MeshIdPSOKey>
{
static constexpr decltype(&PBR_Renderer::CreateMeshIdPSO) CreatePSO = &PBR_Renderer::CreateMeshIdPSO;
};

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

Expand Down Expand Up @@ -484,7 +520,7 @@ IPipelineState* PBR_Renderer::GetPSO(std::unordered_map<KeyType, RefCntAutoPtr<I
{
if (CreateIfNull)
{
CreatePSO(this, Key);
(this->*GetPSOHelper<KeyType>::CreatePSO)(PSOCache, GraphicsDesc, Key);
it = PSOCache.find(Key);
VERIFY_EXPR(it != PSOCache.end());
}
Expand Down
Loading

0 comments on commit daa0829

Please sign in to comment.