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

#include "GLFW/glfw3.h"
#include "dawn/replay/Replay.h"
#include "src/dawn/common/Constants.h"
#include "src/dawn/tests/DawnTest.h"
#include "src/dawn/utils/ComboRenderBundleEncoderDescriptor.h"
#include "src/dawn/utils/ComboRenderPipelineDescriptor.h"
#include "src/dawn/utils/WGPUHelpers.h"
#include "src/utils/compiler.h"
#include "webgpu/webgpu_glfw.h"

namespace dawn {
namespace {

class SurfaceTests : public DawnTest {
  protected:
    void GetRequiredLimits(const dawn::utils::ComboLimits& supported,
                           dawn::utils::ComboLimits& required) override {
        // Just copy all the limits, though all we really care about is
        // maxStorageBuffersInFragmentStage
        supported.UnlinkedCopyTo(&required);
    }

  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"));

        // Causes flaky X11 resource exhaustion when run with SwiftShader.
        DAWN_SUPPRESS_TEST_IF(IsLinux() && IsVulkan() && IsSwiftshader());

        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);
        mWindow.reset(glfwCreateWindow(400, 500, "SurfaceTests window", nullptr, nullptr));

        int width;
        int height;
        glfwGetFramebufferSize(mWindow.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 {
        DawnTest::TearDown();

        // Destroy the window after the `wgpu::Surface surface` created in test body released.
        mWindow.reset();
    }

    wgpu::Surface CreateTestSurface() {
        return wgpu::glfw::CreateSurfaceForWindow(GetInstance(), mWindow.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 (DAWN_UNSAFE_TODO(capabilities.presentModes[i]) == mode) {
                return true;
            }
        }
        return false;
    }

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

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

    // Test the preferred modes and Undefined=Fifo which are required to be supported.
    std::set<wgpu::PresentMode> presentModes{
        wgpu::PresentMode::Undefined,
        wgpu::PresentMode::Fifo,
        config.presentMode,
    };
    for (wgpu::PresentMode presentMode : presentModes) {
        SCOPED_TRACE(absl::StrFormat("present mode: %d", presentMode));

        // Configure
        config.presentMode = presentMode;
        surface.Configure(&config);

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

        // Present
        ASSERT_EQ(wgpu::Status::Success, 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 reconfiguring the surface after GetCurrentTexture
TEST_P(SurfaceTests, ReconfigureAfterGetCurrentTexture) {
    // TODO(crbug.com/500793592): Causes cascading failures on Windows 11/AMD
    // RX 5500 XT w/ backend validation.
    DAWN_SUPPRESS_TEST_IF(IsWindows11() && IsAMD() && IsVulkan() && IsBackendValidationEnabled());

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

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

    {
        surface.Configure(&config);
        wgpu::SurfaceTexture surfaceTexture;
        surface.GetCurrentTexture(&surfaceTexture);
        ClearTexture(surfaceTexture.texture, {0.0, 1.0, 0.0, 1.0});
        ASSERT_EQ(wgpu::Status::Success, surface.Present());
    }
}

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

    {
        surface.Configure(&config);
        wgpu::SurfaceTexture surfaceTexture;
        surface.GetCurrentTexture(&surfaceTexture);
        ClearTexture(surfaceTexture.texture, {1.0, 0.0, 0.0, 1.0});
        ASSERT_EQ(wgpu::Status::Success, surface.Present());
    }

    surface.Unconfigure();

    {
        surface.Configure(&config);
        wgpu::SurfaceTexture surfaceTexture;
        surface.GetCurrentTexture(&surfaceTexture);
        ClearTexture(surfaceTexture.texture, {0.0, 1.0, 0.0, 1.0});
        ASSERT_EQ(wgpu::Status::Success, surface.Present());
    }
}

// Test unconfiguring after GetCurrentTexture but before the Present
TEST_P(SurfaceTests, UnconfigureAfterGet) {
    // TODO(crbug.com/500793592): Causes cascading failures on Windows 11/AMD
    // RX 5500 XT w/ backend validation.
    DAWN_SUPPRESS_TEST_IF(IsWindows11() && IsAMD() && IsVulkan() && IsBackendValidationEnabled());

    // TODO(crbug.com/500766623): Fails due to backend validation errors on
    // Windows 11/AMD RX 5500 XT w/ D3D12.
    DAWN_SUPPRESS_TEST_IF(IsWindows11() && IsAMD() && IsD3D12() && IsBackendValidationEnabled());

    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());

    // crbug.com/358166481
    DAWN_SUPPRESS_TEST_IF(IsLinux() && IsNvidia() && IsVulkan());

    // TODO(crbug.com/463614521): Flakily causes a device loss on Snapdragon X
    // Elite SoCs which causes all subsequent tests to fail.
    DAWN_SUPPRESS_TEST_IF(IsWindows() && IsQualcomm() && IsD3D12());

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

    wgpu::Surface surface = CreateTestSurface();

    wgpu::SurfaceCapabilities capabilities;
    surface.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(surface);

            {
                config.presentMode = mode1;
                surface.Configure(&config);

                wgpu::SurfaceTexture surfaceTexture;
                surface.GetCurrentTexture(&surfaceTexture);
                ClearTexture(surfaceTexture.texture, {0.0, 0.0, 0.0, 1.0});
                ASSERT_EQ(wgpu::Status::Success, surface.Present());
            }

            {
                config.presentMode = mode2;
                surface.Configure(&config);

                wgpu::SurfaceTexture surfaceTexture;
                surface.GetCurrentTexture(&surfaceTexture);
                ClearTexture(surfaceTexture.texture, {0.0, 0.0, 0.0, 1.0});
                ASSERT_EQ(wgpu::Status::Success, surface.Present());
                surface.Unconfigure();
            }
        }
    }
}

// Test resizing the surface and without resizing the window.
TEST_P(SurfaceTests, ResizingSurfaceOnly) {
    // TODO(crbug.com/468228358): Flaky on Snapdragon X Elite SoCs w/ D3D12.
    DAWN_SUPPRESS_TEST_IF(IsWindows() && IsQualcomm() && IsD3D12());

    // TODO(crbug.com/500766623): Fails due to backend validation errors on
    // Windows 11/AMD RX 5500 XT w/ D3D12.
    DAWN_SUPPRESS_TEST_IF(IsWindows11() && IsAMD() && IsD3D12() && IsBackendValidationEnabled());

    wgpu::Surface surface = CreateTestSurface();

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

        surface.Configure(&config);
        wgpu::SurfaceTexture surfaceTexture;
        surface.GetCurrentTexture(&surfaceTexture);
        ClearTexture(surfaceTexture.texture, {0.05f * i, 0.0, 0.0, 1.0});
        ASSERT_EQ(wgpu::Status::Success, surface.Present());
    }
}

// Test resizing the window but not the surface.
TEST_P(SurfaceTests, ResizingWindowOnly) {
    // Hangs on NVIDIA GTX 1660
    DAWN_SUPPRESS_TEST_IF(IsD3D12() && IsNvidia());
    // TODO(crbug.com/42241486): Crashes on Linux NVIDIA GTX 1660 with 535.183.01 driver
    DAWN_SUPPRESS_TEST_IF(IsLinux() && IsVulkan() && IsNvidia());

    // TODO(crbug.com/500766623): Fails due to backend validation errors on
    // Windows 11/AMD RX 5500 XT w/ D3D12.
    DAWN_SUPPRESS_TEST_IF(IsWindows11() && IsAMD() && IsD3D12() && IsBackendValidationEnabled());

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

    surface.Configure(&config);

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

        wgpu::SurfaceTexture surfaceTexture;
        surface.GetCurrentTexture(&surfaceTexture);
        ClearTexture(surfaceTexture.texture, {0.05f * i, 0.0, 0.0, 1.0});
        ASSERT_EQ(wgpu::Status::Success, 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());

    // TODO(crbug.com/465497433): Flakily loses device on Snapdragon X Elite
    // SoCs.
    DAWN_SUPPRESS_TEST_IF(IsWindows() && IsQualcomm() && IsD3D12());

    // TODO(crbug.com/500766623): Fails due to backend validation errors on
    // Windows 11/AMD RX 5500 XT w/ D3D12.
    DAWN_SUPPRESS_TEST_IF(IsWindows11() && IsAMD() && IsD3D12() && IsBackendValidationEnabled());

    wgpu::Surface surface = CreateTestSurface();

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

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

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

        wgpu::SurfaceTexture surfaceTexture;
        surface.GetCurrentTexture(&surfaceTexture);
        ClearTexture(surfaceTexture.texture, {0.05f * i, 0.0, 0.0, 1.0});
        ASSERT_EQ(wgpu::Status::Success, surface.Present());
    }
}

// Test switching devices on the same adapter.
TEST_P(SurfaceTests, SwitchingDevice) {
    // TODO(https://crbug.com/dawn/2116): VVLs crash because oldSwapchain is from a different
    // device. The spec says it is ok if it is only the same instance but clarifications yet to be
    // published by Khronos are that the spec is wrong and should require the swapchain to be from
    // the same device. Suppress on all Vulkan devices while a proper fix is done.
    DAWN_SUPPRESS_TEST_IF(IsVulkan());

    // TODO(dawn:269): This isn't implemented yet but could be supported in the future.
    DAWN_SUPPRESS_TEST_IF(IsD3D11() || IsD3D12());

    wgpu::Device device2 = CreateDevice();

    wgpu::Surface surface = CreateTestSurface();

    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);
        wgpu::SurfaceTexture surfaceTexture;
        surface.GetCurrentTexture(&surfaceTexture);
        ClearTexture(surfaceTexture.texture, {0.0, 1.0, 0.0, 1.0}, deviceToUse);
        ASSERT_EQ(wgpu::Status::Success, 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;
    // No device anymore, so no device error, just the synchronous error and an instance log.
    ASSERT_EQ(wgpu::Status::Error, surface.Present());
    surface.GetCurrentTexture(&surfaceTexture);
    EXPECT_EQ(surfaceTexture.status, wgpu::SurfaceGetCurrentTextureStatus::Error);
}

// Getting current texture after losing the device should appear as if we got a texture.
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::SuccessOptimal);
}

// Presenting without configuring fails
TEST_P(SurfaceTests, PresentWithoutConfigure) {
    wgpu::Surface surface = CreateTestSurface();
    ASSERT_EQ(wgpu::Status::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();

    // No device anymore, so no device error, just the synchronous error and an instance log.
    ASSERT_EQ(wgpu::Status::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);

    wgpu::Status presentStatus;
    ASSERT_DEVICE_ERROR(presentStatus = surface.Present());
    ASSERT_EQ(wgpu::Status::Success, presentStatus);
}

// 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);

    ASSERT_EQ(wgpu::Status::Success, surface.Present());
}

// Test copying from the surface when it is supported.
TEST_P(SurfaceTests, CopyFrom) {
    // TODO(crbug.com/500766623): Fails due to backend validation errors on
    // Windows 11/AMD RX 5500 XT w/ D3D12.
    DAWN_SUPPRESS_TEST_IF(IsWindows11() && IsAMD() && IsD3D12() && IsBackendValidationEnabled());

    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);
    }

    ASSERT_EQ(wgpu::Status::Success, surface.Present());
}

// Test copying to the surface when it is supported.
TEST_P(SurfaceTests, CopyTo) {
    // TODO(crbug.com/500766623): Fails due to backend validation errors on
    // Windows 11/AMD RX 5500 XT w/ D3D12.
    DAWN_SUPPRESS_TEST_IF(IsWindows11() && IsAMD() && IsD3D12() && IsBackendValidationEnabled());

    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::TexelCopyTextureInfo dest = {};
    dest.texture = t.texture;
    wgpu::TexelCopyBufferLayout 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);
    }

    ASSERT_EQ(wgpu::Status::Success, surface.Present());
}

// Test using the surface as a storage texture when supported.
TEST_P(SurfaceTests, Storage) {
    DAWN_TEST_UNSUPPORTED_IF(GetSupportedLimits().maxStorageBuffersInFragmentStage < 1);
    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(device, DAWN_UNSAFE_TODO(caps.formats[i]))) {
            storageCapableFormat = DAWN_UNSAFE_TODO(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);

    ASSERT_EQ(wgpu::Status::Success, surface.Present());
}

// TODO(crbug.com/465183957): Implement swap chain for WebGPUBackend.
DAWN_INSTANTIATE_TEST(SurfaceTests,
                      D3D11Backend(),
                      D3D11Backend({"d3d11_delay_flush_to_gpu"}),
                      D3D12Backend(),
                      MetalBackend(),
                      OpenGLBackend(),
                      OpenGLESBackend(),
                      VulkanBackend(),
                      WebGPUBackend());

}  // anonymous namespace
}  // namespace dawn
