// Copyright 2021 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <optional>
#include <vector>

#include "dawn/tests/DawnTest.h"
#include "dawn/utils/ComboRenderPipelineDescriptor.h"
#include "dawn/utils/TextureUtils.h"
#include "dawn/utils/WGPUHelpers.h"

namespace dawn {
namespace {

constexpr static uint32_t kSize = 4;

using TextureFormat = wgpu::TextureFormat;
DAWN_TEST_PARAM_STRUCT(ReadOnlyDepthStencilAttachmentTestsParams, TextureFormat);

class ReadOnlyDepthStencilAttachmentTests
    : public DawnTestWithParams<ReadOnlyDepthStencilAttachmentTestsParams> {
  protected:
    void SetUp() override {
        DawnTestWithParams<ReadOnlyDepthStencilAttachmentTestsParams>::SetUp();
        DAWN_TEST_UNSUPPORTED_IF(!mIsFormatSupported);
    }

    std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
        switch (GetParam().mTextureFormat) {
            case wgpu::TextureFormat::Depth32FloatStencil8:
                if (SupportsFeatures({wgpu::FeatureName::Depth32FloatStencil8})) {
                    mIsFormatSupported = true;
                    return {wgpu::FeatureName::Depth32FloatStencil8};
                }

                return {};
            default:
                mIsFormatSupported = true;
                return {};
        }
    }

    struct TestSpec {
        wgpu::TextureAspect readonlyAspects;
        std::optional<wgpu::TextureAspect> sampledAspect = std::nullopt;

        wgpu::CompareFunction depthCompare = wgpu::CompareFunction::Always;
        wgpu::CompareFunction stencilCompare = wgpu::CompareFunction::Always;
        wgpu::OptionalBool depthWriteEnabled = wgpu::OptionalBool::False;
        bool stencilWriteEnabled = false;

        float depthClearValue = 0.0;
        uint32_t stencilClearValue = 0;
        uint32_t stencilRef = 0;

        wgpu::Texture depthStencilTexture;
    };

    wgpu::RenderPipeline CreateRenderPipeline(wgpu::TextureFormat format,
                                              const TestSpec& spec) const {
        utils::ComboRenderPipelineDescriptor pipelineDescriptor;

        // Draw a rectangle via two triangles. The depth value of the top of the rectangle is 0.4.
        // The depth value of the bottom is 0.0. The depth value gradually change from 0.4 to 0.0
        // from the top to the bottom. The top part will compare with the depth values and fail to
        // pass the depth test. The bottom part will compare with the depth values in depth buffer
        // and pass the depth test, and sample from the depth buffer in fragment shader in the same
        // pipeline.
        pipelineDescriptor.vertex.module = utils::CreateShaderModule(device, R"(
            @vertex
            fn main(@builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4f {
                var pos = array(
                    vec3f(-1.0,  1.0, 0.4),
                    vec3f(-1.0, -1.0, 0.0),
                    vec3f( 1.0,  1.0, 0.4),
                    vec3f( 1.0,  1.0, 0.4),
                    vec3f(-1.0, -1.0, 0.0),
                    vec3f( 1.0, -1.0, 0.0));
                return vec4f(pos[VertexIndex], 1.0);
            })");

        wgpu::BindGroupLayout bgl;
        if (!spec.sampledAspect.has_value()) {
            // Draw a solid blue into color buffer if not sample from depth/stencil attachment.
            pipelineDescriptor.cFragment.module = utils::CreateShaderModule(device, R"(
                @fragment fn main() -> @location(0) vec4f {
                    return vec4f(0.0, 0.0, 1.0, 0.0);
                })");
            bgl = utils::MakeBindGroupLayout(device, {});
        } else if (spec.sampledAspect == wgpu::TextureAspect::DepthOnly) {
            // Sample from depth attachment and draw that sampled texel into color buffer.
            if (IsCompatibilityMode()) {
                // Can not use texture_depth_xx with non-comparison sampler in compat mode.
                pipelineDescriptor.cFragment.module = utils::CreateShaderModule(device, R"(
                        @group(0) @binding(0) var samp : sampler;
                        @group(0) @binding(1) var tex : texture_2d<f32>;

                        @fragment
                        fn main(@builtin(position) FragCoord : vec4f) -> @location(0) vec4f {
                            return vec4f(textureSample(tex, samp, FragCoord.xy).r, 0.0, 0.0, 0.0);
                        })");
                bgl = utils::MakeBindGroupLayout(
                    device,
                    {
                        {0, wgpu::ShaderStage::Fragment, wgpu::SamplerBindingType::NonFiltering},
                        {1, wgpu::ShaderStage::Fragment,
                         wgpu::TextureSampleType::UnfilterableFloat},
                    });
            } else {
                pipelineDescriptor.cFragment.module = utils::CreateShaderModule(device, R"(
                        @group(0) @binding(0) var samp : sampler;
                        @group(0) @binding(1) var tex : texture_depth_2d;

                        @fragment
                        fn main(@builtin(position) FragCoord : vec4f) -> @location(0) vec4f {
                            return vec4f(textureSample(tex, samp, FragCoord.xy), 0.0, 0.0, 0.0);
                        })");
                bgl = utils::MakeBindGroupLayout(
                    device,
                    {
                        {0, wgpu::ShaderStage::Fragment, wgpu::SamplerBindingType::NonFiltering},
                        {1, wgpu::ShaderStage::Fragment, wgpu::TextureSampleType::Depth},
                    });
            }
        } else {
            DAWN_ASSERT(spec.sampledAspect == wgpu::TextureAspect::StencilOnly);
            // Sample from stencil attachment and draw that sampled texel into color buffer.
            pipelineDescriptor.cFragment.module = utils::CreateShaderModule(device, R"(
                    @group(0) @binding(0) var samp : sampler;
                    @group(0) @binding(1) var tex : texture_2d<u32>;

                    @fragment
                    fn main(@builtin(position) FragCoord : vec4f) -> @location(0) vec4f {
                        _ = samp;
                        var texel = textureLoad(tex, vec2i(FragCoord.xy), 0);
                        return vec4f(f32(texel[0]) / 255.0, 0.0, 0.0, 0.0);
                    })");
            bgl = utils::MakeBindGroupLayout(
                device,
                {
                    {0, wgpu::ShaderStage::Fragment, wgpu::SamplerBindingType::NonFiltering},
                    {1, wgpu::ShaderStage::Fragment, wgpu::TextureSampleType::Uint},
                });
        }

        wgpu::DepthStencilState* depthStencil = pipelineDescriptor.EnableDepthStencil(format);
        depthStencil->depthCompare = spec.depthCompare;
        depthStencil->depthWriteEnabled = spec.depthWriteEnabled;
        depthStencil->stencilFront.compare = spec.stencilCompare;
        if (spec.stencilWriteEnabled) {
            depthStencil->stencilFront.passOp = wgpu::StencilOperation::Replace;
        }

        wgpu::PipelineLayoutDescriptor plDescriptor;
        plDescriptor.bindGroupLayoutCount = 1;
        plDescriptor.bindGroupLayouts = &bgl;
        pipelineDescriptor.layout = device.CreatePipelineLayout(&plDescriptor);

        return device.CreateRenderPipeline(&pipelineDescriptor);
    }

    struct RenderResult {
        wgpu::Texture color;
        wgpu::Texture depthStencil;
    };
    RenderResult DoRender(const TestSpec& spec) const {
        wgpu::TextureFormat testFormat = GetParam().mTextureFormat;

        // Create or reuse the test textures.
        wgpu::Texture depthStencilTexture = spec.depthStencilTexture;
        if (!depthStencilTexture) {
            wgpu::TextureDescriptor dsTextureDesc = {};
            dsTextureDesc.size = {kSize, kSize, 1};
            dsTextureDesc.format = testFormat;
            dsTextureDesc.usage =
                wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding;
            depthStencilTexture = device.CreateTexture(&dsTextureDesc);
        }

        wgpu::TextureDescriptor colorTextureDesc = {};
        colorTextureDesc.size = {kSize, kSize, 1};
        colorTextureDesc.format = wgpu::TextureFormat::RGBA8Unorm;
        colorTextureDesc.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc;
        wgpu::Texture colorTexture = device.CreateTexture(&colorTextureDesc);

        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();

        // Do a first render pass that writes the initial values to the aspects that will be
        // readonly.
        if (!spec.depthStencilTexture) {
            utils::ComboRenderPassDescriptor passDescriptorInit({},
                                                                depthStencilTexture.CreateView());
            passDescriptorInit.UnsetDepthStencilLoadStoreOpsForFormat(testFormat);
            passDescriptorInit.cDepthStencilAttachmentInfo.depthClearValue = spec.depthClearValue;
            passDescriptorInit.cDepthStencilAttachmentInfo.stencilClearValue =
                spec.stencilClearValue;

            wgpu::RenderPassEncoder passInit = commandEncoder.BeginRenderPass(&passDescriptorInit);
            passInit.End();
        }

        // Do the render pass with the readonly attachment, that will potentially use the pipeline
        // to read and/or write attachments.
        utils::ComboRenderPassDescriptor passDescriptor({colorTexture.CreateView()},
                                                        depthStencilTexture.CreateView());
        passDescriptor.cDepthStencilAttachmentInfo.depthLoadOp = wgpu::LoadOp::Load;
        passDescriptor.cDepthStencilAttachmentInfo.stencilLoadOp = wgpu::LoadOp::Load;
        passDescriptor.UnsetDepthStencilLoadStoreOpsForFormat(testFormat);

        if (spec.readonlyAspects != wgpu::TextureAspect::StencilOnly) {
            passDescriptor.cDepthStencilAttachmentInfo.depthReadOnly = true;
            passDescriptor.cDepthStencilAttachmentInfo.depthLoadOp = wgpu::LoadOp::Undefined;
            passDescriptor.cDepthStencilAttachmentInfo.depthStoreOp = wgpu::StoreOp::Undefined;
        }
        if (spec.readonlyAspects != wgpu::TextureAspect::DepthOnly) {
            passDescriptor.cDepthStencilAttachmentInfo.stencilReadOnly = true;
            passDescriptor.cDepthStencilAttachmentInfo.stencilLoadOp = wgpu::LoadOp::Undefined;
            passDescriptor.cDepthStencilAttachmentInfo.stencilStoreOp = wgpu::StoreOp::Undefined;
        }

        // Create a render pass with readonly depth/stencil attachment. The attachment has already
        // been initialized. The pipeline in this render pass will sample from the attachment. TODO
        // The pipeline will read from the attachment to do depth/stencil test too.
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&passDescriptor);
        wgpu::RenderPipeline pipeline = CreateRenderPipeline(testFormat, spec);
        pass.SetPipeline(pipeline);
        pass.SetStencilReference(spec.stencilRef);

        // Bind the bindgroup is needed.
        if (spec.sampledAspect.has_value()) {
            wgpu::TextureViewDescriptor viewDesc = {};
            viewDesc.aspect = spec.sampledAspect.value();
            wgpu::TextureView view = depthStencilTexture.CreateView(&viewDesc);

            wgpu::BindGroup bindGroup = utils::MakeBindGroup(
                device, pipeline.GetBindGroupLayout(0), {{0, device.CreateSampler()}, {1, view}});
            pass.SetBindGroup(0, bindGroup);
        } else {
            wgpu::BindGroup bindGroup =
                utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0), {});
            pass.SetBindGroup(0, bindGroup);
        }

        pass.Draw(6);
        pass.End();

        wgpu::CommandBuffer commands = commandEncoder.Finish();
        queue.Submit(1, &commands);

        return {colorTexture, depthStencilTexture};
    }

    void CheckFullColor(wgpu::Texture color, utils::RGBA8 fullColor) {
        std::vector<utils::RGBA8> expected(kSize * kSize, fullColor);
        EXPECT_TEXTURE_EQ(expected.data(), color, {0, 0}, {kSize, kSize});
    }

    void CheckTopBottomColor(wgpu::Texture color, utils::RGBA8 topColor, utils::RGBA8 bottomColor) {
        std::vector<utils::RGBA8> expectedTop(kSize * kSize / 2, topColor);
        EXPECT_TEXTURE_EQ(expectedTop.data(), color, {0, 0}, {kSize, kSize / 2});
        std::vector<utils::RGBA8> expectedBottom(kSize * kSize / 2, bottomColor);
        EXPECT_TEXTURE_EQ(expectedBottom.data(), color, {0, kSize / 2}, {kSize, kSize / 2});
    }

  private:
    bool mIsFormatSupported = false;
};

class ReadOnlyDepthAttachmentTests : public ReadOnlyDepthStencilAttachmentTests {};

TEST_P(ReadOnlyDepthAttachmentTests, SampleFromAttachment) {
    TestSpec spec;
    spec.readonlyAspects = wgpu::TextureAspect::DepthOnly;
    spec.sampledAspect = wgpu::TextureAspect::DepthOnly;
    spec.depthCompare = wgpu::CompareFunction::LessEqual;
    spec.depthClearValue = 0.2;
    auto render = DoRender(spec);

    // The top part is not rendered by the pipeline. Its color is the default clear color for
    // color attachment.
    // The bottom part is rendered, whose red channel is sampled from depth attachment, which
    // is initialized into 0.2.
    CheckTopBottomColor(render.color, {0, 0, 0, 0}, {static_cast<uint8_t>(0.2 * 255), 0, 0, 0});
}

TEST_P(ReadOnlyDepthAttachmentTests, NotSampleFromAttachment) {
    TestSpec spec;
    spec.readonlyAspects = wgpu::TextureAspect::DepthOnly;
    spec.depthCompare = wgpu::CompareFunction::LessEqual;
    spec.depthClearValue = 0.2;
    auto render = DoRender(spec);

    // The top part is not rendered by the pipeline. Its color is the default clear color for
    // color attachment.
    // The bottom part is rendered. Its color is set to blue.
    CheckTopBottomColor(render.color, {0, 0, 0, 0}, {0, 0, 255, 0});
}

// Regression test for crbug.com/dawn/1512 where having aspectReadOnly for an unused aspect of a
// depth-stencil texture would cause the attachment to be considered read-only, causing layout
// mismatch issues.
TEST_P(ReadOnlyDepthAttachmentTests, UnusedAspectWithReadOnly) {
    wgpu::TextureFormat format = GetParam().mTextureFormat;
    wgpu::TextureDescriptor tDesc;
    tDesc.size = {1, 1};
    tDesc.format = format;
    tDesc.usage = wgpu::TextureUsage::RenderAttachment;
    wgpu::Texture depthStencilTexture = device.CreateTexture(&tDesc);

    utils::ComboRenderPassDescriptor passDescriptor({}, depthStencilTexture.CreateView());
    if (utils::IsStencilOnlyFormat(format)) {
        passDescriptor.cDepthStencilAttachmentInfo.depthReadOnly = true;
        passDescriptor.cDepthStencilAttachmentInfo.depthLoadOp = wgpu::LoadOp::Undefined;
        passDescriptor.cDepthStencilAttachmentInfo.depthStoreOp = wgpu::StoreOp::Undefined;
    } else {
        passDescriptor.cDepthStencilAttachmentInfo.depthReadOnly = false;
    }
    if (utils::IsDepthOnlyFormat(format)) {
        passDescriptor.cDepthStencilAttachmentInfo.stencilReadOnly = true;
        passDescriptor.cDepthStencilAttachmentInfo.stencilLoadOp = wgpu::LoadOp::Undefined;
        passDescriptor.cDepthStencilAttachmentInfo.stencilStoreOp = wgpu::StoreOp::Undefined;
    } else {
        passDescriptor.cDepthStencilAttachmentInfo.stencilReadOnly = false;
    }

    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&passDescriptor);
    pass.End();
    wgpu::CommandBuffer commands = encoder.Finish();

    queue.Submit(1, &commands);
}

class ReadOnlyStencilAttachmentTests : public ReadOnlyDepthStencilAttachmentTests {};

TEST_P(ReadOnlyStencilAttachmentTests, SampleFromAttachment) {
    // TODO(crbug.com/40238674): Fails on Pixel 10.
    DAWN_SUPPRESS_TEST_IF(IsImgTec());
    // stencilRefValue < stencilValue (stencilInitValue), so stencil test passes. The pipeline
    // samples from stencil buffer and writes into color buffer.
    {
        TestSpec spec;
        spec.readonlyAspects = wgpu::TextureAspect::StencilOnly;
        spec.sampledAspect = wgpu::TextureAspect::StencilOnly;
        spec.stencilCompare = wgpu::CompareFunction::LessEqual;
        spec.stencilClearValue = 3;
        spec.stencilRef = 2;
        auto render = DoRender(spec);
        CheckFullColor(render.color, {3, 0, 0, 0});
    }

    // stencilRefValue > stencilValue (stencilInitValue), so stencil test fails. The pipeline
    // doesn't change color buffer. Sampled data from stencil buffer is discarded.
    {
        TestSpec spec;
        spec.readonlyAspects = wgpu::TextureAspect::StencilOnly;
        spec.sampledAspect = wgpu::TextureAspect::StencilOnly;
        spec.stencilCompare = wgpu::CompareFunction::LessEqual;
        spec.stencilClearValue = 1;
        spec.stencilRef = 2;
        auto render = DoRender(spec);
        CheckFullColor(render.color, {0, 0, 0, 0});
    }
}

TEST_P(ReadOnlyStencilAttachmentTests, NotSampleFromAttachment) {
    // TODO(crbug.com/40238674): Fails on Pixel 10.
    DAWN_SUPPRESS_TEST_IF(IsImgTec());
    // stencilRefValue < stencilValue (stencilInitValue), so stencil test passes. The pipeline
    // draw solid blue into color buffer.
    {
        TestSpec spec;
        spec.readonlyAspects = wgpu::TextureAspect::StencilOnly;
        spec.stencilCompare = wgpu::CompareFunction::LessEqual;
        spec.stencilClearValue = 3;
        spec.stencilRef = 2;
        auto render = DoRender(spec);
        CheckFullColor(render.color, {0, 0, 255, 0});
    }

    // stencilRefValue > stencilValue (stencilInitValue), so stencil test fails. The pipeline
    // doesn't change color buffer. drawing data is discarded.
    {
        TestSpec spec;
        spec.readonlyAspects = wgpu::TextureAspect::StencilOnly;
        spec.stencilCompare = wgpu::CompareFunction::LessEqual;
        spec.stencilClearValue = 1;
        spec.stencilRef = 2;
        auto render = DoRender(spec);
        CheckFullColor(render.color, {0, 0, 0, 0});
    }
}

class ReadOnlyDepthAndStencilAttachmentTests : public ReadOnlyDepthStencilAttachmentTests {
  protected:
    void SetUp() override {
        ReadOnlyDepthStencilAttachmentTests::SetUp();

        // TODO(crbug.com/473870505): [Capture] support depth/stencil and multi-planar textures.
        DAWN_SUPPRESS_TEST_IF(IsCaptureReplayCheckingEnabled());
    }
};

// Test that using stencilReadOnly while modifying the depth aspect works.
TEST_P(ReadOnlyDepthAndStencilAttachmentTests, ModifyDepthSampleStencil) {
    // TODO(crbug.com/40238674): Fails on Pixel 10.
    DAWN_SUPPRESS_TEST_IF(IsImgTec());
    // Stencil test is always true but the depth test passes only for the
    TestSpec spec1;
    spec1.readonlyAspects = wgpu::TextureAspect::StencilOnly;
    spec1.sampledAspect = wgpu::TextureAspect::StencilOnly;
    spec1.stencilClearValue = 42;
    spec1.depthClearValue = 0.2;
    spec1.depthCompare = wgpu::CompareFunction::LessEqual;
    spec1.depthWriteEnabled = wgpu::OptionalBool::True;
    auto render1 = DoRender(spec1);

    // Stencil was read successfully, but only in the bottom part.
    CheckTopBottomColor(render1.color, {0, 0, 0, 0}, {42, 0, 0, 0});

    // Check that the depth was written by setting depthCompare equal, and rendering a solid
    // blue color. The depth was only written on the bottom half due to the depth test in the
    // first render.
    TestSpec spec2;
    spec2.readonlyAspects = wgpu::TextureAspect::StencilOnly;
    spec2.depthStencilTexture = render1.depthStencil;
    spec2.depthCompare = wgpu::CompareFunction::Equal;
    auto render2 = DoRender(spec2);
    CheckTopBottomColor(render2.color, {0, 0, 0, 0}, {0, 0, 255, 0});
}

// Test that using depthReadOnly while modifying the stencil aspect works.
TEST_P(ReadOnlyDepthAndStencilAttachmentTests, SampleDepthModifyStencil) {
    // Depth/stencil tests are true, the depth is correctly sampled from the depthClearValue.
    // The stencil is written to the value of the stencil ref.
    TestSpec spec1;
    spec1.readonlyAspects = wgpu::TextureAspect::DepthOnly;
    spec1.sampledAspect = wgpu::TextureAspect::DepthOnly;
    spec1.depthClearValue = 0.2;
    spec1.stencilWriteEnabled = true;
    spec1.stencilRef = 42;
    spec1.stencilClearValue = 0;
    auto render1 = DoRender(spec1);
    CheckFullColor(render1.color, {static_cast<uint8_t>(0.2 * 255), 0, 0, 0});

    // The stencil test checks that the stencil ref matches what's in the stencil buffer
    // so that we know it was correctly written. The whole quad should be drawn.
    TestSpec spec2;
    spec2.readonlyAspects = wgpu::TextureAspect::DepthOnly;
    spec2.depthStencilTexture = render1.depthStencil;
    spec2.stencilCompare = wgpu::CompareFunction::Equal;
    spec2.stencilRef = 42;
    auto render2 = DoRender(spec2);
    CheckFullColor(render2.color, {0, 0, 255, 0});
}

// Test sampling depth with both the depth and stencil readonly.
TEST_P(ReadOnlyDepthAndStencilAttachmentTests, BothReadOnlySampleDepth) {
    // TODO(crbug.com/40238674): Fails on Pixel 10.
    DAWN_SUPPRESS_TEST_IF(IsImgTec());
    // Sample the depth while using both depth an stencil testing.

    // First render: depth test passes only for the bottom half, stencil passes.
    TestSpec spec;
    spec.readonlyAspects = wgpu::TextureAspect::All;
    spec.sampledAspect = wgpu::TextureAspect::DepthOnly;
    spec.depthCompare = wgpu::CompareFunction::LessEqual;
    spec.depthClearValue = 0.2;
    spec.stencilRef = 42;
    spec.stencilClearValue = 43;
    spec.stencilCompare = wgpu::CompareFunction::LessEqual;
    auto render1 = DoRender(spec);
    CheckTopBottomColor(render1.color, {0, 0, 0, 0}, {static_cast<uint8_t>(0.2 * 255), 0, 0, 0});

    // Second render: stencil test fails.
    spec.stencilClearValue = 41;
    auto render2 = DoRender(spec);
    CheckFullColor(render2.color, {0, 0, 0, 0});
}

// Test sampling stencil with both the depth and stencil readonly.
TEST_P(ReadOnlyDepthAndStencilAttachmentTests, BothReadOnlySampleStencil) {
    // TODO(crbug.com/40238674): Fails on Pixel 10.
    DAWN_SUPPRESS_TEST_IF(IsImgTec());
    // Sample the stencil while using both depth an stencil testing.

    // First render: depth test passes only for the bottom half, stencil passes.
    TestSpec spec;
    spec.readonlyAspects = wgpu::TextureAspect::All;
    spec.sampledAspect = wgpu::TextureAspect::StencilOnly;
    spec.depthCompare = wgpu::CompareFunction::LessEqual;
    spec.depthClearValue = 0.2;
    spec.stencilRef = 42;
    spec.stencilClearValue = 43;
    spec.stencilCompare = wgpu::CompareFunction::LessEqual;
    auto render1 = DoRender(spec);
    CheckTopBottomColor(render1.color, {0, 0, 0, 0}, {43, 0, 0, 0});

    // Second render: stencil test fails.
    spec.stencilClearValue = 41;
    auto render2 = DoRender(spec);
    CheckFullColor(render2.color, {0, 0, 0, 0});
}

DAWN_INSTANTIATE_TEST_P(
    ReadOnlyDepthAttachmentTests,
    {D3D11Backend(), D3D12Backend(), D3D12Backend({}, {"use_d3d12_render_pass"}), MetalBackend(),
     OpenGLBackend(), OpenGLESBackend(), VulkanBackend({"vulkan_use_dynamic_rendering"}, {}),
     VulkanBackend({"vulkan_use_create_render_pass_2"}, {"vulkan_use_dynamic_rendering"}),
     VulkanBackend({}, {"vulkan_use_create_render_pass_2", "vulkan_use_dynamic_rendering"}),
     WebGPUBackend()},
    std::vector<wgpu::TextureFormat>(utils::kDepthFormats.begin(), utils::kDepthFormats.end()));
DAWN_INSTANTIATE_TEST_P(
    ReadOnlyStencilAttachmentTests,
    {D3D11Backend(), D3D12Backend(), D3D12Backend({}, {"use_d3d12_render_pass"}), MetalBackend(),
     OpenGLBackend(), OpenGLESBackend(), VulkanBackend({"vulkan_use_dynamic_rendering"}, {}),
     VulkanBackend({"vulkan_use_create_render_pass_2"}, {"vulkan_use_dynamic_rendering"}),
     VulkanBackend({}, {"vulkan_use_create_render_pass_2", "vulkan_use_dynamic_rendering"}),
     WebGPUBackend()},
    std::vector<wgpu::TextureFormat>(utils::kStencilFormats.begin(), utils::kStencilFormats.end()));
DAWN_INSTANTIATE_TEST_P(
    ReadOnlyDepthAndStencilAttachmentTests,
    {D3D11Backend(), D3D12Backend(), D3D12Backend({}, {"use_d3d12_render_pass"}), MetalBackend(),
     OpenGLBackend(), OpenGLESBackend(), VulkanBackend({"vulkan_use_dynamic_rendering"}, {}),
     VulkanBackend({"vulkan_use_create_render_pass_2"}, {"vulkan_use_dynamic_rendering"}),
     VulkanBackend({}, {"vulkan_use_create_render_pass_2", "vulkan_use_dynamic_rendering"}),
     WebGPUBackend()},
    std::vector<wgpu::TextureFormat>(utils::kDepthAndStencilFormats.begin(),
                                     utils::kDepthAndStencilFormats.end()));

}  // anonymous namespace
}  // namespace dawn
