From 8304cd9c32cd38c0f7e2b1deea93bebd1a3a0e1a Mon Sep 17 00:00:00 2001 From: Jeremy Nelson Date: Mon, 16 Jun 2025 15:21:33 -0700 Subject: [PATCH] simplified attachment logic --- filament/backend/src/webgpu/WebGPUDriver.cpp | 25 ++-- .../src/webgpu/WebGPUPipelineCreation.cpp | 4 +- .../src/webgpu/WebGPUPipelineCreation.h | 2 +- .../backend/src/webgpu/WebGPURenderTarget.cpp | 136 +++++++++--------- .../backend/src/webgpu/WebGPURenderTarget.h | 17 ++- filament/backend/src/webgpu/WebGPUSwapChain.h | 2 - 6 files changed, 94 insertions(+), 92 deletions(-) diff --git a/filament/backend/src/webgpu/WebGPUDriver.cpp b/filament/backend/src/webgpu/WebGPUDriver.cpp index be0bdbf191..89c20c5f5d 100644 --- a/filament/backend/src/webgpu/WebGPUDriver.cpp +++ b/filament/backend/src/webgpu/WebGPUDriver.cpp @@ -452,7 +452,7 @@ void WebGPUDriver::createDefaultRenderTargetR(Handle renderTarge } void WebGPUDriver::createRenderTargetR(Handle renderTargetHandle, - const TargetBufferFlags targets, const uint32_t width, const uint32_t height, + const TargetBufferFlags targetFlags, const uint32_t width, const uint32_t height, const uint8_t samples, const uint8_t layerCount, const MRT color, const TargetBufferInfo depth, const TargetBufferInfo stencil) { constructHandle(renderTargetHandle, width, height, samples, layerCount, @@ -834,7 +834,7 @@ void WebGPUDriver::beginRenderPass(Handle renderTargetHandle, defaultDepthStencilView = mSwapChain->getDepthTextureView(); defaultDepthStencilFormat = mSwapChain->getDepthFormat(); - if (any(renderTarget->getTargets() & TargetBufferFlags::STENCIL) && + if (any(renderTarget->getTargetFlags() & TargetBufferFlags::STENCIL) && !(defaultDepthStencilFormat == wgpu::TextureFormat::Depth24PlusStencil8 || defaultDepthStencilFormat == wgpu::TextureFormat::Depth32FloatStencil8 || defaultDepthStencilFormat == wgpu::TextureFormat::Stencil8)) { @@ -842,7 +842,7 @@ void WebGPUDriver::beginRenderPass(Handle renderTargetHandle, << (uint32_t)defaultDepthStencilFormat << " does not have a stencil aspect."; } - if (any(renderTarget->getTargets() & TargetBufferFlags::DEPTH) && + if (any(renderTarget->getTargetFlags() & TargetBufferFlags::DEPTH) && !(defaultDepthStencilFormat == wgpu::TextureFormat::Depth16Unorm || defaultDepthStencilFormat == wgpu::TextureFormat::Depth32Float || defaultDepthStencilFormat == wgpu::TextureFormat::Depth24Plus || @@ -893,7 +893,7 @@ void WebGPUDriver::beginRenderPass(Handle renderTargetHandle, customDepthStencilView = dsTexture->getOrMakeTextureView(dsMipLevel, dsArrayLayer); customDepthStencilFormat = dsTexture->getViewFormat(); - if (any(renderTarget->getTargets() & TargetBufferFlags::STENCIL) && + if (any(renderTarget->getTargetFlags() & TargetBufferFlags::STENCIL) && !(customDepthStencilFormat == wgpu::TextureFormat::Depth24PlusStencil8 || customDepthStencilFormat == wgpu::TextureFormat::Depth32FloatStencil8 || @@ -905,7 +905,7 @@ void WebGPUDriver::beginRenderPass(Handle renderTargetHandle, << (uint32_t) customDepthStencilFormat << " does not have a stencil aspect."; } - if (any(renderTarget->getTargets() & TargetBufferFlags::DEPTH) && + if (any(renderTarget->getTargetFlags() & TargetBufferFlags::DEPTH) && !(customDepthStencilFormat == wgpu::TextureFormat::Depth16Unorm || customDepthStencilFormat == wgpu::TextureFormat::Depth32Float || customDepthStencilFormat == @@ -972,18 +972,21 @@ void WebGPUDriver::makeCurrent(Handle drawSch, Handle assert_invariant(mDefaultRenderTarget); wgpu::TextureFormat depthFormat = mSwapChain->getDepthFormat(); - mDefaultRenderTarget->mTargetFlags = filament::backend::TargetBufferFlags::NONE; + TargetBufferFlags newTargetFlags = filament::backend::TargetBufferFlags::NONE; - mDefaultRenderTarget->mTargetFlags |= filament::backend::TargetBufferFlags::COLOR; + newTargetFlags = filament::backend::TargetBufferFlags::NONE; + newTargetFlags |= filament::backend::TargetBufferFlags::COLOR; if (depthFormat != wgpu::TextureFormat::Undefined) { - mDefaultRenderTarget->mTargetFlags |= filament::backend::TargetBufferFlags::DEPTH; + newTargetFlags |= filament::backend::TargetBufferFlags::DEPTH; if (depthFormat == wgpu::TextureFormat::Depth24PlusStencil8 || depthFormat == wgpu::TextureFormat::Depth32FloatStencil8) { - mDefaultRenderTarget->mTargetFlags |= filament::backend::TargetBufferFlags::STENCIL; + newTargetFlags |= filament::backend::TargetBufferFlags::STENCIL; } } + mDefaultRenderTarget->setTargetFlags(newTargetFlags); + wgpu::CommandEncoderDescriptor commandEncoderDescriptor = { .label = "command_encoder" }; mCommandEncoder = mDevice.CreateCommandEncoder(&commandEncoderDescriptor); assert_invariant(mCommandEncoder); @@ -1127,7 +1130,7 @@ void WebGPUDriver::bindPipeline(PipelineState const& pipelineState) { pipelineColorFormats.push_back(mSwapChain->getColorFormat()); pipelineDepthStencilFormat = mSwapChain->getDepthFormat(); pipelineSamples = mCurrentRenderTarget->getSamples(); - requestedStencil = any(mCurrentRenderTarget->getTargets() & TargetBufferFlags::STENCIL); + requestedStencil = any(mCurrentRenderTarget->getTargetFlags() & TargetBufferFlags::STENCIL); } else { const auto& mrtColorAttachments = mCurrentRenderTarget->getColorAttachmentInfos(); for (size_t i = 0; i < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT; ++i) { @@ -1155,7 +1158,7 @@ void WebGPUDriver::bindPipeline(PipelineState const& pipelineState) { } } pipelineSamples = mCurrentRenderTarget->getSamples(); - requestedStencil = any(mCurrentRenderTarget->getTargets() & TargetBufferFlags::STENCIL); + requestedStencil = any(mCurrentRenderTarget->getTargetFlags() & TargetBufferFlags::STENCIL); } // TODO: We expected this to be a sane check, however it complains when running shadowtest. diff --git a/filament/backend/src/webgpu/WebGPUPipelineCreation.cpp b/filament/backend/src/webgpu/WebGPUPipelineCreation.cpp index 40165edf42..90345d5fd8 100644 --- a/filament/backend/src/webgpu/WebGPUPipelineCreation.cpp +++ b/filament/backend/src/webgpu/WebGPUPipelineCreation.cpp @@ -169,7 +169,7 @@ wgpu::RenderPipeline createWebGPURenderPipeline(wgpu::Device const& device, wgpu::PipelineLayout const& layout, RasterState const& rasterState, StencilState const& stencilState, PolygonOffset const& polygonOffset, const PrimitiveType primitiveType, std::vector const& colorFormats, - const wgpu::TextureFormat depthStencilFormat, const uint8_t samplesCount, bool filamentRequestedStencil) { + const wgpu::TextureFormat depthStencilFormat, const uint8_t samplesCount, bool requestedStencil) { assert_invariant(program.vertexShaderModule); wgpu::DepthStencilState depthStencilState{}; @@ -188,7 +188,7 @@ wgpu::RenderPipeline createWebGPURenderPipeline(wgpu::Device const& device, depthStencilState.depthBiasClamp = 0.0f; } - if (hasStencilAspect(depthStencilFormat) && filamentRequestedStencil) { + if (hasStencilAspect(depthStencilFormat) && requestedStencil) { depthStencilState.stencilFront = { .compare = toWebGPU(stencilState.front.stencilFunc), .failOp = toWebGPU(stencilState.front.stencilOpStencilFail), diff --git a/filament/backend/src/webgpu/WebGPUPipelineCreation.h b/filament/backend/src/webgpu/WebGPUPipelineCreation.h index 7e45ce4bc8..987c8fb233 100644 --- a/filament/backend/src/webgpu/WebGPUPipelineCreation.h +++ b/filament/backend/src/webgpu/WebGPUPipelineCreation.h @@ -41,7 +41,7 @@ class WebGPUProgram; WebGPUProgram const&, WebGPUVertexBufferInfo const&, wgpu::PipelineLayout const&, RasterState const&, StencilState const&, PolygonOffset const&, PrimitiveType primitiveType, std::vector const& colorFormats, wgpu::TextureFormat depthFormat, - uint8_t samplesCount, bool filamentRequestedStencil); + uint8_t samplesCount, bool requestedStencil); }// namespace filament::backend diff --git a/filament/backend/src/webgpu/WebGPURenderTarget.cpp b/filament/backend/src/webgpu/WebGPURenderTarget.cpp index d7ac39a74f..598bc98e22 100644 --- a/filament/backend/src/webgpu/WebGPURenderTarget.cpp +++ b/filament/backend/src/webgpu/WebGPURenderTarget.cpp @@ -32,10 +32,10 @@ namespace filament::backend { WebGPURenderTarget::WebGPURenderTarget(const uint32_t width, const uint32_t height, const uint8_t samples, const uint8_t layerCount, MRT const& colorAttachmentsMRT, - Attachment const& depthAttachmentInfo, Attachment const& stencilAttachmentInfo, TargetBufferFlags targetFlags) + Attachment const& depthAttachmentInfo, Attachment const& stencilAttachmentInfo, TargetBufferFlags const& targetFlags) : HwRenderTarget{ width, height }, - mTargetFlags(targetFlags), mDefaultRenderTarget{ false }, + mTargetFlags{ targetFlags }, mSamples{ samples }, mLayerCount{ layerCount }, mColorAttachments{ colorAttachmentsMRT }, @@ -48,8 +48,8 @@ WebGPURenderTarget::WebGPURenderTarget(const uint32_t width, const uint32_t heig // Default constructor for the default render target WebGPURenderTarget::WebGPURenderTarget() : HwRenderTarget{ 0, 0 }, - mTargetFlags(TargetBufferFlags::NONE), mDefaultRenderTarget{ true }, + mTargetFlags{ TargetBufferFlags::NONE }, mSamples{ 1 }, mLayerCount{ 1 } {} @@ -83,27 +83,26 @@ void WebGPURenderTarget::setUpRenderPassAttachments(wgpu::RenderPassDescriptor& const wgpu::TextureFormat customDepthFormat, const wgpu::TextureFormat customStencilFormat) { mColorAttachmentDescriptors.clear(); - mHasDepthStencilAttachment = false; - bool hasDepth = any(mTargetFlags & TargetBufferFlags::DEPTH); - bool hasStencil = any(mTargetFlags & TargetBufferFlags::STENCIL); + const bool hasDepth = any(mTargetFlags & TargetBufferFlags::DEPTH); + const bool hasStencil = any(mTargetFlags & TargetBufferFlags::STENCIL); + mHasDepthStencilAttachment = hasDepth || hasStencil; bool const depthReadOnly = (params.readOnlyDepthStencil & RenderPassParams::READONLY_DEPTH) > 0; + // Color attachments if (mDefaultRenderTarget) { assert_invariant(defaultColorTextureView); - mColorAttachmentDescriptors.push_back({ .view = defaultColorTextureView, + mColorAttachmentDescriptors.push_back({ + .view = defaultColorTextureView, .resolveTarget = nullptr, .loadOp = WebGPURenderTarget::getLoadOperation(params, TargetBufferFlags::COLOR0), .storeOp = WebGPURenderTarget::getStoreOperation(params, TargetBufferFlags::COLOR0), .clearValue = { params.clearColor.r, params.clearColor.g, params.clearColor.b, - params.clearColor.a } }); - - outDescriptor.colorAttachmentCount = mColorAttachmentDescriptors.size(); - outDescriptor.colorAttachments = mColorAttachmentDescriptors.data(); + params.clearColor.a } + }); } else { - outDescriptor.colorAttachmentCount = customColorTextureViewCount; for (uint32_t i = 0; i < customColorTextureViewCount; ++i) { if (customColorTextureViews[i]) { mColorAttachmentDescriptors.push_back({ .view = customColorTextureViews[i], @@ -118,61 +117,60 @@ void WebGPURenderTarget::setUpRenderPassAttachments(wgpu::RenderPassDescriptor& .a = params.clearColor.a } }); } } - outDescriptor.colorAttachmentCount = mColorAttachmentDescriptors.size(); // Set actual count - outDescriptor.colorAttachments = mColorAttachmentDescriptors.data(); + } + outDescriptor.colorAttachmentCount = mColorAttachmentDescriptors.size(); + outDescriptor.colorAttachments = mColorAttachmentDescriptors.data(); + + if(mHasDepthStencilAttachment){ + wgpu::TextureView depthStencilViewToUse; + + if (mDefaultRenderTarget) { + depthStencilViewToUse = defaultDepthStencilTextureView; + assert_invariant(depthStencilViewToUse); + } else { + if (customDepthTextureView || customStencilTextureView) { + // WebGPU requires combined depth/stencil textures. Ensure consistency for custom RTs. + FILAMENT_CHECK_POSTCONDITION( + customDepthTextureView.Get() == customStencilTextureView.Get() || + !customDepthTextureView || !customStencilTextureView) + << "WebGPU backend requires depth and stencil to be in a single texture. " + << "If both are specified, they must refer to the same resource " + "(wgpu::TextureView)."; + + depthStencilViewToUse = customDepthTextureView ? customDepthTextureView : customStencilTextureView; + } + } } - // Depth/Stencil attachment - if (mDefaultRenderTarget) { - if (hasDepth || hasStencil) { - assert_invariant(defaultDepthStencilTextureView); - mDepthStencilAttachmentDescriptor.view = defaultDepthStencilTextureView; + // Depth/Stencil Attachments + if (mHasDepthStencilAttachment) { + wgpu::TextureView depthStencilViewToUse; + if (mDefaultRenderTarget) { + depthStencilViewToUse = defaultDepthStencilTextureView; - if (hasDepth) { - mDepthStencilAttachmentDescriptor.depthLoadOp = depthReadOnly ? wgpu::LoadOp::Undefined : - getLoadOperation(params, TargetBufferFlags::DEPTH); - mDepthStencilAttachmentDescriptor.depthStoreOp = depthReadOnly ? wgpu::StoreOp::Undefined : - getStoreOperation(params, TargetBufferFlags::DEPTH); - mDepthStencilAttachmentDescriptor.depthClearValue = static_cast(params.clearDepth); - mDepthStencilAttachmentDescriptor.depthReadOnly = - (params.readOnlyDepthStencil & RenderPassParams::READONLY_DEPTH) > 0; - } else { - mDepthStencilAttachmentDescriptor.depthLoadOp = wgpu::LoadOp::Undefined; - mDepthStencilAttachmentDescriptor.depthStoreOp = wgpu::StoreOp::Undefined; - mDepthStencilAttachmentDescriptor.depthReadOnly = true; - } + assert_invariant(depthStencilViewToUse); + } else { + if (customDepthTextureView || customStencilTextureView) { - if (hasStencil) { - mDepthStencilAttachmentDescriptor.stencilLoadOp = - getLoadOperation(params, TargetBufferFlags::STENCIL); - mDepthStencilAttachmentDescriptor.stencilStoreOp = - getStoreOperation(params, TargetBufferFlags::STENCIL); - mDepthStencilAttachmentDescriptor.stencilClearValue = params.clearStencil; - mDepthStencilAttachmentDescriptor.stencilReadOnly = - (params.readOnlyDepthStencil & RenderPassParams::READONLY_STENCIL) > 0; - } else { - mDepthStencilAttachmentDescriptor.stencilLoadOp = wgpu::LoadOp::Undefined; - mDepthStencilAttachmentDescriptor.stencilStoreOp = wgpu::StoreOp::Undefined; - mDepthStencilAttachmentDescriptor.stencilReadOnly = true; + FILAMENT_CHECK_POSTCONDITION( + customDepthTextureView.Get() == customStencilTextureView.Get() || + !customDepthTextureView || !customStencilTextureView) + << "WebGPU backend requires depth and stencil to be in a single texture. " + << "If both are specified, they must refer to the same resource " + "(wgpu::TextureView)."; + + depthStencilViewToUse = customDepthTextureView ? customDepthTextureView : customStencilTextureView; } - mHasDepthStencilAttachment = true; } - } else { - if (customDepthTextureView || customStencilTextureView) { - assert_invariant((hasDepth || hasStencil) && - "Depth or Texture view without a valid texture format"); + + if (depthStencilViewToUse) { mDepthStencilAttachmentDescriptor = {}; - mDepthStencilAttachmentDescriptor.view = - customDepthTextureView ? customDepthTextureView : customStencilTextureView; + mDepthStencilAttachmentDescriptor.view = depthStencilViewToUse; if (hasDepth) { - mDepthStencilAttachmentDescriptor.depthLoadOp = depthReadOnly ? wgpu::LoadOp::Undefined : - WebGPURenderTarget::getLoadOperation(params, TargetBufferFlags::DEPTH); - mDepthStencilAttachmentDescriptor.depthStoreOp = - depthReadOnly ? wgpu::StoreOp::Undefined : - WebGPURenderTarget::getStoreOperation(params, TargetBufferFlags::DEPTH); - mDepthStencilAttachmentDescriptor.depthClearValue = - static_cast(params.clearDepth); + mDepthStencilAttachmentDescriptor.depthLoadOp = depthReadOnly ? wgpu::LoadOp::Undefined :getLoadOperation(params, TargetBufferFlags::DEPTH); + mDepthStencilAttachmentDescriptor.depthStoreOp = depthReadOnly ? wgpu::StoreOp::Undefined :getStoreOperation(params, TargetBufferFlags::DEPTH); + mDepthStencilAttachmentDescriptor.depthClearValue = params.clearDepth; mDepthStencilAttachmentDescriptor.depthReadOnly = depthReadOnly; } else { mDepthStencilAttachmentDescriptor.depthLoadOp = wgpu::LoadOp::Undefined; @@ -181,23 +179,27 @@ void WebGPURenderTarget::setUpRenderPassAttachments(wgpu::RenderPassDescriptor& } if (hasStencil) { - mDepthStencilAttachmentDescriptor.stencilLoadOp = - getLoadOperation(params, TargetBufferFlags::STENCIL); - mDepthStencilAttachmentDescriptor.stencilStoreOp = - getStoreOperation(params, TargetBufferFlags::STENCIL); + mDepthStencilAttachmentDescriptor.stencilLoadOp = getLoadOperation(params, TargetBufferFlags::STENCIL); + mDepthStencilAttachmentDescriptor.stencilStoreOp = getStoreOperation(params, TargetBufferFlags::STENCIL); mDepthStencilAttachmentDescriptor.stencilClearValue = params.clearStencil; - mDepthStencilAttachmentDescriptor.stencilReadOnly = - (params.readOnlyDepthStencil & RenderPassParams::READONLY_STENCIL) > 0; + mDepthStencilAttachmentDescriptor.stencilReadOnly = (params.readOnlyDepthStencil & RenderPassParams::READONLY_STENCIL) > 0; } else { mDepthStencilAttachmentDescriptor.stencilLoadOp = wgpu::LoadOp::Undefined; mDepthStencilAttachmentDescriptor.stencilStoreOp = wgpu::StoreOp::Undefined; mDepthStencilAttachmentDescriptor.stencilReadOnly = true; } - mHasDepthStencilAttachment = true; + outDescriptor.depthStencilAttachment = &mDepthStencilAttachmentDescriptor; + + } else { + + outDescriptor.depthStencilAttachment = nullptr; + mDepthStencilAttachmentDescriptor = {}; } + + } else { + outDescriptor.depthStencilAttachment = nullptr; + mDepthStencilAttachmentDescriptor = {}; } - outDescriptor.depthStencilAttachment = - mHasDepthStencilAttachment ? &mDepthStencilAttachmentDescriptor : nullptr; // descriptor.sampleCount was removed from the core spec. If your webgpu.h still has it, // and your Dawn version expects it, you might need to set it here based on this->samples. diff --git a/filament/backend/src/webgpu/WebGPURenderTarget.h b/filament/backend/src/webgpu/WebGPURenderTarget.h index f859d4c23f..8b5aa3f7a9 100644 --- a/filament/backend/src/webgpu/WebGPURenderTarget.h +++ b/filament/backend/src/webgpu/WebGPURenderTarget.h @@ -34,13 +34,13 @@ public: WebGPURenderTarget(uint32_t width, uint32_t height, uint8_t samples, uint8_t layerCount, MRT const& colorAttachments, Attachment const& depthAttachment, - Attachment const& stencilAttachment, TargetBufferFlags targetFlags); + Attachment const& stencilAttachment, TargetBufferFlags const& targetFlags); // Default constructor for the default render target WebGPURenderTarget(); - // Updated signature: takes resolved views for custom RTs, and default views for default RT - void setUpRenderPassAttachments(wgpu::RenderPassDescriptor& outDescriptor, + void setUpRenderPassAttachments( + wgpu::RenderPassDescriptor& outDescriptor, RenderPassParams const& params, // For default render target: wgpu::TextureView const& defaultColorTextureView, @@ -48,7 +48,8 @@ public: wgpu::TextureFormat const& defaultDepthStencilFormat, // For custom render targets: wgpu::TextureView const* customColorTextureViews, // Array of views - uint32_t customColorTextureViewCount, wgpu::TextureView const& customDepthTextureView, + uint32_t customColorTextureViewCount, + wgpu::TextureView const& customDepthTextureView, wgpu::TextureView const& customStencilTextureView, wgpu::TextureFormat customDepthFormat, wgpu::TextureFormat customStencilFormat); @@ -56,23 +57,21 @@ public: [[nodiscard]] uint8_t getSamples() const { return mSamples; } [[nodiscard]] uint8_t getLayerCount() const { return mLayerCount; } - // Accessors for the driver to get stored attachment info [[nodiscard]] MRT const& getColorAttachmentInfos() const { return mColorAttachments; } [[nodiscard]] Attachment const& getDepthAttachmentInfo() const { return mDepthAttachment; } [[nodiscard]] Attachment const& getStencilAttachmentInfo() const { return mStencilAttachment; } - // Static helpers for load/store operations [[nodiscard]] static wgpu::LoadOp getLoadOperation(RenderPassParams const& params, TargetBufferFlags buffer); [[nodiscard]] static wgpu::StoreOp getStoreOperation(RenderPassParams const& params, TargetBufferFlags buffer); - [[nodiscard]] TargetBufferFlags getTargets() const { return mTargetFlags; } - - TargetBufferFlags mTargetFlags = TargetBufferFlags::NONE; + [[nodiscard]] TargetBufferFlags getTargetFlags() const { return mTargetFlags; } + void setTargetFlags( TargetBufferFlags value) { mTargetFlags = value; } private: bool mDefaultRenderTarget = false; + TargetBufferFlags mTargetFlags = TargetBufferFlags::NONE; uint8_t mSamples = 1; uint8_t mLayerCount = 1; diff --git a/filament/backend/src/webgpu/WebGPUSwapChain.h b/filament/backend/src/webgpu/WebGPUSwapChain.h index e62bf85ad2..9b3b796f3b 100644 --- a/filament/backend/src/webgpu/WebGPUSwapChain.h +++ b/filament/backend/src/webgpu/WebGPUSwapChain.h @@ -36,8 +36,6 @@ public: [[nodiscard]] wgpu::TextureFormat getDepthFormat() const { return mDepthFormat; } - [[nodiscard]] bool getNeedStencil() const { return mNeedStencil; } - [[nodiscard]] wgpu::TextureView getCurrentSurfaceTextureView(wgpu::Extent2D const&); [[nodiscard]] wgpu::TextureView getDepthTextureView() const { return mDepthTextureView; }