Repository: google/filament
File: filament/backend/src/webgpu/WebGPUHandles.cpp (C++)

Code before:
                .stencilClearValue = params.clearStencil,
                .stencilReadOnly = (params.readOnlyDepthStencil & RenderPassParams::READONLY_STENCIL) > 0,
            };
            mHasDepthStencilAttachment = true;
        }
    } else { // Custom Render Target
        for (uint32_t i = 0; i < customColorTextureViewCount; ++i) {
            if (customColorTextureViews[i]) {
                wgpu::RenderPassColorAttachment colorAttDesc{};

                colorAttDesc.view = customColorTextureViews[i];
//                colorAttDesc.resolveTarget = customColorTextureViews[i];;// TODO: MSAA resolve for custom RT
                colorAttDesc.loadOp =
                        WGPURenderTarget::getLoadOperation(params, getTargetBufferFlagsAt(i));
                colorAttDesc.storeOp =
                        WGPURenderTarget::getStoreOperation(params, getTargetBufferFlagsAt(i));
                colorAttDesc.clearValue = {
                    .r = params.clearColor.r,
                    .g = params.clearColor.g,
                    .b = params.clearColor.b,
                    .a = params.clearColor.a };
                mColorAttachmentDescriptors.push_back(colorAttDesc);
            }
        }

        wgpu::TextureView combinedDsView = customDepthTextureView ? customDepthTextureView : customStencilTextureView;

        if (combinedDsView) {
            mDepthStencilAttachmentDescriptor = {};
            mDepthStencilAttachmentDescriptor.view = combinedDsView;

            if (customDepthTextureView) {
                mDepthStencilAttachmentDescriptor.depthLoadOp = WGPURenderTarget::getLoadOperation(params, TargetBufferFlags::DEPTH);
                mDepthStencilAttachmentDescriptor.depthStoreOp = WGPURenderTarget::getStoreOperation(params, TargetBufferFlags::DEPTH);
                mDepthStencilAttachmentDescriptor.depthClearValue = static_cast<float>(params.clearDepth);
                mDepthStencilAttachmentDescriptor.depthReadOnly = (params.readOnlyDepthStencil & RenderPassParams::READONLY_DEPTH) > 0;
            } else {

                mDepthStencilAttachmentDescriptor.depthLoadOp = wgpu::LoadOp::Undefined;
                mDepthStencilAttachmentDescriptor.depthStoreOp = wgpu::StoreOp::Undefined;
                mDepthStencilAttachmentDescriptor.depthReadOnly = true;
            }

            if (customStencilTextureView) {
                mDepthStencilAttachmentDescriptor.stencilLoadOp = WGPURenderTarget::getLoadOperation(params, TargetBufferFlags::STENCIL);
                mDepthStencilAttachmentDescriptor.stencilStoreOp = WGPURenderTarget::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;

Review comment (suggestion):
SHOULDN'T getting BOTH a texture view AND a stencil view be INVALID?
this is because WebGPU only allows ONE view for the render pass depth/stencil attachment

valid possibilities:
- depth texture view with depth+stencil + no stencil texture view (depth + stencil)
- depth texture view with depth + no stencil texture view (depth only)
- no depth texture view + stencil texture view (stencil only)

INVALID possibilities?
- depth texture view with depth+stencil + stencil texture view (depth + stencil) (stencil texture view should be ignored?)
- depth texture view with depth + stencil texture view (depth + stencil) (but we HAVE TO IGNORE the stencil texture view)

thus:
has depth == has depth texture view
has stencil == has depth texture view with stencil bit (check depth format) OR has stencil texture view

Code after:

        FILAMENT_CHECK_POSTCONDITION(!(customDepthTextureView && customStencilTextureView))
                << "WebGPU CANNOT support separate texture views for depth + stencil. depth + "
                   "stencil needs to be in one texture view";

        const bool hasStencil =
                customStencilTextureView ||
                (customDepthFormat == wgpu::TextureFormat::Depth24PlusStencil8 ||
                        customDepthFormat == wgpu::TextureFormat::Depth32FloatStencil8);

        const bool hasDepth =
                customDepthTextureView ||
                (customStencilFormat == wgpu::TextureFormat::Depth24PlusStencil8 ||
                        customDepthFormat == wgpu::TextureFormat::Depth32FloatStencil8);

        if (customDepthTextureView || customStencilTextureView) {
            assert_invariant((hasDepth || hasStencil) &&
                             "Depth or Texture view without a valid texture format");
            mDepthStencilAttachmentDescriptor = {};
            mDepthStencilAttachmentDescriptor.view =
                    customDepthTextureView ? customDepthTextureView : customStencilTextureView;

            if (hasDepth) {
                mDepthStencilAttachmentDescriptor.depthLoadOp =
                        WGPURenderTarget::getLoadOperation(params, TargetBufferFlags::DEPTH);
                mDepthStencilAttachmentDescriptor.depthStoreOp =
                        WGPURenderTarget::getStoreOperation(params, TargetBufferFlags::DEPTH);
                mDepthStencilAttachmentDescriptor.depthClearValue =
                        static_cast<float>(params.clearDepth);
                mDepthStencilAttachmentDescriptor.depthReadOnly =
                        (params.readOnlyDepthStencil & RenderPassParams::READONLY_DEPTH) > 0;
            } else {
                mDepthStencilAttachmentDescriptor.depthLoadOp = wgpu::LoadOp::Undefined;
                mDepthStencilAttachmentDescriptor.depthStoreOp = wgpu::StoreOp::Undefined;
                mDepthStencilAttachmentDescriptor.depthReadOnly = true;
            }

            if (hasStencil) {
                mDepthStencilAttachmentDescriptor.stencilLoadOp =
                        WGPURenderTarget::getLoadOperation(params, TargetBufferFlags::STENCIL);
                mDepthStencilAttachmentDescriptor.stencilStoreOp =
                        WGPURenderTarget::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;
            }
            mHasDepthStencilAttachment = true;