// 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 <algorithm>
#include <string>
#include <vector>

#include "src/dawn/common/Enumerator.h"
#include "src/dawn/common/ExternalTextureParams.h"
#include "src/dawn/tests/DawnTest.h"
#include "src/dawn/utils/ComboRenderPipelineDescriptor.h"
#include "src/dawn/utils/WGPUHelpers.h"

namespace dawn {
namespace {

wgpu::Texture Create2DTexture(wgpu::Device device,
                              uint32_t width,
                              uint32_t height,
                              wgpu::TextureFormat format,
                              wgpu::TextureUsage usage) {
    wgpu::TextureDescriptor descriptor;
    descriptor.dimension = wgpu::TextureDimension::e2D;
    descriptor.size.width = width;
    descriptor.size.height = height;
    descriptor.size.depthOrArrayLayers = 1;
    descriptor.sampleCount = 1;
    descriptor.format = format;
    descriptor.mipLevelCount = 1;
    descriptor.usage = usage;
    return device.CreateTexture(&descriptor);
}

struct YUVTestData {
    float y;
    float u;
    float v;
    std::array<float, 4> rgbaFloats;
    utils::RGBA8 rgba;
};
static const YUVTestData kBlack = {
    0.0, 0.5, 0.5, {0.0, 0.0, 0.0, 1.0}, utils::RGBA8::kBlack,
};
static const YUVTestData kRed = {
    0.2126, 0.4172, 1.0, {1.0, 0.0, 0.0, 1.0}, utils::RGBA8::kRed,
};
static const YUVTestData kGreen = {
    0.7152, 0.1402, 0.0175, {0.0, 1.0, 0.0, 1.0}, utils::RGBA8::kGreen,
};
static const YUVTestData kBlue = {
    0.0722, 1.0, 0.4937, {0.0, 0.0, 1.0, 1.0}, utils::RGBA8::kBlue,
};
static const YUVTestData kColor1 = {0.6402,
                                    0.3214,
                                    0.6624,
                                    {246 / 255.0, 169 / 255.0, 89 / 255.0, 1},
                                    {246, 169, 89, 255}};

template <typename Parent>
class ExternalTextureTestsBase : public Parent {
  protected:
    void SetUp() override {
        Parent::SetUp();

        vsModule = utils::CreateShaderModule(this->device, R"(
            @vertex fn main(@builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4f {
                var positions = array(
                    vec4f(-3, -1, 0, 1),
                    vec4f( 3, -1, 0, 1),
                    vec4f( 0,  2, 0, 1),
                );
                return positions[VertexIndex];
            })");

        fsSampleExternalTextureModule = utils::CreateShaderModule(this->device, R"(
            @group(0) @binding(0) var s : sampler;
            @group(0) @binding(1) var t : texture_external;

            @fragment fn main(@builtin(position) FragCoord : vec4f)
                                     -> @location(0) vec4f {
                return textureSampleBaseClampToEdge(t, s, FragCoord.xy / vec2f(4.0, 4.0));
            })");

        // Set up the BT709 to sRGB color space conversion.
        wgpu::Status status = ComputeExternalTextureParams(
            {
                .primaries = wgpu::ColorSpacePrimariesDawn::Rec709,
                .transfer = wgpu::ColorSpaceTransferDawn::SMPTE_170M,
                .yCbCrRange = wgpu::ColorSpaceYCbCrRangeDawn::Narrow,
                .yCbCrMatrix = wgpu::ColorSpaceYCbCrMatrixDawn::Rec709,
            },
            wgpu::PredefinedColorSpace::SRGB, &bt709ColorSpaceParams);
        DAWN_ASSERT(status == wgpu::Status::Success);
    }

    wgpu::ExternalTextureDescriptor InitExternalTextureDescriptor(wgpu::Texture plane0,
                                                                  wgpu::Texture plane1 = nullptr) {
        wgpu::ExternalTextureDescriptor desc;
        desc.plane0 = plane0.CreateView();
        desc.plane1 = plane1 != nullptr ? plane1.CreateView() : nullptr;

        const auto& params = plane1 == nullptr ? noopRGBColorSpaceParams : bt709ColorSpaceParams;

        desc.yuvToRgbConversionMatrix = params.yuvToRgbConversionMatrix.data();
        desc.gamutConversionMatrix = params.gamutConversionMatrix.data();
        desc.srcTransferFunctionParameters = params.srcTransferFunction.data();
        desc.dstTransferFunctionParameters = params.dstTransferFunction.data();
        desc.cropOrigin = {0, 0};
        desc.cropSize = {plane0.GetWidth(), plane0.GetHeight()};
        desc.apparentSize = {plane0.GetWidth(), plane0.GetHeight()};

        return desc;
    }

    // Helper function to render a quad of data in a texture with a different color for each
    // corner as well as an optional color for the outside of the quad. (the quad can be scaled
    // to make it fill only parts of the texture).
    struct QuadData {
        std::array<float, 4> upperLeft;
        std::array<float, 4> upperRight;
        std::array<float, 4> lowerLeft;
        std::array<float, 4> lowerRight;
        std::array<float, 4> outsideData = {};
        float scale = 1.0;
        std::array<float, 3> padding = {};
    };
    void RenderQuad(const wgpu::Texture& texture, const QuadData& quad) {
        // Make the pipeline drawing a quad in the texture, taking the colors as a uniform buffer.
        wgpu::ShaderModule module = utils::CreateShaderModule(this->device, R"(
            struct VsOut {
                @builtin(position) pos : vec4f,
                @interpolate(perspective) @location(0) ndc : vec4f,
            }
            @vertex fn vs(@builtin(vertex_index) VertexIndex : u32) -> VsOut {
                var pos = array(
                    vec4f(-3, -1, 0, 1),
                    vec4f( 3, -1, 0, 1),
                    vec4f( 0,  2, 0, 1),
                );
                return VsOut(pos[VertexIndex], pos[VertexIndex]);
            }

            struct QuadData {
                upperLeft : vec4f,
                upperRight : vec4f,
                lowerLeft : vec4f,
                lowerRight : vec4f,
                outside : vec4f,
                scale : f32,
            }
            @group(0) @binding(0) var<uniform> quad : QuadData;
            @fragment fn fs(@interpolate(perspective) @location(0) ndc : vec4f)
                                     -> @location(0) vec4f {
                if abs(ndc.x) > quad.scale || abs(ndc.y) > quad.scale {
                    return quad.outside;
                }

                if ndc.x <= 0 && ndc.y >= 0 {
                    return quad.upperLeft;
                } else if ndc.x >= 0 && ndc.y >= 0 {
                    return quad.upperRight;
                } else if ndc.x <= 0 && ndc.y <= 0 {
                    return quad.lowerLeft;
                } else {
                    return quad.lowerRight;
                }
            })");

        utils::ComboRenderPipelineDescriptor pDesc;
        pDesc.vertex.module = module;
        pDesc.cFragment.module = module;
        pDesc.cTargets[0].format = texture.GetFormat();
        wgpu::RenderPipeline quadPipeline = this->device.CreateRenderPipeline(&pDesc);

        // Make the storage buffer and the bind group containing it.
        wgpu::Buffer quadData = utils::CreateBufferFromData(this->device, &quad, sizeof(quad),
                                                            wgpu::BufferUsage::Uniform);
        wgpu::BindGroup bg =
            utils::MakeBindGroup(this->device, quadPipeline.GetBindGroupLayout(0), {{0, quadData}});

        // Do the render.
        wgpu::CommandEncoder encoder = this->device.CreateCommandEncoder();
        utils::ComboRenderPassDescriptor renderPass({texture.CreateView()});
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
        pass.SetPipeline(quadPipeline);
        pass.SetBindGroup(0, bg);
        pass.Draw(3);
        pass.End();

        wgpu::CommandBuffer commands = encoder.Finish();
        this->queue.Submit(1, &commands);
    }

    wgpu::Texture MakeTestTexture(wgpu::TextureFormat format,
                                  uint32_t width,
                                  uint32_t height,
                                  wgpu::Color color) {
        wgpu::TextureDescriptor tDesc = {
            .usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding,
            .size = {width, height},
            .format = format,
        };
        wgpu::Texture texture = this->device.CreateTexture(&tDesc);

        // Use a render pass clear to set the value for the texture so that it works whatever the
        // format.
        wgpu::RenderPassColorAttachment attachment = {
            .view = texture.CreateView(),
            .loadOp = wgpu::LoadOp::Clear,
            .storeOp = wgpu::StoreOp::Store,
            .clearValue = color,
        };
        wgpu::RenderPassDescriptor rpDesc = {
            .colorAttachmentCount = 1,
            .colorAttachments = &attachment,
        };

        wgpu::CommandEncoder encoder = this->device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&rpDesc);
        pass.End();
        wgpu::CommandBuffer commands = encoder.Finish();
        this->queue.Submit(1, &commands);

        return texture;
    }

    void CheckColorSpaceConversion(wgpu::ColorSpaceDawn srcColorSpace,
                                   wgpu::PredefinedColorSpace dstColorSpace,
                                   wgpu::Color srcColor,
                                   std::array<float, 3> expectedColor) {
        // Create the external texture from the color spaces and srcColor.
        wgpu::Texture srcTexture =
            MakeTestTexture(wgpu::TextureFormat::RGBA16Float, 1, 1, srcColor);

        ExternalTextureColorSpaceParams colorSpaceParams;
        wgpu::Status status =
            ComputeExternalTextureParams(srcColorSpace, dstColorSpace, &colorSpaceParams);
        DAWN_ASSERT(status == wgpu::Status::Success);

        wgpu::ExternalTextureDescriptor etDesc;
        etDesc.plane0 = srcTexture.CreateView();
        etDesc.yuvToRgbConversionMatrix = colorSpaceParams.yuvToRgbConversionMatrix.data();
        etDesc.gamutConversionMatrix = colorSpaceParams.gamutConversionMatrix.data();
        etDesc.srcTransferFunctionParameters = colorSpaceParams.srcTransferFunction.data();
        etDesc.dstTransferFunctionParameters = colorSpaceParams.dstTransferFunction.data();
        etDesc.cropOrigin = {0, 0};
        etDesc.cropSize = {srcTexture.GetWidth(), srcTexture.GetHeight()};
        etDesc.apparentSize = {srcTexture.GetWidth(), srcTexture.GetHeight()};
        wgpu::ExternalTexture externalTexture = this->device.CreateExternalTexture(&etDesc);

        // Create the test pipeline that will just load the single texel of the ExternalTexture.
        wgpu::ComputePipelineDescriptor csDesc;
        csDesc.compute.module = utils::CreateShaderModule(this->device, R"(
            @group(0) @binding(0) var t : texture_external;
            @group(0) @binding(1) var<storage, read_write> results : vec4f;

            @compute @workgroup_size(1) fn main() {
                results = textureLoad(t, vec2(0));
            }
        )");
        wgpu::ComputePipeline pipeline = this->device.CreateComputePipeline(&csDesc);

        // Run the pipeline and store results in a buffer.
        wgpu::BufferDescriptor resultDesc = {
            .usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc,
            .size = sizeof(uint32_t) + 256,
        };
        wgpu::Buffer resultBuffer = this->device.CreateBuffer(&resultDesc);

        wgpu::BindGroup bindGroup =
            utils::MakeBindGroup(this->device, pipeline.GetBindGroupLayout(0),
                                 {{0, externalTexture}, {1, resultBuffer}});

        wgpu::CommandEncoder encoder = this->device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.SetBindGroup(0, bindGroup);
        pass.SetPipeline(pipeline);
        pass.DispatchWorkgroups(1);
        pass.End();

        wgpu::CommandBuffer commands = encoder.Finish();
        this->queue.Submit(1, &commands);

        // Check that we got the expected values. Make the tolerance 1% of the maximum expected
        // value as some of them can get somewhat large. (so a hardcoded .01 is too small).
        float tolerance = 0;
        for (auto [_, value] : Enumerate(expectedColor)) {
            tolerance = std::max(tolerance, std::abs(value) * 0.01f);
        }

        EXPECT_BUFFER_FLOAT_RANGE_TOLERANCE_EQ(expectedColor.data(), resultBuffer, 0, 3, tolerance);
        EXPECT_BUFFER_FLOAT_EQ(1.0, resultBuffer, 12);
    }

    static constexpr uint32_t kWidth = 4;
    static constexpr uint32_t kHeight = 4;
    static constexpr wgpu::TextureFormat kFormat = wgpu::TextureFormat::RGBA8Unorm;
    static constexpr wgpu::TextureUsage kSampledUsage = wgpu::TextureUsage::TextureBinding;

    wgpu::ShaderModule vsModule;
    wgpu::ShaderModule fsSampleExternalTextureModule;

    ExternalTextureColorSpaceParams noopRGBColorSpaceParams = GetNoopColorSpaceParams();
    ExternalTextureColorSpaceParams bt709ColorSpaceParams;
};

class ExternalTextureTests : public ExternalTextureTestsBase<DawnTest> {
  protected:
    std::vector<wgpu::FeatureName> GetRequiredFeatures() override {
        std::vector<wgpu::FeatureName> requiredFeatures = {};
        if (SupportsFeatures({wgpu::FeatureName::Unorm16TextureFormats})) {
            mIsUnorm16TextureFormatsSupported = true;
            requiredFeatures.push_back(wgpu::FeatureName::Unorm16TextureFormats);
        }
        return requiredFeatures;
    }

    bool IsUnorm16TextureFormatsSupported() { return mIsUnorm16TextureFormatsSupported; }

    bool mIsUnorm16TextureFormatsSupported = false;
};

TEST_P(ExternalTextureTests, CreateExternalTextureSuccess) {
    wgpu::Texture texture = Create2DTexture(device, kWidth, kHeight, kFormat, kSampledUsage);

    // Import the external texture
    wgpu::ExternalTextureDescriptor externalDesc = InitExternalTextureDescriptor(texture);
    wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);

    ASSERT_NE(externalTexture.Get(), nullptr);
}

TEST_P(ExternalTextureTests, SampleExternalTexture) {
    // TODO(crbug.com/dawn/2295): diagnose this failure on Pixel 4 OpenGLES
    DAWN_SUPPRESS_TEST_IF(IsOpenGLES() && IsAndroid() && IsQualcomm());

    // TODO(crbug.com/522868202): Produces incorrect result on Pixel 10.
    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsImgTec() && IsVulkan());

    wgpu::Texture sampledTexture =
        Create2DTexture(device, kWidth, kHeight, kFormat,
                        wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment);
    wgpu::Texture renderTexture =
        Create2DTexture(device, kWidth, kHeight, kFormat,
                        wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment);

    // Initialize texture with green to ensure it is sampled from later.
    {
        utils::ComboRenderPassDescriptor renderPass({sampledTexture.CreateView()}, nullptr);
        renderPass.cColorAttachments[0].clearValue = {0.0f, 1.0f, 0.0f, 1.0f};
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
        pass.End();

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

    // Pipeline Creation
    utils::ComboRenderPipelineDescriptor descriptor;
    descriptor.vertex.module = vsModule;
    descriptor.cFragment.module = fsSampleExternalTextureModule;
    descriptor.cTargets[0].format = kFormat;
    wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);

    // Import the external texture
    wgpu::ExternalTextureDescriptor externalDesc = InitExternalTextureDescriptor(sampledTexture);
    wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);

    // Create a sampler and bind group
    wgpu::Sampler sampler = device.CreateSampler();

    wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
                                                     {{0, sampler}, {1, externalTexture}});

    // Run the shader, which should sample from the external texture and draw a triangle into the
    // upper left corner of the render texture.
    wgpu::TextureView renderView = renderTexture.CreateView();
    utils::ComboRenderPassDescriptor renderPass({renderView});
    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
    {
        pass.SetPipeline(pipeline);
        pass.SetBindGroup(0, bindGroup);
        pass.Draw(3);
        pass.End();
    }

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

    EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kGreen, renderTexture, 0, 0);
}

// Tests that a texture view can be used for an externalTexture binding.
TEST_P(ExternalTextureTests, SampleTextureView) {
    // TODO(crbug.com/522868202): Produces incorrect result on Pixel 10.
    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsImgTec() && IsVulkan());

    wgpu::Texture sampledTexture =
        Create2DTexture(device, kWidth, kHeight, kFormat,
                        wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment);
    wgpu::Texture renderTexture =
        Create2DTexture(device, kWidth, kHeight, kFormat,
                        wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment);

    // Initialize texture with green to ensure it is sampled from later.
    {
        utils::ComboRenderPassDescriptor renderPass({sampledTexture.CreateView()}, nullptr);
        renderPass.cColorAttachments[0].clearValue = {0.0f, 1.0f, 0.0f, 1.0f};
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
        pass.End();

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

    // Pipeline Creation
    utils::ComboRenderPipelineDescriptor descriptor;
    descriptor.vertex.module = vsModule;
    descriptor.cFragment.module = fsSampleExternalTextureModule;
    descriptor.cTargets[0].format = kFormat;
    wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);

    wgpu::TextureView textureView = sampledTexture.CreateView();

    // Create a sampler and bind group that uses a TextureView for the external_texture in WGSL
    wgpu::Sampler sampler = device.CreateSampler();

    wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
                                                     {{0, sampler}, {1, textureView}});

    // Run the shader, which should sample from the texture view and draw a triangle into the
    // upper left corner of the render texture.
    wgpu::TextureView renderView = renderTexture.CreateView();
    utils::ComboRenderPassDescriptor renderPass({renderView});
    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
    {
        pass.SetPipeline(pipeline);
        pass.SetBindGroup(0, bindGroup);
        pass.Draw(3);
        pass.End();
    }

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

    EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kGreen, renderTexture, 0, 0);
}

// Tests that textureDimensions WGSL built-in function works when a texture view is used for an
// externalTexture binding.
TEST_P(ExternalTextureTests, TextureDimensionsWithTextureView) {
    DAWN_SUPPRESS_TEST_IF(IsWARP());  // Flaky on WARP

    // TODO(crbug.com/522868202): Produces incorrect result on Pixel 10.
    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsImgTec() && (IsVulkan() || IsOpenGLES()));

    wgpu::TextureDescriptor descriptor;
    descriptor.size = {kWidth, kHeight, 1};
    descriptor.mipLevelCount = 2;
    descriptor.dimension = wgpu::TextureDimension::e2D;
    descriptor.format = wgpu::TextureFormat::RGBA8Unorm;
    descriptor.usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment;
    wgpu::Texture texture = device.CreateTexture(&descriptor);

    for (const auto& mipLevel : {0, 1}) {
        wgpu::TextureViewDescriptor textureViewDesc;
        textureViewDesc.dimension = wgpu::TextureViewDimension::e2D;
        textureViewDesc.mipLevelCount = 1;
        textureViewDesc.baseMipLevel = mipLevel;
        wgpu::TextureView textureView = texture.CreateView(&textureViewDesc);

        // Create buffer that will store texture dimensions
        std::vector<uint32_t> data(2);
        std::vector<uint32_t> expected(2);
        if (mipLevel == 0) {
            expected = {kWidth, kHeight};
        } else {
            expected = {kWidth / 2, kHeight / 2};
        }
        uint64_t bufferSize = static_cast<uint64_t>(data.size() * sizeof(uint32_t));
        wgpu::Buffer buffer =
            utils::CreateBufferFromData(device, data.data(), bufferSize,
                                        wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc);

        wgpu::ShaderModule module = utils::CreateShaderModule(device, R"(
        @group(0) @binding(0) var texture : texture_external;
        @group(0) @binding(1) var<storage, read_write> buffer: vec2u;

        @compute @workgroup_size(1) fn main() {
            buffer = textureDimensions(texture);
        })");

        // Pipeline Creation
        wgpu::ComputePipelineDescriptor csDesc;
        csDesc.compute.module = module;
        wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&csDesc);

        // Set up bind group that uses a TextureView for the external_texture in WGSL
        wgpu::BindGroup bindGroup = utils::MakeBindGroup(
            device, pipeline.GetBindGroupLayout(0), {{0, textureView}, {1, buffer, 0, bufferSize}});

        // Issue dispatch
        wgpu::CommandBuffer commands;
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.SetPipeline(pipeline);
        pass.SetBindGroup(0, bindGroup);
        pass.DispatchWorkgroups(1);
        pass.End();
        commands = encoder.Finish();
        queue.Submit(1, &commands);

        EXPECT_BUFFER_U32_EQ(expected[0], buffer, 0);
        EXPECT_BUFFER_U32_EQ(expected[1], buffer, 4);
    }
}

// Tests that textureLoad WGSL built-in function works when a texture view is used for an
// externalTexture binding.
TEST_P(ExternalTextureTests, TextureLoadWithTextureView) {
    wgpu::Texture texture =
        MakeTestTexture(kFormat, kWidth, kHeight, {1.0 / 255.0, 2.0 / 255.0, 3.0 / 255.0, 1.0});

    // Create buffer that will store textureLoad result
    uint32_t kZero = 0;
    wgpu::Buffer buffer = utils::CreateBufferFromData(
        device, &kZero, sizeof(uint32_t), wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc);

    wgpu::ShaderModule module = utils::CreateShaderModule(device, R"(
        @group(0) @binding(0) var texture : texture_external;
        @group(0) @binding(1) var<storage, read_write> buffer: u32;

        @compute @workgroup_size(1) fn main() {
            buffer = pack4x8unorm(textureLoad(texture, vec2(0, 0)));
        })");

    // Pipeline Creation
    wgpu::ComputePipelineDescriptor csDesc;
    csDesc.compute.module = module;
    wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&csDesc);

    // Set up bind group that uses a TextureView for the external_texture in WGSL
    wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
                                                     {{0, texture.CreateView()}, {1, buffer}});

    // Issue dispatch
    wgpu::CommandBuffer commands;
    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
    pass.SetPipeline(pipeline);
    pass.SetBindGroup(0, bindGroup);
    pass.DispatchWorkgroups(1);
    pass.End();
    commands = encoder.Finish();
    queue.Submit(1, &commands);

    EXPECT_BUFFER_RGBA8_EQ(utils::RGBA8(1, 2, 3, 255), buffer, 0);
}

// https://crbug.com/1515439
TEST_P(ExternalTextureTests, SampleExternalTextureDifferingGroup) {
    // TODO(crbug.com/dawn/2295): diagnose this failure on Pixel 4 OpenGLES
    DAWN_SUPPRESS_TEST_IF(IsOpenGLES() && IsAndroid() && IsQualcomm());

    // TODO(crbug.com/522868202): Produces incorrect result on Pixel 10.
    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsImgTec() && IsVulkan());

    wgpu::Texture sampledTexture =
        Create2DTexture(device, kWidth, kHeight, kFormat,
                        wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment);
    wgpu::Texture renderTexture =
        Create2DTexture(device, kWidth, kHeight, kFormat,
                        wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment);

    // Initialize texture with green to ensure it is sampled from later.
    {
        utils::ComboRenderPassDescriptor renderPass({sampledTexture.CreateView()}, nullptr);
        renderPass.cColorAttachments[0].clearValue = {0.0f, 1.0f, 0.0f, 1.0f};
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
        pass.End();

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

    wgpu::ShaderModule fsModule = utils::CreateShaderModule(device, R"(
            @group(0) @binding(0) var s : sampler;
            @group(1) @binding(0) var t : texture_external;

            @fragment fn main(@builtin(position) FragCoord : vec4f)
                                     -> @location(0) vec4f {
                return textureSampleBaseClampToEdge(t, s, FragCoord.xy / vec2f(4.0, 4.0));
            })");

    // Pipeline Creation
    utils::ComboRenderPipelineDescriptor descriptor;
    descriptor.vertex.module = vsModule;
    descriptor.cFragment.module = fsModule;
    descriptor.cTargets[0].format = kFormat;
    wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);

    // Import the external texture
    wgpu::ExternalTextureDescriptor externalDesc = InitExternalTextureDescriptor(sampledTexture);
    wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);

    // Create a sampler and bind group
    wgpu::Sampler sampler = device.CreateSampler();

    wgpu::BindGroup samplerBindGroup =
        utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0), {{0, sampler}});
    wgpu::BindGroup texBindGroup =
        utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(1), {{0, externalTexture}});

    // Run the shader, which should sample from the external texture and draw a triangle into the
    // upper left corner of the render texture.
    wgpu::TextureView renderView = renderTexture.CreateView();
    utils::ComboRenderPassDescriptor renderPass({renderView}, nullptr);
    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
    {
        pass.SetPipeline(pipeline);
        pass.SetBindGroup(0, samplerBindGroup);
        pass.SetBindGroup(1, texBindGroup);
        pass.Draw(3);
        pass.End();
    }

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

    EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kGreen, renderTexture, 0, 0);
}

TEST_P(ExternalTextureTests, SampleMultiplanarExternalTexture) {
    // TODO(crbug.com/dawn/2295): diagnose this failure on Pixel 4 OpenGLES
    DAWN_SUPPRESS_TEST_IF(IsOpenGLES() && IsAndroid() && IsQualcomm());

    // TODO(https://crbug.com/468988322): Fails because of precision issues on Mac AMD.
    DAWN_SUPPRESS_TEST_IF(IsMetal() && IsAMD());

    // TODO(crbug.com/500766620): Fails on Windows 11/AMD RX 5500 XT.
    DAWN_SUPPRESS_TEST_IF(IsWindows11() && IsAMD());

    // TODO(crbug.com/522868202): Produces incorrect result on Pixel 10.
    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsImgTec() && IsVulkan());

    wgpu::Texture sampledTexturePlane0 =
        Create2DTexture(device, kWidth, kHeight, wgpu::TextureFormat::R8Unorm,
                        wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment);
    wgpu::Texture sampledTexturePlane1 =
        Create2DTexture(device, kWidth, kHeight, wgpu::TextureFormat::RG8Unorm,
                        wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment);

    wgpu::Texture renderTexture =
        Create2DTexture(device, kWidth, kHeight, kFormat,
                        wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment);

    // Create a texture view for the external texture
    wgpu::TextureView externalViewPlane0 = sampledTexturePlane0.CreateView();
    wgpu::TextureView externalViewPlane1 = sampledTexturePlane1.CreateView();

    for (const auto& expectation : {kBlack, kRed, kGreen, kBlue, kColor1}) {
        // Initialize the texture planes with YUV data
        {
            utils::ComboRenderPassDescriptor renderPass({externalViewPlane0, externalViewPlane1},
                                                        nullptr);
            renderPass.cColorAttachments[0].clearValue = {expectation.y, 0.0f, 0.0f, 0.0f};
            renderPass.cColorAttachments[1].clearValue = {expectation.u, expectation.v, 0.0f, 0.0f};
            wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
            wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
            pass.End();

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

        // Pipeline Creation
        utils::ComboRenderPipelineDescriptor descriptor;
        // descriptor.layout = utils::MakeBasicPipelineLayout(device, &bgl);
        descriptor.vertex.module = vsModule;
        descriptor.cFragment.module = fsSampleExternalTextureModule;
        descriptor.cTargets[0].format = kFormat;
        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);

        // Import the external texture
        wgpu::ExternalTextureDescriptor externalDesc =
            InitExternalTextureDescriptor(sampledTexturePlane0, sampledTexturePlane1);
        wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);

        // Create a sampler and bind group
        wgpu::Sampler sampler = device.CreateSampler();

        wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
                                                         {{0, sampler}, {1, externalTexture}});

        // Run the shader, which should sample from the external texture and draw a triangle into
        // the upper left corner of the render texture.
        wgpu::TextureView renderView = renderTexture.CreateView();
        utils::ComboRenderPassDescriptor renderPass({renderView}, nullptr);
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
        {
            pass.SetPipeline(pipeline);
            pass.SetBindGroup(0, bindGroup);
            pass.Draw(3);
            pass.End();
        }

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

        EXPECT_PIXEL_RGBA8_EQ(expectation.rgba, renderTexture, 0, 0);
    }
}

TEST_P(ExternalTextureTests, SampleMultiplanarExternalTextureNorm16) {
    DAWN_TEST_UNSUPPORTED_IF(!IsUnorm16TextureFormatsSupported());

    // TODO(crbug.com/dawn/2295): diagnose this failure on Pixel 4 OpenGLES
    DAWN_SUPPRESS_TEST_IF(IsOpenGLES() && IsAndroid() && IsQualcomm());

    // TODO(crbug.com/522868202): Produces incorrect result on Pixel 10.
    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsImgTec() && IsVulkan());

    wgpu::Texture sampledTexturePlane0 =
        Create2DTexture(device, kWidth, kHeight, wgpu::TextureFormat::R16Unorm,
                        wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment);
    wgpu::Texture sampledTexturePlane1 =
        Create2DTexture(device, kWidth, kHeight, wgpu::TextureFormat::RG16Unorm,
                        wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment);

    wgpu::Texture renderTexture =
        Create2DTexture(device, kWidth, kHeight, kFormat,
                        wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment);

    // Create a texture view for the external texture
    wgpu::TextureView externalViewPlane0 = sampledTexturePlane0.CreateView();
    wgpu::TextureView externalViewPlane1 = sampledTexturePlane1.CreateView();

    for (const auto& expectation : {kBlack, kRed, kGreen, kBlue, kColor1}) {
        // Initialize the texture planes with YUV data
        {
            utils::ComboRenderPassDescriptor renderPass({externalViewPlane0, externalViewPlane1},
                                                        nullptr);
            renderPass.cColorAttachments[0].clearValue = {expectation.y, 0.0f, 0.0f, 0.0f};
            renderPass.cColorAttachments[1].clearValue = {expectation.u, expectation.v, 0.0f, 0.0f};
            wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
            wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
            pass.End();

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

        // Pipeline Creation
        utils::ComboRenderPipelineDescriptor descriptor;
        descriptor.vertex.module = vsModule;
        descriptor.cFragment.module = fsSampleExternalTextureModule;
        descriptor.cTargets[0].format = kFormat;
        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);

        // Import the external texture
        wgpu::ExternalTextureDescriptor externalDesc =
            InitExternalTextureDescriptor(sampledTexturePlane0, sampledTexturePlane1);
        wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);

        // Create a sampler and bind group
        wgpu::Sampler sampler = device.CreateSampler();

        wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
                                                         {{0, sampler}, {1, externalTexture}});

        // Run the shader, which should sample from the external texture and draw a triangle into
        // the upper left corner of the render texture.
        wgpu::TextureView renderView = renderTexture.CreateView();
        utils::ComboRenderPassDescriptor renderPass({renderView}, nullptr);
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
        {
            pass.SetPipeline(pipeline);
            pass.SetBindGroup(0, bindGroup);
            pass.Draw(3);
            pass.End();
        }

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

        EXPECT_PIXEL_RGBA8_EQ(expectation.rgba, renderTexture, 0, 0);
    }
}

// Test draws a green square in the upper left quadrant, a black square in the upper right, a red
// square in the lower left and a blue square in the lower right. The image is then sampled as an
// external texture and rotated 0, 90, 180, and 270 degrees with and without the y-axis flipped.
TEST_P(ExternalTextureTests, RotateAndOrFlipSampleSinglePlane) {
    // TODO(crbug.com/dawn/2295): diagnose this failure on Pixel 4 OpenGLES
    DAWN_SUPPRESS_TEST_IF(IsOpenGLES() && IsAndroid() && IsQualcomm());

    // TODO(crbug.com/522868202): Produces incorrect result on Pixel 10.
    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsImgTec() && IsVulkan());

    wgpu::Texture sourceTexture =
        Create2DTexture(device, kWidth, kHeight, kFormat,
                        wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment);
    RenderQuad(sourceTexture,
               {kGreen.rgbaFloats, kBlack.rgbaFloats, kRed.rgbaFloats, kBlue.rgbaFloats});

    wgpu::Texture renderTexture =
        Create2DTexture(device, kWidth, kHeight, kFormat,
                        wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment);

    // Control case to verify mirrored and rotation defaults
    {
        // Pipeline Creation
        utils::ComboRenderPipelineDescriptor descriptor;
        descriptor.vertex.module = vsModule;
        descriptor.cFragment.module = fsSampleExternalTextureModule;
        descriptor.cTargets[0].format = kFormat;
        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);

        // Import the external texture
        wgpu::ExternalTextureDescriptor externalDesc = InitExternalTextureDescriptor(sourceTexture);
        wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);

        // Create a sampler and bind group
        wgpu::Sampler sampler = device.CreateSampler();

        wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
                                                         {{0, sampler}, {1, externalTexture}});

        // Run the shader, which should sample from the external texture and draw a triangle into
        // the upper left corner of the render texture.
        wgpu::TextureView renderView = renderTexture.CreateView();
        utils::ComboRenderPassDescriptor renderPass({renderView}, nullptr);
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
        {
            pass.SetPipeline(pipeline);
            pass.SetBindGroup(0, bindGroup);
            pass.Draw(3);
            pass.End();
        }

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

        EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kGreen, renderTexture, 0, 0);
        EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kBlack, renderTexture, 3, 0);
        EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kRed, renderTexture, 0, 3);
        EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kBlue, renderTexture, 3, 3);
    }

    struct RotationExpectation {
        wgpu::ExternalTextureRotation rotation;
        bool mirrored;
        utils::RGBA8 upperLeftColor;
        utils::RGBA8 upperRightColor;
        utils::RGBA8 lowerLeftColor;
        utils::RGBA8 lowerRightColor;
    };

    std::array<RotationExpectation, 8> expectations = {
        {{wgpu::ExternalTextureRotation::Rotate0Degrees, false, utils::RGBA8::kGreen,
          utils::RGBA8::kBlack, utils::RGBA8::kRed, utils::RGBA8::kBlue},
         {wgpu::ExternalTextureRotation::Rotate90Degrees, false, utils::RGBA8::kRed,
          utils::RGBA8::kGreen, utils::RGBA8::kBlue, utils::RGBA8::kBlack},
         {wgpu::ExternalTextureRotation::Rotate180Degrees, false, utils::RGBA8::kBlue,
          utils::RGBA8::kRed, utils::RGBA8::kBlack, utils::RGBA8::kGreen},
         {wgpu::ExternalTextureRotation::Rotate270Degrees, false, utils::RGBA8::kBlack,
          utils::RGBA8::kBlue, utils::RGBA8::kGreen, utils::RGBA8::kRed},
         {wgpu::ExternalTextureRotation::Rotate0Degrees, true, utils::RGBA8::kBlack,
          utils::RGBA8::kGreen, utils::RGBA8::kBlue, utils::RGBA8::kRed},
         {wgpu::ExternalTextureRotation::Rotate90Degrees, true, utils::RGBA8::kGreen,
          utils::RGBA8::kRed, utils::RGBA8::kBlack, utils::RGBA8::kBlue},
         {wgpu::ExternalTextureRotation::Rotate180Degrees, true, utils::RGBA8::kRed,
          utils::RGBA8::kBlue, utils::RGBA8::kGreen, utils::RGBA8::kBlack},
         {wgpu::ExternalTextureRotation::Rotate270Degrees, true, utils::RGBA8::kBlue,
          utils::RGBA8::kBlack, utils::RGBA8::kRed, utils::RGBA8::kGreen}}};

    for (const RotationExpectation& exp : expectations) {
        // Pipeline Creation
        utils::ComboRenderPipelineDescriptor descriptor;
        descriptor.vertex.module = vsModule;
        descriptor.cFragment.module = fsSampleExternalTextureModule;
        descriptor.cTargets[0].format = kFormat;
        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);

        // Import the external texture
        wgpu::ExternalTextureDescriptor externalDesc = InitExternalTextureDescriptor(sourceTexture);
        externalDesc.rotation = exp.rotation;
        externalDesc.mirrored = exp.mirrored;
        wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);

        // Create a sampler and bind group
        wgpu::Sampler sampler = device.CreateSampler();

        wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
                                                         {{0, sampler}, {1, externalTexture}});

        // Run the shader, which should sample from the external texture and draw a triangle into
        // the upper left corner of the render texture.
        wgpu::TextureView renderView = renderTexture.CreateView();
        utils::ComboRenderPassDescriptor renderPass({renderView}, nullptr);
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
        {
            pass.SetPipeline(pipeline);
            pass.SetBindGroup(0, bindGroup);
            pass.Draw(3);
            pass.End();
        }

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

        EXPECT_PIXEL_RGBA8_EQ(exp.upperLeftColor, renderTexture, 0, 0);
        EXPECT_PIXEL_RGBA8_EQ(exp.upperLeftColor, renderTexture, 1, 1);
        EXPECT_PIXEL_RGBA8_EQ(exp.upperRightColor, renderTexture, 3, 0);
        EXPECT_PIXEL_RGBA8_EQ(exp.upperRightColor, renderTexture, 2, 1);
        EXPECT_PIXEL_RGBA8_EQ(exp.lowerLeftColor, renderTexture, 0, 3);
        EXPECT_PIXEL_RGBA8_EQ(exp.lowerLeftColor, renderTexture, 1, 2);
        EXPECT_PIXEL_RGBA8_EQ(exp.lowerRightColor, renderTexture, 3, 3);
        EXPECT_PIXEL_RGBA8_EQ(exp.lowerRightColor, renderTexture, 2, 2);
    }
}

// Test for a bug found during review where the cropSize was not correctly rotated during the
// initialization of the ExternalTexture, which could lead to incorrect textureLoad operations when
// rotating 90 and 270 degrees.
TEST_P(ExternalTextureTests, RotateAndOrFlipTextureLoadSinglePlaneNotSquare) {
    // TODO(crbug.com/dawn/2295): diagnose this failure on Pixel 4 OpenGLES
    DAWN_SUPPRESS_TEST_IF(IsOpenGLES() && IsAndroid() && IsQualcomm());

    // TODO(crbug.com/522868202): Produces incorrect result on Pixel 10.
    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsImgTec() && IsVulkan());

    wgpu::Texture sourceTexture =
        Create2DTexture(device, 2, 16, kFormat,
                        wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment);
    RenderQuad(sourceTexture,
               {kGreen.rgbaFloats, kBlack.rgbaFloats, kRed.rgbaFloats, kBlue.rgbaFloats});

    wgpu::Texture renderTexture = Create2DTexture(
        device, 2, 2, kFormat, wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment);
    wgpu::Texture dimensionTexture =
        Create2DTexture(device, 2, 2, wgpu::TextureFormat::RG32Uint,
                        wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment);

    struct RotationExpectation {
        wgpu::ExternalTextureRotation rotation;
        bool mirrored;
        utils::RGBA8 upperLeftColor;
        utils::RGBA8 upperRightColor;
        utils::RGBA8 lowerLeftColor;
        utils::RGBA8 lowerRightColor;
    };
    std::array<RotationExpectation, 8> expectations = {
        {{wgpu::ExternalTextureRotation::Rotate0Degrees, false, utils::RGBA8::kGreen,
          utils::RGBA8::kBlack, utils::RGBA8::kRed, utils::RGBA8::kBlue},
         {wgpu::ExternalTextureRotation::Rotate90Degrees, false, utils::RGBA8::kRed,
          utils::RGBA8::kGreen, utils::RGBA8::kBlue, utils::RGBA8::kBlack},
         {wgpu::ExternalTextureRotation::Rotate180Degrees, false, utils::RGBA8::kBlue,
          utils::RGBA8::kRed, utils::RGBA8::kBlack, utils::RGBA8::kGreen},
         {wgpu::ExternalTextureRotation::Rotate270Degrees, false, utils::RGBA8::kBlack,
          utils::RGBA8::kBlue, utils::RGBA8::kGreen, utils::RGBA8::kRed},
         {wgpu::ExternalTextureRotation::Rotate0Degrees, true, utils::RGBA8::kBlack,
          utils::RGBA8::kGreen, utils::RGBA8::kBlue, utils::RGBA8::kRed},
         {wgpu::ExternalTextureRotation::Rotate90Degrees, true, utils::RGBA8::kGreen,
          utils::RGBA8::kRed, utils::RGBA8::kBlack, utils::RGBA8::kBlue},
         {wgpu::ExternalTextureRotation::Rotate180Degrees, true, utils::RGBA8::kRed,
          utils::RGBA8::kBlue, utils::RGBA8::kGreen, utils::RGBA8::kBlack},
         {wgpu::ExternalTextureRotation::Rotate270Degrees, true, utils::RGBA8::kBlue,
          utils::RGBA8::kBlack, utils::RGBA8::kRed, utils::RGBA8::kGreen}}};

    wgpu::ShaderModule loadModule = utils::CreateShaderModule(device, R"(
        @group(0) @binding(0) var t : texture_external;

        struct FragOut {
          @location(0) color: vec4f,
          @location(1) dimension: vec2u,
        };

        @fragment fn main(@builtin(position) FragCoord : vec4f)
                                 -> FragOut {
            let dimension = textureDimensions(t);
            let coords = textureDimensions(t) / 2 + vec2u(FragCoord.xy) - vec2(1, 1);
            return FragOut(textureLoad(t, coords), dimension);
        })");

    wgpu::BufferDescriptor dimensionBufferDesc;
    dimensionBufferDesc.size = 256;
    dimensionBufferDesc.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::CopySrc;
    wgpu::Buffer dimensionBuffer = device.CreateBuffer(&dimensionBufferDesc);

    for (const RotationExpectation& exp : expectations) {
        // Pipeline Creation
        utils::ComboRenderPipelineDescriptor descriptor;
        descriptor.vertex.module = vsModule;
        descriptor.cFragment.module = loadModule;
        descriptor.cFragment.targetCount = 2;
        descriptor.cTargets[0].format = kFormat;
        descriptor.cTargets[1].format = wgpu::TextureFormat::RG32Uint;
        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);

        // Import the external texture and make the bindgroup.
        wgpu::ExternalTextureDescriptor externalDesc = InitExternalTextureDescriptor(sourceTexture);
        externalDesc.rotation = exp.rotation;
        externalDesc.mirrored = exp.mirrored;

        wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);
        wgpu::BindGroup bindGroup =
            utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0), {{0, externalTexture}});

        // Run the shader, which should sample from the external texture and draw a triangle into
        // the upper left corner of the render texture.
        utils::ComboRenderPassDescriptor renderPass(
            {renderTexture.CreateView(), dimensionTexture.CreateView()});
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
        pass.SetPipeline(pipeline);
        pass.SetBindGroup(0, bindGroup);
        pass.Draw(3);
        pass.End();

        {
            wgpu::TexelCopyTextureInfo texelCopyTextureInfo =
                utils::CreateTexelCopyTextureInfo(dimensionTexture, 0, {0, 0, 0});
            wgpu::TexelCopyBufferInfo texelCopyBufferInfo =
                utils::CreateTexelCopyBufferInfo(dimensionBuffer, 0, 256, 1);
            wgpu::Extent3D size = {1, 1, 1};
            encoder.CopyTextureToBuffer(&texelCopyTextureInfo, &texelCopyBufferInfo, &size);
        }

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

        EXPECT_PIXEL_RGBA8_EQ(exp.upperLeftColor, renderTexture, 0, 0);
        EXPECT_PIXEL_RGBA8_EQ(exp.upperRightColor, renderTexture, 1, 0);
        EXPECT_PIXEL_RGBA8_EQ(exp.lowerLeftColor, renderTexture, 0, 1);
        EXPECT_PIXEL_RGBA8_EQ(exp.lowerRightColor, renderTexture, 1, 1);

        if (exp.rotation == wgpu::ExternalTextureRotation::Rotate90Degrees ||
            exp.rotation == wgpu::ExternalTextureRotation::Rotate270Degrees) {
            EXPECT_BUFFER_U32_EQ(sourceTexture.GetHeight(), dimensionBuffer, 0);
            EXPECT_BUFFER_U32_EQ(sourceTexture.GetWidth(), dimensionBuffer, 4);
        } else {
            EXPECT_BUFFER_U32_EQ(sourceTexture.GetWidth(), dimensionBuffer, 0);
            EXPECT_BUFFER_U32_EQ(sourceTexture.GetHeight(), dimensionBuffer, 4);
        }
    }
}

// Test draws a green square in the upper left quadrant, a black square in the upper right, a red
// square in the lower left and a blue square in the lower right. The image is then sampled as an
// external texture and rotated 0, 90, 180, and 270 degrees with and without the y-axis flipped.
TEST_P(ExternalTextureTests, RotateAndOrFlipSampleMultiplanar) {
    // TODO(crbug.com/dawn/2295): diagnose this failure on Pixel 4 OpenGLES
    DAWN_SUPPRESS_TEST_IF(IsOpenGLES() && IsAndroid() && IsQualcomm());

    // TODO(crbug.com/522868202): Produces incorrect result on Pixel 10.
    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsImgTec() && IsVulkan());

    wgpu::Texture sourceTexturePlane0 =
        Create2DTexture(device, kWidth, kHeight, wgpu::TextureFormat::R8Unorm,
                        wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment);
    wgpu::Texture sourceTexturePlane1 =
        Create2DTexture(device, kWidth, kHeight, wgpu::TextureFormat::RG8Unorm,
                        wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment);
    RenderQuad(sourceTexturePlane0, {{kGreen.y}, {kBlack.y}, {kRed.y}, {kBlue.y}});
    RenderQuad(sourceTexturePlane1,
               {{kGreen.u, kGreen.v}, {kBlack.u, kBlack.v}, {kRed.u, kRed.v}, {kBlue.u, kBlue.v}});

    wgpu::Texture renderTexture =
        Create2DTexture(device, kWidth, kHeight, kFormat,
                        wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment);

    // Control case to verify mirrored and rotation defaults
    {
        // Pipeline Creation
        utils::ComboRenderPipelineDescriptor descriptor;
        descriptor.vertex.module = vsModule;
        descriptor.cFragment.module = fsSampleExternalTextureModule;
        descriptor.cTargets[0].format = kFormat;
        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);

        // Create an ExternalTextureDescriptor from the texture view
        wgpu::ExternalTextureDescriptor externalDesc =
            InitExternalTextureDescriptor(sourceTexturePlane0, sourceTexturePlane1);

        // Import the external texture
        wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);

        // Create a sampler and bind group
        wgpu::Sampler sampler = device.CreateSampler();

        wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
                                                         {{0, sampler}, {1, externalTexture}});

        // Run the shader, which should sample from the external texture and draw a triangle into
        // the upper left corner of the render texture.
        wgpu::TextureView renderView = renderTexture.CreateView();
        utils::ComboRenderPassDescriptor renderPass({renderView}, nullptr);
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
        {
            pass.SetPipeline(pipeline);
            pass.SetBindGroup(0, bindGroup);
            pass.Draw(3);
            pass.End();
        }

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

        EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kGreen, renderTexture, 0, 0);
        EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kBlack, renderTexture, 3, 0);
        EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kRed, renderTexture, 0, 3);
        EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kBlue, renderTexture, 3, 3);
    }

    struct RotationExpectation {
        wgpu::ExternalTextureRotation rotation;
        bool mirrored;
        utils::RGBA8 upperLeftColor;
        utils::RGBA8 upperRightColor;
        utils::RGBA8 lowerLeftColor;
        utils::RGBA8 lowerRightColor;
    };

    std::array<RotationExpectation, 8> expectations = {
        {{wgpu::ExternalTextureRotation::Rotate0Degrees, false, utils::RGBA8::kGreen,
          utils::RGBA8::kBlack, utils::RGBA8::kRed, utils::RGBA8::kBlue},
         {wgpu::ExternalTextureRotation::Rotate90Degrees, false, utils::RGBA8::kRed,
          utils::RGBA8::kGreen, utils::RGBA8::kBlue, utils::RGBA8::kBlack},
         {wgpu::ExternalTextureRotation::Rotate180Degrees, false, utils::RGBA8::kBlue,
          utils::RGBA8::kRed, utils::RGBA8::kBlack, utils::RGBA8::kGreen},
         {wgpu::ExternalTextureRotation::Rotate270Degrees, false, utils::RGBA8::kBlack,
          utils::RGBA8::kBlue, utils::RGBA8::kGreen, utils::RGBA8::kRed},
         {wgpu::ExternalTextureRotation::Rotate0Degrees, true, utils::RGBA8::kBlack,
          utils::RGBA8::kGreen, utils::RGBA8::kBlue, utils::RGBA8::kRed},
         {wgpu::ExternalTextureRotation::Rotate90Degrees, true, utils::RGBA8::kGreen,
          utils::RGBA8::kRed, utils::RGBA8::kBlack, utils::RGBA8::kBlue},
         {wgpu::ExternalTextureRotation::Rotate180Degrees, true, utils::RGBA8::kRed,
          utils::RGBA8::kBlue, utils::RGBA8::kGreen, utils::RGBA8::kBlack},
         {wgpu::ExternalTextureRotation::Rotate270Degrees, true, utils::RGBA8::kBlue,
          utils::RGBA8::kBlack, utils::RGBA8::kRed, utils::RGBA8::kGreen}}};

    for (const RotationExpectation& exp : expectations) {
        // Pipeline Creation
        utils::ComboRenderPipelineDescriptor descriptor;
        descriptor.vertex.module = vsModule;
        descriptor.cFragment.module = fsSampleExternalTextureModule;
        descriptor.cTargets[0].format = kFormat;
        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);

        // Import the external texture
        wgpu::ExternalTextureDescriptor externalDesc =
            InitExternalTextureDescriptor(sourceTexturePlane0, sourceTexturePlane1);
        externalDesc.rotation = exp.rotation;
        externalDesc.mirrored = exp.mirrored;
        wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);

        // Create a sampler and bind group
        wgpu::Sampler sampler = device.CreateSampler();

        wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
                                                         {{0, sampler}, {1, externalTexture}});

        // Run the shader, which should sample from the external texture and draw a triangle into
        // the upper left corner of the render texture.
        wgpu::TextureView renderView = renderTexture.CreateView();
        utils::ComboRenderPassDescriptor renderPass({renderView}, nullptr);
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
        {
            pass.SetPipeline(pipeline);
            pass.SetBindGroup(0, bindGroup);
            pass.Draw(3);
            pass.End();
        }

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

        EXPECT_PIXEL_RGBA8_EQ(exp.upperLeftColor, renderTexture, 0, 0);
        EXPECT_PIXEL_RGBA8_EQ(exp.upperLeftColor, renderTexture, 1, 1);
        EXPECT_PIXEL_RGBA8_EQ(exp.upperRightColor, renderTexture, 3, 0);
        EXPECT_PIXEL_RGBA8_EQ(exp.upperRightColor, renderTexture, 2, 1);
        EXPECT_PIXEL_RGBA8_EQ(exp.lowerLeftColor, renderTexture, 0, 3);
        EXPECT_PIXEL_RGBA8_EQ(exp.lowerLeftColor, renderTexture, 1, 2);
        EXPECT_PIXEL_RGBA8_EQ(exp.lowerRightColor, renderTexture, 3, 3);
        EXPECT_PIXEL_RGBA8_EQ(exp.lowerRightColor, renderTexture, 2, 2);
    }
}

// This test draws a 2x2 multi-colored square surrounded by a 1px black border. We test the external
// texture crop functionality by cropping to specific ranges inside the texture.
TEST_P(ExternalTextureTests, CropSinglePlane) {
    // TODO(crbug.com/dawn/2295): diagnose this failure on Pixel 4 OpenGLES
    DAWN_SUPPRESS_TEST_IF(IsOpenGLES() && IsAndroid() && IsQualcomm());

    // TODO(crbug.com/522868202): Produces incorrect result on Pixel 10.
    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsImgTec() && IsVulkan());

    wgpu::Texture sourceTexture =
        Create2DTexture(device, kWidth, kHeight, kFormat,
                        wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment);
    RenderQuad(sourceTexture, {kGreen.rgbaFloats, kColor1.rgbaFloats, kRed.rgbaFloats,
                               kBlue.rgbaFloats, kBlack.rgbaFloats, 0.5});

    wgpu::Texture renderTexture =
        Create2DTexture(device, kWidth, kHeight, kFormat,
                        wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment);

    struct CropExpectation {
        wgpu::Origin2D cropOrigin;
        wgpu::Extent2D cropSize;
        wgpu::ExternalTextureRotation rotation;
        utils::RGBA8 upperLeftColor;
        utils::RGBA8 upperRightColor;
        utils::RGBA8 lowerLeftColor;
        utils::RGBA8 lowerRightColor;
    };

    std::array<CropExpectation, 9> expectations = {{
        {{0, 0},
         {kWidth, kHeight},
         wgpu::ExternalTextureRotation::Rotate0Degrees,
         utils::RGBA8::kBlack,
         utils::RGBA8::kBlack,
         utils::RGBA8::kBlack,
         utils::RGBA8::kBlack},
        {{kWidth / 4, kHeight / 4},
         {kWidth / 4, kHeight / 4},
         wgpu::ExternalTextureRotation::Rotate0Degrees,
         utils::RGBA8::kGreen,
         utils::RGBA8::kGreen,
         utils::RGBA8::kGreen,
         utils::RGBA8::kGreen},
        {{kWidth / 2, kHeight / 4},
         {kWidth / 4, kHeight / 4},
         wgpu::ExternalTextureRotation::Rotate0Degrees,
         kColor1.rgba,
         kColor1.rgba,
         kColor1.rgba,
         kColor1.rgba},
        {{kWidth / 4, kHeight / 2},
         {kWidth / 4, kHeight / 4},
         wgpu::ExternalTextureRotation::Rotate0Degrees,
         utils::RGBA8::kRed,
         utils::RGBA8::kRed,
         utils::RGBA8::kRed,
         utils::RGBA8::kRed},
        {{kWidth / 2, kHeight / 2},
         {kWidth / 4, kHeight / 4},
         wgpu::ExternalTextureRotation::Rotate0Degrees,
         utils::RGBA8::kBlue,
         utils::RGBA8::kBlue,
         utils::RGBA8::kBlue,
         utils::RGBA8::kBlue},
        {{kWidth / 4, kHeight / 4},
         {kWidth / 2, kHeight / 2},
         wgpu::ExternalTextureRotation::Rotate0Degrees,
         utils::RGBA8::kGreen,
         kColor1.rgba,
         utils::RGBA8::kRed,
         utils::RGBA8::kBlue},
        {{kWidth / 4, kHeight / 4},
         {kWidth / 2, kHeight / 2},
         wgpu::ExternalTextureRotation::Rotate90Degrees,
         utils::RGBA8::kRed,
         utils::RGBA8::kGreen,
         utils::RGBA8::kBlue,
         kColor1.rgba},
        {{kWidth / 4, kHeight / 4},
         {kWidth / 2, kHeight / 2},
         wgpu::ExternalTextureRotation::Rotate180Degrees,
         utils::RGBA8::kBlue,
         utils::RGBA8::kRed,
         kColor1.rgba,
         utils::RGBA8::kGreen},
        {{kWidth / 4, kHeight / 4},
         {kWidth / 2, kHeight / 2},
         wgpu::ExternalTextureRotation::Rotate270Degrees,
         kColor1.rgba,
         utils::RGBA8::kBlue,
         utils::RGBA8::kGreen,
         utils::RGBA8::kRed},
    }};

    for (const CropExpectation& exp : expectations) {
        // Pipeline Creation
        utils::ComboRenderPipelineDescriptor descriptor;
        descriptor.vertex.module = vsModule;
        descriptor.cFragment.module = fsSampleExternalTextureModule;
        descriptor.cTargets[0].format = kFormat;
        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);

        // Import the external texture
        wgpu::ExternalTextureDescriptor externalDesc = InitExternalTextureDescriptor(sourceTexture);
        externalDesc.rotation = exp.rotation;
        externalDesc.cropOrigin = exp.cropOrigin;
        externalDesc.cropSize = exp.cropSize;
        externalDesc.apparentSize = exp.cropSize;
        wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);

        // Create a sampler and bind group
        wgpu::Sampler sampler = device.CreateSampler();

        wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
                                                         {{0, sampler}, {1, externalTexture}});

        // Run the shader, which should sample from the external texture and draw a triangle into
        // the upper left corner of the render texture.
        wgpu::TextureView renderView = renderTexture.CreateView();
        utils::ComboRenderPassDescriptor renderPass({renderView}, nullptr);
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
        {
            pass.SetPipeline(pipeline);
            pass.SetBindGroup(0, bindGroup);
            pass.Draw(3);
            pass.End();
        }

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

        EXPECT_PIXEL_RGBA8_EQ(exp.upperLeftColor, renderTexture, 0, 0);
        EXPECT_PIXEL_RGBA8_EQ(exp.upperRightColor, renderTexture, 3, 0);
        EXPECT_PIXEL_RGBA8_EQ(exp.lowerLeftColor, renderTexture, 0, 3);
        EXPECT_PIXEL_RGBA8_EQ(exp.lowerRightColor, renderTexture, 3, 3);
    }
}

// Test that the apparentSize takes effect by using it to scale a texture and "blitting" it.
TEST_P(ExternalTextureTests, ApparentSizeEffect) {
    // TODO(crbug.com/522868202): Produces incorrect result on Pixel 10.
    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsImgTec() && IsVulkan());

    // Create the test pipeline
    wgpu::ShaderModule blitAndOutputSize = utils::CreateShaderModule(this->device, R"(
        @group(0) @binding(0) var t : texture_external;

        struct FragOut {
          @location(0) color: vec4f,
          @location(1) dimension: vec2u,
        };

        @fragment fn main(@builtin(position) FragCoord : vec4f)
                                 -> FragOut {
            let dimensions = textureDimensions(t);
            return FragOut(textureLoad(t, vec2u(FragCoord.xy)), dimensions);
        })");

    utils::ComboRenderPipelineDescriptor descriptor;
    descriptor.vertex.module = vsModule;
    descriptor.cFragment.module = blitAndOutputSize;
    descriptor.cFragment.targetCount = 2;
    descriptor.cTargets[0].format = kFormat;
    descriptor.cTargets[1].format = wgpu::TextureFormat::RG32Uint;
    wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);

    // The source texture will contain a quad and have a larger apparent size.
    wgpu::Texture sourceTexture =
        Create2DTexture(device, 2, 2, kFormat,
                        wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment);
    RenderQuad(sourceTexture,
               {kGreen.rgbaFloats, kColor1.rgbaFloats, kRed.rgbaFloats, kBlue.rgbaFloats});

    wgpu::ExternalTextureDescriptor externalDesc = InitExternalTextureDescriptor(sourceTexture);
    externalDesc.apparentSize = {8, 16};
    wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);

    // The texture that will receive the blit operation, uses apparentSize
    wgpu::Texture renderTexture = Create2DTexture(
        device, externalDesc.apparentSize.width, externalDesc.apparentSize.height, kFormat,
        wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment);
    wgpu::Texture dimensionTexture =
        Create2DTexture(device, externalDesc.apparentSize.width, externalDesc.apparentSize.height,
                        wgpu::TextureFormat::RG32Uint,
                        wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment);

    // The buffer that will receive the result of `textureDimensions`
    wgpu::BufferDescriptor bufDesc;
    bufDesc.size = 256;
    bufDesc.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::CopySrc;
    wgpu::Buffer dimensionBuffer = device.CreateBuffer(&bufDesc);

    wgpu::BindGroup bindGroup =
        utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0), {{0, externalTexture}});

    // Do the blit
    utils::ComboRenderPassDescriptor renderPass(
        {renderTexture.CreateView(), dimensionTexture.CreateView()});
    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
    {
        pass.SetPipeline(pipeline);
        pass.SetBindGroup(0, bindGroup);
        pass.Draw(3);
        pass.End();
    }

    {
        wgpu::TexelCopyTextureInfo texelCopyTextureInfo =
            utils::CreateTexelCopyTextureInfo(dimensionTexture, 0, {0, 0, 0});
        wgpu::TexelCopyBufferInfo texelCopyBufferInfo =
            utils::CreateTexelCopyBufferInfo(dimensionBuffer, 0, 256, 1);
        wgpu::Extent3D size = {1, 1, 1};
        encoder.CopyTextureToBuffer(&texelCopyTextureInfo, &texelCopyBufferInfo, &size);
    }

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

    // Check that the apparentSize is correct and that the center of the quad has moved due to the
    // scaling with apparentSize.
    EXPECT_BUFFER_U32_EQ(externalDesc.apparentSize.width, dimensionBuffer, 0);
    EXPECT_BUFFER_U32_EQ(externalDesc.apparentSize.height, dimensionBuffer, 4);

    EXPECT_PIXEL_RGBA8_EQ(kGreen.rgba, renderTexture, 3, 7);
    EXPECT_PIXEL_RGBA8_EQ(kColor1.rgba, renderTexture, 4, 7);
    EXPECT_PIXEL_RGBA8_EQ(kRed.rgba, renderTexture, 3, 8);
    EXPECT_PIXEL_RGBA8_EQ(kBlue.rgba, renderTexture, 4, 8);
}

// This test draws a 2x2 multi-colored square surrounded by a 1px black border. We test the external
// texture crop functionality by cropping to specific ranges inside the texture.
TEST_P(ExternalTextureTests, CropMultiplanar) {
    // TODO(crbug.com/dawn/2295): diagnose this failure on Pixel 4 OpenGLES
    DAWN_SUPPRESS_TEST_IF(IsOpenGLES() && IsAndroid() && IsQualcomm());

    // TODO(https://crbug.com/468988322): Fails because of precision issues on Mac AMD.
    DAWN_SUPPRESS_TEST_IF(IsMetal() && IsAMD());

    // TODO(crbug.com/500766620): Fails on Windows 11/AMD RX 5500 XT.
    DAWN_SUPPRESS_TEST_IF(IsWindows11() && IsAMD());

    // TODO(crbug.com/522868202): Produces incorrect result on Pixel 10.
    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsImgTec() && IsVulkan());

    wgpu::Texture sourceTexturePlane0 =
        Create2DTexture(device, kWidth, kHeight, wgpu::TextureFormat::R8Unorm,
                        wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment);
    wgpu::Texture sourceTexturePlane1 =
        Create2DTexture(device, kWidth, kHeight, wgpu::TextureFormat::RG8Unorm,
                        wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment);
    RenderQuad(sourceTexturePlane0,
               {{kGreen.y}, {kColor1.y}, {kRed.y}, {kBlue.y}, {kBlack.y}, 0.5});
    RenderQuad(sourceTexturePlane1, {{kGreen.u, kGreen.v},
                                     {kColor1.u, kColor1.v},
                                     {kRed.u, kRed.v},
                                     {kBlue.u, kBlue.v},
                                     {kBlack.u, kBlack.v},
                                     0.5});

    wgpu::Texture renderTexture =
        Create2DTexture(device, kWidth, kHeight, kFormat,
                        wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment);

    struct CropExpectation {
        wgpu::Origin2D cropOrigin;
        wgpu::Extent2D cropSize;
        wgpu::ExternalTextureRotation rotation;
        utils::RGBA8 upperLeftColor;
        utils::RGBA8 upperRightColor;
        utils::RGBA8 lowerLeftColor;
        utils::RGBA8 lowerRightColor;
    };

    std::array<CropExpectation, 9> expectations = {
        {{{0, 0},
          {kWidth, kHeight},
          wgpu::ExternalTextureRotation::Rotate0Degrees,
          utils::RGBA8::kBlack,
          utils::RGBA8::kBlack,
          utils::RGBA8::kBlack,
          utils::RGBA8::kBlack},
         {{kWidth / 4, kHeight / 4},
          {kWidth / 4, kHeight / 4},
          wgpu::ExternalTextureRotation::Rotate0Degrees,
          utils::RGBA8::kGreen,
          utils::RGBA8::kGreen,
          utils::RGBA8::kGreen,
          utils::RGBA8::kGreen},
         {{kWidth / 2, kHeight / 4},
          {kWidth / 4, kHeight / 4},
          wgpu::ExternalTextureRotation::Rotate0Degrees,
          kColor1.rgba,
          kColor1.rgba,
          kColor1.rgba,
          kColor1.rgba},
         {{kWidth / 4, kHeight / 2},
          {kWidth / 4, kHeight / 4},
          wgpu::ExternalTextureRotation::Rotate0Degrees,
          utils::RGBA8::kRed,
          utils::RGBA8::kRed,
          utils::RGBA8::kRed,
          utils::RGBA8::kRed},
         {{kWidth / 2, kHeight / 2},
          {kWidth / 4, kHeight / 4},
          wgpu::ExternalTextureRotation::Rotate0Degrees,
          utils::RGBA8::kBlue,
          utils::RGBA8::kBlue,
          utils::RGBA8::kBlue,
          utils::RGBA8::kBlue},
         {{kWidth / 4, kHeight / 4},
          {kWidth / 2, kHeight / 2},
          wgpu::ExternalTextureRotation::Rotate0Degrees,
          utils::RGBA8::kGreen,
          kColor1.rgba,
          utils::RGBA8::kRed,
          utils::RGBA8::kBlue},
         {{kWidth / 4, kHeight / 4},
          {kWidth / 2, kHeight / 2},
          wgpu::ExternalTextureRotation::Rotate90Degrees,
          utils::RGBA8::kRed,
          utils::RGBA8::kGreen,
          utils::RGBA8::kBlue,
          kColor1.rgba},
         {{kWidth / 4, kHeight / 4},
          {kWidth / 2, kHeight / 2},
          wgpu::ExternalTextureRotation::Rotate180Degrees,
          utils::RGBA8::kBlue,
          utils::RGBA8::kRed,
          kColor1.rgba,
          utils::RGBA8::kGreen},
         {{kWidth / 4, kHeight / 4},
          {kWidth / 2, kHeight / 2},
          wgpu::ExternalTextureRotation::Rotate270Degrees,
          kColor1.rgba,
          utils::RGBA8::kBlue,
          utils::RGBA8::kGreen,
          utils::RGBA8::kRed}}};

    for (const CropExpectation& exp : expectations) {
        // Pipeline Creation
        utils::ComboRenderPipelineDescriptor descriptor;
        descriptor.vertex.module = vsModule;
        descriptor.cFragment.module = fsSampleExternalTextureModule;
        descriptor.cTargets[0].format = kFormat;
        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);

        // Import the external texture
        wgpu::ExternalTextureDescriptor externalDesc =
            InitExternalTextureDescriptor(sourceTexturePlane0, sourceTexturePlane1);
        externalDesc.rotation = exp.rotation;
        externalDesc.cropOrigin = exp.cropOrigin;
        externalDesc.cropSize = exp.cropSize;
        externalDesc.apparentSize = exp.cropSize;
        wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);

        // Create a sampler and bind group
        wgpu::Sampler sampler = device.CreateSampler();

        wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
                                                         {{0, sampler}, {1, externalTexture}});

        // Run the shader, which should sample from the external texture and draw a triangle into
        // the upper left corner of the render texture.
        wgpu::TextureView renderView = renderTexture.CreateView();
        utils::ComboRenderPassDescriptor renderPass({renderView}, nullptr);
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
        {
            pass.SetPipeline(pipeline);
            pass.SetBindGroup(0, bindGroup);
            pass.Draw(3);
            pass.End();
        }

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

        EXPECT_PIXEL_RGBA8_EQ(exp.upperLeftColor, renderTexture, 0, 0);
        EXPECT_PIXEL_RGBA8_EQ(exp.upperRightColor, renderTexture, 3, 0);
        EXPECT_PIXEL_RGBA8_EQ(exp.lowerLeftColor, renderTexture, 0, 3);
        EXPECT_PIXEL_RGBA8_EQ(exp.lowerRightColor, renderTexture, 3, 3);
    }
}

// Test that sampling an external texture with non-one alpha preserves the alpha channel.
TEST_P(ExternalTextureTests, SampleExternalTextureAlpha) {
    // TODO(crbug.com/dawn/2295): diagnose this failure on Pixel 4 OpenGLES
    DAWN_SUPPRESS_TEST_IF(IsOpenGLES() && IsAndroid() && IsQualcomm());

    // TODO(crbug.com/522868202): Produces incorrect result on Pixel 10.
    DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsImgTec() && IsVulkan());

    wgpu::Texture sampledTexture =
        Create2DTexture(device, kWidth, kHeight, kFormat,
                        wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment);
    wgpu::Texture renderTexture =
        Create2DTexture(device, kWidth, kHeight, kFormat,
                        wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment);

    utils::RGBA8 kColor = {255, 255, 255, 128};

    // Initialize texture with green to ensure it is sampled from later.
    {
        utils::ComboRenderPassDescriptor renderPass({sampledTexture.CreateView()}, nullptr);
        renderPass.cColorAttachments[0].clearValue = {kColor.r / 255.0f, kColor.g / 255.0f,
                                                      kColor.b / 255.0f, kColor.a / 255.0f};
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
        pass.End();

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

    // Pipeline Creation
    utils::ComboRenderPipelineDescriptor descriptor;
    descriptor.vertex.module = vsModule;
    descriptor.cFragment.module = fsSampleExternalTextureModule;
    descriptor.cTargets[0].format = kFormat;
    wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);

    // Import the external texture
    wgpu::ExternalTextureDescriptor externalDesc = InitExternalTextureDescriptor(sampledTexture);
    wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);

    // Create a sampler and bind group
    wgpu::Sampler sampler = device.CreateSampler();

    wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
                                                     {{0, sampler}, {1, externalTexture}});

    // Run the shader, which should sample from the external texture and draw a triangle into the
    // upper left corner of the render texture.
    wgpu::TextureView renderView = renderTexture.CreateView();
    utils::ComboRenderPassDescriptor renderPass({renderView}, nullptr);
    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
    {
        pass.SetPipeline(pipeline);
        pass.SetBindGroup(0, bindGroup);
        pass.Draw(3);
        pass.End();
    }

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

    EXPECT_PIXEL_RGBA8_EQ(kColor, renderTexture, 0, 0);
}

// Test for crbug.com/dawn/2472
TEST_P(ExternalTextureTests, RemappingBugDawn2472) {
    auto wgslModule = utils::CreateShaderModule(device, R"(
    @vertex
    fn vertexMain() -> @builtin(position) vec4f {
      return vec4f(1);
    }

    @group(0) @binding(0) var myTexture: texture_external;

    @fragment
    fn fragmentMain() -> @location(0) vec4f {
      let result = textureLoad(myTexture, vec2u(1, 1));
      return vec4f(1);
    })");

    // Pipeline Creation
    utils::ComboRenderPipelineDescriptor descriptor;
    descriptor.vertex.module = wgslModule;
    descriptor.cFragment.module = wgslModule;
    wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);

    ASSERT_NE(pipeline.Get(), nullptr);
}

// Regression test for issue 346174896.
TEST_P(ExternalTextureTests, Regression346174896) {
    auto wgslModule = utils::CreateShaderModule(device, R"(
        @vertex fn vertexMain() -> @builtin(position) vec4f {
            return vec4f(1);
        }

        @group(0) @binding(1) var<uniform> dimension : vec2u;
        @group(0) @binding(0) var t : texture_external;

        @fragment fn main(@builtin(position) FragCoord : vec4f) -> @location(0) vec4f {
            _ = dimension;
            return textureLoad(t, vec2u(0, 0));
        })");

    utils::ComboRenderPipelineDescriptor descriptor;
    descriptor.vertex.module = wgslModule;
    descriptor.cFragment.module = wgslModule;
    wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);

    ASSERT_NE(pipeline.Get(), nullptr);
}

TEST_P(ExternalTextureTests, MultipleBindings) {
    auto wgslModule = utils::CreateShaderModule(device, R"(
    @vertex
    fn vertexMain() -> @builtin(position) vec4f {
      return vec4f(1);
    }

    @group(0) @binding(0) var<uniform> u : f32;
    @group(0) @binding(1) var s : sampler;
    @group(0) @binding(2) var et : texture_external;

    @fragment
    fn main() -> @location(0) vec4f {
      return textureSampleBaseClampToEdge(et, s, vec2f(u));
    })");

    // Pipeline Creation
    utils::ComboRenderPipelineDescriptor descriptor;
    descriptor.vertex.module = wgslModule;
    descriptor.cFragment.module = wgslModule;
    wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);

    ASSERT_NE(pipeline.Get(), nullptr);
}

// Tests using multiple textures in the same pipeline and checks that sampling them returns the
// expected result. It rolls the RGBA and multiplanar external textures to check that the Vulkan
// pipeline specialization works correctly (and doesn't reuse when it shouldn't).
//
// Case with all in the same bindgroup layout.
TEST_P(ExternalTextureTests, SampleDifferentKindsSameBindGroup) {
    DAWN_SUPPRESS_TEST_IF(IsWARP());

    // Create our three test external of different kinds as well as the expected data.
    std::vector<wgpu::ExternalTexture> externalTextures;
    std::vector<utils::RGBA8> colors;

    // The RGBA external textures.
    externalTextures.push_back(utils::MakePassthroughExternalTexture(
        device, MakeTestTexture(wgpu::TextureFormat::RGBA8Unorm, 1, 1,
                                {1.0 / 255.0, 2.0 / 255.0, 3.0 / 255.0, 4.0 / 255.0})));
    colors.push_back(utils::RGBA8(1, 2, 3, 4));

    externalTextures.push_back(utils::MakePassthroughExternalTexture(
        device, MakeTestTexture(wgpu::TextureFormat::RGBA8Unorm, 1, 1,
                                {2.0 / 255.0, 4.0 / 255.0, 6.0 / 255.0, 8.0 / 255.0})));
    colors.push_back(utils::RGBA8(2, 4, 6, 8));

    // The multiplanar external texture.
    externalTextures.push_back(utils::MakePassthroughExternalTexture(
        device, MakeTestTexture(wgpu::TextureFormat::R8Unorm, 2, 2, {10.0 / 255.0, 0, 0, 0}),
        MakeTestTexture(wgpu::TextureFormat::RG8Unorm, 1, 1, {20.0 / 255.0, 30.0 / 255.0, 0, 0})));
    colors.push_back(utils::RGBA8(10, 20, 30, 255));

    // Create the pipeline that copies from the three external texture to a buffer.
    wgpu::ComputePipelineDescriptor csDesc;
    csDesc.compute.module = utils::CreateShaderModule(device, R"(
        @group(0) @binding(0) var s : sampler;
        @group(0) @binding(1) var<storage, read_write> results : array<u32, 3>;

        @group(0) @binding(2) var t0 : texture_external;
        @group(0) @binding(3) var t1 : texture_external;
        @group(0) @binding(4) var t2 : texture_external;
        @compute @workgroup_size(1) fn main() {
            results[0] = pack4x8unorm(textureSampleBaseClampToEdge(t0, s, vec2(0)));
            results[1] = pack4x8unorm(textureSampleBaseClampToEdge(t1, s, vec2(0)));
            results[2] = pack4x8unorm(textureSampleBaseClampToEdge(t2, s, vec2(0)));
        }
    )");
    wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&csDesc);

    wgpu::BufferDescriptor resultDesc = {
        .usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc,
        .size = 3 * sizeof(uint32_t),
    };
    wgpu::Buffer resultBuffer = device.CreateBuffer(&resultDesc);

    // Run the pipeline, rolling the external textures in the bindgroup such that a new
    // specialization of the shader should be created each time.
    for (size_t roll = 0; roll < externalTextures.size(); roll++) {
        wgpu::BindGroup bg = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
                                                  {
                                                      {0, device.CreateSampler()},
                                                      {1, resultBuffer},
                                                      {2, externalTextures[(0 + roll) % 3]},
                                                      {3, externalTextures[(1 + roll) % 3]},
                                                      {4, externalTextures[(2 + roll) % 3]},
                                                  });
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.SetBindGroup(0, bg);
        pass.SetPipeline(pipeline);
        pass.DispatchWorkgroups(1);
        pass.End();

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

        EXPECT_BUFFER_RGBA8_EQ(colors[(0 + roll) % 3], resultBuffer, 0);
        EXPECT_BUFFER_RGBA8_EQ(colors[(1 + roll) % 3], resultBuffer, 4);
        EXPECT_BUFFER_RGBA8_EQ(colors[(2 + roll) % 3], resultBuffer, 8);
    }
}

// Case with all in different bind group layouts.
TEST_P(ExternalTextureTests, SampleDifferentKindsDifferentBindGroups) {
    DAWN_SUPPRESS_TEST_IF(IsWARP());

    // Create our three test external of different kinds as well as the expected data.
    std::vector<wgpu::ExternalTexture> externalTextures;
    std::vector<utils::RGBA8> colors;

    // The RGBA external textures.
    externalTextures.push_back(utils::MakePassthroughExternalTexture(
        device, MakeTestTexture(wgpu::TextureFormat::RGBA8Unorm, 1, 1,
                                {1.0 / 255.0, 2.0 / 255.0, 3.0 / 255.0, 4.0 / 255.0})));
    colors.push_back(utils::RGBA8(1, 2, 3, 4));

    externalTextures.push_back(utils::MakePassthroughExternalTexture(
        device, MakeTestTexture(wgpu::TextureFormat::RGBA8Unorm, 1, 1,
                                {2.0 / 255.0, 4.0 / 255.0, 6.0 / 255.0, 8.0 / 255.0})));
    colors.push_back(utils::RGBA8(2, 4, 6, 8));

    // The multiplanar external texture.
    externalTextures.push_back(utils::MakePassthroughExternalTexture(
        device, MakeTestTexture(wgpu::TextureFormat::R8Unorm, 2, 2, {10.0 / 255.0, 0, 0, 0}),
        MakeTestTexture(wgpu::TextureFormat::RG8Unorm, 1, 1, {20.0 / 255.0, 30.0 / 255.0, 0, 0})));
    colors.push_back(utils::RGBA8(10, 20, 30, 255));

    // Create the pipeline that copies from the three external texture to a buffer.
    wgpu::ComputePipelineDescriptor csDesc;
    csDesc.compute.module = utils::CreateShaderModule(device, R"(
        @group(0) @binding(0) var s : sampler;
        @group(0) @binding(1) var<storage, read_write> results : array<u32, 3>;

        @group(1) @binding(0) var t0 : texture_external;
        @group(2) @binding(0) var t1 : texture_external;
        @group(3) @binding(0) var t2 : texture_external;
        @compute @workgroup_size(1) fn main() {
            results[0] = pack4x8unorm(textureSampleBaseClampToEdge(t0, s, vec2(0)));
            results[1] = pack4x8unorm(textureSampleBaseClampToEdge(t1, s, vec2(0)));
            results[2] = pack4x8unorm(textureSampleBaseClampToEdge(t2, s, vec2(0)));
        }
    )");
    wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&csDesc);

    wgpu::BufferDescriptor resultDesc = {
        .usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc,
        .size = 3 * sizeof(uint32_t),
    };
    wgpu::Buffer resultBuffer = device.CreateBuffer(&resultDesc);

    // Run the pipeline, rolling the external textures in the bindgroup such that a new
    // specialization of the shader should be created each time.
    for (size_t roll = 0; roll < externalTextures.size(); roll++) {
        wgpu::BindGroup bg0 = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
                                                   {
                                                       {0, device.CreateSampler()},
                                                       {1, resultBuffer},
                                                   });

        wgpu::BindGroup bg1 = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(1),
                                                   {{0, externalTextures[(0 + roll) % 3]}});
        wgpu::BindGroup bg2 = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(2),
                                                   {{0, externalTextures[(1 + roll) % 3]}});
        wgpu::BindGroup bg3 = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(3),
                                                   {{0, externalTextures[(2 + roll) % 3]}});

        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.SetBindGroup(0, bg0);
        pass.SetBindGroup(1, bg1);
        pass.SetBindGroup(2, bg2);
        pass.SetBindGroup(3, bg3);
        pass.SetPipeline(pipeline);
        pass.DispatchWorkgroups(1);
        pass.End();

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

        EXPECT_BUFFER_RGBA8_EQ(colors[(0 + roll) % 3], resultBuffer, 0);
        EXPECT_BUFFER_RGBA8_EQ(colors[(1 + roll) % 3], resultBuffer, 4);
        EXPECT_BUFFER_RGBA8_EQ(colors[(2 + roll) % 3], resultBuffer, 8);
    }
}

// Test using a pipeline with two external textures in the layout, one of which is unused.
TEST_P(ExternalTextureTests, LayoutWithUnusedExternalTexture) {
    // Make the two external textures.
    wgpu::ExternalTexture usedET = utils::MakePassthroughExternalTexture(
        device, MakeTestTexture(wgpu::TextureFormat::RGBA8Unorm, 1, 1,
                                {1.0 / 255.0, 2.0 / 255.0, 3.0 / 255.0, 4.0 / 255.0}));

    wgpu::ExternalTexture unusedET = utils::MakePassthroughExternalTexture(
        device, MakeTestTexture(wgpu::TextureFormat::RGBA8Unorm, 1, 1,
                                {2.0 / 255.0, 4.0 / 255.0, 6.0 / 255.0, 8.0 / 255.0}));

    // Create the layout using both external textures.
    wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout(
        device, {
                    {0, wgpu::ShaderStage::Compute, wgpu::SamplerBindingType::Filtering},
                    {1, wgpu::ShaderStage::Compute, wgpu::BufferBindingType::Storage},
                    {2, wgpu::ShaderStage::Compute, &utils::kExternalTextureBindingLayout},
                    {3, wgpu::ShaderStage::Compute, &utils::kExternalTextureBindingLayout},
                });

    wgpu::PipelineLayout pl = utils::MakePipelineLayout(device, {bgl});

    // Create the pipeline that samples only one of the external textures that's in the layout.
    wgpu::ComputePipelineDescriptor csDesc;
    csDesc.compute.module = utils::CreateShaderModule(device, R"(
        @group(0) @binding(0) var s : sampler;
        @group(0) @binding(1) var<storage, read_write> results : u32;
        @group(0) @binding(2) var t : texture_external;

        @compute @workgroup_size(1) fn main() {
            results = pack4x8unorm(textureSampleBaseClampToEdge(t, s, vec2(0)));
        }
    )");
    csDesc.layout = pl;
    wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&csDesc);

    // Run the pipeline and check the results.
    wgpu::BufferDescriptor resultDesc = {
        .usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc,
        .size = sizeof(uint32_t),
    };
    wgpu::Buffer resultBuffer = device.CreateBuffer(&resultDesc);

    wgpu::BindGroup bg = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
                                              {
                                                  {0, device.CreateSampler()},
                                                  {1, resultBuffer},
                                                  {2, usedET},
                                                  {3, unusedET},
                                              });
    wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
    wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
    pass.SetBindGroup(0, bg);
    pass.SetPipeline(pipeline);
    pass.DispatchWorkgroups(1);
    pass.End();

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

    EXPECT_BUFFER_RGBA8_EQ(utils::RGBA8(1, 2, 3, 4), resultBuffer, 0);
}

// Test that using a dynamic offset works when there is an external texture in the same
// BindGroupLayout
TEST_P(ExternalTextureTests, UseExternalTextureWithDynamicOffset) {
    // TODO(42242119): fail on Qualcomm Adreno X1.
    DAWN_SUPPRESS_TEST_IF(IsD3D11() && IsQualcomm());

    // Make the two external textures.
    wgpu::ExternalTexture et = utils::MakePassthroughExternalTexture(
        device, MakeTestTexture(wgpu::TextureFormat::RGBA8Unorm, 1, 1,
                                {1.0 / 255.0, 2.0 / 255.0, 3.0 / 255.0, 4.0 / 255.0}));

    // Create the layout using both external textures.
    wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout(
        device, {
                    {0, wgpu::ShaderStage::Compute, wgpu::SamplerBindingType::Filtering},
                    {1, wgpu::ShaderStage::Compute, wgpu::BufferBindingType::Storage, true},
                    {2, wgpu::ShaderStage::Compute, &utils::kExternalTextureBindingLayout},
                });

    wgpu::PipelineLayout pl = utils::MakePipelineLayout(device, {bgl});

    // Create the pipeline that samples only one of the external textures that's in the layout.
    wgpu::ComputePipelineDescriptor csDesc;
    csDesc.compute.module = utils::CreateShaderModule(device, R"(
        @group(0) @binding(0) var s : sampler;
        @group(0) @binding(1) var<storage, read_write> results : u32;
        @group(0) @binding(2) var t : texture_external;

        @compute @workgroup_size(1) fn main() {
            results = pack4x8unorm(textureSampleBaseClampToEdge(t, s, vec2(0)));
        }
    )");
    csDesc.layout = pl;
    wgpu::ComputePipeline pipeline = device.CreateComputePipeline(&csDesc);

    for (uint32_t offset : {0, 256}) {
        // Run the pipeline and check the results.
        wgpu::BufferDescriptor resultDesc = {
            .usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc,
            .size = sizeof(uint32_t) + 256,
        };
        wgpu::Buffer resultBuffer = device.CreateBuffer(&resultDesc);

        wgpu::BindGroup bg = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
                                                  {
                                                      {0, device.CreateSampler()},
                                                      {1, resultBuffer, 0, 4},
                                                      {2, et},
                                                  });
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
        pass.SetBindGroup(0, bg, 1, &offset);
        pass.SetPipeline(pipeline);
        pass.DispatchWorkgroups(1);
        pass.End();

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

        EXPECT_BUFFER_RGBA8_EQ(utils::RGBA8(1, 2, 3, 4), resultBuffer, offset);
        EXPECT_BUFFER_RGBA8_EQ(utils::RGBA8(0, 0, 0, 0), resultBuffer, 256 - offset);
    }
}

// Test that the color conversion from PQ to sRGBLinear works as expected.
TEST_P(ExternalTextureTests, ColorSpaceConversion_PQ_sRGBLinear) {
    // https://apps.colorjs.io/convert/?color=color(rec2100-pq%200.4%200.2%200.1)&precision=5
    CheckColorSpaceConversion(
        {
            .primaries = wgpu::ColorSpacePrimariesDawn::Rec2020,
            .transfer = wgpu::ColorSpaceTransferDawn::PQ,
        },
        wgpu::PredefinedColorSpace::SRGBLinear, {0.4, 0.2, 0.1, 1},
        {0.25826747, -0.00636454, -0.00231619});

    // https://apps.colorjs.io/convert/?color=color(rec2100-pq%200.5%200.6%200.9)&precision=5
    CheckColorSpaceConversion(
        {
            .primaries = wgpu::ColorSpacePrimariesDawn::Rec2020,
            .transfer = wgpu::ColorSpaceTransferDawn::PQ,
        },
        wgpu::PredefinedColorSpace::SRGBLinear, {0.5, 0.6, 0.9, 1}, {-1.3534, 1.1445, 21.395});

    // Same test as above but using a different reference white luminance.
    {
        float factor = 203.0 / 100.0;
        CheckColorSpaceConversion(
            {
                .primaries = wgpu::ColorSpacePrimariesDawn::Rec2020,
                .transfer = wgpu::ColorSpaceTransferDawn::PQ,
                .hdrReferenceWhiteLuminance = 100,
            },
            wgpu::PredefinedColorSpace::SRGBLinear, {0.5, 0.6, 0.9, 1},
            {-1.3534f * factor, 1.1445f * factor, 21.395f * factor});
    }
}

// Test that the color conversion from HLG to Rec2020Linear works as expected.
TEST_P(ExternalTextureTests, ColorSpaceConversion_HLG_Rec2020Linear) {
    struct TestVector {
        wgpu::Color hlg;
        std::array<float, 3> rec2020;
    };
    // Test vector were generated using Skia to convert between two SkColorSpaces.
    auto testVectors = std::array<TestVector, 8>({
        {{1.00, 1.00, 1.00, 1.0}, {4.926219, 4.926220, 4.926220}},
        {{0.75, 0.75, 0.75, 1.0}, {1.000729, 1.000729, 1.000729}},
        {{0.00, 0.00, 0.75, 1.0}, {0.000000, 0.000000, 0.568750}},
        {{0.00, 0.75, 0.00, 1.0}, {0.000000, 0.925928, 0.000000}},
        {{0.75, 0.00, 0.00, 1.0}, {0.765934, 0.000000, 0.000000}},
        {{0.25, 0.50, 0.75, 1.0}, {0.061563, 0.246247, 0.782958}},
        {{0.50, 0.75, 0.25, 1.0}, {0.298348, 0.948618, 0.074588}},
        {{0.75, 0.25, 0.50, 1.0}, {0.803970, 0.063215, 0.252855}},
    });

    for (const auto& testVector : testVectors) {
        CheckColorSpaceConversion(
            {
                .primaries = wgpu::ColorSpacePrimariesDawn::Rec2020,
                .transfer = wgpu::ColorSpaceTransferDawn::HLG,
            },
            wgpu::PredefinedColorSpace::Rec2020Linear, testVector.hlg, testVector.rec2020);
    }
}

// Test that the color conversion from HLG to SRGB (non-linear) works as expected.
TEST_P(ExternalTextureTests, ColorSpaceConversion_HLG_SRGB) {
    struct TestVector {
        wgpu::Color hlg;
        std::array<float, 3> srgb;
    };
    // Test vector were generated using Skia to convert between two SkColorSpaces.
    auto testVectors = std::array<TestVector, 8>({
        {{1.00, 1.00, 1.00, 1.0}, {1.994927, 1.995262, 1.995293}},
        {{0.75, 0.75, 0.75, 1.0}, {1.000107, 1.000290, 1.000305}},
        {{0.00, 0.00, 0.75, 1.0}, {-0.224957, -0.058485, 0.818867}},
        {{0.00, 0.75, 0.00, 1.0}, {-0.763752, 1.021187, -0.337370}},
        {{0.75, 0.00, 0.00, 1.0}, {1.111084, -0.341290, -0.122559}},
        {{0.25, 0.50, 0.75, 1.0}, {-0.348418, 0.551422, 0.930966}},
        {{0.50, 0.75, 0.25, 1.0}, {-0.288479, 1.016007, -0.139914}},
        {{0.75, 0.25, 0.50, 1.0}, {1.113976, -0.191790, 0.548725}},
    });

    for (const auto& testVector : testVectors) {
        CheckColorSpaceConversion(
            {
                .primaries = wgpu::ColorSpacePrimariesDawn::Rec2020,
                .transfer = wgpu::ColorSpaceTransferDawn::HLG,
            },
            wgpu::PredefinedColorSpace::SRGB, testVector.hlg, testVector.srgb);
    }
}

// Test that PredefinedColorSpace::Rec2020Linear is the same color space as using primaries of
// Rec2020 and an identity transfer function. (the Rec2020 primaries are tested as part of the PQ
// and HLG tests above).
TEST_P(ExternalTextureTests, ColorSpaceConversion_Rec2020_Rec2020Linear) {
    CheckColorSpaceConversion(
        {
            .primaries = wgpu::ColorSpacePrimariesDawn::Rec2020,
        },
        wgpu::PredefinedColorSpace::Rec2020Linear, {0.4, 0.2, 0.1, 1}, {0.4, 0.2, 0.1});
}

// TODO(https://crbug.com/468988322): Add tests of ExternalTextures being used with a resource table
// and with Vulkan's extended dynamic state as these are other interactions that could easily break.

DAWN_INSTANTIATE_TEST(ExternalTextureTests,
                      D3D11Backend(),
                      D3D12Backend(),
                      D3D12Backend({}, {"d3d12_use_root_signature_version_1_1"}),
                      MetalBackend(),
                      OpenGLBackend(),
                      OpenGLESBackend(),
                      VulkanBackend(),
                      VulkanBackend({"vulkan_force_static_samplers_for_external_textures"}),
                      WebGPUBackend());

enum class AccessMode { Sample, Load };
enum class OOBAccess { BelowBottomLeft, OverTopRight };
enum class Flip { None, Mirrored };

using Rotation = wgpu::ExternalTextureRotation;

std::ostream& operator<<(std::ostream& o, Flip flip) {
    switch (flip) {
        case Flip::None:
            o << "no flip ";
            break;
        case Flip::Mirrored:
            o << "mirrored ";
            break;
        default:
            DAWN_UNREACHABLE();
            break;
    }

    return o;
}

std::ostream& operator<<(std::ostream& o, AccessMode mode) {
    switch (mode) {
        case AccessMode::Sample:
            o << "sample ";
            break;
        case AccessMode::Load:
            o << "load ";
            break;
        default:
            DAWN_UNREACHABLE();
            break;
    }

    return o;
}

std::ostream& operator<<(std::ostream& o, OOBAccess rect) {
    switch (rect) {
        case OOBAccess::BelowBottomLeft:
            o << "below bottom left ";
            break;
        case OOBAccess::OverTopRight:
            o << "over top right";
            break;
        default:
            DAWN_UNREACHABLE();
            break;
    }

    return o;
}

DAWN_TEST_PARAM_STRUCT(OOBTestParams, Rotation, Flip, AccessMode, OOBAccess);

class ExternalTextureOOBTests : public ExternalTextureTestsBase<DawnTestWithParams<OOBTestParams>> {
  protected:
    void SetUp() override {
        ExternalTextureTestsBase<DawnTestWithParams<OOBTestParams>>::SetUp();

        // TODO(crbug.com/522872460): Produces incorrect result on Pixel 10.
        DAWN_SUPPRESS_TEST_IF(IsAndroid() && IsImgTec() && IsVulkan());

        sourceTexturePlane0 = Create2DTexture(
            device, kPlaneWidth, kPlaneHeight, wgpu::TextureFormat::R8Unorm,
            wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment);
        sourceTexturePlane1 = Create2DTexture(
            device, kPlaneWidth, kPlaneHeight, wgpu::TextureFormat::RG8Unorm,
            wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment);
        RenderQuad(sourceTexturePlane0,
                   {{kGreen.y}, {kColor1.y}, {kRed.y}, {kBlue.y}, {kBlack.y}, 0.5});
        RenderQuad(sourceTexturePlane1, {{kGreen.u, kGreen.v},
                                         {kColor1.u, kColor1.v},
                                         {kRed.u, kRed.v},
                                         {kBlue.u, kBlue.v},
                                         {kBlack.u, kBlack.v},
                                         0.5});

        renderTexture =
            Create2DTexture(device, kPlaneWidth, kPlaneHeight, kFormat,
                            wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment);

        oobTestShaderModule = utils::CreateShaderModule(device, R"(
        @vertex fn main(@builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4f {
            var positions = array(
                vec4f(-3, -1, 0, 1),
                vec4f( 3, -1, 0, 1),
                vec4f( 0,  2, 0, 1),
            );
            return positions[VertexIndex];
        }

        @group(0) @binding(0) var s : sampler;
        @group(0) @binding(1) var t : texture_external;

        @fragment fn sampleOverTopRight() -> @location(0) vec4f {
            return textureSampleBaseClampToEdge(t, s, vec2f(1.1, 1.1));
        }

        @fragment fn sampleBelowBottomLeft() -> @location(0) vec4f {
            return textureSampleBaseClampToEdge(t, s, vec2f(-0.1, -0.1));
        }

        @fragment fn loadOverTopRight() -> @location(0) vec4f {
            _ = textureSampleBaseClampToEdge(t, s, vec2f(0.0, 0.0));
            return textureLoad(t, vec2<i32>(5, 5));
        }

        @fragment fn loadBelowBottomLeft() -> @location(0) vec4f {
            _ = textureSampleBaseClampToEdge(t, s, vec2f(0.0, 0.0));
            return textureLoad(t, vec2<i32>(-1, -1));
        }

        )");
    }

    std::string GetEntryPoint(AccessMode mode, OOBAccess access) {
        switch (mode) {
            case AccessMode::Sample:
                switch (access) {
                    case OOBAccess::BelowBottomLeft:
                        return "sampleBelowBottomLeft";
                    case OOBAccess::OverTopRight:
                        return "sampleOverTopRight";
                    default:
                        DAWN_UNREACHABLE();
                }
                break;
            case AccessMode::Load:
                switch (access) {
                    case OOBAccess::BelowBottomLeft:
                        return "loadBelowBottomLeft";
                    case OOBAccess::OverTopRight:
                        return "loadOverTopRight";
                    default:
                        DAWN_UNREACHABLE();
                }
                break;
            default:
                DAWN_UNREACHABLE();
        }
    }

    void DoTest() {
        wgpu::ExternalTextureRotation rotation = GetParam().mRotation;
        OOBAccess oobAccess = GetParam().mOOBAccess;
        AccessMode accessMode = GetParam().mAccessMode;
        Flip flip = GetParam().mFlip;

        utils::ComboRenderPipelineDescriptor descriptor;
        descriptor.vertex.module = oobTestShaderModule;
        descriptor.vertex.entryPoint = "main";
        descriptor.cFragment.module = oobTestShaderModule;
        std::string fragmentEntryPoint = GetEntryPoint(accessMode, oobAccess);

        descriptor.cFragment.entryPoint = fragmentEntryPoint.c_str();
        descriptor.cTargets[0].format = kFormat;
        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&descriptor);

        // Import the external texture
        wgpu::ExternalTextureDescriptor externalDesc =
            InitExternalTextureDescriptor(sourceTexturePlane0, sourceTexturePlane1);
        externalDesc.rotation = rotation;
        externalDesc.mirrored = flip == Flip::Mirrored;
        wgpu::ExternalTexture externalTexture = device.CreateExternalTexture(&externalDesc);

        // Create a sampler and bind group
        wgpu::Sampler sampler = device.CreateSampler();

        wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
                                                         {{0, sampler}, {1, externalTexture}});

        // Run the shader, which should sample from the external texture and draw a triangle into
        // the upper left corner of the render texture.
        wgpu::TextureView renderView = renderTexture.CreateView();
        utils::ComboRenderPassDescriptor renderPass({renderView}, nullptr);
        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
        {
            pass.SetPipeline(pipeline);
            pass.SetBindGroup(0, bindGroup);
            pass.Draw(3);
            pass.End();
        }

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

        // Border color is black.
        EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kBlack, renderTexture, 0, 0);
    }

    static constexpr uint32_t kPlaneWidth = 5;
    static constexpr uint32_t kPlaneHeight = 5;
    wgpu::ShaderModule oobTestShaderModule;
    wgpu::Texture sourceTexturePlane0;
    wgpu::Texture sourceTexturePlane1;
    wgpu::Texture renderTexture;
};

// Test for OOB access
TEST_P(ExternalTextureOOBTests, ExternalTextureOOB) {
    // TODO(crbug.com/dawn/2295): diagnose this failure on Pixel 4 OpenGLES
    DAWN_SUPPRESS_TEST_IF(IsOpenGLES() && IsAndroid() && IsQualcomm());

    DoTest();
}

DAWN_INSTANTIATE_TEST_P(
    ExternalTextureOOBTests,
    {D3D11Backend(), D3D12Backend(), D3D12Backend({}, {"d3d12_use_root_signature_version_1_1"}),
     MetalBackend(), OpenGLBackend(), OpenGLESBackend(), VulkanBackend(),
     VulkanBackend({"vulkan_force_static_samplers_for_external_textures"}), WebGPUBackend()},
    std::vector<wgpu::ExternalTextureRotation>({wgpu::ExternalTextureRotation::Rotate0Degrees,
                                                wgpu::ExternalTextureRotation::Rotate90Degrees,
                                                wgpu::ExternalTextureRotation::Rotate180Degrees,
                                                wgpu::ExternalTextureRotation::Rotate270Degrees}),
    std::vector<Flip>({Flip::None, Flip::Mirrored}),
    std::vector<AccessMode>({AccessMode::Sample, AccessMode::Load}),
    std::vector<OOBAccess>({OOBAccess::BelowBottomLeft, OOBAccess::OverTopRight}));

}  // anonymous namespace
}  // namespace dawn
