Skip to content

Commit 296edc3

Browse files
PBR Renderer: implemented OIT layers rendering
1 parent 3225fda commit 296edc3

File tree

8 files changed

+138
-10
lines changed

8 files changed

+138
-10
lines changed

Hydrogent/interface/HnRenderPassState.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,15 @@ class HnRenderPassState final : public pxr::HdRenderPassState
8484
return m_FrameAttribsSRB;
8585
}
8686

87+
void SetRWOITLayersSRB(IShaderResourceBinding* pSRB)
88+
{
89+
m_RWOITLayersSRB = pSRB;
90+
}
91+
IShaderResourceBinding* GetRWOITLayersSRB() const
92+
{
93+
return m_RWOITLayersSRB;
94+
}
95+
8796
void SetFrontFaceCCW(bool FrontFaceCCW)
8897
{
8998
m_FrontFaceCCW = FrontFaceCCW;
@@ -144,6 +153,7 @@ class HnRenderPassState final : public pxr::HdRenderPassState
144153
TEXTURE_FORMAT m_DepthFormat = TEX_FORMAT_UNKNOWN;
145154

146155
IShaderResourceBinding* m_FrameAttribsSRB = nullptr;
156+
IShaderResourceBinding* m_RWOITLayersSRB = nullptr;
147157

148158
std::array<ITextureView*, MAX_RENDER_TARGETS> m_RTVs = {};
149159
ITextureView* m_DSV = nullptr;

Hydrogent/interface/Tasks/HnBeginOITPassTask.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class HnBeginOITPassTask final : public HnTask
8080
HnRenderPassState m_RenderPassState;
8181

8282
RefCntAutoPtr<IShaderResourceBinding> m_ClearLayersSRB;
83+
RefCntAutoPtr<IShaderResourceBinding> m_RWLayersSRB;
8384

8485
Uint32 m_BoundOITResourcesVersion = ~0u;
8586
};

Hydrogent/src/HnRenderPass.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ struct HnRenderPass::RenderState
114114

115115
IDeviceContext* const pCtx;
116116

117-
const USD_Renderer::ALPHA_MODE AlphaMode;
117+
const USD_Renderer::RenderPassType Type;
118+
const USD_Renderer::ALPHA_MODE AlphaMode;
118119

119120
const Uint32 ConstantBufferOffsetAlignment;
120121
const bool NativeMultiDrawSupported;
@@ -129,6 +130,7 @@ struct HnRenderPass::RenderState
129130
USDRenderer{*RenderDelegate.GetUSDRenderer()},
130131
RendererSettings{USDRenderer.GetSettings()},
131132
pCtx{RenderDelegate.GetDeviceContext()},
133+
Type{RenderPass.m_Params.Type},
132134
AlphaMode{MaterialTagToPbrAlphaMode(RenderPass.m_MaterialTag)},
133135
ConstantBufferOffsetAlignment{RenderDelegate.GetDevice()->GetAdapterInfo().Buffer.ConstantBufferOffsetAlignment},
134136
NativeMultiDrawSupported{RenderDelegate.GetDevice()->GetDeviceInfo().Features.NativeMultiDraw == DEVICE_FEATURE_STATE_ENABLED}
@@ -170,6 +172,13 @@ struct HnRenderPass::RenderState
170172
pCtx->CommitShaderResources(pFrameSRB, RESOURCE_STATE_TRANSITION_MODE_VERIFY);
171173
}
172174

175+
if (Type == PBR_Renderer::RenderPassType::OITLayers && pRWOITLayersSRB == nullptr)
176+
{
177+
pRWOITLayersSRB = RPState.GetRWOITLayersSRB();
178+
VERIFY_EXPR(pRWOITLayersSRB != nullptr);
179+
pCtx->CommitShaderResources(pRWOITLayersSRB, RESOURCE_STATE_TRANSITION_MODE_VERIFY);
180+
}
181+
173182
pCtx->CommitShaderResources(pNewSRB, RESOURCE_STATE_TRANSITION_MODE_VERIFY);
174183
pMaterialSRB = pNewSRB;
175184
}
@@ -221,9 +230,10 @@ struct HnRenderPass::RenderState
221230
}
222231

223232
private:
224-
IPipelineState* pPSO = nullptr;
225-
IShaderResourceBinding* pMaterialSRB = nullptr;
226-
IShaderResourceBinding* pFrameSRB = nullptr;
233+
IPipelineState* pPSO = nullptr;
234+
IShaderResourceBinding* pMaterialSRB = nullptr;
235+
IShaderResourceBinding* pFrameSRB = nullptr;
236+
IShaderResourceBinding* pRWOITLayersSRB = nullptr;
227237

228238
IBuffer* pIndexBuffer = nullptr;
229239

Hydrogent/src/Tasks/HnBeginOITPassTask.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ void HnBeginOITPassTask::Prepare(pxr::HdTaskContext* TaskCtx,
8383
{
8484
FrameTargets->OIT = {};
8585
m_ClearLayersSRB.Release();
86+
m_RWLayersSRB.Release();
8687
}
8788
}
8889

@@ -192,11 +193,16 @@ void HnBeginOITPassTask::Execute(pxr::HdTaskContext* TaskCtx)
192193
{
193194
Renderer.CreateClearOITLayersSRB(RenderDelegate->GetFrameAttribsCB(), m_FrameTargets->OIT.Layers, &m_ClearLayersSRB);
194195
}
196+
if (!m_RWLayersSRB)
197+
{
198+
Renderer.CreateRWOITLayersSRB(m_FrameTargets->OIT.Layers, &m_RWLayersSRB);
199+
}
195200
const TextureDesc& OITTailDesc = m_FrameTargets->OIT.Tail->GetDesc();
196201
Renderer.ClearOITLayers(pCtx, m_ClearLayersSRB, OITTailDesc.Width, OITTailDesc.Height);
197202

198203
IShaderResourceBinding* pFrameAttribsSRB = RenderDelegate->GetFrameAttribsSRB(HnRenderDelegate::FrameAttribsSRBType::OITLayers);
199204
m_RenderPassState.SetFrameAttribsSRB(pFrameAttribsSRB);
205+
m_RenderPassState.SetRWOITLayersSRB(m_RWLayersSRB);
200206
m_RenderPassState.Commit(pCtx);
201207
}
202208

PBR/interface/PBR_Renderer.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,7 @@ class PBR_Renderer
796796
static OITResources CreateOITResources(IRenderDevice* pDevice, Uint32 Width, Uint32 Height, Uint32 LayerCount);
797797
OITResources CreateOITResources(Uint32 Width, Uint32 Height) const;
798798
void CreateClearOITLayersSRB(IBuffer* pFrameAttribs, IBuffer* OITLayers, IShaderResourceBinding** ppSRB) const;
799+
void CreateRWOITLayersSRB(IBuffer* OITLayers, IShaderResourceBinding** ppSRB) const;
799800
void ClearOITLayers(IDeviceContext* pCtx, IShaderResourceBinding* pSRB, Uint32 Width, Uint32 Height) const;
800801

801802
protected:
@@ -932,8 +933,9 @@ class PBR_Renderer
932933

933934
std::unordered_map<GraphicsPipelineDesc, PsoHashMapType> m_PSOs;
934935

935-
static constexpr Uint32 ClearOITLayersThreadGroupSize = 16;
936-
RefCntAutoPtr<IPipelineState> m_ClearOITLayersPSO;
936+
static constexpr Uint32 ClearOITLayersThreadGroupSize = 16;
937+
RefCntAutoPtr<IPipelineState> m_ClearOITLayersPSO;
938+
RefCntAutoPtr<IPipelineResourceSignature> m_RWOITLayersSignature;
937939

938940
std::unique_ptr<StaticShaderTextureIdsArrayType> m_StaticShaderTextureIds;
939941
};

PBR/src/PBR_Renderer.cpp

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,6 +1250,17 @@ void PBR_Renderer::CreateSignature()
12501250
}
12511251

12521252
CreateCustomSignature(std::move(SignatureDesc));
1253+
1254+
if (m_Settings.OITLayerCount > 0)
1255+
{
1256+
PipelineResourceSignatureDescX OITLayersSignDesc{"RW OIT Layers"};
1257+
OITLayersSignDesc
1258+
.SetBindingIndex(static_cast<Uint8>(m_ResourceSignatures.size()))
1259+
.SetUseCombinedTextureSamplers(m_Device.GetDeviceInfo().IsGLDevice())
1260+
.AddResource(SHADER_TYPE_PIXEL, "g_rwOITLayers", SHADER_RESOURCE_TYPE_BUFFER_UAV, SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE);
1261+
m_RWOITLayersSignature = m_Device.CreatePipelineResourceSignature(OITLayersSignDesc);
1262+
VERIFY_EXPR(m_RWOITLayersSignature);
1263+
}
12531264
}
12541265

12551266
void PBR_Renderer::CreateCustomSignature(PipelineResourceSignatureDescX&& SignatureDesc)
@@ -1861,6 +1872,12 @@ void PBR_Renderer::CreatePSO(PsoHashMapType& PsoHashMap,
18611872
Macros.Add("USE_GL_POINT_SIZE", "1");
18621873
}
18631874

1875+
const Uint32 OITLayerCount = (Key.GetType() == RenderPassType::OITLayers) ||
1876+
(Key.GetType() == RenderPassType::Main && Key.GetAlphaMode() == ALPHA_MODE_BLEND) ?
1877+
m_Settings.OITLayerCount :
1878+
0;
1879+
Macros.Add("NUM_OIT_LAYERS", static_cast<int>(OITLayerCount));
1880+
18641881
const bool UseCombinedSamplers = m_Device.GetDeviceInfo().IsGLDevice();
18651882

18661883
const SHADER_COMPILE_FLAGS ShaderCompileFlags =
@@ -1970,14 +1987,24 @@ void PBR_Renderer::CreatePSO(PsoHashMapType& PsoHashMap,
19701987
pPS = m_Device.CreateShader(ShaderCI);
19711988
}
19721989

1973-
GraphicsPipeline = GraphicsDesc;
1990+
GraphicsPipeline = GraphicsDesc;
1991+
if (Key.GetType() == RenderPassType::OITLayers)
1992+
{
1993+
GraphicsPipeline.DepthStencilDesc.DepthWriteEnable = False;
1994+
}
1995+
19741996
GraphicsPipeline.InputLayout = InputLayout;
19751997

19761998
IPipelineResourceSignature* ppSignatures[MAX_RESOURCE_SIGNATURES];
19771999
for (size_t i = 0; i < m_ResourceSignatures.size(); ++i)
19782000
ppSignatures[i] = m_ResourceSignatures[i];
19792001
PSOCreateInfo.ppResourceSignatures = ppSignatures;
19802002
PSOCreateInfo.ResourceSignaturesCount = static_cast<Uint32>(m_ResourceSignatures.size());
2003+
if (Key.GetType() == RenderPassType::OITLayers)
2004+
{
2005+
ppSignatures[PSOCreateInfo.ResourceSignaturesCount] = m_RWOITLayersSignature;
2006+
++PSOCreateInfo.ResourceSignaturesCount;
2007+
}
19812008

19822009
PSOCreateInfo.pVS = pVS;
19832010
PSOCreateInfo.pPS = pPS;
@@ -2193,8 +2220,21 @@ void PBR_Renderer::CreateClearOITLayersSRB(IBuffer* pFrameAttribs, IBuffer* OITL
21932220

21942221
m_ClearOITLayersPSO->CreateShaderResourceBinding(ppSRB, true);
21952222
VERIFY_EXPR(*ppSRB);
2196-
(*ppSRB)->GetVariableByName(SHADER_TYPE_COMPUTE, "cbFrameAttribs")->Set(pFrameAttribs);
2197-
(*ppSRB)->GetVariableByName(SHADER_TYPE_COMPUTE, "g_rwOITLayers")->Set(OITLayers->GetDefaultView(BUFFER_VIEW_UNORDERED_ACCESS));
2223+
ShaderResourceVariableX{*ppSRB, SHADER_TYPE_COMPUTE, "cbFrameAttribs"}.Set(pFrameAttribs);
2224+
ShaderResourceVariableX{*ppSRB, SHADER_TYPE_COMPUTE, "g_rwOITLayers"}.Set(OITLayers->GetDefaultView(BUFFER_VIEW_UNORDERED_ACCESS));
2225+
}
2226+
2227+
void PBR_Renderer::CreateRWOITLayersSRB(IBuffer* OITLayers, IShaderResourceBinding** ppSRB) const
2228+
{
2229+
if (!m_RWOITLayersSignature)
2230+
{
2231+
LOG_ERROR_MESSAGE("RW OIT Layers signature is not initialized");
2232+
return;
2233+
}
2234+
2235+
m_RWOITLayersSignature->CreateShaderResourceBinding(ppSRB, true);
2236+
VERIFY_EXPR(*ppSRB);
2237+
ShaderResourceVariableX{*ppSRB, SHADER_TYPE_PIXEL, "g_rwOITLayers"}.Set(OITLayers->GetDefaultView(BUFFER_VIEW_UNORDERED_ACCESS));
21982238
}
21992239

22002240
void PBR_Renderer::ClearOITLayers(IDeviceContext* pCtx, IShaderResourceBinding* pSRB, Uint32 Width, Uint32 Height) const

Shaders/Common/public/OIT.fxh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,6 @@ uint GetOITLayerDataOffset(uint2 PixelCoord, uint2 ScreenSize, uint NumLayers)
2121
{
2222
return (PixelCoord.y * ScreenSize.x + PixelCoord.x) * NumLayers;
2323
}
24+
25+
// Opacity is stored as 8-bit value. Any value less than 1/255 is flushed to 0.
26+
#define OIT_OPACITY_THRESHOLD (1.0/255.0)

Shaders/PBR/private/UpdateOITLayers.psh

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "VSOutputStruct.generated"
66

77
#include "PBR_Textures.fxh"
8+
#include "OIT.fxh"
89

910
cbuffer cbFrameAttribs
1011
{
@@ -31,17 +32,72 @@ cbuffer cbMaterialAttribs
3132
PBRMaterialShaderInfo g_Material;
3233
}
3334

35+
// WebGPU does not support the earlydepthstencil attribute, so we have
36+
// to manually perform the depth test in the shader.
37+
#if USE_MANUAL_DEPTH_TEST
38+
Texture2D<float> g_DepthBuffer;
39+
#endif
40+
41+
RWStructuredBuffer<uint> g_rwOITLayers;
42+
3443
struct PSOutput
3544
{
3645
float4 Color : SV_Target0;
3746
};
3847

48+
// By default, early depth stencil will be disabled for this shader because it writes to a UAV.
49+
// Force it to be enabled.
50+
[earlydepthstencil]
3951
PSOutput main(in VSOutput VSOut,
4052
in bool IsFrontFace : SV_IsFrontFace)
4153
{
54+
float D = VSOut.ClipPos.z;
55+
#if USE_MANUAL_DEPTH_TEST
56+
if (D >= g_DepthBuffer.Load(int3(VSOut.ClipPos.xy, 0)))
57+
{
58+
discard;
59+
}
60+
#endif
61+
4262
float4 BaseColor = GetBaseColor(VSOut, g_Material, g_Frame.Renderer.MipBias, PRIMITIVE.FallbackColor);
4363

64+
float A = BaseColor.a;
65+
uint Layer = 0xFFFFFFFFu;
66+
if (A > OIT_OPACITY_THRESHOLD)
67+
{
68+
float T = 1.0 - A; // Transmittance
69+
Layer = PackOITLayer(D, T);
70+
uint Offset = GetOITLayerDataOffset(uint2(VSOut.ClipPos.xy), uint2(g_Frame.Camera.f4ViewportSize.xy), uint(NUM_OIT_LAYERS));
71+
for (uint i = 0; i < uint(NUM_OIT_LAYERS); ++i)
72+
{
73+
uint OrigLayer;
74+
InterlockedMin(g_rwOITLayers[Offset + i], Layer, OrigLayer);
75+
if (OrigLayer == 0xFFFFFFFFu || // Empty space
76+
OrigLayer == Layer) // Layer matches another one exactly
77+
{
78+
// Do not update tail transmittance
79+
Layer = 0xFFFFFFFFu;
80+
break;
81+
}
82+
// Layer > OrigLayer: we did not insert the layer
83+
// Layer < OrigLayer: we inserted the layer, so now we need to insert the original layer
84+
Layer = max(Layer, OrigLayer);
85+
}
86+
}
87+
4488
PSOutput PSOut;
45-
PSOut.Color = BaseColor;
89+
90+
// RGB Blend: Src * 1 + Dst * 1
91+
// A Blend: Src * 0 + Dst * SrcA
92+
if (Layer == 0xFFFFFFFFu)
93+
{
94+
PSOut.Color = float4(0.0, 0.0, 0.0, 1.0);
95+
}
96+
else
97+
{
98+
float TailT = GetOITLayerTransmittance(Layer);
99+
PSOut.Color = float4(1.0 / 255.0, 0.0, 0.0, TailT);
100+
}
101+
46102
return PSOut;
47103
}

0 commit comments

Comments
 (0)