Skip to content

Commit

Permalink
PBR Renderer: unified PBR and unshaded (used to be wireframe) PSO caches
Browse files Browse the repository at this point in the history
  • Loading branch information
TheMostDiligent committed Nov 7, 2023
1 parent 84c0fe7 commit 43ab92e
Show file tree
Hide file tree
Showing 14 changed files with 203 additions and 297 deletions.
11 changes: 6 additions & 5 deletions Hydrogent/src/HnRenderPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ struct HnRenderPass::RenderState

const PBR_Renderer::ALPHA_MODE AlphaMode;

USD_Renderer::PbrPsoCacheAccessor PbrPSOCache;
USD_Renderer::WireframePsoCacheAccessor WireframePSOCache;
USD_Renderer::PsoCacheAccessor PbrPSOCache;
USD_Renderer::PsoCacheAccessor WireframePSOCache;

IPipelineState* pPSO = nullptr;
};
Expand Down Expand Up @@ -109,14 +109,14 @@ void HnRenderPass::_Execute(const pxr::HdRenderPassStateSharedPtr& RPState,
if (m_RenderParams.RenderMode == HN_RENDER_MODE_SOLID)
{
GraphicsDesc.PrimitiveTopology = PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
State.PbrPSOCache = USDRenderer->GetPbrPsoCacheAccessor(GraphicsDesc);
State.PbrPSOCache = USDRenderer->GetPsoCacheAccessor(GraphicsDesc);
VERIFY_EXPR(State.PbrPSOCache);
}
else if (m_RenderParams.RenderMode == HN_RENDER_MODE_MESH_EDGES ||
m_RenderParams.RenderMode == HN_RENDER_MODE_POINTS)
{
GraphicsDesc.PrimitiveTopology = m_RenderParams.RenderMode == HN_RENDER_MODE_MESH_EDGES ? PRIMITIVE_TOPOLOGY_LINE_LIST : PRIMITIVE_TOPOLOGY_POINT_LIST;
State.WireframePSOCache = USDRenderer->GetWireframePsoCacheAccessor(GraphicsDesc);
State.WireframePSOCache = USDRenderer->GetPsoCacheAccessor(GraphicsDesc);
VERIFY_EXPR(State.WireframePSOCache);
}
else
Expand Down Expand Up @@ -322,6 +322,7 @@ void HnRenderPass::RenderMesh(RenderState& State,
else if (m_RenderParams.RenderMode == HN_RENDER_MODE_MESH_EDGES ||
m_RenderParams.RenderMode == HN_RENDER_MODE_POINTS)
{
PSOFlags |= PBR_Renderer::PSO_FLAG_UNSHADED;
pPSO = State.WireframePSOCache.Get({PSOFlags, /*DoubleSided = */ false}, true);
}
else
Expand Down Expand Up @@ -361,7 +362,7 @@ void HnRenderPass::RenderMesh(RenderState& State,
RendererParams.IBLScale = m_RenderParams.IBLScale;

RendererParams.PrefilteredCubeMipLevels = 5; //m_Settings.UseIBL ? static_cast<float>(m_pPrefilteredEnvMapSRV->GetTexture()->GetDesc().MipLevels) : 0.f;
RendererParams.WireframeColor = m_RenderParams.RenderMode == HN_RENDER_MODE_POINTS ? m_RenderParams.PointColor : m_RenderParams.WireframeColor;
RendererParams.UnshadedColor = m_RenderParams.RenderMode == HN_RENDER_MODE_POINTS ? m_RenderParams.PointColor : m_RenderParams.WireframeColor;
RendererParams.HighlightColor = float4{0, 0, 0, 0};

// Tone mapping is performed in the post-processing pass
Expand Down
10 changes: 9 additions & 1 deletion Hydrogent/src/Tasks/HnReadRprimIdTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,15 @@ void HnReadRprimIdTask::Execute(pxr::HdTaskContext* TaskCtx)
{
MappedTextureSubresource MappedData;
pCtx->MapTextureSubresource(pStagingTex, 0, 0, MAP_READ, MAP_FLAG_DO_NOT_WAIT, nullptr, MappedData);
m_MeshIndex = static_cast<Uint32>(*static_cast<const float*>(MappedData.pData));
if (MappedData.pData != nullptr)
{
float fMeshIndex = *static_cast<const float*>(MappedData.pData);
m_MeshIndex = fMeshIndex >= 0.f ? static_cast<Uint32>(fMeshIndex) : 0u;
}
else
{
UNEXPECTED("Mapped data pointer is null");
}
pCtx->UnmapTextureSubresource(pStagingTex, 0, 0);
}
m_MeshIdReadBackQueue->Recycle(std::move(pStagingTex));
Expand Down
4 changes: 2 additions & 2 deletions PBR/interface/GLTF_PBR_Renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,8 @@ 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;
PsoCacheAccessor m_PbrPSOCache;
PsoCacheAccessor m_WireframePSOCache;
};

DEFINE_FLAG_ENUM_OPERATORS(GLTF_PBR_Renderer::RenderInfo::ALPHA_MODE_FLAGS)
Expand Down
174 changes: 27 additions & 147 deletions PBR/interface/PBR_Renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,9 @@ class PBR_Renderer
PSO_FLAG_CONVERT_OUTPUT_TO_SRGB = 1u << 15u,
PSO_FLAG_ENABLE_CUSTOM_DATA_OUTPUT = 1u << 16u,
PSO_FLAG_ENABLE_TONE_MAPPING = 1u << 17u,
PSO_FLAG_UNSHADED = 1u << 18u,

PSO_FLAG_LAST = PSO_FLAG_ENABLE_TONE_MAPPING,
PSO_FLAG_LAST = PSO_FLAG_UNSHADED,

PSO_FLAG_FIRST_USER_DEFINED = PSO_FLAG_LAST << 1u,

Expand All @@ -254,73 +255,45 @@ class PBR_Renderer
PSO_FLAG_ALL_USER_DEFINED = ~(PSO_FLAG_FIRST_USER_DEFINED - 1u)
};

struct PSOKey
class PSOKey
{
PSO_FLAGS Flags = PSO_FLAG_NONE;
bool DoubleSided = false;

public:
constexpr PSOKey() noexcept {};
constexpr PSOKey(PSO_FLAGS _Flags, bool _DoubleSided) noexcept :
Flags{_Flags}, DoubleSided{_DoubleSided}
PSOKey(PSO_FLAGS _Flags, ALPHA_MODE _AlphaMode, bool _DoubleSided) noexcept;
PSOKey(PSO_FLAGS _Flags, bool _DoubleSided) noexcept :
PSOKey{_Flags, ALPHA_MODE_OPAQUE, _DoubleSided}
{}

constexpr bool operator==(const PSOKey& rhs) const noexcept
{
return Flags == rhs.Flags && DoubleSided == rhs.DoubleSided;
return Hash == rhs.Hash && Flags == rhs.Flags && DoubleSided == rhs.DoubleSided && AlphaMode == rhs.AlphaMode;
}
constexpr bool operator!=(const PSOKey& rhs) const noexcept
{
return Flags != rhs.Flags || DoubleSided != rhs.DoubleSided;
return !(*this == rhs);
}

struct Hasher
{
size_t operator()(const PSOKey& Key) const noexcept
{
return ComputeHash(Key.Flags, Key.DoubleSided);
return Key.Hash;
}
};
};

struct PbrPSOKey : PSOKey
{
static const PSO_FLAGS SupportedFlags;

ALPHA_MODE AlphaMode = ALPHA_MODE_OPAQUE;

PbrPSOKey() noexcept {};
PbrPSOKey(PSO_FLAGS _Flags, ALPHA_MODE _AlphaMode, bool _DoubleSided) noexcept;
constexpr PSO_FLAGS GetFlags() const noexcept { return Flags; }
constexpr bool IsDoubleSided() const noexcept { return DoubleSided; }
constexpr ALPHA_MODE GetAlphaMode() const noexcept { return AlphaMode; }

bool operator==(const PbrPSOKey& rhs) const noexcept
{
return PSOKey::operator==(rhs) && AlphaMode == rhs.AlphaMode;
}
bool operator!=(const PbrPSOKey& rhs) const noexcept
{
return PSOKey::operator!=(rhs) || AlphaMode != rhs.AlphaMode;
}

struct Hasher
{
size_t operator()(const PbrPSOKey& Key) const noexcept
{
size_t Hash = PSOKey::Hasher{}(Key);
HashCombine(Hash, Key.AlphaMode);
return Hash;
}
};
private:
PSO_FLAGS Flags = PSO_FLAG_NONE;
ALPHA_MODE AlphaMode = ALPHA_MODE_OPAQUE;
bool DoubleSided = false;
size_t Hash = 0;
};

using PsoHashMapType = std::unordered_map<PSOKey, RefCntAutoPtr<IPipelineState>, PSOKey::Hasher>;

struct WireframePSOKey : PSOKey
{
static const PSO_FLAGS SupportedFlags;

WireframePSOKey() noexcept {};
WireframePSOKey(PSO_FLAGS _Flags, bool _DoubleSided) noexcept;
};

template <typename PsoHashMapType, typename PsoKeyType>
class PsoCacheAccessor
{
public:
Expand All @@ -337,7 +310,7 @@ class PBR_Renderer
return m_pRenderer != nullptr && m_pPsoHashMap != nullptr && m_pGraphicsDesc != nullptr;
}

IPipelineState* Get(const PsoKeyType& Key, bool CreateIfNull) const
IPipelineState* Get(const PSOKey& Key, bool CreateIfNull) const
{
if (!*this)
{
Expand All @@ -363,14 +336,7 @@ class PBR_Renderer
const GraphicsPipelineDesc* m_pGraphicsDesc = nullptr;
};

using PbrPsoHashMapType = std::unordered_map<PbrPSOKey, RefCntAutoPtr<IPipelineState>, PbrPSOKey::Hasher>;
using WireframePsoHashMapType = std::unordered_map<WireframePSOKey, RefCntAutoPtr<IPipelineState>, WireframePSOKey::Hasher>;

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

PbrPsoCacheAccessor GetPbrPsoCacheAccessor(const GraphicsPipelineDesc& GraphicsDesc);
WireframePsoCacheAccessor GetWireframePsoCacheAccessor(const GraphicsPipelineDesc& GraphicsDesc);
PsoCacheAccessor GetPsoCacheAccessor(const GraphicsPipelineDesc& GraphicsDesc);

void InitCommonSRBVars(IShaderResourceBinding* pSRB,
IBuffer* pCameraAttribs,
Expand All @@ -381,33 +347,19 @@ class PBR_Renderer

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

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);
IPipelineState* GetPSO(PsoHashMapType& PsoHashMap,
const GraphicsPipelineDesc& GraphicsDesc,
const PSOKey& Key,
bool CreateIfNull);

static std::string GetVSOutputStruct(PSO_FLAGS PSOFlags);
static std::string GetPSOutputStruct(PSO_FLAGS PSOFlags);

void CreateShaders(PSO_FLAGS PSOFlags,
const char* VSPath,
const char* VSName,
const char* PSPath,
const char* PSName,
RefCntAutoPtr<IShader>& pVS,
RefCntAutoPtr<IShader>& pPS,
InputLayoutDescX& InputLayout);

private:
void PrecomputeBRDF(IDeviceContext* pCtx,
Uint32 NumBRDFSamples = 512);

void CreatePbrPSO(PbrPsoHashMapType& PbrPSOs, const GraphicsPipelineDesc& GraphicsDesc, const PbrPSOKey& Key);
void CreateWireframePSO(WireframePsoHashMapType& WireframePSOs, const GraphicsPipelineDesc& GraphicsDesc, const WireframePSOKey& Key);
void CreatePSO(PsoHashMapType& PsoHashMap, const GraphicsPipelineDesc& GraphicsDesc, const PSOKey& Key);
void CreateSignature();

protected:
Expand Down Expand Up @@ -442,81 +394,9 @@ class PBR_Renderer

RefCntAutoPtr<IPipelineResourceSignature> m_ResourceSignature;

std::unordered_map<GraphicsPipelineDesc, PbrPsoHashMapType> m_PbrPSOs;
std::unordered_map<GraphicsPipelineDesc, WireframePsoHashMapType> m_WireframePSOs;
std::unordered_map<GraphicsPipelineDesc, PsoHashMapType> m_PSOs;
};

DEFINE_FLAG_ENUM_OPERATORS(PBR_Renderer::PSO_FLAGS)

inline PBR_Renderer::PbrPSOKey::PbrPSOKey(PSO_FLAGS _Flags,
ALPHA_MODE _AlphaMode,
bool _DoubleSided) noexcept :
PSOKey{_Flags & SupportedFlags, _DoubleSided},
AlphaMode{_AlphaMode}
{}

inline PBR_Renderer::WireframePSOKey::WireframePSOKey(PSO_FLAGS _Flags,
bool _DoubleSided) noexcept :
PSOKey{_Flags & SupportedFlags, _DoubleSided}
{}

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 <typename KeyType>
IPipelineState* PBR_Renderer::GetPSO(std::unordered_map<KeyType, RefCntAutoPtr<IPipelineState>, typename KeyType::Hasher>& PSOCache,
const GraphicsPipelineDesc& GraphicsDesc,
KeyType Key,
bool CreateIfNull)
{
Key.Flags &= KeyType::SupportedFlags;

if (!m_Settings.EnableIBL)
{
Key.Flags &= ~PSO_FLAG_USE_IBL;
}
if (!m_Settings.EnableAO)
{
Key.Flags &= ~PSO_FLAG_USE_AO_MAP;
}
if (!m_Settings.EnableEmissive)
{
Key.Flags &= ~PSO_FLAG_USE_EMISSIVE_MAP;
}
if (m_Settings.MaxJointCount == 0)
{
Key.Flags &= ~PSO_FLAG_USE_JOINTS;
}
if (m_Settings.UseSeparateMetallicRoughnessTextures)
{
DEV_CHECK_ERR((Key.Flags & PSO_FLAG_USE_PHYS_DESC_MAP) == 0, "Physical descriptor map is not enabled");
}
else
{
DEV_CHECK_ERR((Key.Flags & (PSO_FLAG_USE_METALLIC_MAP | PSO_FLAG_USE_ROUGHNESS_MAP)) == 0, "Separate metallic and roughness maps are not enaled");
}

auto it = PSOCache.find(Key);
if (it == PSOCache.end())
{
if (CreateIfNull)
{
(this->*GetPSOHelper<KeyType>::CreatePSO)(PSOCache, GraphicsDesc, Key);
it = PSOCache.find(Key);
VERIFY_EXPR(it != PSOCache.end());
}
}

return it != PSOCache.end() ? it->second.RawPtr() : nullptr;
}

} // namespace Diligent
Loading

0 comments on commit 43ab92e

Please sign in to comment.