Revert "Remove SwapChain from the API"

This reverts commit 8faad454e56c4de1a648a17cf1a7010e28503d5c.

Reason for revert: Causing ASSERT failures on Windows with
--enable-implicit-device-sync. And, causing Linux TSAN use-after-free errors.
https://bugs.chromium.org/p/dawn/issues/detail?id=2320#c4

Original change's description:
> Remove SwapChain from the API
>
> This applies the switch from manipulating a SwapChain object to calling
> Surface::configure that was brung to the standard webgpu.h a couple of
> months ago.
>
> I believe this needs a bit of extra work, but at this stage I need a
> review from people more familiar with the codebase to tell me if I am
> going in the right direction.
>
> The SwapChain object is still here, but no longer present in the API.
> Instances of the swap chain are now owned by the surface object. The
> test for surface capabilities is partly calling a method of the
> PhysicalDevice in order to have backend-specific capabilities.
>
> So far I mostly tested with the Vulkan backend, though I tried to
> provide a valid implementation for all backends.
>
> Bug: dawn:2320
> Change-Id: I69d3c64873213eca375c66170cb648debd8ec91d
> Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/167600
> Kokoro: Kokoro <noreply+kokoro@google.com>
> Commit-Queue: Élie Michel <elie.michel.fr@gmail.com>
> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
> Reviewed-by: Austin Eng <enga@chromium.org>

Bug: dawn:2320
Change-Id: Icaf912bc87ac5a7f2a646bc5405a9c3ef37bb932
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/178885
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Austin Eng <enga@chromium.org>
Auto-Submit: Austin Eng <enga@chromium.org>
Reviewed-by: Loko Kung <lokokung@google.com>
diff --git a/generator/templates/dawn/wire/WireCmd.cpp b/generator/templates/dawn/wire/WireCmd.cpp
index 1f70e40..9e63d7b 100644
--- a/generator/templates/dawn/wire/WireCmd.cpp
+++ b/generator/templates/dawn/wire/WireCmd.cpp
@@ -221,7 +221,7 @@
                         //* Structures might contain more pointers so we need to add their extra size as well.
                         {% if member.type.category == "structure" %}
                             for (decltype(memberLength) i = 0; i < memberLength; ++i) {
-                                {% do assert(member.annotation == "const*" or member.annotation == "*", "unhandled annotation: " + member.annotation)%}
+                                {% do assert(member.annotation == "const*", "unhandled annotation: " + member.annotation) %}
                                 result += {{as_cType(member.type.name)}}GetExtraRequiredSize(record.{{as_varName(member.name)}}[i]);
                             }
                         {% endif %}
diff --git a/src/dawn/dawn.json b/src/dawn/dawn.json
index 9f7e882..d7c6757 100644
--- a/src/dawn/dawn.json
+++ b/src/dawn/dawn.json
@@ -389,14 +389,15 @@
     },
     "surface capabilities": {
         "category": "structure",
+        "tags": ["upstream"],
         "extensible": "out",
         "members": [
             {"name": "format count", "type": "size_t"},
-            {"name": "formats", "type": "texture format", "annotation": "const*"},
+            {"name": "formats", "type": "texture format", "annotation": "*"},
             {"name": "present mode count", "type": "size_t"},
-            {"name": "present modes", "type": "present mode", "annotation": "const*"},
+            {"name": "present modes", "type": "present mode", "annotation": "*"},
             {"name": "alpha mode count", "type": "size_t"},
-            {"name": "alpha modes", "type": "composite alpha mode", "annotation": "const*"}
+            {"name": "alpha modes", "type": "composite alpha mode", "annotation": "*"}
         ],
         "methods": [
             {
@@ -408,17 +409,18 @@
     },
     "surface configuration": {
         "category": "structure",
+        "tags": ["upstream"],
         "extensible": "in",
         "members": [
             {"name": "device", "type": "device"},
             {"name": "format", "type": "texture format"},
-            {"name": "usage", "type": "texture usage", "default": "render attachment"},
-            {"name": "view format count", "type": "size_t", "default": 0},
-            {"name": "view formats", "type": "texture format", "annotation": "const*", "length": "view format count"},
-            {"name": "alpha mode", "type": "composite alpha mode", "default": "opaque"},
+            {"name": "usage", "type": "texture usage"},
+            {"name": "view format count", "type": "size_t"},
+            {"name": "view formats", "type": "texture format", "annotation": "const*"},
+            {"name": "alpha mode", "type": "composite alpha mode"},
             {"name": "width", "type": "uint32_t"},
             {"name": "height", "type": "uint32_t"},
-            {"name": "present mode", "type": "present mode", "default": "fifo"}
+            {"name": "present mode", "type": "present mode"}
         ]
     },
     "external texture binding entry": {
@@ -1014,6 +1016,7 @@
     },
     "composite alpha mode": {
         "category": "enum",
+        "tags": ["upstream"],
         "values": [
             {"value": 0, "name": "auto"},
             {"value": 1, "name": "opaque"},
@@ -3405,6 +3408,7 @@
             {
                 "name": "configure",
                 "returns": "void",
+                "tags": ["upstream"],
                 "args": [
                     {"name": "config", "type": "surface configuration", "annotation": "const*"}
                 ]
@@ -3412,6 +3416,7 @@
             {
                 "name": "get capabilities",
                 "returns": "void",
+                "tags": ["upstream"],
                 "args": [
                     {"name": "adapter", "type": "adapter"},
                     {"name": "capabilities", "type": "surface capabilities", "annotation": "*"}
@@ -3420,6 +3425,7 @@
             {
                 "name": "get current texture",
                 "returns": "void",
+                "tags": ["upstream"],
                 "args": [
                     {"name": "surface texture", "type": "surface texture", "annotation": "*"}
                 ]
@@ -3434,20 +3440,14 @@
             {
                 "name": "present",
                 "returns": "void",
+                "tags": ["upstream"],
                 "args": []
             },
             {
                 "name": "unconfigure",
                 "returns": "void",
+                "tags": ["upstream"],
                 "args": []
-            },
-            {
-                "name": "set label",
-                "tags": [],
-                "returns": "void",
-                "args": [
-                    {"name": "label", "type": "char", "annotation": "const*", "length": "strlen"}
-                ]
             }
         ]
     },
@@ -3566,6 +3566,7 @@
     },
     "surface texture": {
         "category": "structure",
+        "tags": ["upstream"],
         "members": [
             {"name": "texture", "type": "texture"},
             {"name": "suboptimal", "type": "bool"},
@@ -3709,6 +3710,7 @@
     },
     "surface get current texture status": {
         "category": "enum",
+        "tags": ["upstream"],
         "values": [
             {"value": 0, "name": "success"},
             {"value": 1, "name": "timeout"},
diff --git a/src/dawn/dawn_wire.json b/src/dawn/dawn_wire.json
index 061c06f..234bbc9 100644
--- a/src/dawn/dawn_wire.json
+++ b/src/dawn/dawn_wire.json
@@ -240,7 +240,6 @@
             "QueueOnSubmittedWorkDoneF",
             "QueueWriteBuffer",
             "QueueWriteTexture",
-            "SurfaceGetCapabilities",
             "SurfaceGetPreferredFormat",
             "TextureGetWidth",
             "TextureGetHeight",
@@ -261,8 +260,6 @@
             "DeviceInjectError",
             "InstanceProcessEvents",
             "InstanceWaitAny",
-            "SurfaceConfigure",
-            "SurfaceGetCurrentTexture",
             "SwapChainGetCurrentTexture"
         ],
         "client_special_objects": [
@@ -274,7 +271,6 @@
             "Queue",
             "ShaderModule",
             "Surface",
-            "SurfaceCapabilities",
             "SwapChain",
             "Texture"
         ],
diff --git a/src/dawn/native/Adapter.cpp b/src/dawn/native/Adapter.cpp
index 4145b7c..8e9a5c4 100644
--- a/src/dawn/native/Adapter.cpp
+++ b/src/dawn/native/Adapter.cpp
@@ -29,7 +29,6 @@
 
 #include <algorithm>
 #include <memory>
-#include <string>
 #include <tuple>
 #include <utility>
 #include <vector>
@@ -71,10 +70,6 @@
     return mPhysicalDevice.Get();
 }
 
-const PhysicalDeviceBase* AdapterBase::GetPhysicalDevice() const {
-    return mPhysicalDevice.Get();
-}
-
 InstanceBase* AdapterBase::APIGetInstance() const {
     InstanceBase* instance = mPhysicalDevice->GetInstance();
     DAWN_ASSERT(instance != nullptr);
@@ -338,10 +333,6 @@
     return mFeatureLevel;
 }
 
-const std::string& AdapterBase::GetName() const {
-    return mPhysicalDevice->GetName();
-}
-
 std::vector<Ref<AdapterBase>> SortAdapters(std::vector<Ref<AdapterBase>> adapters,
                                            const RequestAdapterOptions* options) {
     const bool highPerformance =
diff --git a/src/dawn/native/Adapter.h b/src/dawn/native/Adapter.h
index 6e81b5f..2f8a405 100644
--- a/src/dawn/native/Adapter.h
+++ b/src/dawn/native/Adapter.h
@@ -28,12 +28,10 @@
 #ifndef SRC_DAWN_NATIVE_ADAPTER_H_
 #define SRC_DAWN_NATIVE_ADAPTER_H_
 
-#include <string>
 #include <vector>
 
 #include "dawn/common/Ref.h"
 #include "dawn/common/RefCounted.h"
-#include "dawn/common/WeakRefSupport.h"
 #include "dawn/native/DawnNative.h"
 #include "dawn/native/PhysicalDevice.h"
 #include "dawn/native/dawn_platform.h"
@@ -44,7 +42,7 @@
 class TogglesState;
 struct SupportedLimits;
 
-class AdapterBase : public RefCounted, public WeakRefSupport<AdapterBase> {
+class AdapterBase : public RefCounted {
   public:
     AdapterBase(Ref<PhysicalDeviceBase> physicalDevice,
                 FeatureLevel featureLevel,
@@ -72,16 +70,12 @@
 
     // Return the underlying PhysicalDevice.
     PhysicalDeviceBase* GetPhysicalDevice();
-    const PhysicalDeviceBase* GetPhysicalDevice() const;
 
     // Get the actual toggles state of the adapter.
     const TogglesState& GetTogglesState() const;
 
     FeatureLevel GetFeatureLevel() const;
 
-    // Get a human readable label for the adapter (in practice, the physical device name)
-    const std::string& GetName() const;
-
   private:
     Ref<PhysicalDeviceBase> mPhysicalDevice;
     FeatureLevel mFeatureLevel;
diff --git a/src/dawn/native/Device.cpp b/src/dawn/native/Device.cpp
index 89a55c9..195bf85 100644
--- a/src/dawn/native/Device.cpp
+++ b/src/dawn/native/Device.cpp
@@ -1409,18 +1409,7 @@
     Ref<SwapChainBase> result;
     if (ConsumedError(CreateSwapChain(surface, descriptor), &result,
                       "calling %s.CreateSwapChain(%s).", this, descriptor)) {
-        SurfaceConfiguration config;
-        config.nextInChain = descriptor->nextInChain;
-        config.device = this;
-        config.width = descriptor->width;
-        config.height = descriptor->height;
-        config.format = descriptor->format;
-        config.usage = descriptor->usage;
-        config.presentMode = descriptor->presentMode;
-        config.viewFormatCount = 0;
-        config.viewFormats = nullptr;
-        config.alphaMode = wgpu::CompositeAlphaMode::Opaque;
-        result = SwapChainBase::MakeError(this, &config);
+        result = SwapChainBase::MakeError(this, descriptor);
     }
     return ReturnToAPI(std::move(result));
 }
@@ -2114,31 +2103,15 @@
 ResultOrError<Ref<SwapChainBase>> DeviceBase::CreateSwapChain(
     Surface* surface,
     const SwapChainDescriptor* descriptor) {
-    EmitDeprecationWarning(
-        "The explicit creation of a SwapChain object is deprecated and should be replaced by "
-        "Surface configuration.");
-
     DAWN_TRY(ValidateIsAlive());
     if (IsValidationEnabled()) {
         DAWN_TRY_CONTEXT(ValidateSwapChainDescriptor(this, surface, descriptor), "validating %s",
                          descriptor);
     }
 
-    SurfaceConfiguration config;
-    config.nextInChain = descriptor->nextInChain;
-    config.device = this;
-    config.width = descriptor->width;
-    config.height = descriptor->height;
-    config.format = descriptor->format;
-    config.usage = descriptor->usage;
-    config.presentMode = descriptor->presentMode;
-    config.viewFormatCount = 0;
-    config.viewFormats = nullptr;
-    config.alphaMode = wgpu::CompositeAlphaMode::Opaque;
-
     SwapChainBase* previousSwapChain = surface->GetAttachedSwapChain();
     ResultOrError<Ref<SwapChainBase>> maybeNewSwapChain =
-        CreateSwapChainImpl(surface, previousSwapChain, &config);
+        CreateSwapChainImpl(surface, previousSwapChain, descriptor);
 
     if (previousSwapChain != nullptr) {
         previousSwapChain->DetachFromSurface();
@@ -2152,13 +2125,6 @@
     return newSwapChain;
 }
 
-ResultOrError<Ref<SwapChainBase>> DeviceBase::CreateSwapChain(Surface* surface,
-                                                              SwapChainBase* previousSwapChain,
-                                                              const SurfaceConfiguration* config) {
-    // Nothing to validate here as it is done in Surface::Configure
-    return CreateSwapChainImpl(surface, previousSwapChain, config);
-}
-
 ResultOrError<Ref<TextureBase>> DeviceBase::CreateTexture(const TextureDescriptor* descriptorOrig) {
     DAWN_TRY(ValidateIsAlive());
 
diff --git a/src/dawn/native/Device.h b/src/dawn/native/Device.h
index f8db590..95c8dcd 100644
--- a/src/dawn/native/Device.h
+++ b/src/dawn/native/Device.h
@@ -266,13 +266,8 @@
     ResultOrError<Ref<ShaderModuleBase>> CreateShaderModule(
         const ShaderModuleDescriptor* descriptor,
         std::unique_ptr<OwnedCompilationMessages>* compilationMessages = nullptr);
-    // Deprecated: this was the way to create a SwapChain when it was explicitly manipulated by the
-    // end user.
     ResultOrError<Ref<SwapChainBase>> CreateSwapChain(Surface* surface,
                                                       const SwapChainDescriptor* descriptor);
-    ResultOrError<Ref<SwapChainBase>> CreateSwapChain(Surface* surface,
-                                                      SwapChainBase* previousSwapChain,
-                                                      const SurfaceConfiguration* config);
     ResultOrError<Ref<TextureBase>> CreateTexture(const TextureDescriptor* rawDescriptor);
     ResultOrError<Ref<TextureViewBase>> CreateTextureView(TextureBase* texture,
                                                           const TextureViewDescriptor* descriptor);
@@ -311,9 +306,7 @@
     ShaderModuleBase* APICreateShaderModule(const ShaderModuleDescriptor* descriptor);
     ShaderModuleBase* APICreateErrorShaderModule(const ShaderModuleDescriptor* descriptor,
                                                  const char* errorMessage);
-    // TODO (dawn:2320) Remove after deprecation
-    SwapChainBase* APICreateSwapChain(Surface* surface,
-                                      const SwapChainDescriptor* descriptor);  // Deprecated
+    SwapChainBase* APICreateSwapChain(Surface* surface, const SwapChainDescriptor* descriptor);
     TextureBase* APICreateTexture(const TextureDescriptor* descriptor);
 
     wgpu::TextureUsage APIGetSupportedSurfaceUsage(Surface* surface);
@@ -519,7 +512,7 @@
     virtual ResultOrError<Ref<SwapChainBase>> CreateSwapChainImpl(
         Surface* surface,
         SwapChainBase* previousSwapChain,
-        const SurfaceConfiguration* config) = 0;
+        const SwapChainDescriptor* descriptor) = 0;
     virtual ResultOrError<Ref<TextureBase>> CreateTextureImpl(
         const UnpackedPtr<TextureDescriptor>& descriptor) = 0;
     virtual ResultOrError<Ref<TextureViewBase>> CreateTextureViewImpl(
diff --git a/src/dawn/native/PhysicalDevice.h b/src/dawn/native/PhysicalDevice.h
index 77e51f2..d509f4e 100644
--- a/src/dawn/native/PhysicalDevice.h
+++ b/src/dawn/native/PhysicalDevice.h
@@ -48,13 +48,6 @@
 
 class DeviceBase;
 
-// Structure that holds surface capabilities for a (Surface, PhysicalDevice) pair.
-struct PhysicalDeviceSurfaceCapabilities {
-    std::vector<wgpu::TextureFormat> formats;
-    std::vector<wgpu::PresentMode> presentModes;
-    std::vector<wgpu::CompositeAlphaMode> alphaModes;
-};
-
 struct FeatureValidationResult {
     // Constructor of successful result
     FeatureValidationResult();
@@ -117,9 +110,6 @@
     // Populate backend properties. Ownership of allocations written are owned by the caller.
     virtual void PopulateBackendProperties(UnpackedPtr<AdapterProperties>& properties) const = 0;
 
-    virtual ResultOrError<PhysicalDeviceSurfaceCapabilities> GetSurfaceCapabilities(
-        const Surface* surface) const = 0;
-
   protected:
     uint32_t mVendorId = 0xFFFFFFFF;
     std::string mVendorName;
diff --git a/src/dawn/native/Surface.cpp b/src/dawn/native/Surface.cpp
index bd0cc8e..8929dd6 100644
--- a/src/dawn/native/Surface.cpp
+++ b/src/dawn/native/Surface.cpp
@@ -27,17 +27,10 @@
 
 #include "dawn/native/Surface.h"
 
-#include <memory>
-#include <string>
-#include <utility>
-
 #include "dawn/common/Platform.h"
 #include "dawn/native/ChainUtils.h"
-#include "dawn/native/Device.h"
 #include "dawn/native/Instance.h"
 #include "dawn/native/SwapChain.h"
-#include "dawn/native/ValidationUtils_autogen.h"
-#include "dawn/native/utils/WGPUHelpers.h"
 
 #if defined(DAWN_USE_WINDOWS_UI)
 #include <windows.ui.core.h>
@@ -193,111 +186,6 @@
     }
 }
 
-MaybeError ValidateSurfaceConfiguration(DeviceBase* device,
-                                        const PhysicalDeviceSurfaceCapabilities& capabilities,
-                                        const SurfaceConfiguration* config,
-                                        const Surface* surface) {
-    UnpackedPtr<SurfaceConfiguration> unpacked;
-    DAWN_TRY_ASSIGN(unpacked, ValidateAndUnpack(config));
-
-    DAWN_TRY(config->device->ValidateIsAlive());
-
-    const Format* format = nullptr;
-    DAWN_TRY_ASSIGN(format, device->GetInternalFormat(config->format));
-    DAWN_ASSERT(format != nullptr);
-
-    // TODO(crbug.com/dawn/160): Lift this restriction once
-    // wgpu::Instance::GetPreferredSurfaceFormat is implemented.
-    // TODO(dawn:286):
-#if DAWN_PLATFORM_IS(ANDROID)
-    constexpr wgpu::TextureFormat kRequireSwapChainFormat = wgpu::TextureFormat::RGBA8Unorm;
-#else
-    constexpr wgpu::TextureFormat kRequireSwapChainFormat = wgpu::TextureFormat::BGRA8Unorm;
-#endif  // !DAWN_PLATFORM_IS(ANDROID)
-    DAWN_INVALID_IF(config->format != kRequireSwapChainFormat,
-                    "Format (%s) is not %s, which is (currently) the only accepted format.",
-                    config->format, kRequireSwapChainFormat);
-
-    if (device->HasFeature(Feature::SurfaceCapabilities)) {
-        wgpu::TextureUsage validUsage;
-        DAWN_TRY_ASSIGN(validUsage, device->GetSupportedSurfaceUsage(surface));
-        DAWN_INVALID_IF(
-            !IsSubset(config->usage, validUsage),
-            "Usage (%s) is not supported, %s are (currently) the only accepted usage flags.",
-            config->usage, validUsage);
-    } else {
-        DAWN_INVALID_IF(config->usage != wgpu::TextureUsage::RenderAttachment,
-                        "Usage (%s) is not %s, which is (currently) the only accepted usage. Other "
-                        "usage flags require enabling %s",
-                        config->usage, wgpu::TextureUsage::RenderAttachment,
-                        wgpu::FeatureName::SurfaceCapabilities);
-    }
-
-    for (size_t i = 0; i < config->viewFormatCount; ++i) {
-        const wgpu::TextureFormat apiViewFormat = config->viewFormats[i];
-        const Format* viewFormat = nullptr;
-        DAWN_TRY_ASSIGN(viewFormat, device->GetInternalFormat(apiViewFormat));
-        DAWN_ASSERT(viewFormat != nullptr);
-
-        DAWN_INVALID_IF(std::find(capabilities.formats.begin(), capabilities.formats.end(),
-                                  apiViewFormat) == capabilities.formats.end(),
-                        "View format (%s) is not supported by the adapter (%s) for this surface.",
-                        apiViewFormat, device->GetAdapter());
-    }
-
-    DAWN_TRY(ValidatePresentMode(config->presentMode));
-
-    // Check that config matches capabilities
-    auto formatIt =
-        std::find(capabilities.formats.begin(), capabilities.formats.end(), config->format);
-    DAWN_INVALID_IF(formatIt == capabilities.formats.end(),
-                    "Format (%s) is not supported by the adapter (%s) for this surface.",
-                    config->format, config->device->GetAdapter());
-
-    auto presentModeIt = std::find(capabilities.presentModes.begin(),
-                                   capabilities.presentModes.end(), config->presentMode);
-    DAWN_INVALID_IF(presentModeIt == capabilities.presentModes.end(),
-                    "Present mode (%s) is not supported by the adapter (%s) for this surface.",
-                    config->format, config->device->GetAdapter());
-
-    auto alphaModeIt = std::find(capabilities.alphaModes.begin(), capabilities.alphaModes.end(),
-                                 config->alphaMode);
-    DAWN_INVALID_IF(alphaModeIt == capabilities.alphaModes.end(),
-                    "Alpha mode (%s) is not supported by the adapter (%s) for this surface.",
-                    config->format, config->device->GetAdapter());
-
-    DAWN_INVALID_IF(config->width == 0 || config->height == 0,
-                    "Surface configuration size (width: %u, height: %u) is empty.", config->width,
-                    config->height);
-
-    DAWN_INVALID_IF(
-        config->width > device->GetLimits().v1.maxTextureDimension2D ||
-            config->height > device->GetLimits().v1.maxTextureDimension2D,
-        "Surface configuration size (width: %u, height: %u) is greater than the maximum 2D texture "
-        "size (width: %u, height: %u).",
-        config->width, config->height, device->GetLimits().v1.maxTextureDimension2D,
-        device->GetLimits().v1.maxTextureDimension2D);
-
-    return {};
-}
-
-class AdapterSurfaceCapCache {
-  public:
-    template <typename F>
-    MaybeError WithAdapterCapabilities(AdapterBase* adapter, const Surface* surface, F f) {
-        if (mCachedCapabilitiesAdapter.Promote().Get() != adapter) {
-            const PhysicalDeviceBase* physicalDevice = adapter->GetPhysicalDevice();
-            DAWN_TRY_ASSIGN(mCachedCapabilities, physicalDevice->GetSurfaceCapabilities(surface));
-            mCachedCapabilitiesAdapter = GetWeakRef(adapter);
-        }
-        return f(mCachedCapabilities);
-    }
-
-  private:
-    WeakRef<AdapterBase> mCachedCapabilitiesAdapter = nullptr;
-    PhysicalDeviceSurfaceCapabilities mCachedCapabilities;
-};
-
 // static
 Ref<Surface> Surface::MakeError(InstanceBase* instance) {
     return AcquireRef(new Surface(instance, ErrorMonad::kError));
@@ -306,13 +194,7 @@
 Surface::Surface(InstanceBase* instance, ErrorTag tag) : ErrorMonad(tag), mInstance(instance) {}
 
 Surface::Surface(InstanceBase* instance, const UnpackedPtr<SurfaceDescriptor>& descriptor)
-    : ErrorMonad(),
-      mInstance(instance),
-      mCapabilityCache(std::make_unique<AdapterSurfaceCapCache>()) {
-    if (descriptor->label != nullptr && strlen(descriptor->label) != 0) {
-        mLabel = descriptor->label;
-    }
-
+    : ErrorMonad(), mInstance(instance) {
     // Type is validated in validation, otherwise this may crash with an assert failure.
     wgpu::SType type = descriptor
                            .ValidateBranches<Branch<SurfaceDescriptorFromAndroidNativeWindow>,
@@ -378,30 +260,18 @@
 
 Surface::~Surface() {
     if (mSwapChain != nullptr) {
-        DAWN_UNUSED(mInstance->ConsumedError(Unconfigure()));
-    }
-
-    if (mRecycledSwapChain != nullptr) {
-        mRecycledSwapChain->DetachFromSurface();
-        mRecycledSwapChain->APIRelease();
-        mRecycledSwapChain = nullptr;
+        mSwapChain->DetachFromSurface();
+        mSwapChain = nullptr;
     }
 }
 
 SwapChainBase* Surface::GetAttachedSwapChain() {
     DAWN_ASSERT(!IsError());
-    DAWN_ASSERT(mIsSwapChainManagedBySurface == ManagesSwapChain::Unknown ||
-                mIsSwapChainManagedBySurface == ManagesSwapChain::No);
-    mIsSwapChainManagedBySurface = ManagesSwapChain::No;
-
     return mSwapChain.Get();
 }
+
 void Surface::SetAttachedSwapChain(SwapChainBase* swapChain) {
     DAWN_ASSERT(!IsError());
-    DAWN_ASSERT(mIsSwapChainManagedBySurface == ManagesSwapChain::Unknown ||
-                mIsSwapChainManagedBySurface == ManagesSwapChain::No);
-    mIsSwapChainManagedBySurface = ManagesSwapChain::No;
-
     mSwapChain = swapChain;
 }
 
@@ -409,10 +279,6 @@
     return mInstance.Get();
 }
 
-DeviceBase* Surface::GetCurrentDevice() const {
-    return mCurrentDevice.Get();
-}
-
 Surface::Type Surface::GetType() const {
     DAWN_ASSERT(!IsError());
     return mType;
@@ -482,200 +348,13 @@
     return mXWindow;
 }
 
-MaybeError Surface::Configure(const SurfaceConfiguration* config) {
-    DAWN_INVALID_IF(IsError(), "%s is invalid.", this);
-    mCurrentDevice = config->device;  // next errors are routed to the new device
-    DAWN_INVALID_IF(mIsSwapChainManagedBySurface == ManagesSwapChain::No,
-                    "%s cannot be configured because it is used by legacy swapchain %s.", this,
-                    mSwapChain.Get());
-
-    mIsSwapChainManagedBySurface = ManagesSwapChain::Yes;
-
-    DAWN_TRY(mCapabilityCache->WithAdapterCapabilities(
-        GetCurrentDevice()->GetAdapter(), this,
-        [&](const PhysicalDeviceSurfaceCapabilities& caps) -> MaybeError {
-            return ValidateSurfaceConfiguration(GetCurrentDevice(), caps, config, this);
-        }));
-
-    Ref<SwapChainBase> previousSwapChain = mSwapChain;
-    if (previousSwapChain == nullptr && mRecycledSwapChain != nullptr &&
-        mRecycledSwapChain->GetDevice() == config->device) {
-        std::swap(previousSwapChain, mRecycledSwapChain);
-    }
-
-    // Don't keep swap chains older than 1 call to Unconfigure
-    if (mRecycledSwapChain != nullptr) {
-        mRecycledSwapChain->DetachFromSurface();
-        mRecycledSwapChain->APIRelease();
-        mRecycledSwapChain = nullptr;
-    }
-
-    DAWN_TRY_ASSIGN(mSwapChain,
-                    GetCurrentDevice()->CreateSwapChain(this, previousSwapChain.Get(), config));
-
-    // NB: There must be no DAWN_TRY beyond this point, to ensure that if the
-    // configuration failed, the previous swap chain remains valid.
-
-    if (previousSwapChain != nullptr) {
-        previousSwapChain->DetachFromSurface();
-        previousSwapChain->APIRelease();
-    }
-
-    mSwapChain->SetIsAttached();
-
-    return {};
-}
-
-MaybeError Surface::Unconfigure() {
-    DAWN_INVALID_IF(IsError(), "%s is invalid.", this);
-    DAWN_INVALID_IF(!mSwapChain.Get(), "%s is not configured.", this);
-
-    if (mSwapChain != nullptr) {
-        if (mIsSwapChainManagedBySurface == ManagesSwapChain::Yes) {
-            if (mRecycledSwapChain != nullptr) {
-                mRecycledSwapChain->DetachFromSurface();
-                mRecycledSwapChain->APIRelease();
-                mRecycledSwapChain = nullptr;
-            }
-            mRecycledSwapChain = mSwapChain;
-        } else {
-            mSwapChain->DetachFromSurface();
-        }
-        mSwapChain = nullptr;
-    }
-
-    return {};
-}
-
-MaybeError Surface::GetCapabilities(AdapterBase* adapter, SurfaceCapabilities* capabilities) const {
-    DAWN_INVALID_IF(IsError(), "%s is invalid.", this);
-
-    DAWN_TRY(mCapabilityCache->WithAdapterCapabilities(
-        adapter, this,
-        [&capabilities](const PhysicalDeviceSurfaceCapabilities& caps) -> MaybeError {
-            capabilities->nextInChain = nullptr;
-            DAWN_TRY(utils::AllocateApiSeqFromStdVector(capabilities->formats,
-                                                        capabilities->formatCount, caps.formats));
-            DAWN_TRY(utils::AllocateApiSeqFromStdVector(
-                capabilities->presentModes, capabilities->presentModeCount, caps.presentModes));
-            DAWN_TRY(utils::AllocateApiSeqFromStdVector(
-                capabilities->alphaModes, capabilities->alphaModeCount, caps.alphaModes));
-            return {};
-        }));
-
-    return {};
-}
-
-void APISurfaceCapabilitiesFreeMembers(WGPUSurfaceCapabilities capabilities) {
-    utils::FreeApiSeq(capabilities.formats, capabilities.formatCount);
-    utils::FreeApiSeq(capabilities.presentModes, capabilities.presentModeCount);
-    utils::FreeApiSeq(capabilities.alphaModes, capabilities.alphaModeCount);
-}
-
-MaybeError Surface::GetCurrentTexture(SurfaceTexture* surfaceTexture) const {
-    DAWN_INVALID_IF(IsError(), "%s is invalid.", this);
-    DAWN_INVALID_IF(!mSwapChain.Get(), "%s is not configured.", this);
-
-    DAWN_TRY_ASSIGN(*surfaceTexture, mSwapChain->GetCurrentTexture());
-
-    return {};
-}
-
-ResultOrError<wgpu::TextureFormat> Surface::GetPreferredFormat(AdapterBase* adapter) const {
-    wgpu::TextureFormat format = wgpu::TextureFormat::Undefined;
-
-    DAWN_TRY(mCapabilityCache->WithAdapterCapabilities(
-        adapter, this, [&](const PhysicalDeviceSurfaceCapabilities& caps) -> MaybeError {
-            DAWN_INVALID_IF(caps.formats.empty(), "No format is supported by %s for %s.", adapter,
-                            this);
-            format = caps.formats.front();
-            return {};
-        }));
-
-    return format;
-}
-
-MaybeError Surface::Present() {
-    DAWN_INVALID_IF(IsError(), "%s is invalid.", this);
-    DAWN_INVALID_IF(!mSwapChain.Get(), "%s is not configured.", this);
-    mSwapChain->APIPresent();
-    return {};
-}
-
-const std::string& Surface::GetLabel() const {
-    return mLabel;
-}
-
-void Surface::APIConfigure(const SurfaceConfiguration* config) {
-    MaybeError maybeError = Configure(config);
-    if (!GetCurrentDevice()) {
-        mInstance->ConsumedError(std::move(maybeError));
-    } else {
-        DAWN_UNUSED(GetCurrentDevice()->ConsumedError(std::move(maybeError),
-                                                      "calling %s.Configure().", this));
-    }
-}
-
-void Surface::APIGetCapabilities(AdapterBase* adapter, SurfaceCapabilities* capabilities) const {
-    MaybeError maybeError = GetCapabilities(adapter, capabilities);
-    if (!GetCurrentDevice()) {
-        mInstance->ConsumedError(std::move(maybeError));
-    } else {
-        DAWN_UNUSED(GetCurrentDevice()->ConsumedError(std::move(maybeError),
-                                                      "calling %s.Configure().", this));
-    }
-}
-
-void Surface::APIGetCurrentTexture(SurfaceTexture* surfaceTexture) const {
-    MaybeError maybeError = GetCurrentTexture(surfaceTexture);
-    if (!GetCurrentDevice()) {
-        if (mInstance->ConsumedError(std::move(maybeError))) {
-            // TODO(dawn:2320) This is the closest status to "surface was not configured so there is
-            // no associated device" but SurfaceTexture may change soon upstream.
-            surfaceTexture->status = wgpu::SurfaceGetCurrentTextureStatus::DeviceLost;
-            surfaceTexture->suboptimal = true;
-            surfaceTexture->texture = nullptr;
-        }
-    } else {
-        DAWN_UNUSED(GetCurrentDevice()->ConsumedError(std::move(maybeError)));
-    }
-}
-
 wgpu::TextureFormat Surface::APIGetPreferredFormat(AdapterBase* adapter) const {
-    ResultOrError<wgpu::TextureFormat> resultOrError = GetPreferredFormat(adapter);
-    wgpu::TextureFormat format;
-    if (!GetCurrentDevice()) {
-        if (mInstance->ConsumedError(std::move(resultOrError), &format)) {
-            return wgpu::TextureFormat::Undefined;
-        }
-    } else if (GetCurrentDevice()->ConsumedError(std::move(resultOrError), &format,
-                                                 "calling %s.GetPreferredFormat(%s).", this,
-                                                 adapter)) {
-        return wgpu::TextureFormat::Undefined;
-    }
-    return format;
-}
-
-void Surface::APIPresent() {
-    MaybeError maybeError = Present();
-    if (!GetCurrentDevice()) {
-        mInstance->ConsumedError(std::move(maybeError));
-    } else {
-        DAWN_UNUSED(GetCurrentDevice()->ConsumedError(std::move(maybeError)));
-    }
-}
-
-void Surface::APIUnconfigure() {
-    MaybeError maybeError = Unconfigure();
-    if (!GetCurrentDevice()) {
-        mInstance->ConsumedError(std::move(maybeError));
-    } else {
-        DAWN_UNUSED(GetCurrentDevice()->ConsumedError(std::move(maybeError)));
-    }
-}
-
-void Surface::APISetLabel(const char* label) {
-    mLabel = label;
+    // This is the only supported format in native mode (see crbug.com/dawn/160).
+#if DAWN_PLATFORM_IS(ANDROID)
+    return wgpu::TextureFormat::RGBA8Unorm;
+#else
+    return wgpu::TextureFormat::BGRA8Unorm;
+#endif  // !DAWN_PLATFORM_IS(ANDROID)
 }
 
 }  // namespace dawn::native
diff --git a/src/dawn/native/Surface.h b/src/dawn/native/Surface.h
index 662098a..71abec4 100644
--- a/src/dawn/native/Surface.h
+++ b/src/dawn/native/Surface.h
@@ -28,9 +28,6 @@
 #ifndef SRC_DAWN_NATIVE_SURFACE_H_
 #define SRC_DAWN_NATIVE_SURFACE_H_
 
-#include <memory>
-#include <string>
-
 #include "dawn/native/Error.h"
 #include "dawn/native/Forward.h"
 #include "dawn/native/ObjectBase.h"
@@ -51,20 +48,10 @@
 
 namespace dawn::native {
 
-struct PhysicalDeviceSurfaceCapabilities;
-
-// Adapter surface capabilities are cached by the surface
-class AdapterSurfaceCapCache;
-
 ResultOrError<UnpackedPtr<SurfaceDescriptor>> ValidateSurfaceDescriptor(
     InstanceBase* instance,
     const SurfaceDescriptor* rawDescriptor);
 
-MaybeError ValidateSurfaceConfiguration(DeviceBase* device,
-                                        const PhysicalDeviceSurfaceCapabilities& capabilities,
-                                        const SurfaceConfiguration* config,
-                                        const Surface* surface);
-
 // A surface is a sum types of all the kind of windows Dawn supports. The OS-specific types
 // aren't used because they would cause compilation errors on other OSes (or require
 // ObjectiveC).
@@ -76,6 +63,9 @@
 
     Surface(InstanceBase* instance, const UnpackedPtr<SurfaceDescriptor>& descriptor);
 
+    void SetAttachedSwapChain(SwapChainBase* swapChain);
+    SwapChainBase* GetAttachedSwapChain();
+
     // These are valid to call on all Surfaces.
     enum class Type {
         AndroidWindow,
@@ -88,7 +78,6 @@
     };
     Type GetType() const;
     InstanceBase* GetInstance() const;
-    DeviceBase* GetCurrentDevice() const;
 
     // Valid to call if the type is MetalLayer
     void* GetMetalLayer() const;
@@ -114,61 +103,19 @@
     void* GetXDisplay() const;
     uint32_t GetXWindow() const;
 
-    // TODO(dawn:2320) Remove these 2 accessors once the deprecation period is finished and
-    // Device::APICreateSwapChain gets dropped
-    SwapChainBase* GetAttachedSwapChain();
-    void SetAttachedSwapChain(SwapChainBase* swapChain);
-
-    const std::string& GetLabel() const;
-
     // Dawn API
-    void APIConfigure(const SurfaceConfiguration* config);
-    void APIGetCapabilities(AdapterBase* adapter, SurfaceCapabilities* capabilities) const;
-    void APIGetCurrentTexture(SurfaceTexture* surfaceTexture) const;
     wgpu::TextureFormat APIGetPreferredFormat(AdapterBase* adapter) const;
-    void APIPresent();
-    void APIUnconfigure();
-    void APISetLabel(const char* label);
 
   private:
     Surface(InstanceBase* instance, ErrorMonad::ErrorTag tag);
     ~Surface() override;
 
-    MaybeError Configure(const SurfaceConfiguration* config);
-    MaybeError Unconfigure();
-
-    MaybeError GetCapabilities(AdapterBase* adapter, SurfaceCapabilities* capabilities) const;
-    MaybeError GetCurrentTexture(SurfaceTexture* surfaceTexture) const;
-    ResultOrError<wgpu::TextureFormat> GetPreferredFormat(AdapterBase* adapter) const;
-    MaybeError Present();
-
     Ref<InstanceBase> mInstance;
     Type mType;
-    std::string mLabel;
 
-    // The surface has an associated device only when it is configured
-    Ref<DeviceBase> mCurrentDevice;
-
-    // The swapchain is created when configuring the surface.
+    // The swapchain will set this to null when it is destroyed.
     Ref<SwapChainBase> mSwapChain;
 
-    // We keep on storing the previous swap chain after Unconfigure in case we could reuse it
-    Ref<SwapChainBase> mRecycledSwapChain;
-
-    // This ensures that the user does not mix the legacy API (ManagesSwapChain::No, i.e., explicit
-    // call to CreateSwapChain) with the new API (ManagesSwapChain::Yes, i.e., surface.configure).
-    // TODO(dawn:2320) Remove and consider it is always Yes once Device::APICreateSwapChain gets
-    // dropped
-    enum class ManagesSwapChain {
-        Yes,
-        No,
-        Unknown,
-    };
-    ManagesSwapChain mIsSwapChainManagedBySurface = ManagesSwapChain::Unknown;
-
-    // A cache is mutable because potentially modified in const-qualified getters
-    std::unique_ptr<AdapterSurfaceCapCache> mCapabilityCache;
-
     // MetalLayer
     raw_ptr<void> mMetalLayer = nullptr;
 
diff --git a/src/dawn/native/SwapChain.cpp b/src/dawn/native/SwapChain.cpp
index 8f76306..3c00d47 100644
--- a/src/dawn/native/SwapChain.cpp
+++ b/src/dawn/native/SwapChain.cpp
@@ -28,7 +28,6 @@
 #include "dawn/native/SwapChain.h"
 
 #include <utility>
-#include <vector>
 
 #include "dawn/common/Constants.h"
 #include "dawn/native/Device.h"
@@ -44,11 +43,11 @@
 
 class ErrorSwapChain final : public SwapChainBase {
   public:
-    explicit ErrorSwapChain(DeviceBase* device, const SurfaceConfiguration* config)
-        : SwapChainBase(device, config, ObjectBase::kError) {}
+    explicit ErrorSwapChain(DeviceBase* device, const SwapChainDescriptor* desc)
+        : SwapChainBase(device, desc, ObjectBase::kError) {}
 
   private:
-    ResultOrError<SwapChainTextureInfo> GetCurrentTextureImpl() override { DAWN_UNREACHABLE(); }
+    ResultOrError<Ref<TextureBase>> GetCurrentTextureImpl() override { DAWN_UNREACHABLE(); }
     MaybeError PresentImpl() override { DAWN_UNREACHABLE(); }
     void DetachFromSurfaceImpl() override { DAWN_UNREACHABLE(); }
 };
@@ -110,8 +109,6 @@
     desc.dimension = wgpu::TextureDimension::e2D;
     desc.size = {swapChain->GetWidth(), swapChain->GetHeight(), 1};
     desc.format = swapChain->GetFormat();
-    desc.viewFormatCount = swapChain->GetViewFormats().size();
-    desc.viewFormats = swapChain->GetViewFormats().data();
     desc.mipLevelCount = 1;
     desc.sampleCount = 1;
 
@@ -120,56 +117,38 @@
 
 SwapChainBase::SwapChainBase(DeviceBase* device,
                              Surface* surface,
-                             const SurfaceConfiguration* config)
+                             const SwapChainDescriptor* descriptor)
     : ApiObjectBase(device, kLabelNotImplemented),
-      mWidth(config->width),
-      mHeight(config->height),
-      mFormat(config->format),
-      mUsage(config->usage),
-      mPresentMode(config->presentMode),
-      mAlphaMode(config->alphaMode),
+      mWidth(descriptor->width),
+      mHeight(descriptor->height),
+      mFormat(descriptor->format),
+      mUsage(descriptor->usage),
+      mPresentMode(descriptor->presentMode),
       mSurface(surface) {
     GetObjectTrackingList()->Track(this);
-    for (uint32_t i = 0; i < config->viewFormatCount; ++i) {
-        if (config->viewFormats[i] == config->format) {
-            // Skip our own format, like texture creations does.
-            continue;
-        }
-        mViewFormats.push_back(config->viewFormats[i]);
-    }
-}
-
-FormatSet SwapChainBase::ComputeViewFormatSet() const {
-    FormatSet viewFormatSet;
-    for (wgpu::TextureFormat format : mViewFormats) {
-        viewFormatSet[GetDevice()->GetValidInternalFormat(format)] = true;
-    }
-    return viewFormatSet;
 }
 
 SwapChainBase::~SwapChainBase() {
-    if (mCurrentTextureInfo.texture != nullptr) {
-        DAWN_ASSERT(mCurrentTextureInfo.texture->IsDestroyed());
+    if (mCurrentTexture != nullptr) {
+        DAWN_ASSERT(mCurrentTexture->IsDestroyed());
     }
 
     DAWN_ASSERT(!mAttached);
 }
 
 SwapChainBase::SwapChainBase(DeviceBase* device,
-                             const SurfaceConfiguration* config,
+                             const SwapChainDescriptor* descriptor,
                              ObjectBase::ErrorTag tag)
     : ApiObjectBase(device, tag),
-      mWidth(config->width),
-      mHeight(config->height),
-      mFormat(config->format),
-      mUsage(config->usage),
-      mPresentMode(config->presentMode),
-      mAlphaMode(config->alphaMode) {}
+      mWidth(descriptor->width),
+      mHeight(descriptor->height),
+      mFormat(descriptor->format),
+      mUsage(descriptor->usage),
+      mPresentMode(descriptor->presentMode) {}
 
 // static
-Ref<SwapChainBase> SwapChainBase::MakeError(DeviceBase* device,
-                                            const SurfaceConfiguration* config) {
-    return AcquireRef(new ErrorSwapChain(device, config));
+Ref<SwapChainBase> SwapChainBase::MakeError(DeviceBase* device, const SwapChainDescriptor* desc) {
+    return AcquireRef(new ErrorSwapChain(device, desc));
 }
 
 void SwapChainBase::DestroyImpl() {}
@@ -199,15 +178,14 @@
 }
 
 TextureBase* SwapChainBase::APIGetCurrentTexture() {
-    SurfaceTexture result;
+    Ref<TextureBase> result;
     if (GetDevice()->ConsumedError(GetCurrentTexture(), &result, "calling %s.GetCurrentTexture()",
                                    this)) {
         TextureDescriptor desc = GetSwapChainBaseTextureDescriptor(this);
-        Ref<TextureBase> errorTexture = TextureBase::MakeError(GetDevice(), &desc);
-        SetChildLabel(errorTexture.Get());
-        result.texture = ReturnToAPI(std::move(errorTexture));
+        result = TextureBase::MakeError(GetDevice(), &desc);
+        SetChildLabel(result.Get());
     }
-    return result.texture;
+    return ReturnToAPI(std::move(result));
 }
 
 TextureViewBase* SwapChainBase::APIGetCurrentTextureView() {
@@ -220,36 +198,33 @@
     return ReturnToAPI(std::move(result));
 }
 
-ResultOrError<SurfaceTexture> SwapChainBase::GetCurrentTexture() {
+ResultOrError<Ref<TextureBase>> SwapChainBase::GetCurrentTexture() {
     DAWN_TRY(ValidateGetCurrentTexture());
-    SurfaceTexture surfaceTexture;
 
-    if (mCurrentTextureInfo.texture == nullptr) {
-        DAWN_TRY_ASSIGN(mCurrentTextureInfo, GetCurrentTextureImpl());
-        SetChildLabel(mCurrentTextureInfo.texture.Get());
-
-        // Check that the return texture matches exactly what was given for this descriptor.
-        DAWN_ASSERT(mCurrentTextureInfo.texture->GetFormat().format == mFormat);
-        DAWN_ASSERT(IsSubset(mUsage, mCurrentTextureInfo.texture->GetUsage()));
-        DAWN_ASSERT(mCurrentTextureInfo.texture->GetDimension() == wgpu::TextureDimension::e2D);
-        DAWN_ASSERT(mCurrentTextureInfo.texture->GetWidth(Aspect::Color) == mWidth);
-        DAWN_ASSERT(mCurrentTextureInfo.texture->GetHeight(Aspect::Color) == mHeight);
-        DAWN_ASSERT(mCurrentTextureInfo.texture->GetNumMipLevels() == 1);
-        DAWN_ASSERT(mCurrentTextureInfo.texture->GetArrayLayers() == 1);
-        DAWN_ASSERT(mCurrentTextureInfo.texture->GetViewFormats() == ComputeViewFormatSet());
+    if (mCurrentTexture != nullptr) {
+        // Calling GetCurrentTexture always returns a new reference.
+        return mCurrentTexture;
     }
 
-    // Calling GetCurrentTexture always returns a new reference.
-    surfaceTexture.texture = Ref<TextureBase>(mCurrentTextureInfo.texture).Detach();
-    surfaceTexture.suboptimal = mCurrentTextureInfo.suboptimal;
-    surfaceTexture.status = mCurrentTextureInfo.status;
-    return surfaceTexture;
+    DAWN_TRY_ASSIGN(mCurrentTexture, GetCurrentTextureImpl());
+    SetChildLabel(mCurrentTexture.Get());
+
+    // Check that the return texture matches exactly what was given for this descriptor.
+    DAWN_ASSERT(mCurrentTexture->GetFormat().format == mFormat);
+    DAWN_ASSERT(IsSubset(mUsage, mCurrentTexture->GetUsage()));
+    DAWN_ASSERT(mCurrentTexture->GetDimension() == wgpu::TextureDimension::e2D);
+    DAWN_ASSERT(mCurrentTexture->GetWidth(Aspect::Color) == mWidth);
+    DAWN_ASSERT(mCurrentTexture->GetHeight(Aspect::Color) == mHeight);
+    DAWN_ASSERT(mCurrentTexture->GetNumMipLevels() == 1);
+    DAWN_ASSERT(mCurrentTexture->GetArrayLayers() == 1);
+
+    return mCurrentTexture;
 }
 
 ResultOrError<Ref<TextureViewBase>> SwapChainBase::GetCurrentTextureView() {
-    SurfaceTexture surfaceTexture;
-    DAWN_TRY_ASSIGN(surfaceTexture, GetCurrentTexture());
-    return surfaceTexture.texture->CreateView();
+    Ref<TextureBase> currentTexture;
+    DAWN_TRY_ASSIGN(currentTexture, GetCurrentTexture());
+    return currentTexture->CreateView();
 }
 
 void SwapChainBase::APIPresent() {
@@ -261,8 +236,8 @@
         return;
     }
 
-    DAWN_ASSERT(mCurrentTextureInfo.texture->IsDestroyed());
-    mCurrentTextureInfo.texture = nullptr;
+    DAWN_ASSERT(mCurrentTexture->IsDestroyed());
+    mCurrentTexture = nullptr;
 }
 
 uint32_t SwapChainBase::GetWidth() const {
@@ -277,10 +252,6 @@
     return mFormat;
 }
 
-const std::vector<wgpu::TextureFormat>& SwapChainBase::GetViewFormats() const {
-    return mViewFormats;
-}
-
 wgpu::TextureUsage SwapChainBase::GetUsage() const {
     return mUsage;
 }
@@ -289,10 +260,6 @@
     return mPresentMode;
 }
 
-wgpu::CompositeAlphaMode SwapChainBase::GetAlphaMode() const {
-    return mAlphaMode;
-}
-
 Surface* SwapChainBase::GetSurface() const {
     return mSurface;
 }
@@ -311,7 +278,7 @@
 
     DAWN_INVALID_IF(!mAttached, "Cannot call Present called on detached %s.", this);
 
-    DAWN_INVALID_IF(mCurrentTextureInfo.texture == nullptr,
+    DAWN_INVALID_IF(mCurrentTexture == nullptr,
                     "GetCurrentTexture was not called on %s this frame prior to calling Present.",
                     this);
 
diff --git a/src/dawn/native/SwapChain.h b/src/dawn/native/SwapChain.h
index 09d1a52..20f9ae3 100644
--- a/src/dawn/native/SwapChain.h
+++ b/src/dawn/native/SwapChain.h
@@ -28,10 +28,7 @@
 #ifndef SRC_DAWN_NATIVE_SWAPCHAIN_H_
 #define SRC_DAWN_NATIVE_SWAPCHAIN_H_
 
-#include <vector>
-
 #include "dawn/native/Error.h"
-#include "dawn/native/Format.h"
 #include "dawn/native/Forward.h"
 #include "dawn/native/ObjectBase.h"
 #include "dawn/native/dawn_platform.h"
@@ -39,25 +36,17 @@
 
 namespace dawn::native {
 
-// TODO(dawn:2320) Remove the SwapChainDescriptor once the deprecation period is finished and
-// APICreateSwapChain gets dropped
 MaybeError ValidateSwapChainDescriptor(const DeviceBase* device,
                                        const Surface* surface,
                                        const SwapChainDescriptor* descriptor);
 
 TextureDescriptor GetSwapChainBaseTextureDescriptor(SwapChainBase* swapChain);
 
-struct SwapChainTextureInfo {
-    Ref<TextureBase> texture;
-    wgpu::Bool suboptimal;
-    wgpu::SurfaceGetCurrentTextureStatus status;
-};
-
 class SwapChainBase : public ApiObjectBase {
   public:
-    SwapChainBase(DeviceBase* device, Surface* surface, const SurfaceConfiguration* config);
+    SwapChainBase(DeviceBase* device, Surface* surface, const SwapChainDescriptor* descriptor);
 
-    static Ref<SwapChainBase> MakeError(DeviceBase* device, const SurfaceConfiguration* config);
+    static Ref<SwapChainBase> MakeError(DeviceBase* device, const SwapChainDescriptor* descriptor);
     ObjectType GetType() const override;
 
     // This is called when the swapchain is detached when one of the following happens:
@@ -99,27 +88,19 @@
     uint32_t GetWidth() const;
     uint32_t GetHeight() const;
     wgpu::TextureFormat GetFormat() const;
-    const std::vector<wgpu::TextureFormat>& GetViewFormats() const;
     wgpu::TextureUsage GetUsage() const;
     wgpu::PresentMode GetPresentMode() const;
-    wgpu::CompositeAlphaMode GetAlphaMode() const;
     Surface* GetSurface() const;
     bool IsAttached() const;
     wgpu::BackendType GetBackendType() const;
 
-    // The returned texture must match the swapchain descriptor exactly.
-    ResultOrError<SurfaceTexture> GetCurrentTexture();
-
   protected:
-    SwapChainBase(DeviceBase* device, const SurfaceConfiguration* config, ObjectBase::ErrorTag tag);
+    SwapChainBase(DeviceBase* device, const SwapChainDescriptor* desc, ObjectBase::ErrorTag tag);
     ~SwapChainBase() override;
     void DestroyImpl() override;
 
   private:
     void SetChildLabel(ApiObjectBase* child) const;
-    // Get a format set from mViewFormats (equivalent information, but easier to validate the
-    // current texture)
-    FormatSet ComputeViewFormatSet() const;
 
     bool mAttached = false;
     uint32_t mWidth;
@@ -127,15 +108,11 @@
     wgpu::TextureFormat mFormat;
     wgpu::TextureUsage mUsage;
     wgpu::PresentMode mPresentMode;
-    // This is not stored as a FormatSet so that it can hold the data pointed to by the
-    // descriptor returned by GetSwapChainBaseTextureDescriptor():
-    std::vector<wgpu::TextureFormat> mViewFormats;
-    wgpu::CompositeAlphaMode mAlphaMode;
 
     // This is a weak reference to the surface. If the surface is destroyed it will call
     // DetachFromSurface and mSurface will be updated to nullptr.
     raw_ptr<Surface> mSurface = nullptr;
-    SwapChainTextureInfo mCurrentTextureInfo;
+    Ref<TextureBase> mCurrentTexture;
 
     MaybeError ValidatePresent() const;
     MaybeError ValidateGetCurrentTexture() const;
@@ -143,7 +120,9 @@
     // GetCurrentTextureImpl and PresentImpl are guaranteed to be called in an interleaved manner,
     // starting with GetCurrentTextureImpl.
 
-    virtual ResultOrError<SwapChainTextureInfo> GetCurrentTextureImpl() = 0;
+    // The returned texture must match the swapchain descriptor exactly.
+    ResultOrError<Ref<TextureBase>> GetCurrentTexture();
+    virtual ResultOrError<Ref<TextureBase>> GetCurrentTextureImpl() = 0;
 
     ResultOrError<Ref<TextureViewBase>> GetCurrentTextureView();
 
diff --git a/src/dawn/native/d3d/PhysicalDeviceD3D.cpp b/src/dawn/native/d3d/PhysicalDeviceD3D.cpp
index c9e2753..926ef45 100644
--- a/src/dawn/native/d3d/PhysicalDeviceD3D.cpp
+++ b/src/dawn/native/d3d/PhysicalDeviceD3D.cpp
@@ -52,34 +52,6 @@
     return mBackend;
 }
 
-ResultOrError<PhysicalDeviceSurfaceCapabilities> PhysicalDevice::GetSurfaceCapabilities(
-    const Surface*) const {
-    PhysicalDeviceSurfaceCapabilities capabilities;
-
-    // Formats
-
-    // This is the only supported format in native mode (see crbug.com/dawn/160).
-    capabilities.formats.push_back(wgpu::TextureFormat::BGRA8Unorm);
-
-    // Present Modes
-
-    capabilities.presentModes = {
-        wgpu::PresentMode::Fifo,
-        wgpu::PresentMode::Immediate,
-        wgpu::PresentMode::Mailbox,
-    };
-
-    // Alpha Modes
-
-    capabilities.alphaModes = {
-        wgpu::CompositeAlphaMode::Opaque,
-        wgpu::CompositeAlphaMode::Premultiplied,
-        wgpu::CompositeAlphaMode::Auto,
-    };
-
-    return capabilities;
-}
-
 MaybeError PhysicalDevice::InitializeImpl() {
     DXGI_ADAPTER_DESC1 adapterDesc;
     GetHardwareAdapter()->GetDesc1(&adapterDesc);
diff --git a/src/dawn/native/d3d/PhysicalDeviceD3D.h b/src/dawn/native/d3d/PhysicalDeviceD3D.h
index 4d69d184..6f73b8d 100644
--- a/src/dawn/native/d3d/PhysicalDeviceD3D.h
+++ b/src/dawn/native/d3d/PhysicalDeviceD3D.h
@@ -47,9 +47,6 @@
     IDXGIAdapter3* GetHardwareAdapter() const;
     Backend* GetBackend() const;
 
-    ResultOrError<PhysicalDeviceSurfaceCapabilities> GetSurfaceCapabilities(
-        const Surface* surface) const override;
-
   protected:
     MaybeError InitializeImpl() override;
 
diff --git a/src/dawn/native/d3d11/DeviceD3D11.cpp b/src/dawn/native/d3d11/DeviceD3D11.cpp
index bdf281d..e42ad64 100644
--- a/src/dawn/native/d3d11/DeviceD3D11.cpp
+++ b/src/dawn/native/d3d11/DeviceD3D11.cpp
@@ -212,10 +212,11 @@
     return ShaderModule::Create(this, descriptor, parseResult, compilationMessages);
 }
 
-ResultOrError<Ref<SwapChainBase>> Device::CreateSwapChainImpl(Surface* surface,
-                                                              SwapChainBase* previousSwapChain,
-                                                              const SurfaceConfiguration* config) {
-    return SwapChain::Create(this, surface, previousSwapChain, config);
+ResultOrError<Ref<SwapChainBase>> Device::CreateSwapChainImpl(
+    Surface* surface,
+    SwapChainBase* previousSwapChain,
+    const SwapChainDescriptor* descriptor) {
+    return SwapChain::Create(this, surface, previousSwapChain, descriptor);
 }
 
 ResultOrError<Ref<TextureBase>> Device::CreateTextureImpl(
diff --git a/src/dawn/native/d3d11/DeviceD3D11.h b/src/dawn/native/d3d11/DeviceD3D11.h
index 5cb7871..7d34cb1 100644
--- a/src/dawn/native/d3d11/DeviceD3D11.h
+++ b/src/dawn/native/d3d11/DeviceD3D11.h
@@ -127,7 +127,7 @@
     ResultOrError<Ref<SwapChainBase>> CreateSwapChainImpl(
         Surface* surface,
         SwapChainBase* previousSwapChain,
-        const SurfaceConfiguration* config) override;
+        const SwapChainDescriptor* descriptor) override;
     ResultOrError<Ref<TextureBase>> CreateTextureImpl(
         const UnpackedPtr<TextureDescriptor>& descriptor) override;
     ResultOrError<Ref<TextureViewBase>> CreateTextureViewImpl(
diff --git a/src/dawn/native/d3d11/SwapChainD3D11.cpp b/src/dawn/native/d3d11/SwapChainD3D11.cpp
index 8a83ac8..8100240 100644
--- a/src/dawn/native/d3d11/SwapChainD3D11.cpp
+++ b/src/dawn/native/d3d11/SwapChainD3D11.cpp
@@ -45,8 +45,8 @@
 ResultOrError<Ref<SwapChain>> SwapChain::Create(Device* device,
                                                 Surface* surface,
                                                 SwapChainBase* previousSwapChain,
-                                                const SurfaceConfiguration* config) {
-    Ref<SwapChain> swapchain = AcquireRef(new SwapChain(device, surface, config));
+                                                const SwapChainDescriptor* descriptor) {
+    Ref<SwapChain> swapchain = AcquireRef(new SwapChain(device, surface, descriptor));
     DAWN_TRY(swapchain->Initialize(previousSwapChain));
     return swapchain;
 }
@@ -84,17 +84,12 @@
     return {};
 }
 
-ResultOrError<SwapChainTextureInfo> SwapChain::GetCurrentTextureImpl() {
+ResultOrError<Ref<TextureBase>> SwapChain::GetCurrentTextureImpl() {
     // Create the API side objects for this use of the swapchain's buffer.
     TextureDescriptor descriptor = GetSwapChainBaseTextureDescriptor(this);
     DAWN_TRY_ASSIGN(mApiTexture,
                     Texture::Create(ToBackend(GetDevice()), Unpack(&descriptor), mBuffer));
-    SwapChainTextureInfo info;
-    info.texture = mApiTexture;
-    info.status = wgpu::SurfaceGetCurrentTextureStatus::Success;
-    // TODO(dawn:2320) Check for optimality
-    info.suboptimal = false;
-    return info;
+    return mApiTexture;
 }
 
 MaybeError SwapChain::DetachAndWaitForDeallocation() {
diff --git a/src/dawn/native/d3d11/SwapChainD3D11.h b/src/dawn/native/d3d11/SwapChainD3D11.h
index 501183d..58a7d4c 100644
--- a/src/dawn/native/d3d11/SwapChainD3D11.h
+++ b/src/dawn/native/d3d11/SwapChainD3D11.h
@@ -44,7 +44,7 @@
     static ResultOrError<Ref<SwapChain>> Create(Device* device,
                                                 Surface* surface,
                                                 SwapChainBase* previousSwapChain,
-                                                const SurfaceConfiguration* config);
+                                                const SwapChainDescriptor* descriptor);
 
   private:
     using Base = d3d::SwapChain;
@@ -53,7 +53,7 @@
 
     // SwapChainBase implementation
     MaybeError PresentImpl() override;
-    ResultOrError<SwapChainTextureInfo> GetCurrentTextureImpl() override;
+    ResultOrError<Ref<TextureBase>> GetCurrentTextureImpl() override;
     void DetachFromSurfaceImpl() override;
 
     // d3d::SwapChain implementation
diff --git a/src/dawn/native/d3d12/DeviceD3D12.cpp b/src/dawn/native/d3d12/DeviceD3D12.cpp
index 7a36600..23adbf8 100644
--- a/src/dawn/native/d3d12/DeviceD3D12.cpp
+++ b/src/dawn/native/d3d12/DeviceD3D12.cpp
@@ -381,10 +381,11 @@
     OwnedCompilationMessages* compilationMessages) {
     return ShaderModule::Create(this, descriptor, parseResult, compilationMessages);
 }
-ResultOrError<Ref<SwapChainBase>> Device::CreateSwapChainImpl(Surface* surface,
-                                                              SwapChainBase* previousSwapChain,
-                                                              const SurfaceConfiguration* config) {
-    return SwapChain::Create(this, surface, previousSwapChain, config);
+ResultOrError<Ref<SwapChainBase>> Device::CreateSwapChainImpl(
+    Surface* surface,
+    SwapChainBase* previousSwapChain,
+    const SwapChainDescriptor* descriptor) {
+    return SwapChain::Create(this, surface, previousSwapChain, descriptor);
 }
 ResultOrError<Ref<TextureBase>> Device::CreateTextureImpl(
     const UnpackedPtr<TextureDescriptor>& descriptor) {
diff --git a/src/dawn/native/d3d12/DeviceD3D12.h b/src/dawn/native/d3d12/DeviceD3D12.h
index f29b550..c908ab9 100644
--- a/src/dawn/native/d3d12/DeviceD3D12.h
+++ b/src/dawn/native/d3d12/DeviceD3D12.h
@@ -205,7 +205,7 @@
     ResultOrError<Ref<SwapChainBase>> CreateSwapChainImpl(
         Surface* surface,
         SwapChainBase* previousSwapChain,
-        const SurfaceConfiguration* config) override;
+        const SwapChainDescriptor* descriptor) override;
     ResultOrError<Ref<TextureBase>> CreateTextureImpl(
         const UnpackedPtr<TextureDescriptor>& descriptor) override;
     ResultOrError<Ref<TextureViewBase>> CreateTextureViewImpl(
diff --git a/src/dawn/native/d3d12/SwapChainD3D12.cpp b/src/dawn/native/d3d12/SwapChainD3D12.cpp
index 2f5da77..0892149 100644
--- a/src/dawn/native/d3d12/SwapChainD3D12.cpp
+++ b/src/dawn/native/d3d12/SwapChainD3D12.cpp
@@ -46,8 +46,8 @@
 ResultOrError<Ref<SwapChain>> SwapChain::Create(Device* device,
                                                 Surface* surface,
                                                 SwapChainBase* previousSwapChain,
-                                                const SurfaceConfiguration* config) {
-    Ref<SwapChain> swapchain = AcquireRef(new SwapChain(device, surface, config));
+                                                const SwapChainDescriptor* descriptor) {
+    Ref<SwapChain> swapchain = AcquireRef(new SwapChain(device, surface, descriptor));
     DAWN_TRY(swapchain->Initialize(previousSwapChain));
     return swapchain;
 }
@@ -105,7 +105,7 @@
     return {};
 }
 
-ResultOrError<SwapChainTextureInfo> SwapChain::GetCurrentTextureImpl() {
+ResultOrError<Ref<TextureBase>> SwapChain::GetCurrentTextureImpl() {
     Queue* queue = ToBackend(GetDevice()->GetQueue());
 
     // Synchronously wait until previous operations on the next swapchain buffer are finished.
@@ -119,13 +119,7 @@
     TextureDescriptor descriptor = GetSwapChainBaseTextureDescriptor(this);
     DAWN_TRY_ASSIGN(mApiTexture, Texture::Create(ToBackend(GetDevice()), Unpack(&descriptor),
                                                  mBuffers[mCurrentBuffer]));
-
-    SwapChainTextureInfo info;
-    info.texture = mApiTexture;
-    info.status = wgpu::SurfaceGetCurrentTextureStatus::Success;
-    // TODO(dawn:2320) Check for optimality
-    info.suboptimal = false;
-    return info;
+    return mApiTexture;
 }
 
 MaybeError SwapChain::DetachAndWaitForDeallocation() {
diff --git a/src/dawn/native/d3d12/SwapChainD3D12.h b/src/dawn/native/d3d12/SwapChainD3D12.h
index b3ecedf..eb0569b 100644
--- a/src/dawn/native/d3d12/SwapChainD3D12.h
+++ b/src/dawn/native/d3d12/SwapChainD3D12.h
@@ -45,7 +45,7 @@
     static ResultOrError<Ref<SwapChain>> Create(Device* device,
                                                 Surface* surface,
                                                 SwapChainBase* previousSwapChain,
-                                                const SurfaceConfiguration* config);
+                                                const SwapChainDescriptor* descriptor);
 
   private:
     using Base = d3d::SwapChain;
@@ -54,7 +54,7 @@
 
     // SwapChainBase implementation
     MaybeError PresentImpl() override;
-    ResultOrError<SwapChainTextureInfo> GetCurrentTextureImpl() override;
+    ResultOrError<Ref<TextureBase>> GetCurrentTextureImpl() override;
     void DetachFromSurfaceImpl() override;
 
     // d3d::SwapChain implementation
diff --git a/src/dawn/native/metal/BackendMTL.mm b/src/dawn/native/metal/BackendMTL.mm
index 50e7693..c4c8314 100644
--- a/src/dawn/native/metal/BackendMTL.mm
+++ b/src/dawn/native/metal/BackendMTL.mm
@@ -304,34 +304,6 @@
 
     bool SupportsFeatureLevel(FeatureLevel) const override { return true; }
 
-    ResultOrError<PhysicalDeviceSurfaceCapabilities> GetSurfaceCapabilities(
-        const Surface*) const override {
-        PhysicalDeviceSurfaceCapabilities capabilities;
-
-        // Formats
-
-        // This is the only supported format in native mode (see crbug.com/dawn/160).
-        capabilities.formats.push_back(wgpu::TextureFormat::BGRA8Unorm);
-
-        // Present Modes
-
-        capabilities.presentModes = {
-            wgpu::PresentMode::Fifo,
-            wgpu::PresentMode::Immediate,
-            wgpu::PresentMode::Mailbox,
-        };
-
-        // Alpha Modes
-
-        capabilities.alphaModes = {
-            wgpu::CompositeAlphaMode::Opaque,
-            wgpu::CompositeAlphaMode::Premultiplied,
-            wgpu::CompositeAlphaMode::Auto,
-        };
-
-        return capabilities;
-    }
-
   private:
     ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(AdapterBase* adapter,
                                                     const UnpackedPtr<DeviceDescriptor>& descriptor,
diff --git a/src/dawn/native/metal/DeviceMTL.h b/src/dawn/native/metal/DeviceMTL.h
index c273e0b..fa40bbb 100644
--- a/src/dawn/native/metal/DeviceMTL.h
+++ b/src/dawn/native/metal/DeviceMTL.h
@@ -113,7 +113,7 @@
     ResultOrError<Ref<SwapChainBase>> CreateSwapChainImpl(
         Surface* surface,
         SwapChainBase* previousSwapChain,
-        const SurfaceConfiguration* config) override;
+        const SwapChainDescriptor* descriptor) override;
     ResultOrError<Ref<TextureBase>> CreateTextureImpl(
         const UnpackedPtr<TextureDescriptor>& descriptor) override;
     ResultOrError<Ref<TextureViewBase>> CreateTextureViewImpl(
diff --git a/src/dawn/native/metal/DeviceMTL.mm b/src/dawn/native/metal/DeviceMTL.mm
index 6158b98..2ac4c5f 100644
--- a/src/dawn/native/metal/DeviceMTL.mm
+++ b/src/dawn/native/metal/DeviceMTL.mm
@@ -224,10 +224,11 @@
     OwnedCompilationMessages* compilationMessages) {
     return ShaderModule::Create(this, descriptor, parseResult, compilationMessages);
 }
-ResultOrError<Ref<SwapChainBase>> Device::CreateSwapChainImpl(Surface* surface,
-                                                              SwapChainBase* previousSwapChain,
-                                                              const SurfaceConfiguration* config) {
-    return SwapChain::Create(this, surface, previousSwapChain, config);
+ResultOrError<Ref<SwapChainBase>> Device::CreateSwapChainImpl(
+    Surface* surface,
+    SwapChainBase* previousSwapChain,
+    const SwapChainDescriptor* descriptor) {
+    return SwapChain::Create(this, surface, previousSwapChain, descriptor);
 }
 ResultOrError<Ref<TextureBase>> Device::CreateTextureImpl(
     const UnpackedPtr<TextureDescriptor>& descriptor) {
diff --git a/src/dawn/native/metal/SwapChainMTL.h b/src/dawn/native/metal/SwapChainMTL.h
index 7786310..3bf596c 100644
--- a/src/dawn/native/metal/SwapChainMTL.h
+++ b/src/dawn/native/metal/SwapChainMTL.h
@@ -45,9 +45,9 @@
     static ResultOrError<Ref<SwapChain>> Create(Device* device,
                                                 Surface* surface,
                                                 SwapChainBase* previousSwapChain,
-                                                const SurfaceConfiguration* config);
+                                                const SwapChainDescriptor* descriptor);
 
-    SwapChain(DeviceBase* device, Surface* surface, const SurfaceConfiguration* config);
+    SwapChain(DeviceBase* device, Surface* surface, const SwapChainDescriptor* descriptor);
     ~SwapChain() override;
 
   private:
@@ -62,7 +62,7 @@
     Ref<Texture> mTexture;
 
     MaybeError PresentImpl() override;
-    ResultOrError<SwapChainTextureInfo> GetCurrentTextureImpl() override;
+    ResultOrError<Ref<TextureBase>> GetCurrentTextureImpl() override;
     void DetachFromSurfaceImpl() override;
 };
 
diff --git a/src/dawn/native/metal/SwapChainMTL.mm b/src/dawn/native/metal/SwapChainMTL.mm
index ad9b9aa..981d415 100644
--- a/src/dawn/native/metal/SwapChainMTL.mm
+++ b/src/dawn/native/metal/SwapChainMTL.mm
@@ -40,14 +40,14 @@
 ResultOrError<Ref<SwapChain>> SwapChain::Create(Device* device,
                                                 Surface* surface,
                                                 SwapChainBase* previousSwapChain,
-                                                const SurfaceConfiguration* config) {
-    Ref<SwapChain> swapchain = AcquireRef(new SwapChain(device, surface, config));
+                                                const SwapChainDescriptor* descriptor) {
+    Ref<SwapChain> swapchain = AcquireRef(new SwapChain(device, surface, descriptor));
     DAWN_TRY(swapchain->Initialize(previousSwapChain));
     return swapchain;
 }
 
-SwapChain::SwapChain(DeviceBase* dev, Surface* sur, const SurfaceConfiguration* config)
-    : SwapChainBase(dev, sur, config) {}
+SwapChain::SwapChain(DeviceBase* dev, Surface* sur, const SwapChainDescriptor* desc)
+    : SwapChainBase(dev, sur, desc) {}
 
 SwapChain::~SwapChain() = default;
 
@@ -82,9 +82,6 @@
     [*mLayer setDevice:ToBackend(GetDevice())->GetMTLDevice()];
     [*mLayer setPixelFormat:MetalPixelFormat(GetDevice(), GetFormat())];
 
-    // TODO(dawn:2320) Check that this behaves as expected by the spec
-    [*mLayer setOpaque:(GetAlphaMode() != wgpu::CompositeAlphaMode::Premultiplied)];
-
 #if DAWN_PLATFORM_IS(MACOS)
     [*mLayer setDisplaySyncEnabled:(GetPresentMode() != wgpu::PresentMode::Immediate)];
 #endif  // DAWN_PLATFORM_IS(MACOS)
@@ -106,7 +103,7 @@
     return {};
 }
 
-ResultOrError<SwapChainTextureInfo> SwapChain::GetCurrentTextureImpl() {
+ResultOrError<Ref<TextureBase>> SwapChain::GetCurrentTextureImpl() {
     @autoreleasepool {
         DAWN_ASSERT(mCurrentDrawable == nullptr);
         mCurrentDrawable = [*mLayer nextDrawable];
@@ -115,13 +112,7 @@
 
         mTexture = Texture::CreateWrapping(ToBackend(GetDevice()), Unpack(&textureDesc),
                                            NSPRef<id<MTLTexture>>([*mCurrentDrawable texture]));
-
-        SwapChainTextureInfo info;
-        info.texture = mTexture;
-        info.status = wgpu::SurfaceGetCurrentTextureStatus::Success;
-        // TODO(dawn:2320) Check for optimality
-        info.suboptimal = false;
-        return info;
+        return mTexture;
     }
 }
 
diff --git a/src/dawn/native/null/DeviceNull.cpp b/src/dawn/native/null/DeviceNull.cpp
index 0d1dbb9..eeb8a16 100644
--- a/src/dawn/native/null/DeviceNull.cpp
+++ b/src/dawn/native/null/DeviceNull.cpp
@@ -66,15 +66,6 @@
     return true;
 }
 
-ResultOrError<PhysicalDeviceSurfaceCapabilities> PhysicalDevice::GetSurfaceCapabilities(
-    const Surface* surface) const {
-    PhysicalDeviceSurfaceCapabilities capabilities;
-    capabilities.formats = {wgpu::TextureFormat::BGRA8Unorm};
-    capabilities.presentModes = {wgpu::PresentMode::Fifo};
-    capabilities.alphaModes = {wgpu::CompositeAlphaMode::Auto};
-    return capabilities;
-}
-
 MaybeError PhysicalDevice::InitializeImpl() {
     return {};
 }
@@ -232,10 +223,11 @@
     DAWN_TRY(module->Initialize(parseResult, compilationMessages));
     return module;
 }
-ResultOrError<Ref<SwapChainBase>> Device::CreateSwapChainImpl(Surface* surface,
-                                                              SwapChainBase* previousSwapChain,
-                                                              const SurfaceConfiguration* config) {
-    return SwapChain::Create(this, surface, previousSwapChain, config);
+ResultOrError<Ref<SwapChainBase>> Device::CreateSwapChainImpl(
+    Surface* surface,
+    SwapChainBase* previousSwapChain,
+    const SwapChainDescriptor* descriptor) {
+    return SwapChain::Create(this, surface, previousSwapChain, descriptor);
 }
 ResultOrError<Ref<TextureBase>> Device::CreateTextureImpl(
     const UnpackedPtr<TextureDescriptor>& descriptor) {
@@ -515,8 +507,8 @@
 ResultOrError<Ref<SwapChain>> SwapChain::Create(Device* device,
                                                 Surface* surface,
                                                 SwapChainBase* previousSwapChain,
-                                                const SurfaceConfiguration* config) {
-    Ref<SwapChain> swapchain = AcquireRef(new SwapChain(device, surface, config));
+                                                const SwapChainDescriptor* descriptor) {
+    Ref<SwapChain> swapchain = AcquireRef(new SwapChain(device, surface, descriptor));
     DAWN_TRY(swapchain->Initialize(previousSwapChain));
     return swapchain;
 }
@@ -541,14 +533,10 @@
     return {};
 }
 
-ResultOrError<SwapChainTextureInfo> SwapChain::GetCurrentTextureImpl() {
+ResultOrError<Ref<TextureBase>> SwapChain::GetCurrentTextureImpl() {
     TextureDescriptor textureDesc = GetSwapChainBaseTextureDescriptor(this);
     mTexture = AcquireRef(new Texture(GetDevice(), Unpack(&textureDesc)));
-    SwapChainTextureInfo info;
-    info.texture = mTexture;
-    info.status = wgpu::SurfaceGetCurrentTextureStatus::Success;
-    info.suboptimal = false;
-    return info;
+    return mTexture;
 }
 
 void SwapChain::DetachFromSurfaceImpl() {
diff --git a/src/dawn/native/null/DeviceNull.h b/src/dawn/native/null/DeviceNull.h
index c338066..db6b596 100644
--- a/src/dawn/native/null/DeviceNull.h
+++ b/src/dawn/native/null/DeviceNull.h
@@ -164,7 +164,7 @@
     ResultOrError<Ref<SwapChainBase>> CreateSwapChainImpl(
         Surface* surface,
         SwapChainBase* previousSwapChain,
-        const SurfaceConfiguration* config) override;
+        const SwapChainDescriptor* descriptor) override;
     ResultOrError<Ref<TextureBase>> CreateTextureImpl(
         const UnpackedPtr<TextureDescriptor>& descriptor) override;
     ResultOrError<Ref<TextureViewBase>> CreateTextureViewImpl(
@@ -194,9 +194,6 @@
 
     bool SupportsFeatureLevel(FeatureLevel featureLevel) const override;
 
-    ResultOrError<PhysicalDeviceSurfaceCapabilities> GetSurfaceCapabilities(
-        const Surface* surface) const override;
-
     // Used for the tests that intend to use an adapter without all features enabled.
     using PhysicalDeviceBase::SetSupportedFeaturesForTesting;
 
@@ -324,7 +321,7 @@
     static ResultOrError<Ref<SwapChain>> Create(Device* device,
                                                 Surface* surface,
                                                 SwapChainBase* previousSwapChain,
-                                                const SurfaceConfiguration* config);
+                                                const SwapChainDescriptor* descriptor);
     ~SwapChain() override;
 
   private:
@@ -334,7 +331,7 @@
     Ref<Texture> mTexture;
 
     MaybeError PresentImpl() override;
-    ResultOrError<SwapChainTextureInfo> GetCurrentTextureImpl() override;
+    ResultOrError<Ref<TextureBase>> GetCurrentTextureImpl() override;
     void DetachFromSurfaceImpl() override;
 };
 
diff --git a/src/dawn/native/opengl/DeviceGL.cpp b/src/dawn/native/opengl/DeviceGL.cpp
index dc3b37d..7c5b95f 100644
--- a/src/dawn/native/opengl/DeviceGL.cpp
+++ b/src/dawn/native/opengl/DeviceGL.cpp
@@ -259,9 +259,10 @@
     OwnedCompilationMessages* compilationMessages) {
     return ShaderModule::Create(this, descriptor, parseResult, compilationMessages);
 }
-ResultOrError<Ref<SwapChainBase>> Device::CreateSwapChainImpl(Surface* surface,
-                                                              SwapChainBase* previousSwapChain,
-                                                              const SurfaceConfiguration* config) {
+ResultOrError<Ref<SwapChainBase>> Device::CreateSwapChainImpl(
+    Surface* surface,
+    SwapChainBase* previousSwapChain,
+    const SwapChainDescriptor* descriptor) {
     return DAWN_VALIDATION_ERROR("New swapchains not implemented.");
 }
 ResultOrError<Ref<TextureBase>> Device::CreateTextureImpl(
diff --git a/src/dawn/native/opengl/DeviceGL.h b/src/dawn/native/opengl/DeviceGL.h
index 6849720..2ad1e2e 100644
--- a/src/dawn/native/opengl/DeviceGL.h
+++ b/src/dawn/native/opengl/DeviceGL.h
@@ -130,7 +130,7 @@
     ResultOrError<Ref<SwapChainBase>> CreateSwapChainImpl(
         Surface* surface,
         SwapChainBase* previousSwapChain,
-        const SurfaceConfiguration* config) override;
+        const SwapChainDescriptor* descriptor) override;
     ResultOrError<Ref<TextureBase>> CreateTextureImpl(
         const UnpackedPtr<TextureDescriptor>& descriptor) override;
     ResultOrError<Ref<TextureViewBase>> CreateTextureViewImpl(
diff --git a/src/dawn/native/opengl/PhysicalDeviceGL.cpp b/src/dawn/native/opengl/PhysicalDeviceGL.cpp
index ed6656b..c92b41b 100644
--- a/src/dawn/native/opengl/PhysicalDeviceGL.cpp
+++ b/src/dawn/native/opengl/PhysicalDeviceGL.cpp
@@ -446,37 +446,6 @@
     return featureLevel == FeatureLevel::Compatibility;
 }
 
-ResultOrError<PhysicalDeviceSurfaceCapabilities> PhysicalDevice::GetSurfaceCapabilities(
-    const Surface*) const {
-    PhysicalDeviceSurfaceCapabilities capabilities;
-
-    // Formats
-
-    // This is the only supported format in native mode (see crbug.com/dawn/160).
-#if DAWN_PLATFORM_IS(ANDROID)
-    capabilities.formats.push_back(wgpu::TextureFormat::RGBA8Unorm);
-#else
-    capabilities.formats.push_back(wgpu::TextureFormat::BGRA8Unorm);
-#endif  // !DAWN_PLATFORM_IS(ANDROID)
-
-    // Present Modes
-
-    capabilities.presentModes = {
-        wgpu::PresentMode::Fifo,
-        wgpu::PresentMode::Immediate,
-        wgpu::PresentMode::Mailbox,
-    };
-
-    // Alpha Modes
-
-    capabilities.alphaModes = {
-        wgpu::CompositeAlphaMode::Opaque,
-        wgpu::CompositeAlphaMode::Auto,
-    };
-
-    return capabilities;
-}
-
 FeatureValidationResult PhysicalDevice::ValidateFeatureSupportedWithTogglesImpl(
     wgpu::FeatureName feature,
     const TogglesState& toggles) const {
diff --git a/src/dawn/native/opengl/PhysicalDeviceGL.h b/src/dawn/native/opengl/PhysicalDeviceGL.h
index 47897a0..e2f4771 100644
--- a/src/dawn/native/opengl/PhysicalDeviceGL.h
+++ b/src/dawn/native/opengl/PhysicalDeviceGL.h
@@ -46,8 +46,6 @@
     // PhysicalDeviceBase Implementation
     bool SupportsExternalImages() const override;
     bool SupportsFeatureLevel(FeatureLevel featureLevel) const override;
-    ResultOrError<PhysicalDeviceSurfaceCapabilities> GetSurfaceCapabilities(
-        const Surface* surface) const override;
 
   private:
     PhysicalDevice(InstanceBase* instance, wgpu::BackendType backendType, EGLDisplay display);
diff --git a/src/dawn/native/utils/WGPUHelpers.h b/src/dawn/native/utils/WGPUHelpers.h
index 5790df7..376f774 100644
--- a/src/dawn/native/utils/WGPUHelpers.h
+++ b/src/dawn/native/utils/WGPUHelpers.h
@@ -136,31 +136,6 @@
 
 const char* GetLabelForTrace(const char* label);
 
-// Given a std vector, allocate an equivalent array that can be returned in an API's foos/fooCount
-// pair of fields. The apiData must eventually be freed using FreeApiSeq.
-template <typename T>
-inline MaybeError AllocateApiSeqFromStdVector(const T*& apiData,
-                                              size_t& apiSize,
-                                              const std::vector<T>& vector) {
-    apiSize = vector.size();
-    if (apiSize > 0) {
-        T* mutableData = new T[apiSize];
-        memcpy(mutableData, vector.data(), apiSize * sizeof(T));
-        apiData = mutableData;
-    } else {
-        apiData = nullptr;
-    }
-    return {};
-}
-
-// Free an API sequence that was allocated by AllocateApiSeqFromStdVector
-template <typename T>
-inline void FreeApiSeq(T*& apiData, size_t& apiSize) {
-    delete[] apiData;
-    apiData = nullptr;
-    apiSize = 0;
-}
-
 }  // namespace dawn::native::utils
 
 #endif  // SRC_DAWN_NATIVE_UTILS_WGPUHELPERS_H_
diff --git a/src/dawn/native/vulkan/DeviceVk.cpp b/src/dawn/native/vulkan/DeviceVk.cpp
index 58fbced..9d3218b 100644
--- a/src/dawn/native/vulkan/DeviceVk.cpp
+++ b/src/dawn/native/vulkan/DeviceVk.cpp
@@ -192,10 +192,11 @@
     OwnedCompilationMessages* compilationMessages) {
     return ShaderModule::Create(this, descriptor, parseResult, compilationMessages);
 }
-ResultOrError<Ref<SwapChainBase>> Device::CreateSwapChainImpl(Surface* surface,
-                                                              SwapChainBase* previousSwapChain,
-                                                              const SurfaceConfiguration* config) {
-    return SwapChain::Create(this, surface, previousSwapChain, config);
+ResultOrError<Ref<SwapChainBase>> Device::CreateSwapChainImpl(
+    Surface* surface,
+    SwapChainBase* previousSwapChain,
+    const SwapChainDescriptor* descriptor) {
+    return SwapChain::Create(this, surface, previousSwapChain, descriptor);
 }
 ResultOrError<Ref<TextureBase>> Device::CreateTextureImpl(
     const UnpackedPtr<TextureDescriptor>& descriptor) {
diff --git a/src/dawn/native/vulkan/DeviceVk.h b/src/dawn/native/vulkan/DeviceVk.h
index 3007197..82856ec 100644
--- a/src/dawn/native/vulkan/DeviceVk.h
+++ b/src/dawn/native/vulkan/DeviceVk.h
@@ -146,7 +146,7 @@
     ResultOrError<Ref<SwapChainBase>> CreateSwapChainImpl(
         Surface* surface,
         SwapChainBase* previousSwapChain,
-        const SurfaceConfiguration* config) override;
+        const SwapChainDescriptor* descriptor) override;
     ResultOrError<Ref<TextureBase>> CreateTextureImpl(
         const UnpackedPtr<TextureDescriptor>& descriptor) override;
     ResultOrError<Ref<TextureViewBase>> CreateTextureViewImpl(
diff --git a/src/dawn/native/vulkan/PhysicalDeviceVk.cpp b/src/dawn/native/vulkan/PhysicalDeviceVk.cpp
index e16aa83..33e5eca 100644
--- a/src/dawn/native/vulkan/PhysicalDeviceVk.cpp
+++ b/src/dawn/native/vulkan/PhysicalDeviceVk.cpp
@@ -36,8 +36,6 @@
 #include "dawn/native/Limits.h"
 #include "dawn/native/vulkan/BackendVk.h"
 #include "dawn/native/vulkan/DeviceVk.h"
-#include "dawn/native/vulkan/SwapChainVk.h"
-#include "dawn/native/vulkan/VulkanError.h"
 #include "dawn/platform/DawnPlatform.h"
 
 #if DAWN_PLATFORM_IS(ANDROID)
@@ -832,81 +830,6 @@
     return mDefaultComputeSubgroupSize;
 }
 
-ResultOrError<PhysicalDeviceSurfaceCapabilities> PhysicalDevice::GetSurfaceCapabilities(
-    const Surface* surface) const {
-    PhysicalDeviceSurfaceCapabilities capabilities;
-
-    // Formats
-
-    // This is the only supported format in native mode (see crbug.com/dawn/160).
-#if DAWN_PLATFORM_IS(ANDROID)
-    capabilities.formats.push_back(wgpu::TextureFormat::RGBA8Unorm);
-#else
-    capabilities.formats.push_back(wgpu::TextureFormat::BGRA8Unorm);
-#endif  // !DAWN_PLATFORM_IS(ANDROID)
-
-    // Present Modes
-
-    // TODO(dawn:2320) Other present modes than Mailbox do not pass tests on Intel Graphics. Once
-    // 'surface' will actually contain a vkSurface we'll be able to test
-    // vkGetPhysicalDeviceSurfaceSupportKHR to avoid this #if.
-#if DAWN_PLATFORM_IS(LINUX)
-    capabilities.presentModes = {
-        wgpu::PresentMode::Mailbox,
-    };
-#else
-    capabilities.presentModes = {
-        wgpu::PresentMode::Fifo,
-        wgpu::PresentMode::Immediate,
-        wgpu::PresentMode::Mailbox,
-    };
-#endif  // !DAWN_PLATFORM_IS(LINUX)
-
-    // Alpha Modes
-
-#if !DAWN_PLATFORM_IS(ANDROID)
-    capabilities.alphaModes.push_back(wgpu::CompositeAlphaMode::Opaque);
-#else
-    VkSurfaceKHR vkSurface;
-    DAWN_TRY_ASSIGN(vkSurface, CreateVulkanSurface(this, surface));
-
-    VkPhysicalDevice vkPhysicalDevice = GetVkPhysicalDevice();
-    const VulkanFunctions& fn = GetVulkanInstance()->GetFunctions();
-    VkInstance vkInstance = GetVulkanInstance()->GetVkInstance();
-    const VulkanFunctions& vkFunctions = GetVulkanInstance()->GetFunctions();
-
-    // Get the surface capabilities
-    VkSurfaceCapabilitiesKHR vkCapabilities;
-    DAWN_TRY_WITH_CLEANUP(CheckVkSuccess(vkFunctions.GetPhysicalDeviceSurfaceCapabilitiesKHR(
-                                             vkPhysicalDevice, vkSurface, &vkCapabilities),
-                                         "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"),
-                          { fn.DestroySurfaceKHR(vkInstance, vkSurface, nullptr); });
-
-    fn.DestroySurfaceKHR(vkInstance, vkSurface, nullptr);
-
-    // TODO(dawn:286): investigate composite alpha for WebGPU native
-    struct AlphaModePairs {
-        VkCompositeAlphaFlagBitsKHR vkBit;
-        wgpu::CompositeAlphaMode webgpuEnum;
-    };
-    AlphaModePairs alphaModePairs[] = {
-        {VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, wgpu::CompositeAlphaMode::Opaque},
-        {VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR, wgpu::CompositeAlphaMode::Premultiplied},
-        {VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR, wgpu::CompositeAlphaMode::Unpremultiplied},
-        {VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR, wgpu::CompositeAlphaMode::Inherit},
-    };
-
-    for (auto mode : alphaModePairs) {
-        if (vkCapabilities.supportedCompositeAlpha & mode.vkBit) {
-            capabilities.alphaModes.push_back(mode.webgpuEnum);
-        }
-    }
-#endif  // #if !DAWN_PLATFORM_IS(ANDROID)
-    capabilities.alphaModes.push_back(wgpu::CompositeAlphaMode::Auto);
-
-    return capabilities;
-}
-
 void PhysicalDevice::PopulateBackendProperties(UnpackedPtr<AdapterProperties>& properties) const {
     if (auto* memoryHeapProperties = properties.Get<AdapterPropertiesMemoryHeaps>()) {
         size_t count = mDeviceInfo.memoryHeaps.size();
diff --git a/src/dawn/native/vulkan/PhysicalDeviceVk.h b/src/dawn/native/vulkan/PhysicalDeviceVk.h
index 136e594..8da4917 100644
--- a/src/dawn/native/vulkan/PhysicalDeviceVk.h
+++ b/src/dawn/native/vulkan/PhysicalDeviceVk.h
@@ -61,9 +61,6 @@
 
     uint32_t GetDefaultComputeSubgroupSize() const;
 
-    ResultOrError<PhysicalDeviceSurfaceCapabilities> GetSurfaceCapabilities(
-        const Surface* surface) const override;
-
   private:
     MaybeError InitializeImpl() override;
     void InitializeSupportedFeaturesImpl() override;
diff --git a/src/dawn/native/vulkan/SwapChainVk.cpp b/src/dawn/native/vulkan/SwapChainVk.cpp
index 8b81b94..b33764e 100644
--- a/src/dawn/native/vulkan/SwapChainVk.cpp
+++ b/src/dawn/native/vulkan/SwapChainVk.cpp
@@ -51,6 +51,149 @@
 
 namespace {
 
+ResultOrError<VkSurfaceKHR> CreateVulkanSurface(const PhysicalDevice* physicalDevice,
+                                                const Surface* surface) {
+    const VulkanGlobalInfo& info = physicalDevice->GetVulkanInstance()->GetGlobalInfo();
+    const VulkanFunctions& fn = physicalDevice->GetVulkanInstance()->GetFunctions();
+    VkInstance instance = physicalDevice->GetVulkanInstance()->GetVkInstance();
+
+    // May not be used in the platform-specific switches below.
+    DAWN_UNUSED(info);
+    DAWN_UNUSED(fn);
+    DAWN_UNUSED(instance);
+
+    switch (surface->GetType()) {
+#if defined(DAWN_ENABLE_BACKEND_METAL)
+        case Surface::Type::MetalLayer:
+            if (info.HasExt(InstanceExt::MetalSurface)) {
+                VkMetalSurfaceCreateInfoEXT createInfo;
+                createInfo.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
+                createInfo.pNext = nullptr;
+                createInfo.flags = 0;
+                createInfo.pLayer = surface->GetMetalLayer();
+
+                VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
+                DAWN_TRY(CheckVkSuccess(
+                    fn.CreateMetalSurfaceEXT(instance, &createInfo, nullptr, &*vkSurface),
+                    "CreateMetalSurface"));
+                return vkSurface;
+            }
+            break;
+#endif  // defined(DAWN_ENABLE_BACKEND_METAL)
+
+#if DAWN_PLATFORM_IS(WINDOWS)
+        case Surface::Type::WindowsHWND:
+            if (info.HasExt(InstanceExt::Win32Surface)) {
+                VkWin32SurfaceCreateInfoKHR createInfo;
+                createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
+                createInfo.pNext = nullptr;
+                createInfo.flags = 0;
+                createInfo.hinstance = static_cast<HINSTANCE>(surface->GetHInstance());
+                createInfo.hwnd = static_cast<HWND>(surface->GetHWND());
+
+                VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
+                DAWN_TRY(CheckVkSuccess(
+                    fn.CreateWin32SurfaceKHR(instance, &createInfo, nullptr, &*vkSurface),
+                    "CreateWin32Surface"));
+                return vkSurface;
+            }
+            break;
+#endif  // DAWN_PLATFORM_IS(WINDOWS)
+
+#if DAWN_PLATFORM_IS(ANDROID)
+        case Surface::Type::AndroidWindow: {
+            if (info.HasExt(InstanceExt::AndroidSurface)) {
+                DAWN_ASSERT(surface->GetAndroidNativeWindow() != nullptr);
+
+                VkAndroidSurfaceCreateInfoKHR createInfo;
+                createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
+                createInfo.pNext = nullptr;
+                createInfo.flags = 0;
+                createInfo.window =
+                    static_cast<struct ANativeWindow*>(surface->GetAndroidNativeWindow());
+
+                VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
+                DAWN_TRY(CheckVkSuccess(
+                    fn.CreateAndroidSurfaceKHR(instance, &createInfo, nullptr, &*vkSurface),
+                    "CreateAndroidSurfaceKHR"));
+                return vkSurface;
+            }
+
+            break;
+        }
+
+#endif  // DAWN_PLATFORM_IS(ANDROID)
+
+#if defined(DAWN_USE_WAYLAND)
+        case Surface::Type::WaylandSurface: {
+            if (info.HasExt(InstanceExt::XlibSurface)) {
+                VkWaylandSurfaceCreateInfoKHR createInfo;
+                createInfo.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
+                createInfo.pNext = nullptr;
+                createInfo.flags = 0;
+                createInfo.display = static_cast<struct wl_display*>(surface->GetWaylandDisplay());
+                createInfo.surface = static_cast<struct wl_surface*>(surface->GetWaylandSurface());
+
+                VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
+                DAWN_TRY(CheckVkSuccess(
+                    fn.CreateWaylandSurfaceKHR(instance, &createInfo, nullptr, &*vkSurface),
+                    "CreateWaylandSurface"));
+                return vkSurface;
+            }
+            break;
+        }
+#endif  // defined(DAWN_USE_WAYLAND)
+
+#if defined(DAWN_USE_X11)
+        case Surface::Type::XlibWindow: {
+            if (info.HasExt(InstanceExt::XlibSurface)) {
+                VkXlibSurfaceCreateInfoKHR createInfo;
+                createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
+                createInfo.pNext = nullptr;
+                createInfo.flags = 0;
+                createInfo.dpy = static_cast<Display*>(surface->GetXDisplay());
+                createInfo.window = surface->GetXWindow();
+
+                VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
+                DAWN_TRY(CheckVkSuccess(
+                    fn.CreateXlibSurfaceKHR(instance, &createInfo, nullptr, &*vkSurface),
+                    "CreateXlibSurface"));
+                return vkSurface;
+            }
+
+            // Fall back to using XCB surfaces if the Xlib extension isn't available.
+            // See https://xcb.freedesktop.org/MixingCalls/ for more information about
+            // interoperability between Xlib and XCB
+            const X11Functions* x11 = physicalDevice->GetInstance()->GetOrLoadX11Functions();
+            DAWN_ASSERT(x11 != nullptr);
+
+            if (info.HasExt(InstanceExt::XcbSurface) && x11->IsX11XcbLoaded()) {
+                VkXcbSurfaceCreateInfoKHR createInfo;
+                createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
+                createInfo.pNext = nullptr;
+                createInfo.flags = 0;
+                // The XCB connection lives as long as the X11 display.
+                createInfo.connection =
+                    x11->xGetXCBConnection(static_cast<Display*>(surface->GetXDisplay()));
+                createInfo.window = surface->GetXWindow();
+
+                VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
+                DAWN_TRY(CheckVkSuccess(
+                    fn.CreateXcbSurfaceKHR(instance, &createInfo, nullptr, &*vkSurface),
+                    "CreateXcbSurfaceKHR"));
+                return vkSurface;
+            }
+            break;
+        }
+#endif  // defined(DAWN_USE_X11)
+
+        default:
+            break;
+    }
+
+    return DAWN_VALIDATION_ERROR("Unsupported surface type (%s) for Vulkan.", surface->GetType());
+}
+
 VkPresentModeKHR ToVulkanPresentMode(wgpu::PresentMode mode) {
     switch (mode) {
         case wgpu::PresentMode::Fifo:
@@ -117,8 +260,8 @@
 ResultOrError<Ref<SwapChain>> SwapChain::Create(Device* device,
                                                 Surface* surface,
                                                 SwapChainBase* previousSwapChain,
-                                                const SurfaceConfiguration* config) {
-    Ref<SwapChain> swapchain = AcquireRef(new SwapChain(device, surface, config));
+                                                const SwapChainDescriptor* descriptor) {
+    Ref<SwapChain> swapchain = AcquireRef(new SwapChain(device, surface, descriptor));
     DAWN_TRY(swapchain->Initialize(previousSwapChain));
     return swapchain;
 }
@@ -494,13 +637,12 @@
     }
 }
 
-ResultOrError<SwapChainTextureInfo> SwapChain::GetCurrentTextureImpl() {
+ResultOrError<Ref<TextureBase>> SwapChain::GetCurrentTextureImpl() {
     return GetCurrentTextureInternal();
 }
 
-ResultOrError<SwapChainTextureInfo> SwapChain::GetCurrentTextureInternal(bool isReentrant) {
+ResultOrError<Ref<TextureBase>> SwapChain::GetCurrentTextureInternal(bool isReentrant) {
     Device* device = ToBackend(GetDevice());
-    SwapChainTextureInfo swapChainTextureInfo;
 
     // Transiently create a semaphore that will be signaled when the presentation engine is done
     // with the swapchain image. Further operations on the image will wait for this semaphore.
@@ -530,17 +672,14 @@
         ToBackend(GetDevice())->GetFencedDeleter()->DeleteWhenUnused(semaphore);
     }
 
-    swapChainTextureInfo.suboptimal = false;
     switch (result) {
+        // TODO(crbug.com/dawn/269): Introduce a mechanism to notify the application that
+        // the swapchain is in a suboptimal state?
         case VK_SUBOPTIMAL_KHR:
-            swapChainTextureInfo.suboptimal = true;
-            ABSL_FALLTHROUGH_INTENDED;
         case VK_SUCCESS:
-            swapChainTextureInfo.status = wgpu::SurfaceGetCurrentTextureStatus::Success;
             break;
 
         case VK_ERROR_OUT_OF_DATE_KHR: {
-            swapChainTextureInfo.status = wgpu::SurfaceGetCurrentTextureStatus::Outdated;
             // Prevent infinite recursive calls to GetCurrentTextureViewInternal when the
             // swapchains always return that they are out of date.
             if (isReentrant) {
@@ -556,9 +695,6 @@
 
         // TODO(crbug.com/dawn/269): Allow losing the surface at Dawn's API level?
         case VK_ERROR_SURFACE_LOST_KHR:
-            swapChainTextureInfo.status = wgpu::SurfaceGetCurrentTextureStatus::Lost;
-            break;
-
         default:
             DAWN_TRY(CheckVkSuccess(::VkResult(result), "AcquireNextImage"));
     }
@@ -574,8 +710,7 @@
 
     // In the happy path we can use the swapchain image directly.
     if (!mConfig.needsBlit) {
-        swapChainTextureInfo.texture = mTexture;
-        return swapChainTextureInfo;
+        return mTexture;
     }
 
     // The blit texture always perfectly matches what the user requested for the swapchain.
@@ -583,8 +718,7 @@
     TextureDescriptor desc = GetSwapChainBaseTextureDescriptor(this);
     DAWN_TRY_ASSIGN(mBlitTexture,
                     Texture::Create(device, Unpack(&desc), VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
-    swapChainTextureInfo.texture = mBlitTexture;
-    return swapChainTextureInfo;
+    return mBlitTexture;
 }
 
 void SwapChain::DetachFromSurfaceImpl() {
@@ -616,147 +750,4 @@
     }
 }
 
-ResultOrError<VkSurfaceKHR> CreateVulkanSurface(const PhysicalDevice* physicalDevice,
-                                                const Surface* surface) {
-    const VulkanGlobalInfo& info = physicalDevice->GetVulkanInstance()->GetGlobalInfo();
-    const VulkanFunctions& fn = physicalDevice->GetVulkanInstance()->GetFunctions();
-    VkInstance instance = physicalDevice->GetVulkanInstance()->GetVkInstance();
-
-    // May not be used in the platform-specific switches below.
-    DAWN_UNUSED(info);
-    DAWN_UNUSED(fn);
-    DAWN_UNUSED(instance);
-
-    switch (surface->GetType()) {
-#if defined(DAWN_ENABLE_BACKEND_METAL)
-        case Surface::Type::MetalLayer:
-            if (info.HasExt(InstanceExt::MetalSurface)) {
-                VkMetalSurfaceCreateInfoEXT createInfo;
-                createInfo.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
-                createInfo.pNext = nullptr;
-                createInfo.flags = 0;
-                createInfo.pLayer = surface->GetMetalLayer();
-
-                VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
-                DAWN_TRY(CheckVkSuccess(
-                    fn.CreateMetalSurfaceEXT(instance, &createInfo, nullptr, &*vkSurface),
-                    "CreateMetalSurface"));
-                return vkSurface;
-            }
-            break;
-#endif  // defined(DAWN_ENABLE_BACKEND_METAL)
-
-#if DAWN_PLATFORM_IS(WINDOWS)
-        case Surface::Type::WindowsHWND:
-            if (info.HasExt(InstanceExt::Win32Surface)) {
-                VkWin32SurfaceCreateInfoKHR createInfo;
-                createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
-                createInfo.pNext = nullptr;
-                createInfo.flags = 0;
-                createInfo.hinstance = static_cast<HINSTANCE>(surface->GetHInstance());
-                createInfo.hwnd = static_cast<HWND>(surface->GetHWND());
-
-                VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
-                DAWN_TRY(CheckVkSuccess(
-                    fn.CreateWin32SurfaceKHR(instance, &createInfo, nullptr, &*vkSurface),
-                    "CreateWin32Surface"));
-                return vkSurface;
-            }
-            break;
-#endif  // DAWN_PLATFORM_IS(WINDOWS)
-
-#if DAWN_PLATFORM_IS(ANDROID)
-        case Surface::Type::AndroidWindow: {
-            if (info.HasExt(InstanceExt::AndroidSurface)) {
-                DAWN_ASSERT(surface->GetAndroidNativeWindow() != nullptr);
-
-                VkAndroidSurfaceCreateInfoKHR createInfo;
-                createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
-                createInfo.pNext = nullptr;
-                createInfo.flags = 0;
-                createInfo.window =
-                    static_cast<struct ANativeWindow*>(surface->GetAndroidNativeWindow());
-
-                VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
-                DAWN_TRY(CheckVkSuccess(
-                    fn.CreateAndroidSurfaceKHR(instance, &createInfo, nullptr, &*vkSurface),
-                    "CreateAndroidSurfaceKHR"));
-                return vkSurface;
-            }
-
-            break;
-        }
-
-#endif  // DAWN_PLATFORM_IS(ANDROID)
-
-#if defined(DAWN_USE_WAYLAND)
-        case Surface::Type::WaylandSurface: {
-            if (info.HasExt(InstanceExt::XlibSurface)) {
-                VkWaylandSurfaceCreateInfoKHR createInfo;
-                createInfo.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
-                createInfo.pNext = nullptr;
-                createInfo.flags = 0;
-                createInfo.display = static_cast<struct wl_display*>(surface->GetWaylandDisplay());
-                createInfo.surface = static_cast<struct wl_surface*>(surface->GetWaylandSurface());
-
-                VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
-                DAWN_TRY(CheckVkSuccess(
-                    fn.CreateWaylandSurfaceKHR(instance, &createInfo, nullptr, &*vkSurface),
-                    "CreateWaylandSurface"));
-                return vkSurface;
-            }
-            break;
-        }
-#endif  // defined(DAWN_USE_WAYLAND)
-
-#if defined(DAWN_USE_X11)
-        case Surface::Type::XlibWindow: {
-            if (info.HasExt(InstanceExt::XlibSurface)) {
-                VkXlibSurfaceCreateInfoKHR createInfo;
-                createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
-                createInfo.pNext = nullptr;
-                createInfo.flags = 0;
-                createInfo.dpy = static_cast<Display*>(surface->GetXDisplay());
-                createInfo.window = surface->GetXWindow();
-
-                VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
-                DAWN_TRY(CheckVkSuccess(
-                    fn.CreateXlibSurfaceKHR(instance, &createInfo, nullptr, &*vkSurface),
-                    "CreateXlibSurface"));
-                return vkSurface;
-            }
-
-            // Fall back to using XCB surfaces if the Xlib extension isn't available.
-            // See https://xcb.freedesktop.org/MixingCalls/ for more information about
-            // interoperability between Xlib and XCB
-            const X11Functions* x11 = physicalDevice->GetInstance()->GetOrLoadX11Functions();
-            DAWN_ASSERT(x11 != nullptr);
-
-            if (info.HasExt(InstanceExt::XcbSurface) && x11->IsX11XcbLoaded()) {
-                VkXcbSurfaceCreateInfoKHR createInfo;
-                createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
-                createInfo.pNext = nullptr;
-                createInfo.flags = 0;
-                // The XCB connection lives as long as the X11 display.
-                createInfo.connection =
-                    x11->xGetXCBConnection(static_cast<Display*>(surface->GetXDisplay()));
-                createInfo.window = surface->GetXWindow();
-
-                VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
-                DAWN_TRY(CheckVkSuccess(
-                    fn.CreateXcbSurfaceKHR(instance, &createInfo, nullptr, &*vkSurface),
-                    "CreateXcbSurfaceKHR"));
-                return vkSurface;
-            }
-            break;
-        }
-#endif  // defined(DAWN_USE_X11)
-
-        default:
-            break;
-    }
-
-    return DAWN_VALIDATION_ERROR("Unsupported surface type (%s) for Vulkan.", surface->GetType());
-}
-
 }  // namespace dawn::native::vulkan
diff --git a/src/dawn/native/vulkan/SwapChainVk.h b/src/dawn/native/vulkan/SwapChainVk.h
index da1f7ea..b0d322d 100644
--- a/src/dawn/native/vulkan/SwapChainVk.h
+++ b/src/dawn/native/vulkan/SwapChainVk.h
@@ -38,7 +38,6 @@
 
 class Device;
 class Texture;
-class PhysicalDevice;
 struct VulkanSurfaceInfo;
 
 class SwapChain : public SwapChainBase {
@@ -46,7 +45,7 @@
     static ResultOrError<Ref<SwapChain>> Create(Device* device,
                                                 Surface* surface,
                                                 SwapChainBase* previousSwapChain,
-                                                const SurfaceConfiguration* config);
+                                                const SwapChainDescriptor* descriptor);
 
     static ResultOrError<wgpu::TextureUsage> GetSupportedSurfaceUsage(const Device* device,
                                                                       const Surface* surface);
@@ -78,11 +77,11 @@
         bool needsBlit = false;
     };
     ResultOrError<Config> ChooseConfig(const VulkanSurfaceInfo& surfaceInfo) const;
-    ResultOrError<SwapChainTextureInfo> GetCurrentTextureInternal(bool isReentrant = false);
+    ResultOrError<Ref<TextureBase>> GetCurrentTextureInternal(bool isReentrant = false);
 
     // SwapChainBase implementation
     MaybeError PresentImpl() override;
-    ResultOrError<SwapChainTextureInfo> GetCurrentTextureImpl() override;
+    ResultOrError<Ref<TextureBase>> GetCurrentTextureImpl() override;
     void DetachFromSurfaceImpl() override;
 
     Config mConfig;
@@ -97,9 +96,6 @@
     Ref<Texture> mTexture;
 };
 
-ResultOrError<VkSurfaceKHR> CreateVulkanSurface(const PhysicalDevice* physicalDevice,
-                                                const Surface* surface);
-
 }  // namespace dawn::native::vulkan
 
 #endif  // SRC_DAWN_NATIVE_VULKAN_SWAPCHAINVK_H_
diff --git a/src/dawn/native/webgpu_absl_format.cpp b/src/dawn/native/webgpu_absl_format.cpp
index e41b2f7..95e2cc3 100644
--- a/src/dawn/native/webgpu_absl_format.cpp
+++ b/src/dawn/native/webgpu_absl_format.cpp
@@ -31,7 +31,6 @@
 #include <vector>
 
 #include "dawn/common/MatchVariant.h"
-#include "dawn/native/Adapter.h"
 #include "dawn/native/AttachmentState.h"
 #include "dawn/native/BindingInfo.h"
 #include "dawn/native/Device.h"
@@ -186,23 +185,6 @@
 //
 
 absl::FormatConvertResult<absl::FormatConversionCharSet::kString> AbslFormatConvert(
-    const AdapterBase* value,
-    const absl::FormatConversionSpec& spec,
-    absl::FormatSink* s) {
-    if (value == nullptr) {
-        s->Append("[null]");
-        return {true};
-    }
-    s->Append("[Adapter");
-    const std::string& name = value->GetName();
-    if (!name.empty()) {
-        s->Append(absl::StrFormat(" \"%s\"", name));
-    }
-    s->Append("]");
-    return {true};
-}
-
-absl::FormatConvertResult<absl::FormatConversionCharSet::kString> AbslFormatConvert(
     const DeviceBase* value,
     const absl::FormatConversionSpec& spec,
     absl::FormatSink* s) {
@@ -299,23 +281,6 @@
     return {true};
 }
 
-absl::FormatConvertResult<absl::FormatConversionCharSet::kString> AbslFormatConvert(
-    const Surface* value,
-    const absl::FormatConversionSpec& spec,
-    absl::FormatSink* s) {
-    if (value == nullptr) {
-        s->Append("[null]");
-        return {true};
-    }
-    s->Append("[Surface");
-    const std::string& label = value->GetLabel();
-    if (!label.empty()) {
-        s->Append(absl::StrFormat(" \"%s\"", label));
-    }
-    s->Append("]");
-    return {true};
-}
-
 //
 // Enums
 //
diff --git a/src/dawn/native/webgpu_absl_format.h b/src/dawn/native/webgpu_absl_format.h
index dceb3bc..e8f9da8 100644
--- a/src/dawn/native/webgpu_absl_format.h
+++ b/src/dawn/native/webgpu_absl_format.h
@@ -106,12 +106,6 @@
 
 class DeviceBase;
 absl::FormatConvertResult<absl::FormatConversionCharSet::kString> AbslFormatConvert(
-    const AdapterBase* value,
-    const absl::FormatConversionSpec& spec,
-    absl::FormatSink* s);
-
-class DeviceBase;
-absl::FormatConvertResult<absl::FormatConversionCharSet::kString> AbslFormatConvert(
     const DeviceBase* value,
     const absl::FormatConversionSpec& spec,
     absl::FormatSink* s);
@@ -128,12 +122,6 @@
     const absl::FormatConversionSpec& spec,
     absl::FormatSink* s);
 
-class Surface;
-absl::FormatConvertResult<absl::FormatConversionCharSet::kString> AbslFormatConvert(
-    const Surface* value,
-    const absl::FormatConversionSpec& spec,
-    absl::FormatSink* s);
-
 //
 // Enums
 //
diff --git a/src/dawn/tests/BUILD.gn b/src/dawn/tests/BUILD.gn
index aaa8aa2..adb0243 100644
--- a/src/dawn/tests/BUILD.gn
+++ b/src/dawn/tests/BUILD.gn
@@ -709,8 +709,6 @@
 
   if (dawn_supports_glfw_for_windowing) {
     sources += [
-      "end2end/SurfaceConfigurationValidationTests.cpp",
-      "end2end/SurfaceTests.cpp",
       "end2end/SwapChainTests.cpp",
       "end2end/SwapChainValidationTests.cpp",
       "end2end/WindowSurfaceTests.cpp",
diff --git a/src/dawn/tests/end2end/SurfaceConfigurationValidationTests.cpp b/src/dawn/tests/end2end/SurfaceConfigurationValidationTests.cpp
deleted file mode 100644
index f473fe1..0000000
--- a/src/dawn/tests/end2end/SurfaceConfigurationValidationTests.cpp
+++ /dev/null
@@ -1,313 +0,0 @@
-// 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 <cmath>
-#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::utils {
-static constexpr std::array<wgpu::CompositeAlphaMode, 5> kAllAlphaModes = {
-    wgpu::CompositeAlphaMode::Auto,          wgpu::CompositeAlphaMode::Opaque,
-    wgpu::CompositeAlphaMode::Premultiplied, wgpu::CompositeAlphaMode::Unpremultiplied,
-    wgpu::CompositeAlphaMode::Inherit,
-};
-static constexpr std::array<wgpu::PresentMode, 3> kAllPresentModes = {
-    wgpu::PresentMode::Fifo,
-    wgpu::PresentMode::Immediate,
-    wgpu::PresentMode::Mailbox,
-};
-}  // namespace dawn::utils
-
-namespace dawn {
-namespace {
-
-struct GLFWindowDestroyer {
-    void operator()(GLFWwindow* ptr) { glfwDestroyWindow(ptr); }
-};
-
-class SurfaceConfigurationValidationTests : public DawnTest {
-  public:
-    void SetUp() override {
-        DawnTest::SetUp();
-        DAWN_TEST_UNSUPPORTED_IF(UsesWire());
-        DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("skip_validation"));
-
-        // TODO(dawn:2320): Reconfiguring/unconfiguring fails with swift shader.
-        // NB: Fixing SurfaceTests.ReconfigureBasic should fix the other test cases as well.
-        DAWN_TEST_UNSUPPORTED_IF(IsSwiftshader());
-
-        glfwSetErrorCallback([](int code, const char* message) {
-            ErrorLog() << "GLFW error " << code << " " << message;
-        });
-
-        // GLFW can fail to start in headless environments, in which SwapChainTests 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(500, 400, "SurfaceConfigurationValidationTests 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;
-    }
-
-    wgpu::Surface CreateTestSurface() {
-        return wgpu::glfw::CreateSurfaceForWindow(GetInstance(), window.get());
-    }
-
-    wgpu::SurfaceConfiguration GetPreferredConfiguration(wgpu::Surface surface) {
-        wgpu::SurfaceCapabilities capabilities;
-        surface.GetCapabilities(adapter, &capabilities);
-
-        wgpu::TextureFormat preferredFormat = surface.GetPreferredFormat(adapter);
-
-        wgpu::SurfaceConfiguration config = baseConfig;
-        config.format = preferredFormat;
-        config.alphaMode = capabilities.alphaModes[0];
-        config.presentMode = capabilities.presentModes[0];
-        return config;
-    }
-
-    bool SupportsFormat(const wgpu::SurfaceCapabilities& capabilities, wgpu::TextureFormat format) {
-        for (size_t i = 0; i < capabilities.formatCount; ++i) {
-            if (capabilities.formats[i] == format) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    bool SupportsAlphaMode(const wgpu::SurfaceCapabilities& capabilities,
-                           wgpu::CompositeAlphaMode mode) {
-        for (size_t i = 0; i < capabilities.alphaModeCount; ++i) {
-            if (capabilities.alphaModes[i] == mode) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    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;
-};
-
-// Using undefined format is not valid
-TEST_P(SurfaceConfigurationValidationTests, UndefinedFormat) {
-    wgpu::SurfaceConfiguration config;
-    config.device = device;
-    config.format = wgpu::TextureFormat::Undefined;
-    ASSERT_DEVICE_ERROR(CreateTestSurface().Configure(&config));
-}
-
-// Supports at least one configuration
-TEST_P(SurfaceConfigurationValidationTests, AtLeastOneSupportedConfiguration) {
-    wgpu::Surface surface = CreateTestSurface();
-
-    wgpu::SurfaceCapabilities capabilities;
-    surface.GetCapabilities(adapter, &capabilities);
-
-    ASSERT_GT(capabilities.formatCount, 0u);
-    ASSERT_GT(capabilities.alphaModeCount, 0u);
-    ASSERT_GT(capabilities.presentModeCount, 0u);
-}
-
-// Using any combination of the reported capability is ok for configuring the surface.
-TEST_P(SurfaceConfigurationValidationTests, AnyCombinationOfCapabilities) {
-    // TODO(dawn:2320): This test crashes width SwiftShader (NB: fixing
-    // SurfaceTests.ReconfigureBasic should fix this test as well)
-    DAWN_SUPPRESS_TEST_IF(IsSwiftshader());
-
-    wgpu::Surface surface = CreateTestSurface();
-
-    wgpu::SurfaceConfiguration config = baseConfig;
-
-    wgpu::SurfaceCapabilities capabilities;
-    surface.GetCapabilities(adapter, &capabilities);
-
-    for (wgpu::TextureFormat format : dawn::utils::kAllTextureFormats) {
-        for (wgpu::CompositeAlphaMode alphaMode : dawn::utils::kAllAlphaModes) {
-            for (wgpu::PresentMode presentMode : dawn::utils::kAllPresentModes) {
-                config.format = format;
-                config.alphaMode = alphaMode;
-                config.presentMode = presentMode;
-
-                // TODO(dawn:2320) Switching to Mailbox from a different present mode may raise a
-                // VK_ERROR_OUT_OF_DEVICE_MEMORY
-                if (IsVulkan() && presentMode == wgpu::PresentMode::Mailbox) {
-                    continue;
-                }
-
-                if (!SupportsFormat(capabilities, config.format) ||
-                    !SupportsAlphaMode(capabilities, config.alphaMode) ||
-                    !SupportsPresentMode(capabilities, config.presentMode)) {
-                    ASSERT_DEVICE_ERROR(surface.Configure(&config));
-                } else {
-                    surface.Configure(&config);
-
-                    // Check that we can present
-                    wgpu::SurfaceTexture surfaceTexture;
-                    surface.GetCurrentTexture(&surfaceTexture);
-                    surface.Present();
-                }
-                device.Tick();
-            }
-        }
-    }
-}
-
-// Preferred format is always valid.
-TEST_P(SurfaceConfigurationValidationTests, PreferredFormatIsValid) {
-    wgpu::Surface surface = CreateTestSurface();
-
-    wgpu::SurfaceCapabilities capabilities;
-    surface.GetCapabilities(adapter, &capabilities);
-
-    wgpu::TextureFormat preferredFormat = surface.GetPreferredFormat(adapter);
-    bool found = false;
-    for (size_t i = 0; i < capabilities.formatCount; ++i) {
-        found = found || capabilities.formats[i] == preferredFormat;
-    }
-    ASSERT_TRUE(found);
-}
-
-// Invalid view format fails
-TEST_P(SurfaceConfigurationValidationTests, InvalidViewFormat) {
-    wgpu::Surface surface = CreateTestSurface();
-    auto invalid = wgpu::TextureFormat::R32Uint;
-
-    wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);
-    config.viewFormatCount = 1;
-    config.viewFormats = &invalid;
-    ASSERT_DEVICE_ERROR(surface.Configure(&config));
-}
-
-// View format is valid when it matches the config format
-TEST_P(SurfaceConfigurationValidationTests, ValidViewFormat) {
-    wgpu::Surface surface = CreateTestSurface();
-
-    wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);
-    config.viewFormatCount = 1;
-    config.viewFormats = &config.format;
-    surface.Configure(&config);
-
-    // TODO(dawn:2320) Also test the equivalent (non-)sRGB view format
-}
-
-// A width of 0 fails
-TEST_P(SurfaceConfigurationValidationTests, ZeroWidth) {
-    wgpu::Surface surface = CreateTestSurface();
-
-    wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);
-    config.width = 0;
-    ASSERT_DEVICE_ERROR(surface.Configure(&config));
-}
-
-// A height of 0 fails
-TEST_P(SurfaceConfigurationValidationTests, ZeroHeight) {
-    wgpu::Surface surface = CreateTestSurface();
-
-    wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);
-    config.height = 0;
-    ASSERT_DEVICE_ERROR(surface.Configure(&config));
-}
-
-// A width that exceeds the maximum texture size fails
-TEST_P(SurfaceConfigurationValidationTests, ExcessiveWidth) {
-    wgpu::Surface surface = CreateTestSurface();
-    wgpu::SupportedLimits supported;
-    device.GetLimits(&supported);
-
-    wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);
-    config.width = supported.limits.maxTextureDimension1D + 1;
-    ASSERT_DEVICE_ERROR(surface.Configure(&config));
-}
-
-// A height that exceeds the maximum texture size fails
-TEST_P(SurfaceConfigurationValidationTests, ExcessiveHeight) {
-    wgpu::Surface surface = CreateTestSurface();
-    wgpu::SupportedLimits supported;
-    device.GetLimits(&supported);
-
-    wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);
-    config.height = supported.limits.maxTextureDimension2D + 1;
-    ASSERT_DEVICE_ERROR(surface.Configure(&config));
-}
-
-// A surface that was not configured must not be unconfigured
-TEST_P(SurfaceConfigurationValidationTests, UnconfigureNonConfiguredSurfaceFails) {
-    // TODO(dawn:2320): With SwiftShader, this throws a device error anyways (maybe because
-    // mInstance->ConsumedError calls the device error callback?). We should have a
-    // ASSERT_INSTANCE_ERROR to fully fix this test case.
-    DAWN_SUPPRESS_TEST_IF(IsSwiftshader());
-
-    // TODO(dawn:2320) This cannot throw a device error since the surface is
-    // not aware of the device at this stage.
-    /*ASSERT_DEVICE_ERROR(*/ CreateTestSurface().Unconfigure() /*)*/;
-}
-
-DAWN_INSTANTIATE_TEST(SurfaceConfigurationValidationTests,
-                      D3D11Backend(),
-                      D3D12Backend(),
-                      MetalBackend(),
-                      NullBackend(),
-                      VulkanBackend());
-
-}  // anonymous namespace
-}  // namespace dawn
diff --git a/src/dawn/tests/end2end/SurfaceTests.cpp b/src/dawn/tests/end2end/SurfaceTests.cpp
deleted file mode 100644
index 39682b2..0000000
--- a/src/dawn/tests/end2end/SurfaceTests.cpp
+++ /dev/null
@@ -1,437 +0,0 @@
-// 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(dawn:2320): Reconfiguring/unconfiguring fails with swift shader.
-        // NB: Fixing SurfaceTests.ReconfigureBasic should fix the other test cases as well.
-        DAWN_TEST_UNSUPPORTED_IF(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);
-        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::TextureFormat preferredFormat = surface.GetPreferredFormat(adapter);
-
-        wgpu::SurfaceConfiguration config = baseConfig;
-        config.format = preferredFormat;
-        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);
-    }
-
-    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 destroying the swapchain after GetCurrentTexture
-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();
-    }
-}
-
-// Test that configuring with TextureBinding usage without enabling SurfaceCapabilities
-// feature should fail.
-TEST_P(SurfaceTests, ErrorCreateWithTextureBindingUsage) {
-    DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("skip_validation"));
-    EXPECT_FALSE(device.HasFeature(wgpu::FeatureName::SurfaceCapabilities));
-
-    wgpu::Surface surface = CreateTestSurface();
-    wgpu::SurfaceTexture surfaceTexture;
-
-    wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);
-    config.usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment;
-
-    ASSERT_DEVICE_ERROR_MSG(
-        { surface.Configure(&config); },
-        testing::HasSubstr("require enabling FeatureName::SurfaceCapabilities"));
-}
-
-// 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_NE(surfaceTexture.status, wgpu::SurfaceGetCurrentTextureStatus::Success);
-}
-
-// Getting current texture after unconfiguring fails
-TEST_P(SurfaceTests, GetAfterUnconfigure) {
-    wgpu::Surface surface = CreateTestSurface();
-    wgpu::SurfaceConfiguration config = GetPreferredConfiguration(surface);
-    wgpu::SurfaceTexture surfaceTexture;
-
-    surface.Configure(&config);
-
-    surface.Unconfigure();
-
-    ASSERT_DEVICE_ERROR(surface.GetCurrentTexture(&surfaceTexture));
-}
-
-// 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());
-}
-
-// TODO(dawn:2320) Enable D3D tests (though they are not enabled in SwapChainTests neither)
-DAWN_INSTANTIATE_TEST(SurfaceTests,
-                      // D3D11Backend(),
-                      // D3D12Backend(),
-                      MetalBackend(),
-                      NullBackend(),
-                      VulkanBackend());
-
-}  // anonymous namespace
-}  // namespace dawn
diff --git a/src/dawn/tests/end2end/SwapChainTests.cpp b/src/dawn/tests/end2end/SwapChainTests.cpp
index 950d246..f007ae3 100644
--- a/src/dawn/tests/end2end/SwapChainTests.cpp
+++ b/src/dawn/tests/end2end/SwapChainTests.cpp
@@ -86,13 +86,6 @@
         DawnTest::TearDown();
     }
 
-    wgpu::SwapChain CreateSwapChain(wgpu::Surface const& otherSurface,
-                                    wgpu::SwapChainDescriptor const* descriptor) {
-        wgpu::SwapChain swapchain;
-        EXPECT_DEPRECATION_WARNING(swapchain = device.CreateSwapChain(otherSurface, descriptor));
-        return swapchain;
-    }
-
     void ClearTexture(wgpu::Texture texture, wgpu::Color color) {
         utils::ComboRenderPassDescriptor desc({texture.CreateView()});
         desc.cColorAttachments[0].loadOp = wgpu::LoadOp::Clear;
@@ -115,47 +108,47 @@
 
 // Basic test for creating a swapchain and presenting one frame.
 TEST_P(SwapChainTests, Basic) {
-    wgpu::SwapChain swapchain = CreateSwapChain(surface, &baseDescriptor);
+    wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &baseDescriptor);
     ClearTexture(swapchain.GetCurrentTexture(), {1.0, 0.0, 0.0, 1.0});
     swapchain.Present();
 }
 
 // Test replacing the swapchain
 TEST_P(SwapChainTests, ReplaceBasic) {
-    wgpu::SwapChain swapchain1 = CreateSwapChain(surface, &baseDescriptor);
+    wgpu::SwapChain swapchain1 = device.CreateSwapChain(surface, &baseDescriptor);
     ClearTexture(swapchain1.GetCurrentTexture(), {1.0, 0.0, 0.0, 1.0});
     swapchain1.Present();
 
-    wgpu::SwapChain swapchain2 = CreateSwapChain(surface, &baseDescriptor);
+    wgpu::SwapChain swapchain2 = device.CreateSwapChain(surface, &baseDescriptor);
     ClearTexture(swapchain2.GetCurrentTexture(), {0.0, 1.0, 0.0, 1.0});
     swapchain2.Present();
 }
 
 // Test replacing the swapchain after GetCurrentTexture
 TEST_P(SwapChainTests, ReplaceAfterGet) {
-    wgpu::SwapChain swapchain1 = CreateSwapChain(surface, &baseDescriptor);
+    wgpu::SwapChain swapchain1 = device.CreateSwapChain(surface, &baseDescriptor);
     ClearTexture(swapchain1.GetCurrentTexture(), {1.0, 0.0, 0.0, 1.0});
 
-    wgpu::SwapChain swapchain2 = CreateSwapChain(surface, &baseDescriptor);
+    wgpu::SwapChain swapchain2 = device.CreateSwapChain(surface, &baseDescriptor);
     ClearTexture(swapchain2.GetCurrentTexture(), {0.0, 1.0, 0.0, 1.0});
     swapchain2.Present();
 }
 
 // Test destroying the swapchain after GetCurrentTexture
 TEST_P(SwapChainTests, DestroyAfterGet) {
-    wgpu::SwapChain swapchain = CreateSwapChain(surface, &baseDescriptor);
+    wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &baseDescriptor);
     ClearTexture(swapchain.GetCurrentTexture(), {1.0, 0.0, 0.0, 1.0});
 }
 
 // Test destroying the surface before the swapchain
 TEST_P(SwapChainTests, DestroySurface) {
-    wgpu::SwapChain swapchain = CreateSwapChain(surface, &baseDescriptor);
+    wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &baseDescriptor);
     surface = nullptr;
 }
 
 // Test destroying the surface before the swapchain but after GetCurrentTexture
 TEST_P(SwapChainTests, DestroySurfaceAfterGet) {
-    wgpu::SwapChain swapchain = CreateSwapChain(surface, &baseDescriptor);
+    wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &baseDescriptor);
     ClearTexture(swapchain.GetCurrentTexture(), {1.0, 0.0, 0.0, 1.0});
     surface = nullptr;
 }
@@ -181,12 +174,12 @@
             wgpu::SwapChainDescriptor desc = baseDescriptor;
 
             desc.presentMode = mode1;
-            wgpu::SwapChain swapchain1 = CreateSwapChain(surface, &desc);
+            wgpu::SwapChain swapchain1 = device.CreateSwapChain(surface, &desc);
             ClearTexture(swapchain1.GetCurrentTexture(), {0.0, 0.0, 0.0, 1.0});
             swapchain1.Present();
 
             desc.presentMode = mode2;
-            wgpu::SwapChain swapchain2 = CreateSwapChain(surface, &desc);
+            wgpu::SwapChain swapchain2 = device.CreateSwapChain(surface, &desc);
             ClearTexture(swapchain2.GetCurrentTexture(), {0.0, 0.0, 0.0, 1.0});
             swapchain2.Present();
         }
@@ -200,7 +193,7 @@
         desc.width += i * 10;
         desc.height -= i * 10;
 
-        wgpu::SwapChain swapchain = CreateSwapChain(surface, &desc);
+        wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &desc);
         ClearTexture(swapchain.GetCurrentTexture(), {0.05f * i, 0.0f, 0.0f, 1.0f});
         swapchain.Present();
     }
@@ -211,7 +204,7 @@
     // TODO(crbug.com/1503912): Failing new ValidateImageAcquireWait in Vulkan Validation Layer.
     DAWN_SUPPRESS_TEST_IF(IsBackendValidationEnabled() && IsWindows() && IsVulkan() && IsIntel());
 
-    wgpu::SwapChain swapchain = CreateSwapChain(surface, &baseDescriptor);
+    wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &baseDescriptor);
 
     for (int i = 0; i < 10; i++) {
         glfwSetWindowSize(window.get(), 400 - 10 * i, 400 + 10 * i);
@@ -238,7 +231,7 @@
         desc.width = width;
         desc.height = height;
 
-        wgpu::SwapChain swapchain = CreateSwapChain(surface, &desc);
+        wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &desc);
         ClearTexture(swapchain.GetCurrentTexture(), {0.05f * i, 0.0f, 0.0f, 1.0f});
         swapchain.Present();
     }
@@ -249,13 +242,12 @@
     // TODO(https://crbug.com/dawn/2116): Disabled due to new Validation Layer failures.
     DAWN_SUPPRESS_TEST_IF(IsVulkan());
 
-    wgpu::Device device1 = CreateDevice();
     wgpu::Device device2 = CreateDevice();
 
     for (int i = 0; i < 3; i++) {
         wgpu::Device deviceToUse;
         if (i % 2 == 0) {
-            deviceToUse = device1;
+            deviceToUse = device;
         } else {
             deviceToUse = device2;
         }
@@ -290,7 +282,7 @@
     desc.usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment;
 
     ASSERT_DEVICE_ERROR_MSG(
-        { auto swapchain = CreateSwapChain(surface, &desc); },
+        { auto swapchain = device.CreateSwapChain(surface, &desc); },
         testing::HasSubstr("require enabling FeatureName::SurfaceCapabilities"));
 }
 
@@ -400,7 +392,7 @@
     auto desc = baseDescriptor;
     desc.usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment;
 
-    wgpu::SwapChain swapchain = CreateSwapChain(surface, &desc);
+    wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &desc);
     ClearTexture(swapchain.GetCurrentTexture(), {1.0, 0.0, 0.0, 1.0});
 
     SampleTexture(swapchain.GetCurrentTexture(), utils::RGBA8::kRed);
@@ -420,7 +412,7 @@
     auto desc = baseDescriptor;
     desc.usage = supportedUsage | wgpu::TextureUsage::StorageBinding;
 
-    ASSERT_DEVICE_ERROR_MSG({ auto swapchain = CreateSwapChain(surface, &desc); },
+    ASSERT_DEVICE_ERROR_MSG({ auto swapchain = device.CreateSwapChain(surface, &desc); },
                             testing::HasSubstr("is not supported"));
 }
 
@@ -437,7 +429,7 @@
     desc.width = 1;
     desc.height = 1;
 
-    wgpu::SwapChain swapchain = CreateSwapChain(surface, &desc);
+    wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &desc);
     wgpu::Texture texture = swapchain.GetCurrentTexture();
     WriteTexture(texture, utils::RGBA8::kRed);
 
@@ -458,7 +450,7 @@
     wgpu::SwapChainDescriptor desc = baseDescriptor;
     desc.usage |= wgpu::TextureUsage::CopySrc;
 
-    wgpu::SwapChain swapchain = CreateSwapChain(surface, &desc);
+    wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &desc);
     wgpu::Texture texture = swapchain.GetCurrentTexture();
 
     ClearTexture(swapchain.GetCurrentTexture(), {1.0, 0.0, 0.0, 1.0});
diff --git a/src/dawn/tests/end2end/SwapChainValidationTests.cpp b/src/dawn/tests/end2end/SwapChainValidationTests.cpp
index a902e25..a81cd26 100644
--- a/src/dawn/tests/end2end/SwapChainValidationTests.cpp
+++ b/src/dawn/tests/end2end/SwapChainValidationTests.cpp
@@ -79,13 +79,6 @@
         DawnTest::TearDown();
     }
 
-    wgpu::SwapChain CreateSwapChain(wgpu::Surface const& otherSurface,
-                                    wgpu::SwapChainDescriptor const* descriptor) {
-        wgpu::SwapChain swapchain;
-        EXPECT_DEPRECATION_WARNING(swapchain = device.CreateSwapChain(otherSurface, descriptor));
-        return swapchain;
-    }
-
   protected:
     std::unique_ptr<GLFWwindow, GLFWindowDestroyer> window = nullptr;
     wgpu::Surface surface;
@@ -143,7 +136,7 @@
 
 // Control case for a successful swapchain creation and presenting.
 TEST_P(SwapChainValidationTests, CreationSuccess) {
-    wgpu::SwapChain swapchain = CreateSwapChain(surface, &goodDescriptor);
+    wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
     swapchain.GetCurrentTexture();
     swapchain.Present();
 }
@@ -153,7 +146,7 @@
     wgpu::SurfaceDescriptor surface_desc = {};
     wgpu::Surface surface = GetInstance().CreateSurface(&surface_desc);
 
-    ASSERT_DEVICE_ERROR_MSG(CreateSwapChain(surface, &goodDescriptor),
+    ASSERT_DEVICE_ERROR_MSG(device.CreateSwapChain(surface, &goodDescriptor),
                             testing::HasSubstr("[Surface] is invalid"));
 }
 
@@ -164,33 +157,33 @@
     {
         wgpu::SwapChainDescriptor desc = goodDescriptor;
         desc.width = 0;
-        ASSERT_DEVICE_ERROR(CreateSwapChain(surface, &desc));
+        ASSERT_DEVICE_ERROR(device.CreateSwapChain(surface, &desc));
     }
     // A height of 0 is invalid.
     {
         wgpu::SwapChainDescriptor desc = goodDescriptor;
         desc.height = 0;
-        ASSERT_DEVICE_ERROR(CreateSwapChain(surface, &desc));
+        ASSERT_DEVICE_ERROR(device.CreateSwapChain(surface, &desc));
     }
 
     // A width of maxTextureDimension2D is valid but maxTextureDimension2D + 1 isn't.
     {
         wgpu::SwapChainDescriptor desc = goodDescriptor;
         desc.width = supportedLimits.maxTextureDimension2D;
-        CreateSwapChain(surface, &desc);
+        device.CreateSwapChain(surface, &desc);
 
         desc.width = supportedLimits.maxTextureDimension2D + 1;
-        ASSERT_DEVICE_ERROR(CreateSwapChain(surface, &desc));
+        ASSERT_DEVICE_ERROR(device.CreateSwapChain(surface, &desc));
     }
 
     // A height of maxTextureDimension2D is valid but maxTextureDimension2D + 1 isn't.
     {
         wgpu::SwapChainDescriptor desc = goodDescriptor;
         desc.height = supportedLimits.maxTextureDimension2D;
-        CreateSwapChain(surface, &desc);
+        device.CreateSwapChain(surface, &desc);
 
         desc.height = supportedLimits.maxTextureDimension2D + 1;
-        ASSERT_DEVICE_ERROR(CreateSwapChain(surface, &desc));
+        ASSERT_DEVICE_ERROR(device.CreateSwapChain(surface, &desc));
     }
 }
 
@@ -198,20 +191,20 @@
 TEST_P(SwapChainValidationTests, InvalidCreationUsage) {
     wgpu::SwapChainDescriptor desc = goodDescriptor;
     desc.usage = wgpu::TextureUsage::TextureBinding;
-    ASSERT_DEVICE_ERROR(CreateSwapChain(surface, &desc));
+    ASSERT_DEVICE_ERROR(device.CreateSwapChain(surface, &desc));
 }
 
 // Checks that the creation format must (currently) be BGRA8Unorm
 TEST_P(SwapChainValidationTests, InvalidCreationFormat) {
     wgpu::SwapChainDescriptor desc = goodDescriptor;
     desc.format = wgpu::TextureFormat::RGBA8Unorm;
-    ASSERT_DEVICE_ERROR(CreateSwapChain(surface, &desc));
+    ASSERT_DEVICE_ERROR(device.CreateSwapChain(surface, &desc));
 }
 
 // Check swapchain operations with an error swapchain are errors
 TEST_P(SwapChainValidationTests, OperationsOnErrorSwapChain) {
     wgpu::SwapChain swapchain;
-    ASSERT_DEVICE_ERROR(swapchain = CreateSwapChain(surface, &badDescriptor));
+    ASSERT_DEVICE_ERROR(swapchain = device.CreateSwapChain(surface, &badDescriptor));
 
     wgpu::Texture texture;
     ASSERT_DEVICE_ERROR(texture = swapchain.GetCurrentTexture());
@@ -222,7 +215,7 @@
 
 // Check it is invalid to call present without getting a current texture.
 TEST_P(SwapChainValidationTests, PresentWithoutCurrentTexture) {
-    wgpu::SwapChain swapchain = CreateSwapChain(surface, &goodDescriptor);
+    wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
 
     // Check it is invalid if we never called GetCurrentTexture
     ASSERT_DEVICE_ERROR(swapchain.Present());
@@ -237,7 +230,7 @@
 // swapchain is kept alive by the surface. Also check after we lose all refs to the surface, the
 // texture is destroyed.
 TEST_P(SwapChainValidationTests, TextureValidAfterSwapChainRefLost) {
-    wgpu::SwapChain swapchain = CreateSwapChain(surface, &goodDescriptor);
+    wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
     wgpu::Texture texture = swapchain.GetCurrentTexture();
 
     swapchain = nullptr;
@@ -249,7 +242,7 @@
 
 // Check that the current texture is the destroyed state after present.
 TEST_P(SwapChainValidationTests, TextureDestroyedAfterPresent) {
-    wgpu::SwapChain swapchain = CreateSwapChain(surface, &goodDescriptor);
+    wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
     wgpu::Texture texture = swapchain.GetCurrentTexture();
     swapchain.Present();
 
@@ -293,7 +286,7 @@
     wgpu::Texture secondTexture = device.CreateTexture(&textureDesc);
 
     // Get the swapchain view and try to use it in the render pass to trigger all the validation.
-    wgpu::SwapChain swapchain = CreateSwapChain(surface, &goodDescriptor);
+    wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
     wgpu::TextureView view = swapchain.GetCurrentTexture().CreateView();
 
     // Validation will also check the dimension of the view is 2D, and it's usage contains
@@ -322,7 +315,7 @@
 TEST_P(SwapChainValidationTests, ReflectionValidGetCurrentTexture) {
     // Check with the goodDescriptor.
     {
-        wgpu::SwapChain swapChain = CreateSwapChain(surface, &goodDescriptor);
+        wgpu::SwapChain swapChain = device.CreateSwapChain(surface, &goodDescriptor);
         CheckTextureMatchesDescriptor(swapChain.GetCurrentTexture(), goodDescriptor);
     }
     // Check with properties that can be changed while keeping a valid descriptor.
@@ -330,7 +323,7 @@
         wgpu::SwapChainDescriptor otherDescriptor = goodDescriptor;
         otherDescriptor.width = 2;
         otherDescriptor.height = 7;
-        wgpu::SwapChain swapChain = CreateSwapChain(surface, &goodDescriptor);
+        wgpu::SwapChain swapChain = device.CreateSwapChain(surface, &goodDescriptor);
         CheckTextureMatchesDescriptor(swapChain.GetCurrentTexture(), goodDescriptor);
     }
 }
@@ -338,7 +331,7 @@
 // Check the reflection of textures returned by GetCurrentTexture on valid swapchain.
 TEST_P(SwapChainValidationTests, ReflectionErrorGetCurrentTexture) {
     wgpu::SwapChain swapChain;
-    ASSERT_DEVICE_ERROR(swapChain = CreateSwapChain(surface, &badDescriptor));
+    ASSERT_DEVICE_ERROR(swapChain = device.CreateSwapChain(surface, &badDescriptor));
     wgpu::Texture texture;
     ASSERT_DEVICE_ERROR(texture = swapChain.GetCurrentTexture());
     CheckTextureMatchesDescriptor(texture, badDescriptor);
@@ -346,8 +339,8 @@
 
 // Check that failing to create a new swapchain doesn't replace the previous one.
 TEST_P(SwapChainValidationTests, ErrorSwapChainDoesntReplacePreviousOne) {
-    wgpu::SwapChain swapchain = CreateSwapChain(surface, &goodDescriptor);
-    ASSERT_DEVICE_ERROR(CreateSwapChain(surface, &badDescriptor));
+    wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
+    ASSERT_DEVICE_ERROR(device.CreateSwapChain(surface, &badDescriptor));
 
     swapchain.GetCurrentTexture();
     swapchain.Present();
@@ -356,15 +349,15 @@
 // Check that after replacement, all swapchain operations are errors and the texture is destroyed.
 TEST_P(SwapChainValidationTests, ReplacedSwapChainIsInvalid) {
     {
-        wgpu::SwapChain replacedSwapChain = CreateSwapChain(surface, &goodDescriptor);
-        CreateSwapChain(surface, &goodDescriptor);
+        wgpu::SwapChain replacedSwapChain = device.CreateSwapChain(surface, &goodDescriptor);
+        device.CreateSwapChain(surface, &goodDescriptor);
         ASSERT_DEVICE_ERROR(replacedSwapChain.GetCurrentTexture());
     }
 
     {
-        wgpu::SwapChain replacedSwapChain = CreateSwapChain(surface, &goodDescriptor);
+        wgpu::SwapChain replacedSwapChain = device.CreateSwapChain(surface, &goodDescriptor);
         wgpu::Texture texture = replacedSwapChain.GetCurrentTexture();
-        CreateSwapChain(surface, &goodDescriptor);
+        device.CreateSwapChain(surface, &goodDescriptor);
 
         CheckTextureIsDestroyed(texture);
         ASSERT_DEVICE_ERROR(replacedSwapChain.Present());
@@ -374,12 +367,12 @@
 // Check that after surface destruction, all swapchain operations are errors and the texture is
 // destroyed. The test is split in two to reset the wgpu::Surface in the middle.
 TEST_P(SwapChainValidationTests, SwapChainIsInvalidAfterSurfaceDestruction_GetTexture) {
-    wgpu::SwapChain replacedSwapChain = CreateSwapChain(surface, &goodDescriptor);
+    wgpu::SwapChain replacedSwapChain = device.CreateSwapChain(surface, &goodDescriptor);
     surface = nullptr;
     ASSERT_DEVICE_ERROR(replacedSwapChain.GetCurrentTexture());
 }
 TEST_P(SwapChainValidationTests, SwapChainIsInvalidAfterSurfaceDestruction_AfterGetTexture) {
-    wgpu::SwapChain replacedSwapChain = CreateSwapChain(surface, &goodDescriptor);
+    wgpu::SwapChain replacedSwapChain = device.CreateSwapChain(surface, &goodDescriptor);
     wgpu::Texture texture = replacedSwapChain.GetCurrentTexture();
     surface = nullptr;
 
@@ -389,7 +382,7 @@
 
 // Test that new swap chain present after device is lost
 TEST_P(SwapChainValidationTests, SwapChainPresentAfterDeviceLost) {
-    wgpu::SwapChain swapchain = CreateSwapChain(surface, &goodDescriptor);
+    wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
     swapchain.GetCurrentTexture();
 
     LoseDeviceForTesting();
@@ -398,7 +391,7 @@
 
 // Test that new swap chain get current texture fails after device is lost
 TEST_P(SwapChainValidationTests, SwapChainGetCurrentTextureFailsAfterDevLost) {
-    wgpu::SwapChain swapchain = CreateSwapChain(surface, &goodDescriptor);
+    wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
 
     LoseDeviceForTesting();
     EXPECT_TRUE(dawn::native::CheckIsErrorForTesting(swapchain.GetCurrentTexture().Get()));
@@ -407,8 +400,8 @@
 // Test that creation of a new swapchain fails after device is lost
 TEST_P(SwapChainValidationTests, CreateSwapChainFailsAfterDevLost) {
     LoseDeviceForTesting();
-    EXPECT_TRUE(
-        dawn::native::CheckIsErrorForTesting(CreateSwapChain(surface, &goodDescriptor).Get()));
+    EXPECT_TRUE(dawn::native::CheckIsErrorForTesting(
+        device.CreateSwapChain(surface, &goodDescriptor).Get()));
 }
 
 DAWN_INSTANTIATE_TEST(SwapChainValidationTests, MetalBackend(), NullBackend());
diff --git a/src/dawn/tests/unittests/native/mocks/DeviceMock.h b/src/dawn/tests/unittests/native/mocks/DeviceMock.h
index cc1027a..d49e9a8 100644
--- a/src/dawn/tests/unittests/native/mocks/DeviceMock.h
+++ b/src/dawn/tests/unittests/native/mocks/DeviceMock.h
@@ -121,7 +121,7 @@
                 (override));
     MOCK_METHOD(ResultOrError<Ref<SwapChainBase>>,
                 CreateSwapChainImpl,
-                (Surface*, SwapChainBase*, const SurfaceConfiguration*),
+                (Surface*, SwapChainBase*, const SwapChainDescriptor*),
                 (override));
     MOCK_METHOD(ResultOrError<Ref<TextureBase>>,
                 CreateTextureImpl,
diff --git a/src/dawn/tests/unittests/native/mocks/SwapChainMock.cpp b/src/dawn/tests/unittests/native/mocks/SwapChainMock.cpp
index 6a459cc..d0c9bcc 100644
--- a/src/dawn/tests/unittests/native/mocks/SwapChainMock.cpp
+++ b/src/dawn/tests/unittests/native/mocks/SwapChainMock.cpp
@@ -31,8 +31,8 @@
 
 SwapChainMock::SwapChainMock(DeviceBase* device,
                              Surface* surface,
-                             const SurfaceConfiguration* config)
-    : SwapChainBase(device, surface, config) {
+                             const SwapChainDescriptor* descriptor)
+    : SwapChainBase(device, surface, descriptor) {
     ON_CALL(*this, DestroyImpl).WillByDefault([this] { this->SwapChainBase::DestroyImpl(); });
 }
 
diff --git a/src/dawn/tests/unittests/native/mocks/SwapChainMock.h b/src/dawn/tests/unittests/native/mocks/SwapChainMock.h
index 4a0ed0c..d1068bd 100644
--- a/src/dawn/tests/unittests/native/mocks/SwapChainMock.h
+++ b/src/dawn/tests/unittests/native/mocks/SwapChainMock.h
@@ -37,12 +37,12 @@
 
 class SwapChainMock : public SwapChainBase {
   public:
-    SwapChainMock(DeviceBase* device, Surface* surface, const SurfaceConfiguration* config);
+    SwapChainMock(DeviceBase* device, Surface* surface, const SwapChainDescriptor* descriptor);
     ~SwapChainMock() override;
 
     MOCK_METHOD(void, DestroyImpl, (), (override));
 
-    MOCK_METHOD(ResultOrError<SwapChainTextureInfo>, GetCurrentTextureImpl, (), (override));
+    MOCK_METHOD(ResultOrError<Ref<TextureBase>>, GetCurrentTextureImpl, (), (override));
     MOCK_METHOD(MaybeError, PresentImpl, (), (override));
     MOCK_METHOD(void, DetachFromSurfaceImpl, (), (override));
 };
diff --git a/src/dawn/utils/CMakeLists.txt b/src/dawn/utils/CMakeLists.txt
index 897a3f0..0b54134 100644
--- a/src/dawn/utils/CMakeLists.txt
+++ b/src/dawn/utils/CMakeLists.txt
@@ -60,9 +60,6 @@
             SPIRV-Tools-opt
 )
 
-# Needed by WGPUHelpers
-target_compile_definitions(dawn_utils PUBLIC -DTINT_BUILD_SPV_READER=$<BOOL:${TINT_BUILD_SPV_READER}>)
-
 if(WIN32 AND NOT WINDOWS_STORE)
     target_sources(dawn_utils PRIVATE "WindowsDebugLogger.cpp")
 else()
diff --git a/src/dawn/wire/client/Surface.cpp b/src/dawn/wire/client/Surface.cpp
index c24f69d..f54aaca 100644
--- a/src/dawn/wire/client/Surface.cpp
+++ b/src/dawn/wire/client/Surface.cpp
@@ -27,11 +27,7 @@
 
 #include "dawn/wire/client/Surface.h"
 
-#include "dawn/common/Log.h"
 #include "dawn/common/Platform.h"
-#include "dawn/wire/client/Client.h"
-#include "dawn/wire/client/Device.h"
-#include "dawn/wire/client/Texture.h"
 
 namespace dawn::wire::client {
 
@@ -43,50 +39,9 @@
     return ObjectType::Surface;
 }
 
-void Surface::Configure(WGPUSurfaceConfiguration const* config) {
-    mTextureDescriptor = {};
-    mTextureDescriptor.size = {config->width, config->height, 1};
-    mTextureDescriptor.format = config->format;
-    mTextureDescriptor.usage = config->usage;
-    mTextureDescriptor.dimension = WGPUTextureDimension_2D;
-    mTextureDescriptor.mipLevelCount = 1;
-    mTextureDescriptor.sampleCount = 1;
-
-    SurfaceConfigureCmd cmd;
-    cmd.self = ToAPI(this);
-    cmd.config = config;
-    GetClient()->SerializeCommand(cmd);
-}
-
 WGPUTextureFormat Surface::GetPreferredFormat([[maybe_unused]] WGPUAdapter adapter) const {
-    // TODO(dawn:2320) Use the result of GetCapabilities
     // This is the only supported format in native mode (see crbug.com/dawn/160).
     return WGPUTextureFormat_BGRA8Unorm;
 }
 
-void Surface::GetCapabilities(WGPUAdapter adapter, WGPUSurfaceCapabilities* capabilities) const {
-    // TODO(dawn:2320) Implement this
-    dawn::ErrorLog() << "surface.GetCapabilities not supported yet with dawn_wire.";
-}
-
-void Surface::GetCurrentTexture(WGPUSurfaceTexture* surfaceTexture) {
-    // TODO(dawn:2320) Implement this
-    dawn::ErrorLog() << "surface.GetCurrentTexture not supported yet with dawn_wire.";
-
-    Client* wireClient = GetClient();
-    Texture* texture = wireClient->Make<Texture>(&mTextureDescriptor);
-    surfaceTexture->texture = ToAPI(texture);
-
-    SurfaceGetCurrentTextureCmd cmd;
-    cmd.self = ToAPI(this);
-    cmd.selfId = GetWireId();
-    // cmd.result = texture->GetWireHandle(); // TODO(dawn:2320) Feed surfaceTexture to cmd
-    wireClient->SerializeCommand(cmd);
-}
-
-void ClientSurfaceCapabilitiesFreeMembers(WGPUSurfaceCapabilities capabilities) {
-    // TODO(dawn:2320) Implement this
-    dawn::ErrorLog() << "surfaceCapabilities.FreeMembers not supported yet with dawn_wire.";
-}
-
 }  // namespace dawn::wire::client
diff --git a/src/dawn/wire/client/Surface.h b/src/dawn/wire/client/Surface.h
index cb776ea..08aae69 100644
--- a/src/dawn/wire/client/Surface.h
+++ b/src/dawn/wire/client/Surface.h
@@ -43,20 +43,9 @@
 
     ObjectType GetObjectType() const override;
 
-    void Configure(WGPUSurfaceConfiguration const* config);
-
     WGPUTextureFormat GetPreferredFormat(WGPUAdapter adapter) const;
-
-    void GetCapabilities(WGPUAdapter adapter, WGPUSurfaceCapabilities* capabilities) const;
-
-    void GetCurrentTexture(WGPUSurfaceTexture* surfaceTexture);
-
-  private:
-    WGPUTextureDescriptor mTextureDescriptor;
 };
 
-void ClientSurfaceCapabilitiesFreeMembers(WGPUSurfaceCapabilities capabilities);
-
 }  // namespace dawn::wire::client
 
 #endif  // SRC_DAWN_WIRE_CLIENT_SURFACE_H_