// Copyright 2024 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 <memory>
#include <string>
#include <vector>

#include "dawn/common/Constants.h"
#include "dawn/tests/DawnTest.h"
#include "dawn/utils/ComboRenderBundleEncoderDescriptor.h"
#include "dawn/utils/ComboRenderPipelineDescriptor.h"
#include "dawn/utils/WGPUHelpers.h"
#include "webgpu/webgpu_glfw.h"

#include "GLFW/glfw3.h"

namespace dawn {
namespace {

struct GLFWindowDestroyer {
    void operator()(GLFWwindow* ptr) { glfwDestroyWindow(ptr); }
};

class SurfaceTests : public DawnTest {
  public:
    void SetUp() override {
        DawnTest::SetUp();
        DAWN_TEST_UNSUPPORTED_IF(UsesWire());

        // TODO(crbug.com/dawn/2531): Failing on newer Linux/Intel driver version.
        // However, IsIntel() and IsMesa() don't work with the null backend.
        DAWN_SUPPRESS_TEST_IF(IsLinux() && IsNull());
        DAWN_SUPPRESS_TEST_IF(IsLinux() && IsVulkan() && IsIntel() && IsMesa("23.2"));

        glfwSetErrorCallback([](int code, const char* message) {
            ErrorLog() << "GLFW error " << code << " " << message;
        });

        // GLFW can fail to start in headless environments, in which SurfaceTests are
        // inapplicable. Skip this cases without producing a test failure.
        if (glfwInit() == GLFW_FALSE) {
            GTEST_SKIP();
        }

        // Set GLFW_NO_API to avoid GLFW bringing up a GL context that we won't use.
        glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
        window.reset(glfwCreateWindow(400, 500, "SurfaceTests window", nullptr, nullptr));

        int width;
        int height;
        glfwGetFramebufferSize(window.get(), &width, &height);

        baseConfig.device = device;
        baseConfig.width = width;
        baseConfig.height = height;
        baseConfig.usage = wgpu::TextureUsage::RenderAttachment;
        baseConfig.viewFormatCount = 0;
        baseConfig.viewFormats = nullptr;
    }

    void TearDown() override {
        // Destroy the surface before the window as required by webgpu-native.
        window.reset();
        DawnTest::TearDown();
    }

    wgpu::Surface CreateTestSurface() {
        return wgpu::glfw::CreateSurfaceForWindow(GetInstance(), window.get());
    }

    wgpu::SurfaceConfiguration GetPreferredConfiguration(wgpu::Surface surface) {
        wgpu::SurfaceCapabilities capabilities;
        surface.GetCapabilities(adapter, &capabilities);

        wgpu::SurfaceConfiguration config = baseConfig;
        config.format = capabilities.formats[0];
        config.alphaMode = capabilities.alphaModes[0];
        config.presentMode = capabilities.presentModes[0];
        return config;
    }

    void ClearTexture(wgpu::Texture texture,
                      wgpu::Color color,
                      wgpu::Device preferredDevice = nullptr) {
        if (preferredDevice == nullptr) {
            preferredDevice = device;
        }

        utils::ComboRenderPassDescriptor desc({texture.CreateView()});
        desc.cColorAttachments[0].loadOp = wgpu::LoadOp::Clear;
        desc.cColorAttachments[0].clearValue = color;

        wgpu::CommandEncoder encoder = preferredDevice.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&desc);
        pass.End();

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

    void SampleLoadTexture(wgpu::Texture texture, utils::RGBA8 expectedColor) {
        LoadTexture(texture, expectedColor, "texture_2d<f32>", ", 0");
    }

    void StorageLoadTexture(wgpu::Texture texture, utils::RGBA8 expectedColor) {
        LoadTexture(texture, expectedColor,
                    "texture_storage_2d<" +
                        std::string(utils::GetWGSLImageFormatQualifier(texture.GetFormat())) +
                        ", read>",
                    "");
    }

    void LoadTexture(wgpu::Texture texture,
                     utils::RGBA8 expectedColor,
                     std::string wgslType,
                     std::string extraLoadArgs) {
        wgpu::TextureDescriptor texDescriptor;
        texDescriptor.size = {texture.GetWidth(), texture.GetHeight()};
        texDescriptor.format = wgpu::TextureFormat::RGBA8Unorm;
        texDescriptor.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc;
        wgpu::Texture dstTexture = device.CreateTexture(&texDescriptor);

        // Create the storage load blit render pipeline.
        wgpu::ShaderModule module = utils::CreateShaderModule(device, R"(
            @vertex fn vs(@builtin(vertex_index) VertexIndex : u32) -> @builtin(position) vec4f {
                var pos = array(
                    vec2f(-1.0, -3.0),
                    vec2f(-1.0,  3.0),
                    vec2f( 2.0,  0.0)
                );
                return vec4f(pos[VertexIndex], 0.0, 1.0);
            }

            @group(0) @binding(0) var texture : )" + wgslType + R"(;
            @fragment fn fs(@builtin(position) coord: vec4f) -> @location(0) vec4f {
                return textureLoad(texture, vec2i(coord.xy))" + extraLoadArgs +
                                                                          R"();
            }
        )");

        utils::ComboRenderPipelineDescriptor pipelineDesc;
        pipelineDesc.vertex.module = module;
        pipelineDesc.cFragment.module = module;
        pipelineDesc.cTargets[0].format = texDescriptor.format;
        wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pipelineDesc);

        // Submit the commands for the blit.
        wgpu::BindGroup bindGroup = utils::MakeBindGroup(device, pipeline.GetBindGroupLayout(0),
                                                         {{0, texture.CreateView()}});

        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        utils::ComboRenderPassDescriptor renderPassInfo({dstTexture.CreateView()});
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPassInfo);
        pass.SetPipeline(pipeline);
        pass.SetBindGroup(0, bindGroup);
        pass.Draw(6);
        pass.End();

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

        EXPECT_TEXTURE_EQ(expectedColor, dstTexture, {0, 0});
        EXPECT_TEXTURE_EQ(expectedColor, dstTexture,
                          {texture.GetWidth() - 1, texture.GetHeight() - 1});
    }

    bool SupportsPresentMode(const wgpu::SurfaceCapabilities& capabilities,
                             wgpu::PresentMode mode) {
        for (size_t i = 0; i < capabilities.presentModeCount; ++i) {
            if (capabilities.presentModes[i] == mode) {
                return true;
            }
        }
        return false;
    }

  protected:
    std::unique_ptr<GLFWwindow, GLFWindowDestroyer> window = nullptr;
    wgpu::SurfaceConfiguration baseConfig;
};

// Basic test for creating a swapchain and presenting one frame.
TEST_P(SurfaceTests, Basic) {
    wgpu::Surface surface = CreateTestSurface();

    // Configure
    wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);
    surface.Configure(&config);

    // Get texture
    wgpu::SurfaceTexture surfaceTexture;
    surface.GetCurrentTexture(&surfaceTexture);
    ASSERT_EQ(surfaceTexture.status, wgpu::SurfaceGetCurrentTextureStatus::Success);
    ClearTexture(surfaceTexture.texture, {1.0, 0.0, 0.0, 1.0});

    // Present
    surface.Present();
}

// Test reconfiguring the surface
TEST_P(SurfaceTests, ReconfigureBasic) {
    wgpu::Surface surface = CreateTestSurface();
    wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);

    surface.Configure(&config);

    surface.Configure(&config);
}

// Test replacing the swapchain after GetCurrentTexture
TEST_P(SurfaceTests, ReconfigureAfterGetCurrentTexture) {
    wgpu::Surface surface = CreateTestSurface();
    wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);
    wgpu::SurfaceTexture surfaceTexture;

    surface.Configure(&config);
    surface.GetCurrentTexture(&surfaceTexture);
    ClearTexture(surfaceTexture.texture, {1.0, 0.0, 0.0, 1.0});

    surface.Configure(&config);
    surface.GetCurrentTexture(&surfaceTexture);
    ClearTexture(surfaceTexture.texture, {0.0, 1.0, 0.0, 1.0});
    surface.Present();
}

// Test inconfiguring then reconfiguring the surface
TEST_P(SurfaceTests, ReconfigureAfterUnconfigure) {
    wgpu::Surface surface = CreateTestSurface();
    wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);
    wgpu::SurfaceTexture surfaceTexture;

    surface.Configure(&config);
    surface.GetCurrentTexture(&surfaceTexture);
    ClearTexture(surfaceTexture.texture, {1.0, 0.0, 0.0, 1.0});
    surface.Present();

    surface.Unconfigure();

    surface.Configure(&config);
    surface.GetCurrentTexture(&surfaceTexture);
    ClearTexture(surfaceTexture.texture, {0.0, 1.0, 0.0, 1.0});
    surface.Present();
}

// Test unconfiguring after GetCurrentTexture but before the Present
TEST_P(SurfaceTests, UnconfigureAfterGet) {
    wgpu::Surface surface = CreateTestSurface();
    wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);
    wgpu::SurfaceTexture surfaceTexture;

    surface.Configure(&config);
    surface.GetCurrentTexture(&surfaceTexture);
    ClearTexture(surfaceTexture.texture, {1.0, 0.0, 0.0, 1.0});

    surface.Unconfigure();
}
// Test switching between surfaces that have different present modes.
TEST_P(SurfaceTests, SwitchPresentMode) {
    // Fails with "internal drawable creation failed" on the Windows NVIDIA CQ builders but not
    // locally.
    DAWN_SUPPRESS_TEST_IF(IsWindows() && IsVulkan() && IsNvidia());

    // TODO(jiawei.shao@intel.com): find out why this test sometimes hangs on the latest Linux Intel
    // Vulkan drivers.
    DAWN_SUPPRESS_TEST_IF(IsLinux() && IsVulkan() && IsIntel());

    constexpr wgpu::PresentMode kAllPresentModes[] = {
        wgpu::PresentMode::Immediate,
        wgpu::PresentMode::Fifo,
        wgpu::PresentMode::Mailbox,
    };

    wgpu::Surface surface1 = CreateTestSurface();
    wgpu::Surface surface2 = CreateTestSurface();
    wgpu::SurfaceTexture surfaceTexture;

    wgpu::SurfaceCapabilities capabilities;
    surface1.GetCapabilities(adapter, &capabilities);

    for (wgpu::PresentMode mode1 : kAllPresentModes) {
        if (!SupportsPresentMode(capabilities, mode1)) {
            continue;
        }
        for (wgpu::PresentMode mode2 : kAllPresentModes) {
            if (!SupportsPresentMode(capabilities, mode2)) {
                continue;
            }

            wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface1);

            config.presentMode = mode1;
            surface1.Configure(&config);
            surface1.GetCurrentTexture(&surfaceTexture);
            ClearTexture(surfaceTexture.texture, {0.0, 0.0, 0.0, 1.0});
            surface1.Present();
            surface1.Unconfigure();

            config.presentMode = mode2;
            surface2.Configure(&config);
            surface2.GetCurrentTexture(&surfaceTexture);
            ClearTexture(surfaceTexture.texture, {0.0, 0.0, 0.0, 1.0});
            surface2.Present();
            surface2.Unconfigure();
        }
    }
}

// Test resizing the surface and without resizing the window.
TEST_P(SurfaceTests, ResizingSurfaceOnly) {
    wgpu::Surface surface = CreateTestSurface();
    wgpu::SurfaceTexture surfaceTexture;

    for (int i = 0; i < 10; i++) {
        wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);
        config.width += i * 10;
        config.height -= i * 10;

        surface.Configure(&config);
        surface.GetCurrentTexture(&surfaceTexture);
        ClearTexture(surfaceTexture.texture, {0.05f * i, 0.0, 0.0, 1.0});
        surface.Present();
    }
}

// Test resizing the window but not the surface.
TEST_P(SurfaceTests, ResizingWindowOnly) {
    // TODO(crbug.com/1503912): Failing new ValidateImageAcquireWait in Vulkan Validation Layer.
    DAWN_SUPPRESS_TEST_IF(IsBackendValidationEnabled() && IsWindows() && IsVulkan() && IsIntel());

    wgpu::Surface surface = CreateTestSurface();
    wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);
    wgpu::SurfaceTexture surfaceTexture;

    surface.Configure(&config);

    for (int i = 0; i < 10; i++) {
        glfwSetWindowSize(window.get(), 400 - 10 * i, 400 + 10 * i);
        glfwPollEvents();

        surface.GetCurrentTexture(&surfaceTexture);
        ClearTexture(surfaceTexture.texture, {0.05f * i, 0.0, 0.0, 1.0});
        surface.Present();
    }
}

// Test resizing both the window and the surface at the same time.
TEST_P(SurfaceTests, ResizingWindowAndSurface) {
    // TODO(crbug.com/dawn/1205): Currently failing on new NVIDIA GTX 1660s on Linux/Vulkan.
    DAWN_SUPPRESS_TEST_IF(IsLinux() && IsVulkan() && IsNvidia());

    wgpu::Surface surface = CreateTestSurface();
    wgpu::SurfaceTexture surfaceTexture;

    for (int i = 0; i < 10; i++) {
        glfwSetWindowSize(window.get(), 400 - 10 * i, 400 + 10 * i);
        glfwPollEvents();

        int width;
        int height;
        glfwGetFramebufferSize(window.get(), &width, &height);

        wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);
        config.width = width;
        config.height = height;
        surface.Configure(&config);

        surface.GetCurrentTexture(&surfaceTexture);
        ClearTexture(surfaceTexture.texture, {0.05f * i, 0.0, 0.0, 1.0});
        surface.Present();
    }
}

// Test switching devices on the same adapter.
TEST_P(SurfaceTests, SwitchingDevice) {
    // TODO(https://crbug.com/dawn/2116): Disabled due to new Validation Layer failures.
    DAWN_SUPPRESS_TEST_IF(IsVulkan());

    wgpu::Device device2 = CreateDevice();

    wgpu::Surface surface = CreateTestSurface();
    wgpu::SurfaceTexture surfaceTexture;

    wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);

    for (int i = 0; i < 3; i++) {
        wgpu::Device deviceToUse;
        if (i % 2 == 0) {
            deviceToUse = device;
        } else {
            deviceToUse = device2;
        }

        config.device = deviceToUse;
        surface.Configure(&config);
        surface.GetCurrentTexture(&surfaceTexture);
        ClearTexture(surfaceTexture.texture, {0.0, 1.0, 0.0, 1.0}, deviceToUse);
        surface.Present();
    }
}

// Getting current texture without configuring returns an invalid surface texture
// It cannot raise a device error at this stage since it has never been configured with a device
TEST_P(SurfaceTests, GetWithoutConfigure) {
    wgpu::Surface surface = CreateTestSurface();

    wgpu::SurfaceTexture surfaceTexture;
    surface.GetCurrentTexture(&surfaceTexture);
    EXPECT_EQ(surfaceTexture.status, wgpu::SurfaceGetCurrentTextureStatus::Error);
}

// Getting current texture after unconfiguring fails
TEST_P(SurfaceTests, GetAfterUnconfigure) {
    wgpu::Surface surface = CreateTestSurface();
    wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);
    surface.Configure(&config);

    surface.Unconfigure();

    wgpu::SurfaceTexture surfaceTexture;
    ASSERT_DEVICE_ERROR(surface.GetCurrentTexture(&surfaceTexture));
    EXPECT_EQ(surfaceTexture.status, wgpu::SurfaceGetCurrentTextureStatus::Error);
}

// Getting current texture after losing the device
TEST_P(SurfaceTests, GetAfterDeviceLoss) {
    wgpu::Surface surface = CreateTestSurface();
    wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);
    surface.Configure(&config);

    LoseDeviceForTesting();

    wgpu::SurfaceTexture surfaceTexture;
    surface.GetCurrentTexture(&surfaceTexture);
    EXPECT_EQ(surfaceTexture.status, wgpu::SurfaceGetCurrentTextureStatus::DeviceLost);
}

// Presenting without configuring fails
TEST_P(SurfaceTests, PresentWithoutConfigure) {
    wgpu::Surface surface = CreateTestSurface();
    // TODO(dawn:2320): This cannot throw a device error since the surface is
    // not aware of the device at this stage.
    /*ASSERT_DEVICE_ERROR(*/ surface.Present() /*)*/;
}

// Presenting after unconfiguring fails
TEST_P(SurfaceTests, PresentAfterUnconfigure) {
    wgpu::Surface surface = CreateTestSurface();
    wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);

    surface.Configure(&config);

    surface.Unconfigure();

    ASSERT_DEVICE_ERROR(surface.Present());
}

// Presenting without getting current texture first fails
TEST_P(SurfaceTests, PresentWithoutGet) {
    wgpu::Surface surface = CreateTestSurface();
    wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);

    surface.Configure(&config);
    ASSERT_DEVICE_ERROR(surface.Present());
}

// Check that all surfaces must support RenderAttachment.
TEST_P(SurfaceTests, RenderAttachmentAlwaysSupported) {
    wgpu::Surface surface = CreateTestSurface();
    wgpu::SurfaceCapabilities caps;
    surface.GetCapabilities(adapter, &caps);

    ASSERT_TRUE(caps.usages & wgpu::TextureUsage::RenderAttachment);
}

// Test sampling from the surface when it is supported.
TEST_P(SurfaceTests, Sampling) {
    wgpu::Surface surface = CreateTestSurface();
    wgpu::SurfaceCapabilities caps;
    surface.GetCapabilities(adapter, &caps);

    // Skip all tests if readable surface doesn't support texture binding
    DAWN_TEST_UNSUPPORTED_IF(!(caps.usages & wgpu::TextureUsage::TextureBinding));

    wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);
    config.usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment;
    surface.Configure(&config);

    // Clear and sample from the texture
    wgpu::SurfaceTexture t;
    surface.GetCurrentTexture(&t);
    ClearTexture(t.texture, {1.0, 0.0, 0.0, 1.0});
    SampleLoadTexture(t.texture, utils::RGBA8::kRed);

    surface.Present();
}

// Test copying from the surface when it is supported.
TEST_P(SurfaceTests, CopyFrom) {
    wgpu::Surface surface = CreateTestSurface();
    wgpu::SurfaceCapabilities caps;
    surface.GetCapabilities(adapter, &caps);

    // Skip all tests if readable surface doesn't support copy src
    DAWN_TEST_UNSUPPORTED_IF(!(caps.usages & wgpu::TextureUsage::CopySrc));

    wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);
    config.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment;
    surface.Configure(&config);

    // Clear and copy from the texture
    wgpu::SurfaceTexture t;
    surface.GetCurrentTexture(&t);
    ClearTexture(t.texture, {1.0, 0.0, 0.0, 1.0});

    if (t.texture.GetFormat() == wgpu::TextureFormat::BGRA8Unorm ||
        t.texture.GetFormat() == wgpu::TextureFormat::BGRA8UnormSrgb) {
        EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kBlue, t.texture, 0, 0);
    } else {
        EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kRed, t.texture, 0, 0);
    }

    surface.Present();
}

// Test copying to the surface when it is supported.
TEST_P(SurfaceTests, CopyTo) {
    wgpu::Surface surface = CreateTestSurface();
    wgpu::SurfaceCapabilities caps;
    surface.GetCapabilities(adapter, &caps);

    // Skip all tests if readable surface doesn't support copy dst or if we can't read back.
    DAWN_TEST_UNSUPPORTED_IF(!(caps.usages & wgpu::TextureUsage::CopyDst));
    DAWN_TEST_UNSUPPORTED_IF(
        !(caps.usages & (wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding)));

    wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);
    config.usage = caps.usages & (wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst |
                                  wgpu::TextureUsage::TextureBinding);
    config.width = 1;
    config.height = 1;
    surface.Configure(&config);

    // Write to the texture and read it back somehow.
    wgpu::SurfaceTexture t;
    surface.GetCurrentTexture(&t);

    wgpu::Extent3D writeSize = {1, 1, 1};
    wgpu::ImageCopyTexture dest = {};
    dest.texture = t.texture;
    wgpu::TextureDataLayout dataLayout = {};
    queue.WriteTexture(&dest, &utils::RGBA8::kRed, sizeof(utils::RGBA8), &dataLayout, &writeSize);

    if (t.texture.GetUsage() & wgpu::TextureUsage::TextureBinding) {
        if (t.texture.GetFormat() == wgpu::TextureFormat::BGRA8Unorm ||
            t.texture.GetFormat() == wgpu::TextureFormat::BGRA8UnormSrgb) {
            SampleLoadTexture(t.texture, utils::RGBA8::kBlue);
        } else {
            SampleLoadTexture(t.texture, utils::RGBA8::kRed);
        }
    }

    if (t.texture.GetUsage() & wgpu::TextureUsage::CopySrc) {
        EXPECT_PIXEL_RGBA8_EQ(utils::RGBA8::kRed, t.texture, 0, 0);
    }

    surface.Present();
}

// Test using the surface as a storage texture when supported.
TEST_P(SurfaceTests, Storage) {
    wgpu::Surface surface = CreateTestSurface();
    wgpu::SurfaceCapabilities caps;
    surface.GetCapabilities(adapter, &caps);

    // Skip all tests if readable surface doesn't support storage or if we can't find a storage-read
    // capable format.
    DAWN_TEST_UNSUPPORTED_IF(!(caps.usages & wgpu::TextureUsage::StorageBinding));

    wgpu::TextureFormat storageCapableFormat = wgpu::TextureFormat::Undefined;
    for (uint32_t i = 0; i < caps.formatCount; i++) {
        if (utils::TextureFormatSupportsStorageTexture(caps.formats[i], device, false)) {
            storageCapableFormat = caps.formats[i];
            break;
        }
    }
    DAWN_TEST_UNSUPPORTED_IF(storageCapableFormat == wgpu::TextureFormat::Undefined);

    wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);
    config.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::StorageBinding;
    config.format = storageCapableFormat;
    surface.Configure(&config);

    // Clear and storage load from the texture
    wgpu::SurfaceTexture t;
    surface.GetCurrentTexture(&t);
    ClearTexture(t.texture, {1.0, 0.0, 0.0, 1.0});
    StorageLoadTexture(t.texture, utils::RGBA8::kRed);

    surface.Present();
}

// TODO(dawn:2320): Enable D3D tests (though they are not enabled in SwapChainTests neither)
DAWN_INSTANTIATE_TEST(SurfaceTests,
                      // D3D11Backend(),
                      // D3D12Backend(),
                      MetalBackend(),
                      VulkanBackend());

}  // anonymous namespace
}  // namespace dawn
