@@ -83,11 +83,13 @@ void HnBeginOITPassTask::Prepare(pxr::HdTaskContext* TaskCtx,
8383 {
8484 FrameTargets->OIT = {};
8585 m_ClearLayersSRB.Release ();
86- m_RWLayersSRB. Release () ;
86+ m_RWLayersSRBs = {} ;
8787 }
8888 }
8989
9090 HnRenderDelegate* RenderDelegate = static_cast <HnRenderDelegate*>(RenderIndex->GetRenderDelegate ());
91+ IRenderDevice* pDevice = RenderDelegate->GetDevice ();
92+ const bool IsWebGPUDevice = pDevice->GetDeviceInfo ().IsWebGPUDevice ();
9193
9294 const USD_Renderer& Renderer = *RenderDelegate->GetUSDRenderer ();
9395 VERIFY_EXPR (Renderer.GetSettings ().OITLayerCount > 0 );
@@ -103,7 +105,9 @@ void HnBeginOITPassTask::Prepare(pxr::HdTaskContext* TaskCtx,
103105 bool UseReverseDepth = false ;
104106 GetTaskContextData (TaskCtx, HnRenderResourceTokens->useReverseDepth , UseReverseDepth);
105107
106- const TEXTURE_FORMAT DepthFormat = FrameTargets->DepthDSV ->GetTexture ()->GetDesc ().Format ;
108+ const TEXTURE_FORMAT DepthFormat = !IsWebGPUDevice ?
109+ FrameTargets->DepthDSV ->GetDesc ().Format :
110+ TEX_FORMAT_UNKNOWN;
107111 if (m_RenderPassState.GetDepthStencilFormat () != DepthFormat ||
108112 m_RenderPassState.GetUseReverseDepth () != UseReverseDepth)
109113 {
@@ -122,7 +126,10 @@ void HnBeginOITPassTask::Prepare(pxr::HdTaskContext* TaskCtx,
122126 0 , // Unused
123127 1 , // Total tail transmittance
124128 };
125- m_RenderPassState.Begin (_countof (OITRTVs), OITRTVs, FrameTargets->DepthDSV , &TailClearValue, 0 , 0x01u );
129+ // WebGPU does not support the earlydepthstencil attribute, so we have to
130+ // perform depth testing manually in the shader.
131+ ITextureView* pDepthDSV = !IsWebGPUDevice ? FrameTargets->DepthDSV : nullptr ;
132+ m_RenderPassState.Begin (_countof (OITRTVs), OITRTVs, pDepthDSV, &TailClearValue, 0 , 0x01u );
126133
127134 const HnCamera* pCamera = nullptr ;
128135 if (GetTaskContextData (TaskCtx, HnRenderResourceTokens->camera , pCamera))
@@ -177,13 +184,16 @@ void HnBeginOITPassTask::Execute(pxr::HdTaskContext* TaskCtx)
177184 }
178185
179186 HnRenderDelegate* RenderDelegate = static_cast <HnRenderDelegate*>(m_RenderIndex->GetRenderDelegate ());
187+ IRenderDevice* pDevice = RenderDelegate->GetDevice ();
188+ const bool IsWebGPUDevice = pDevice->GetDeviceInfo ().IsWebGPUDevice ();
180189 IDeviceContext* pCtx = RenderDelegate->GetDeviceContext ();
181190
182- HnRenderParam* RenderParam = static_cast <HnRenderParam*>(RenderDelegate->GetRenderParam ());
183- if (m_BoundOITResourcesVersion != RenderParam->GetAttribVersion (HnRenderParam::GlobalAttrib::OITResources))
191+ const HnRenderParam* RenderParam = static_cast <HnRenderParam*>(RenderDelegate->GetRenderParam ());
192+ const Uint32 OITResourcesVersion = RenderParam->GetAttribVersion (HnRenderParam::GlobalAttrib::OITResources);
193+ if (m_BoundOITResourcesVersion != OITResourcesVersion)
184194 {
185195 BindOITResources (RenderDelegate);
186- m_BoundOITResourcesVersion = RenderParam-> GetAttribVersion (HnRenderParam::GlobalAttrib::OITResources) ;
196+ m_BoundOITResourcesVersion = OITResourcesVersion ;
187197 }
188198
189199 ScopedDebugGroup DebugGroup{pCtx, " Begin OIT pass" };
@@ -193,16 +203,28 @@ void HnBeginOITPassTask::Execute(pxr::HdTaskContext* TaskCtx)
193203 {
194204 Renderer.CreateClearOITLayersSRB (RenderDelegate->GetFrameAttribsCB (), m_FrameTargets->OIT .Layers , &m_ClearLayersSRB);
195205 }
196- if (!m_RWLayersSRB)
206+
207+ // For WebGPU, we need to ping-pong between two SRBs using odd/even frame depth buffers.
208+ // Other APIs can use a single SRB since they support early depth testing.
209+ RefCntAutoPtr<IShaderResourceBinding>& RWLayersSRB = m_RWLayersSRBs[IsWebGPUDevice ? (RenderParam->GetFrameNumber () & 0x01 ) : 0 ];
210+ if (!RWLayersSRB)
197211 {
198- Renderer.CreateRWOITLayersSRB (m_FrameTargets->OIT .Layers , &m_RWLayersSRB);
212+ ITextureView* pDepthSRV = nullptr ;
213+ if (IsWebGPUDevice)
214+ {
215+ // WebGPU does not support the earlydepthstencil attribute, so we have to
216+ // perform depth testing manually in the shader.
217+ pDepthSRV = m_FrameTargets->DepthDSV ->GetTexture ()->GetDefaultView (TEXTURE_VIEW_SHADER_RESOURCE);
218+ DEV_CHECK_ERR (pDepthSRV != nullptr , " Depth buffer shader resource view is null" );
219+ }
220+ Renderer.CreateRWOITLayersSRB (m_FrameTargets->OIT .Layers , pDepthSRV, &RWLayersSRB);
199221 }
200222 const TextureDesc& OITTailDesc = m_FrameTargets->OIT .Tail ->GetDesc ();
201223 Renderer.ClearOITLayers (pCtx, m_ClearLayersSRB, OITTailDesc.Width , OITTailDesc.Height );
202224
203225 IShaderResourceBinding* pFrameAttribsSRB = RenderDelegate->GetFrameAttribsSRB (HnRenderDelegate::FrameAttribsSRBType::Opaque);
204226 m_RenderPassState.SetFrameAttribsSRB (pFrameAttribsSRB);
205- m_RenderPassState.SetRWOITLayersSRB (m_RWLayersSRB );
227+ m_RenderPassState.SetRWOITLayersSRB (RWLayersSRB );
206228 m_RenderPassState.Commit (pCtx);
207229}
208230
0 commit comments