Skip to content

Commit

Permalink
PBR Renderer: implemented clearing OIT layers
Browse files Browse the repository at this point in the history
  • Loading branch information
TheMostDiligent committed Feb 25, 2025
1 parent f61a2ad commit 3225fda
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 9 deletions.
5 changes: 5 additions & 0 deletions Hydrogent/interface/Tasks/HnBeginOITPassTask.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
#include "HnTask.hpp"
#include "../interface/HnRenderPassState.hpp"

#include "../../../../DiligentCore/Graphics/GraphicsEngine/interface/ShaderResourceBinding.h"
#include "../../../../DiligentCore/Common/interface/RefCntAutoPtr.hpp"

namespace Diligent
{

Expand Down Expand Up @@ -76,6 +79,8 @@ class HnBeginOITPassTask final : public HnTask

HnRenderPassState m_RenderPassState;

RefCntAutoPtr<IShaderResourceBinding> m_ClearLayersSRB;

Uint32 m_BoundOITResourcesVersion = ~0u;
};

Expand Down
26 changes: 18 additions & 8 deletions Hydrogent/src/Tasks/HnBeginOITPassTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ void HnBeginOITPassTask::Prepare(pxr::HdTaskContext* TaskCtx,
if (OITDesc.Width != ColorTargetDesc.Width || OITDesc.Height != ColorTargetDesc.Height)
{
FrameTargets->OIT = {};
m_ClearLayersSRB.Release();
}
}

Expand Down Expand Up @@ -134,19 +135,14 @@ void HnBeginOITPassTask::Prepare(pxr::HdTaskContext* TaskCtx,

void HnBeginOITPassTask::BindOITResources(HnRenderDelegate* RenderDelegate)
{
if (m_FrameTargets == nullptr)
{
UNEXPECTED("Frame targets are null. This likely indicates that Prepare() has not been called.");
return;
}

VERIFY_EXPR(m_FrameTargets != nullptr);
if (!m_FrameTargets->OIT)
{
UNEXPECTED("OIT resources are not initialized. This likely indicates that Prepare() has not been called.");
return;
}

USD_Renderer& Renderer = *RenderDelegate->GetUSDRenderer();
const USD_Renderer& Renderer = *RenderDelegate->GetUSDRenderer();
if (IShaderResourceBinding* pFrameAttribsSRB = RenderDelegate->GetFrameAttribsSRB(HnRenderDelegate::FrameAttribsSRBType::Transparent))
{
Renderer.SetOITResources(pFrameAttribsSRB, m_FrameTargets->OIT);
Expand All @@ -173,6 +169,11 @@ void HnBeginOITPassTask::Execute(pxr::HdTaskContext* TaskCtx)
UNEXPECTED("Render index is null. This likely indicates that Prepare() has not been called.");
return;
}
if (m_FrameTargets == nullptr)
{
UNEXPECTED("Frame targets are null. This likely indicates that Prepare() has not been called.");
return;
}

HnRenderDelegate* RenderDelegate = static_cast<HnRenderDelegate*>(m_RenderIndex->GetRenderDelegate());
IDeviceContext* pCtx = RenderDelegate->GetDeviceContext();
Expand All @@ -186,7 +187,16 @@ void HnBeginOITPassTask::Execute(pxr::HdTaskContext* TaskCtx)

ScopedDebugGroup DebugGroup{pCtx, "Begin OIT pass"};

m_RenderPassState.SetFrameAttribsSRB(RenderDelegate->GetFrameAttribsSRB(HnRenderDelegate::FrameAttribsSRBType::OITLayers));
const USD_Renderer& Renderer = *RenderDelegate->GetUSDRenderer();
if (!m_ClearLayersSRB)
{
Renderer.CreateClearOITLayersSRB(RenderDelegate->GetFrameAttribsCB(), m_FrameTargets->OIT.Layers, &m_ClearLayersSRB);
}
const TextureDesc& OITTailDesc = m_FrameTargets->OIT.Tail->GetDesc();
Renderer.ClearOITLayers(pCtx, m_ClearLayersSRB, OITTailDesc.Width, OITTailDesc.Height);

IShaderResourceBinding* pFrameAttribsSRB = RenderDelegate->GetFrameAttribsSRB(HnRenderDelegate::FrameAttribsSRBType::OITLayers);
m_RenderPassState.SetFrameAttribsSRB(pFrameAttribsSRB);
m_RenderPassState.Commit(pCtx);
}

Expand Down
7 changes: 7 additions & 0 deletions PBR/interface/PBR_Renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,8 @@ class PBR_Renderer

static OITResources CreateOITResources(IRenderDevice* pDevice, Uint32 Width, Uint32 Height, Uint32 LayerCount);
OITResources CreateOITResources(Uint32 Width, Uint32 Height) const;
void CreateClearOITLayersSRB(IBuffer* pFrameAttribs, IBuffer* OITLayers, IShaderResourceBinding** ppSRB) const;
void ClearOITLayers(IDeviceContext* pCtx, IShaderResourceBinding* pSRB, Uint32 Width, Uint32 Height) const;

protected:
ShaderMacroHelper DefineMacros(const PSOKey& Key) const;
Expand All @@ -821,6 +823,8 @@ class PBR_Renderer
const PSOKey& Key,
bool AsyncCompile);

void CreateClearOITLayersPSO();

protected:
enum IBL_FEATURE_FLAGS : Uint32
{
Expand Down Expand Up @@ -928,6 +932,9 @@ class PBR_Renderer

std::unordered_map<GraphicsPipelineDesc, PsoHashMapType> m_PSOs;

static constexpr Uint32 ClearOITLayersThreadGroupSize = 16;
RefCntAutoPtr<IPipelineState> m_ClearOITLayersPSO;

std::unique_ptr<StaticShaderTextureIdsArrayType> m_StaticShaderTextureIds;
};

Expand Down
85 changes: 84 additions & 1 deletion PBR/src/PBR_Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,11 @@ PBR_Renderer::PBR_Renderer(IRenderDevice* pDevice,
LOG_WARNING_MESSAGE("OIT is disabled because the device does not support compute shaders");
m_Settings.OITLayerCount = 0;
}

if (m_Settings.OITLayerCount > 0)
{
CreateClearOITLayersPSO();
}
}

if (InitSignature)
Expand Down Expand Up @@ -1379,7 +1384,7 @@ ShaderMacroHelper PBR_Renderer::DefineMacros(const PSOKey& Key) const
Macros.Add("DEBUG_VIEW_CLEAR_COAT", static_cast<int>(DebugViewType::ClearCoat));
Macros.Add("DEBUG_VIEW_CLEAR_COAT_FACTOR", static_cast<int>(DebugViewType::ClearCoatFactor));
Macros.Add("DEBUG_VIEW_CLEAR_COAT_ROUGHNESS", static_cast<int>(DebugViewType::ClearCoatRoughness));
Macros.Add("DEBUG_VIEW_CLEAR_COAT_NORMAL", static_cast<int>(DebugViewType::ClearCoatNormal));
Macros.Add("DEBUG_VIEW_CLEAR_COAT_NORMAL", static_cast<int>(DebugViewType::ClearCoatNormal));
Macros.Add("DEBUG_VIEW_SHEEN", static_cast<int>(DebugViewType::Sheen));
Macros.Add("DEBUG_VIEW_SHEEN_COLOR", static_cast<int>(DebugViewType::SheenColor));
Macros.Add("DEBUG_VIEW_SHEEN_ROUGHNESS", static_cast<int>(DebugViewType::SheenRoughness));
Expand Down Expand Up @@ -2142,6 +2147,84 @@ IPipelineState* PBR_Renderer::GetPSO(PsoHashMapType& PsoHashMap,
return it != PsoHashMap.end() ? it->second.RawPtr() : nullptr;
}


void PBR_Renderer::CreateClearOITLayersPSO()
{
ComputePipelineStateCreateInfoX PsoCI{"Clear OIT Layers"};

ShaderMacroHelper Macros;
Macros.Add("THREAD_GROUP_SIZE", static_cast<int>(ClearOITLayersThreadGroupSize));
Macros.Add("NUM_OIT_LAYERS", static_cast<int>(m_Settings.OITLayerCount));

ShaderCreateInfo ShaderCI{
"ClearOITLayers.csh",
&DiligentFXShaderSourceStreamFactory::GetInstance(),
"main",
Macros,
SHADER_SOURCE_LANGUAGE_HLSL,
{"PBR VS", SHADER_TYPE_COMPUTE, true},
};
ShaderCI.CompileFlags = m_Settings.PackMatrixRowMajor ? SHADER_COMPILE_FLAG_PACK_MATRIX_ROW_MAJOR : SHADER_COMPILE_FLAG_NONE;

RefCntAutoPtr<IShader> pCS = m_Device.CreateShader(ShaderCI);
if (!pCS)
{
LOG_ERROR_MESSAGE("Failed to create clear OIT layers compute shader");
return;
}

PsoCI.AddShader(pCS);
PsoCI.PSODesc.ResourceLayout.DefaultVariableType = SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE;

m_ClearOITLayersPSO = m_Device.CreateComputePipelineState(PsoCI);
if (!m_ClearOITLayersPSO)
{
LOG_ERROR_MESSAGE("Failed to create clear OIT layers PSO");
}
}

void PBR_Renderer::CreateClearOITLayersSRB(IBuffer* pFrameAttribs, IBuffer* OITLayers, IShaderResourceBinding** ppSRB) const
{
if (!m_ClearOITLayersPSO)
{
LOG_ERROR_MESSAGE("Clear OIT layers PSO is not initialized");
return;
}

m_ClearOITLayersPSO->CreateShaderResourceBinding(ppSRB, true);
VERIFY_EXPR(*ppSRB);
(*ppSRB)->GetVariableByName(SHADER_TYPE_COMPUTE, "cbFrameAttribs")->Set(pFrameAttribs);
(*ppSRB)->GetVariableByName(SHADER_TYPE_COMPUTE, "g_rwOITLayers")->Set(OITLayers->GetDefaultView(BUFFER_VIEW_UNORDERED_ACCESS));
}

void PBR_Renderer::ClearOITLayers(IDeviceContext* pCtx, IShaderResourceBinding* pSRB, Uint32 Width, Uint32 Height) const
{
if (!m_ClearOITLayersPSO)
{
LOG_ERROR_MESSAGE("Clear OIT layers PSO is not initialized");
return;
}
if (pCtx == nullptr)
{
DEV_ERROR("pCtx must not be null");
return;
}
if (pSRB == nullptr)
{
DEV_ERROR("pSRB must not be null");
return;
}

pCtx->SetPipelineState(m_ClearOITLayersPSO);
pCtx->CommitShaderResources(pSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
DispatchComputeAttribs DispatchAttrs{
(Width + ClearOITLayersThreadGroupSize - 1) / ClearOITLayersThreadGroupSize,
(Height + ClearOITLayersThreadGroupSize - 1) / ClearOITLayersThreadGroupSize,
1,
};
pCtx->DispatchCompute(DispatchAttrs);
}

void PBR_Renderer::SetInternalShaderParameters(HLSL::PBRRendererShaderParameters& Renderer)
{
Renderer.PrefilteredCubeLastMip = m_Settings.EnableIBL ? static_cast<float>(m_pPrefilteredEnvMapSRV->GetTexture()->GetDesc().MipLevels - 1) : 0.f;
Expand Down
23 changes: 23 additions & 0 deletions Shaders/Common/public/OIT.fxh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
uint PackOITLayer(float Depth, float Transmittance)
{
// Pack depth into the high 24 bits so that packed values
// can be sorted by depth.
uint D = uint(clamp(Depth, 0.0, 1.0) * 16777215.0);
uint T = uint(clamp(Transmittance, 0.0, 1.0) * 255.0);
return (D << 8u) | T;
}

uint GetOITLayerDepth(uint Layer)
{
return Layer >> 8u;
}

float GetOITLayerTransmittance(uint Layer)
{
return float(Layer & 0xFFu) / 255.0;
}

uint GetOITLayerDataOffset(uint2 PixelCoord, uint2 ScreenSize, uint NumLayers)
{
return (PixelCoord.y * ScreenSize.x + PixelCoord.x) * NumLayers;
}
24 changes: 24 additions & 0 deletions Shaders/PBR/private/ClearOITLayers.csh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include "OIT.fxh"
#include "BasicStructures.fxh"

cbuffer cbFrameAttribs
{
CameraAttribs g_Camera;
}

RWStructuredBuffer<uint> g_rwOITLayers;

[numthreads(THREAD_GROUP_SIZE, THREAD_GROUP_SIZE, 1)]
void main(uint3 ThreadID : SV_DispatchThreadID)
{
uint2 ScreenSize = uint2(g_Camera.f4ViewportSize.x, g_Camera.f4ViewportSize.y);
if (ThreadID.x >= ScreenSize.x ||
ThreadID.y >= ScreenSize.y)
return;

uint Offset = GetOITLayerDataOffset(ThreadID.xy, ScreenSize, uint(NUM_OIT_LAYERS));
for (uint layer = 0; layer < uint(NUM_OIT_LAYERS); ++layer)
{
g_rwOITLayers[Offset + layer] = 0xFFFFFFFFu;
}
}

0 comments on commit 3225fda

Please sign in to comment.