// Copyright 2020 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "tests/DawnTest.h"

#include <array>
#include "common/Constants.h"
#include "common/Math.h"
#include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/TestUtils.h"
#include "utils/TextureFormatUtils.h"
#include "utils/WGPUHelpers.h"

class DepthStencilCopyTests : public DawnTest {
  protected:
    void SetUp() override {
        DawnTest::SetUp();

        // TODO(crbug.com/tint/329): SPIR-V output missing DepthReplacing execution mode.
        DAWN_SKIP_TEST_IF(HasToggleEnabled("use_tint_generator") &&
                          (IsVulkan() || IsOpenGL() || IsOpenGLES()));

        // Draw a square in the bottom left quarter of the screen.
        mVertexModule = utils::CreateShaderModuleFromWGSL(device, R"(
            [[builtin(vertex_idx)]] var<in> VertexIndex : u32;
            [[builtin(position)]] var<out> Position : vec4<f32>;

            [[stage(vertex)]] fn main() -> void {
                const pos : array<vec2<f32>, 6> = array<vec2<f32>, 6>(
                    vec2<f32>(-1.0, -1.0),
                    vec2<f32>( 0.0, -1.0),
                    vec2<f32>(-1.0,  0.0),
                    vec2<f32>(-1.0,  0.0),
                    vec2<f32>( 0.0, -1.0),
                    vec2<f32>( 0.0,  0.0));
                Position = vec4<f32>(pos[VertexIndex], 0.0, 1.0);
            })");
    }

    wgpu::Texture CreateDepthStencilTexture(uint32_t width,
                                            uint32_t height,
                                            wgpu::TextureUsage usage,
                                            uint32_t mipLevelCount = 1) {
        wgpu::TextureDescriptor texDescriptor = {};
        texDescriptor.size = {width, height, 1};
        texDescriptor.format = wgpu::TextureFormat::Depth24PlusStencil8;
        texDescriptor.usage = usage;
        texDescriptor.mipLevelCount = mipLevelCount;
        return device.CreateTexture(&texDescriptor);
    }

    wgpu::Texture CreateDepthTexture(uint32_t width,
                                     uint32_t height,
                                     wgpu::TextureUsage usage,
                                     uint32_t mipLevelCount = 1) {
        wgpu::TextureDescriptor texDescriptor = {};
        texDescriptor.size = {width, height, 1};
        texDescriptor.format = wgpu::TextureFormat::Depth32Float;
        texDescriptor.usage = usage;
        texDescriptor.mipLevelCount = mipLevelCount;
        return device.CreateTexture(&texDescriptor);
    }

    void PopulatePipelineDescriptorWriteDepth(utils::ComboRenderPipelineDescriptor* desc,
                                              wgpu::TextureFormat format,
                                              float regionDepth) {
        desc->vertexStage.module = mVertexModule;

        std::string fsSource = R"(
    #version 450
    void main() {
        gl_FragDepth = )" + std::to_string(regionDepth) +
                               ";\n}";

        desc->cFragmentStage.module =
            utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, fsSource.c_str());
        desc->cDepthStencilState.format = format;
        desc->cDepthStencilState.depthWriteEnabled = true;
        desc->depthStencilState = &desc->cDepthStencilState;
        desc->colorStateCount = 0;
    }

    // Initialize the depth/stencil values for the texture using a render pass.
    // The texture will be cleared to the "clear" value, and then bottom left corner will
    // be written with the "region" value.
    void InitializeDepthTextureRegion(wgpu::Texture texture,
                                      float clearDepth,
                                      float regionDepth,
                                      uint32_t mipLevel = 0) {
        wgpu::TextureViewDescriptor viewDesc = {};
        viewDesc.baseMipLevel = mipLevel;
        viewDesc.mipLevelCount = 1;

        utils::ComboRenderPassDescriptor renderPassDesc({}, texture.CreateView(&viewDesc));
        renderPassDesc.cDepthStencilAttachmentInfo.clearDepth = clearDepth;

        utils::ComboRenderPipelineDescriptor renderPipelineDesc(device);
        PopulatePipelineDescriptorWriteDepth(&renderPipelineDesc, wgpu::TextureFormat::Depth32Float,
                                             regionDepth);

        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&renderPipelineDesc);
        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPassDesc);
        pass.SetPipeline(pipeline);
        pass.Draw(6);
        pass.EndPass();

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

    // Initialize the depth/stencil values for the texture using a render pass.
    // The texture will be cleared to the "clear" values, and then bottom left corner will
    // be written with the "region" values.
    void InitializeDepthStencilTextureRegion(wgpu::Texture texture,
                                             float clearDepth,
                                             float regionDepth,
                                             uint8_t clearStencil,
                                             uint8_t regionStencil,
                                             uint32_t mipLevel = 0) {
        wgpu::TextureViewDescriptor viewDesc = {};
        viewDesc.baseMipLevel = mipLevel;
        viewDesc.mipLevelCount = 1;

        utils::ComboRenderPassDescriptor renderPassDesc({}, texture.CreateView(&viewDesc));
        renderPassDesc.cDepthStencilAttachmentInfo.clearDepth = clearDepth;
        renderPassDesc.cDepthStencilAttachmentInfo.clearStencil = clearStencil;

        utils::ComboRenderPipelineDescriptor renderPipelineDesc(device);
        PopulatePipelineDescriptorWriteDepth(&renderPipelineDesc,
                                             wgpu::TextureFormat::Depth24PlusStencil8, regionDepth);

        renderPipelineDesc.cDepthStencilState.stencilFront.passOp = wgpu::StencilOperation::Replace;

        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&renderPipelineDesc);

        // Draw the quad (two triangles)
        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&renderPassDesc);
        pass.SetPipeline(pipeline);
        pass.SetStencilReference(regionStencil);
        pass.Draw(6);
        pass.EndPass();

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

    wgpu::Texture CreateInitializeDepthStencilTextureAndCopyT2T(float clearDepth,
                                                                float regionDepth,
                                                                uint8_t clearStencil,
                                                                uint8_t regionStencil,
                                                                uint32_t width,
                                                                uint32_t height,
                                                                wgpu::TextureUsage usage,
                                                                uint32_t mipLevel = 0) {
        wgpu::Texture src = CreateDepthStencilTexture(
            width, height, wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc,
            mipLevel + 1);

        wgpu::Texture dst = CreateDepthStencilTexture(
            width, height, usage | wgpu::TextureUsage::CopyDst, mipLevel + 1);

        InitializeDepthStencilTextureRegion(src, clearDepth, regionDepth, clearStencil,
                                            regionStencil, mipLevel);

        // Perform a T2T copy of all aspects
        {
            wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
            wgpu::TextureCopyView srcView = utils::CreateTextureCopyView(src, mipLevel, {0, 0, 0});
            wgpu::TextureCopyView dstView = utils::CreateTextureCopyView(dst, mipLevel, {0, 0, 0});
            wgpu::Extent3D copySize = {width >> mipLevel, height >> mipLevel, 1};
            commandEncoder.CopyTextureToTexture(&srcView, &dstView, &copySize);

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

        return dst;
    }

    // Check depth by uploading expected data to a sampled texture, writing it out as a depth
    // attachment, and then using the "equals" depth test to check the contents are the same.
    void ExpectDepthData(wgpu::Texture depthTexture,
                         wgpu::TextureFormat depthFormat,
                         uint32_t width,
                         uint32_t height,
                         uint32_t mipLevel,
                         std::vector<float> expected) {
        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();

        // Make the color attachment that we'll use to read back.
        wgpu::TextureDescriptor colorTexDesc = {};
        colorTexDesc.size = {width, height, 1};
        colorTexDesc.format = wgpu::TextureFormat::R32Uint;
        colorTexDesc.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc;
        wgpu::Texture colorTexture = device.CreateTexture(&colorTexDesc);

        // Make a sampleable texture to store the depth data. We'll sample this in the
        // shader to output depth.
        wgpu::TextureDescriptor depthDataDesc = {};
        depthDataDesc.size = {width, height, 1};
        depthDataDesc.format = wgpu::TextureFormat::R32Float;
        depthDataDesc.usage = wgpu::TextureUsage::Sampled | wgpu::TextureUsage::CopyDst;
        wgpu::Texture depthDataTexture = device.CreateTexture(&depthDataDesc);

        // Upload the depth data.
        uint32_t bytesPerRow = utils::GetMinimumBytesPerRow(wgpu::TextureFormat::R32Float, width);
        wgpu::BufferDescriptor uploadBufferDesc = {};
        uploadBufferDesc.size = utils::RequiredBytesInCopy(bytesPerRow, height, depthDataDesc.size,
                                                           wgpu::TextureFormat::R32Float);
        uploadBufferDesc.usage = wgpu::BufferUsage::CopySrc;
        uploadBufferDesc.mappedAtCreation = true;

        // TODO(enga): Use WriteTexture when implemented on OpenGL.
        wgpu::Buffer uploadBuffer = device.CreateBuffer(&uploadBufferDesc);
        uint8_t* dst = static_cast<uint8_t*>(uploadBuffer.GetMappedRange());
        float* src = expected.data();
        for (uint32_t y = 0; y < height; ++y) {
            memcpy(dst, src, width * sizeof(float));
            dst += bytesPerRow;
            src += width;
        }
        uploadBuffer.Unmap();

        wgpu::BufferCopyView bufferCopy =
            utils::CreateBufferCopyView(uploadBuffer, 0, bytesPerRow, height);
        wgpu::TextureCopyView textureCopy =
            utils::CreateTextureCopyView(depthDataTexture, 0, {0, 0, 0}, wgpu::TextureAspect::All);
        commandEncoder.CopyBufferToTexture(&bufferCopy, &textureCopy, &depthDataDesc.size);

        // Pipeline for a full screen quad.
        utils::ComboRenderPipelineDescriptor pipelineDescriptor(device);

        pipelineDescriptor.vertexStage.module = utils::CreateShaderModuleFromWGSL(device, R"(
            [[builtin(vertex_idx)]] var<in> VertexIndex : u32;
            [[builtin(position)]] var<out> Position : vec4<f32>;

            [[stage(vertex)]] fn main() -> void {
                const pos : array<vec2<f32>, 3> = array<vec2<f32>, 3>(
                    vec2<f32>(-1.0, -1.0),
                    vec2<f32>( 3.0, -1.0),
                    vec2<f32>(-1.0,  3.0));
                Position = vec4<f32>(pos[VertexIndex], 0.0, 1.0);
            })");

        // Sample the input texture and write out depth. |result| will only be set to 1 if we
        // pass the depth test.
        pipelineDescriptor.cFragmentStage.module =
            utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"(
        #version 450
        layout(set = 0, binding = 0) uniform sampler sampler0;
        layout(set = 0, binding = 1) uniform texture2D texture0;

        layout(location = 0) out uint result;
        void main() {
            result = 1u;
            gl_FragDepth = texelFetch(sampler2D(texture0, sampler0), ivec2(gl_FragCoord), 0)[0];
        })");

        // Pass the depth test only if the depth is equal.
        pipelineDescriptor.primitiveTopology = wgpu::PrimitiveTopology::TriangleList;
        pipelineDescriptor.depthStencilState = &pipelineDescriptor.cDepthStencilState;
        pipelineDescriptor.cDepthStencilState.format = depthFormat;
        pipelineDescriptor.cDepthStencilState.depthCompare = wgpu::CompareFunction::Equal;
        pipelineDescriptor.cColorStates[0].format = colorTexDesc.format;

        // TODO(jiawei.shao@intel.com): The Intel Mesa Vulkan driver can't set gl_FragDepth unless
        // depthWriteEnabled == true. This either needs to be fixed in the driver or restricted by
        // the WebGPU API.
        pipelineDescriptor.cDepthStencilState.depthWriteEnabled = true;

        wgpu::TextureViewDescriptor viewDesc = {};
        viewDesc.baseMipLevel = mipLevel;
        viewDesc.mipLevelCount = 1;

        utils::ComboRenderPassDescriptor passDescriptor({colorTexture.CreateView()},
                                                        depthTexture.CreateView(&viewDesc));
        passDescriptor.cDepthStencilAttachmentInfo.depthLoadOp = wgpu::LoadOp::Load;
        passDescriptor.cDepthStencilAttachmentInfo.stencilLoadOp = wgpu::LoadOp::Load;

        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDescriptor);

        // Bind a sampler and the depth data texture.
        wgpu::SamplerDescriptor samplerDesc = {};
        wgpu::BindGroup bindGroup = utils::MakeBindGroup(
            device, pipeline.GetBindGroupLayout(0),
            {{0, device.CreateSampler(&samplerDesc)}, {1, depthDataTexture.CreateView()}});

        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&passDescriptor);
        pass.SetPipeline(pipeline);
        pass.SetBindGroup(0, bindGroup);
        pass.Draw(3);
        pass.EndPass();

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

        std::vector<uint32_t> colorData(width * height, 1u);
        EXPECT_TEXTURE_EQ(colorData.data(), colorTexture, 0, 0, width, height, 0, 0);
    }

    wgpu::ShaderModule mVertexModule;
};

// Test copying the depth-only aspect into a buffer.
TEST_P(DepthStencilCopyTests, FromDepthAspect) {
    constexpr uint32_t kWidth = 4;
    constexpr uint32_t kHeight = 4;

    wgpu::Texture depthTexture = CreateDepthTexture(
        kWidth, kHeight, wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc);

    InitializeDepthTextureRegion(depthTexture, 0.f, 0.3f);

    // This expectation is the test as it performs the CopyTextureToBuffer.
    std::vector<float> expectedData = {
        0.0, 0.0, 0.0, 0.0,  //
        0.0, 0.0, 0.0, 0.0,  //
        0.3, 0.3, 0.0, 0.0,  //
        0.3, 0.3, 0.0, 0.0,  //
    };
    EXPECT_TEXTURE_EQ(expectedData.data(), depthTexture, 0, 0, kWidth, kHeight, 0, 0,
                      wgpu::TextureAspect::DepthOnly);
}

// Test copying the stencil-only aspect into a buffer.
TEST_P(DepthStencilCopyTests, FromStencilAspect) {
    constexpr uint32_t kWidth = 4;
    constexpr uint32_t kHeight = 4;

    wgpu::Texture depthStencilTexture = CreateDepthStencilTexture(
        kWidth, kHeight, wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc);

    InitializeDepthStencilTextureRegion(depthStencilTexture, 0.f, 0.3f, 0u, 1u);

    // This expectation is the test as it performs the CopyTextureToBuffer.
    std::vector<uint8_t> expectedData = {
        0u, 0u, 0u, 0u,  //
        0u, 0u, 0u, 0u,  //
        1u, 1u, 0u, 0u,  //
        1u, 1u, 0u, 0u,  //
    };
    EXPECT_TEXTURE_EQ(expectedData.data(), depthStencilTexture, 0, 0, kWidth, kHeight, 0, 0,
                      wgpu::TextureAspect::StencilOnly);
}

// Test copying the non-zero mip, stencil-only aspect into a buffer.
TEST_P(DepthStencilCopyTests, FromNonZeroMipStencilAspect) {
    // TODO(enga): Figure out why this fails on MacOS Intel Iris.
    // It passes on AMD Radeon Pro and Intel HD Graphics 630.
    DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());

    wgpu::Texture depthStencilTexture = CreateDepthStencilTexture(
        9, 9, wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc, 2);

    InitializeDepthStencilTextureRegion(depthStencilTexture, 0.f, 0.3f, 0u, 1u, 1u);

    // This expectation is the test as it performs the CopyTextureToBuffer.
    std::vector<uint8_t> expectedData = {
        0u, 0u, 0u, 0u,  //
        0u, 0u, 0u, 0u,  //
        1u, 1u, 0u, 0u,  //
        1u, 1u, 0u, 0u,  //
    };
    EXPECT_TEXTURE_EQ(expectedData.data(), depthStencilTexture, 0, 0, 4, 4, 1, 0,
                      wgpu::TextureAspect::StencilOnly);
}

// Test copying the non-zero mip, depth-only aspect into a buffer.
TEST_P(DepthStencilCopyTests, FromNonZeroMipDepthAspect) {
    wgpu::Texture depthTexture = CreateDepthTexture(
        9, 9, wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc, 2);

    InitializeDepthTextureRegion(depthTexture, 0.f, 0.4f, 1);

    // This expectation is the test as it performs the CopyTextureToBuffer.
    std::vector<float> expectedData = {
        0.0, 0.0, 0.0, 0.0,  //
        0.0, 0.0, 0.0, 0.0,  //
        0.4, 0.4, 0.0, 0.0,  //
        0.4, 0.4, 0.0, 0.0,  //
    };
    EXPECT_TEXTURE_EQ(expectedData.data(), depthTexture, 0, 0, 4, 4, 1, 0,
                      wgpu::TextureAspect::DepthOnly);
}

// Test copying both aspects in a T2T copy, then copying only stencil.
TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyStencil) {
    // TODO(enga): Figure out why this fails on MacOS Intel Iris.
    // It passes on AMD Radeon Pro and Intel HD Graphics 630.
    // Maybe has to do with the RenderAttachment usage. Notably, a later test
    // T2TBothAspectsThenCopyNonRenderableStencil does not use RenderAttachment and works correctly.
    DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());

    constexpr uint32_t kWidth = 4;
    constexpr uint32_t kHeight = 4;

    wgpu::Texture texture = CreateInitializeDepthStencilTextureAndCopyT2T(
        0.1f, 0.3f, 1u, 3u, kWidth, kHeight,
        wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment);

    // Check the stencil
    std::vector<uint8_t> expectedData = {
        1u, 1u, 1u, 1u,  //
        1u, 1u, 1u, 1u,  //
        3u, 3u, 1u, 1u,  //
        3u, 3u, 1u, 1u,  //
    };
    EXPECT_TEXTURE_EQ(expectedData.data(), texture, 0, 0, kWidth, kHeight, 0, 0,
                      wgpu::TextureAspect::StencilOnly);
}

// Test that part of a non-renderable stencil aspect can be copied. Notably,
// this test has different behavior on some platforms than T2TBothAspectsThenCopyStencil.
TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyNonRenderableStencil) {
    constexpr uint32_t kWidth = 4;
    constexpr uint32_t kHeight = 4;

    wgpu::Texture texture = CreateInitializeDepthStencilTextureAndCopyT2T(
        0.1f, 0.3f, 1u, 3u, kWidth, kHeight, wgpu::TextureUsage::CopySrc);

    // Check the stencil
    std::vector<uint8_t> expectedData = {
        1u, 1u, 1u, 1u,  //
        1u, 1u, 1u, 1u,  //
        3u, 3u, 1u, 1u,  //
        3u, 3u, 1u, 1u,  //
    };
    EXPECT_TEXTURE_EQ(expectedData.data(), texture, 0, 0, kWidth, kHeight, 0, 0,
                      wgpu::TextureAspect::StencilOnly);
}

// Test that part of a non-renderable, non-zero mip stencil aspect can be copied. Notably,
// this test has different behavior on some platforms than T2TBothAspectsThenCopyStencil.
TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyNonRenderableNonZeroMipStencil) {
    // TODO(enga): Figure out why this fails on MacOS Intel Iris.
    // It passes on AMD Radeon Pro and Intel HD Graphics 630.
    // Maybe has to do with the non-zero mip. Notably, a previous test
    // T2TBothAspectsThenCopyNonRenderableStencil works correctly.
    DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());

    wgpu::Texture texture = CreateInitializeDepthStencilTextureAndCopyT2T(
        0.1f, 0.3f, 1u, 3u, 9, 9, wgpu::TextureUsage::CopySrc, 1);

    // Check the stencil
    std::vector<uint8_t> expectedData = {
        1u, 1u, 1u, 1u,  //
        1u, 1u, 1u, 1u,  //
        3u, 3u, 1u, 1u,  //
        3u, 3u, 1u, 1u,  //
    };
    EXPECT_TEXTURE_EQ(expectedData.data(), texture, 0, 0, 4, 4, 1, 0,
                      wgpu::TextureAspect::StencilOnly);
}

// Test copying both aspects in a T2T copy, then copying only depth.
TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyDepth) {
    constexpr uint32_t kWidth = 4;
    constexpr uint32_t kHeight = 4;

    wgpu::Texture texture = CreateInitializeDepthStencilTextureAndCopyT2T(
        0.1f, 0.3f, 1u, 3u, kWidth, kHeight, wgpu::TextureUsage::RenderAttachment);

    // Check the depth
    ExpectDepthData(texture, wgpu::TextureFormat::Depth24PlusStencil8, kWidth, kHeight, 0,
                    {
                        0.1, 0.1, 0.1, 0.1,  //
                        0.1, 0.1, 0.1, 0.1,  //
                        0.3, 0.3, 0.1, 0.1,  //
                        0.3, 0.3, 0.1, 0.1,  //
                    });
}

// Test copying both aspects in a T2T copy, then copying only depth at a nonzero mip.
TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyNonZeroMipDepth) {
    wgpu::Texture texture = CreateInitializeDepthStencilTextureAndCopyT2T(
        0.1f, 0.3f, 1u, 3u, 8, 8, wgpu::TextureUsage::RenderAttachment, 1);

    // Check the depth
    ExpectDepthData(texture, wgpu::TextureFormat::Depth24PlusStencil8, 4, 4, 1,
                    {
                        0.1, 0.1, 0.1, 0.1,  //
                        0.1, 0.1, 0.1, 0.1,  //
                        0.3, 0.3, 0.1, 0.1,  //
                        0.3, 0.3, 0.1, 0.1,  //
                    });
}

// Test copying both aspects in a T2T copy, then copying stencil, then copying depth
TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyStencilThenDepth) {
    constexpr uint32_t kWidth = 4;
    constexpr uint32_t kHeight = 4;

    wgpu::Texture texture = CreateInitializeDepthStencilTextureAndCopyT2T(
        0.1f, 0.3f, 1u, 3u, kWidth, kHeight,
        wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment);

    // Check the stencil
    std::vector<uint8_t> expectedData = {
        1u, 1u, 1u, 1u,  //
        1u, 1u, 1u, 1u,  //
        3u, 3u, 1u, 1u,  //
        3u, 3u, 1u, 1u,  //
    };
    EXPECT_TEXTURE_EQ(expectedData.data(), texture, 0, 0, kWidth, kHeight, 0, 0,
                      wgpu::TextureAspect::StencilOnly);

    // Check the depth
    ExpectDepthData(texture, wgpu::TextureFormat::Depth24PlusStencil8, kWidth, kHeight, 0,
                    {
                        0.1, 0.1, 0.1, 0.1,  //
                        0.1, 0.1, 0.1, 0.1,  //
                        0.3, 0.3, 0.1, 0.1,  //
                        0.3, 0.3, 0.1, 0.1,  //
                    });
}

// Test copying both aspects in a T2T copy, then copying depth, then copying stencil
TEST_P(DepthStencilCopyTests, T2TBothAspectsThenCopyDepthThenStencil) {
    // TODO(enga): Figure out why this fails on MacOS Intel Iris.
    // It passes on AMD Radeon Pro and Intel HD Graphics 630.
    // It seems like the depth readback copy mutates the stencil because the previous
    // test T2TBothAspectsThenCopyStencil passes.
    // T2TBothAspectsThenCopyStencilThenDepth which checks stencil first also passes.
    DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());

    constexpr uint32_t kWidth = 4;
    constexpr uint32_t kHeight = 4;

    wgpu::Texture texture = CreateInitializeDepthStencilTextureAndCopyT2T(
        0.1f, 0.3f, 1u, 3u, kWidth, kHeight,
        wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment);

    // Check the depth
    ExpectDepthData(texture, wgpu::TextureFormat::Depth24PlusStencil8, kWidth, kHeight, 0,
                    {
                        0.1, 0.1, 0.1, 0.1,  //
                        0.1, 0.1, 0.1, 0.1,  //
                        0.3, 0.3, 0.1, 0.1,  //
                        0.3, 0.3, 0.1, 0.1,  //
                    });

    // Check the stencil
    std::vector<uint8_t> expectedData = {
        1u, 1u, 1u, 1u,  //
        1u, 1u, 1u, 1u,  //
        3u, 3u, 1u, 1u,  //
        3u, 3u, 1u, 1u,  //
    };
    EXPECT_TEXTURE_EQ(expectedData.data(), texture, 0, 0, kWidth, kHeight, 0, 0,
                      wgpu::TextureAspect::StencilOnly);
}

// Test copying to the stencil-aspect of a buffer
TEST_P(DepthStencilCopyTests, ToStencilAspect) {
    // Copies to a single aspect are unsupported on OpenGL.
    DAWN_SKIP_TEST_IF(IsOpenGL());
    DAWN_SKIP_TEST_IF(IsOpenGLES());

    // TODO(enga): Figure out why this fails on MacOS Intel Iris.
    // It passes on AMD Radeon Pro and Intel HD Graphics 630.
    DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());

    // TODO(enga): Figure out why this fails on Windows Intel Vulkan.
    // Reading back the depth does not work.
    DAWN_SKIP_TEST_IF(IsWindows() && IsIntel() && IsVulkan());

    // Create a stencil texture
    constexpr uint32_t kWidth = 4;
    constexpr uint32_t kHeight = 4;

    wgpu::Texture depthStencilTexture =
        CreateDepthStencilTexture(kWidth, kHeight,
                                  wgpu::TextureUsage::RenderAttachment |
                                      wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst);

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

        // Clear depth to 0.7, so we can check that the stencil copy doesn't mutate the depth.
        utils::ComboRenderPassDescriptor passDescriptor({}, depthStencilTexture.CreateView());
        passDescriptor.cDepthStencilAttachmentInfo.clearDepth = 0.7;

        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&passDescriptor);
        pass.EndPass();

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

    std::vector<uint8_t> stencilData = {
        1u,  2u,  3u,  4u,   //
        5u,  6u,  7u,  8u,   //
        9u,  10u, 11u, 12u,  //
        13u, 14u, 15u, 16u,  //
    };

    // After copying stencil data in, we will decrement stencil values in the bottom left
    // of the screen. This is the expected result.
    std::vector<uint8_t> expectedStencilData = {
        1u,  2u,  3u,  4u,   //
        5u,  6u,  7u,  8u,   //
        8u,  9u,  11u, 12u,  //
        12u, 13u, 15u, 16u,  //
    };

    // Upload the stencil data.
    wgpu::TextureDataLayout stencilDataLayout = {};
    stencilDataLayout.bytesPerRow = kWidth * sizeof(uint8_t);

    wgpu::TextureCopyView stencilDataCopyView = utils::CreateTextureCopyView(
        depthStencilTexture, 0, {0, 0, 0}, wgpu::TextureAspect::StencilOnly);

    wgpu::Extent3D writeSize = {kWidth, kHeight, 1};
    queue.WriteTexture(&stencilDataCopyView, stencilData.data(),
                       stencilData.size() * sizeof(uint8_t), &stencilDataLayout, &writeSize);

    // Decrement the stencil value in a render pass to ensure the data is visible to the pipeline.
    {
        wgpu::CommandEncoder commandEncoder = device.CreateCommandEncoder();
        // Create a render pipline which decrements the stencil value for passing fragments.
        // A quad is drawn in the bottom left.
        utils::ComboRenderPipelineDescriptor renderPipelineDesc(device);
        renderPipelineDesc.vertexStage.module = mVertexModule;
        renderPipelineDesc.cFragmentStage.module = utils::CreateShaderModuleFromWGSL(device, R"(
            [[stage(fragment)]] fn main() -> void {
            })");
        renderPipelineDesc.cDepthStencilState.format = wgpu::TextureFormat::Depth24PlusStencil8;
        renderPipelineDesc.cDepthStencilState.stencilFront.passOp =
            wgpu::StencilOperation::DecrementClamp;
        renderPipelineDesc.depthStencilState = &renderPipelineDesc.cDepthStencilState;
        renderPipelineDesc.colorStateCount = 0;

        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&renderPipelineDesc);

        // Create a render pass which loads the stencil. We want to load the values we
        // copied in. Also load the canary depth values so they're not lost.
        utils::ComboRenderPassDescriptor passDescriptor({}, depthStencilTexture.CreateView());
        passDescriptor.cDepthStencilAttachmentInfo.stencilLoadOp = wgpu::LoadOp::Load;
        passDescriptor.cDepthStencilAttachmentInfo.depthLoadOp = wgpu::LoadOp::Load;

        // Draw the quad in the bottom left (two triangles).
        wgpu::RenderPassEncoder pass = commandEncoder.BeginRenderPass(&passDescriptor);
        pass.SetPipeline(pipeline);
        pass.Draw(6);
        pass.EndPass();

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

    // Copy back the stencil data and check it is correct.
    EXPECT_TEXTURE_EQ(expectedStencilData.data(), depthStencilTexture, 0, 0, kWidth, kHeight, 0, 0,
                      wgpu::TextureAspect::StencilOnly);

    ExpectDepthData(depthStencilTexture, wgpu::TextureFormat::Depth24PlusStencil8, kWidth, kHeight,
                    0,
                    {
                        0.7, 0.7, 0.7, 0.7,  //
                        0.7, 0.7, 0.7, 0.7,  //
                        0.7, 0.7, 0.7, 0.7,  //
                        0.7, 0.7, 0.7, 0.7,  //
                    });
}

DAWN_INSTANTIATE_TEST(DepthStencilCopyTests,
                      D3D12Backend(),
                      MetalBackend(),
                      OpenGLBackend(),
                      OpenGLESBackend(),
                      VulkanBackend());
