d3d11: implement Adaptor, Backend, etc

This CL also moves some comman code in d3d12::Adapter and
d3d11::Backend to d3d::Adapter and d3d::Backend, so it can be
shared with d3d11 backend.

Bug: dawn:1705
Change-Id: Ica3bf33232d3380b7d4799c77bf9b43a8374a66e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/126220
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Peng Huang <penghuang@chromium.org>
diff --git a/include/dawn/native/D3D11Backend.h b/include/dawn/native/D3D11Backend.h
new file mode 100644
index 0000000..c2a03d9
--- /dev/null
+++ b/include/dawn/native/D3D11Backend.h
@@ -0,0 +1,35 @@
+// Copyright 2023 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef INCLUDE_DAWN_NATIVE_D3D11BACKEND_H_
+#define INCLUDE_DAWN_NATIVE_D3D11BACKEND_H_
+
+#include <dxgi1_4.h>
+#include <windows.h>
+#include <wrl/client.h>
+
+#include <memory>
+
+#include "dawn/native/D3DBackend.h"
+
+namespace dawn::native::d3d11 {
+
+struct DAWN_NATIVE_EXPORT AdapterDiscoveryOptions : public d3d::AdapterDiscoveryOptions {
+    AdapterDiscoveryOptions();
+    explicit AdapterDiscoveryOptions(Microsoft::WRL::ComPtr<IDXGIAdapter> adapter);
+};
+
+}  // namespace dawn::native::d3d11
+
+#endif  // INCLUDE_DAWN_NATIVE_D3D11BACKEND_H_
diff --git a/include/dawn/native/D3D12Backend.h b/include/dawn/native/D3D12Backend.h
index 15a7e6f..131afa7 100644
--- a/include/dawn/native/D3D12Backend.h
+++ b/include/dawn/native/D3D12Backend.h
@@ -24,7 +24,7 @@
 #include <vector>
 
 #include "dawn/dawn_wsi.h"
-#include "dawn/native/DawnNative.h"
+#include "dawn/native/D3DBackend.h"
 
 struct ID3D12Device;
 struct ID3D12Resource;
@@ -126,11 +126,9 @@
     std::unique_ptr<ExternalImageDXGIImpl> mImpl;
 };
 
-struct DAWN_NATIVE_EXPORT AdapterDiscoveryOptions : public AdapterDiscoveryOptionsBase {
+struct DAWN_NATIVE_EXPORT AdapterDiscoveryOptions : public d3d::AdapterDiscoveryOptions {
     AdapterDiscoveryOptions();
     explicit AdapterDiscoveryOptions(Microsoft::WRL::ComPtr<IDXGIAdapter> adapter);
-
-    Microsoft::WRL::ComPtr<IDXGIAdapter> dxgiAdapter;
 };
 
 }  // namespace dawn::native::d3d12
diff --git a/include/dawn/native/D3DBackend.h b/include/dawn/native/D3DBackend.h
new file mode 100644
index 0000000..e8ced2d
--- /dev/null
+++ b/include/dawn/native/D3DBackend.h
@@ -0,0 +1,33 @@
+// Copyright 2023 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef INCLUDE_DAWN_NATIVE_D3DBACKEND_H_
+#define INCLUDE_DAWN_NATIVE_D3DBACKEND_H_
+
+#include <dxgi1_4.h>
+#include <windows.h>
+#include <wrl/client.h>
+
+#include "dawn/native/DawnNative.h"
+
+namespace dawn::native::d3d {
+
+struct DAWN_NATIVE_EXPORT AdapterDiscoveryOptions : public AdapterDiscoveryOptionsBase {
+    AdapterDiscoveryOptions(WGPUBackendType type, Microsoft::WRL::ComPtr<IDXGIAdapter> adapter);
+    Microsoft::WRL::ComPtr<IDXGIAdapter> dxgiAdapter;
+};
+
+}  // namespace dawn::native::d3d
+
+#endif  // INCLUDE_DAWN_NATIVE_D3DBACKEND_H_
diff --git a/scripts/dawn_features.gni b/scripts/dawn_features.gni
index b72e39e..baaf2c5 100644
--- a/scripts/dawn_features.gni
+++ b/scripts/dawn_features.gni
@@ -54,6 +54,9 @@
   # standalone to produce static libraries to use in their projects.
   dawn_complete_static_libs = false
 
+  # Enables the compilation of Dawn's D3D11 backend
+  dawn_enable_d3d11 = false
+
   # Enables the compilation of Dawn's D3D12 backend
   dawn_enable_d3d12 = is_win
 
diff --git a/src/dawn/common/BUILD.gn b/src/dawn/common/BUILD.gn
index ebc61e4..533ec13 100644
--- a/src/dawn/common/BUILD.gn
+++ b/src/dawn/common/BUILD.gn
@@ -58,6 +58,9 @@
     ]
   }
 
+  if (dawn_enable_d3d11) {
+    defines += [ "DAWN_ENABLE_BACKEND_D3D11" ]
+  }
   if (dawn_enable_d3d12) {
     defines += [ "DAWN_ENABLE_BACKEND_D3D12" ]
   }
diff --git a/src/dawn/native/BUILD.gn b/src/dawn/native/BUILD.gn
index 1e6bceb..e3cf1e0 100644
--- a/src/dawn/native/BUILD.gn
+++ b/src/dawn/native/BUILD.gn
@@ -134,7 +134,9 @@
 
     # Include all backend's public headers so that dependencies can include
     # them even when the backends are disabled.
+    "${dawn_root}/include/dawn/native/D3D11Backend.h",
     "${dawn_root}/include/dawn/native/D3D12Backend.h",
+    "${dawn_root}/include/dawn/native/D3DBackend.h",
     "${dawn_root}/include/dawn/native/MetalBackend.h",
     "${dawn_root}/include/dawn/native/NullBackend.h",
     "${dawn_root}/include/dawn/native/OpenGLBackend.h",
@@ -393,7 +395,7 @@
   # Somehow use dxcompiler.lib makes CoreApp unable to activate
   # WinPIX should be added as third party tools and linked statically
 
-  if (dawn_enable_d3d12) {
+  if (dawn_enable_d3d11 || dawn_enable_d3d12) {
     sources += [
       "d3d/AdapterD3D.cpp",
       "d3d/AdapterD3D.h",
@@ -401,6 +403,7 @@
       "d3d/BackendD3D.h",
       "d3d/BlobD3D.cpp",
       "d3d/BlobD3D.h",
+      "d3d/D3DBackend.cpp",
       "d3d/D3DCompilationRequest.h",
       "d3d/D3DError.cpp",
       "d3d/D3DError.h",
@@ -417,6 +420,21 @@
     ]
   }
 
+  if (dawn_enable_d3d11) {
+    libs += [ "dxguid.lib" ]
+    sources += [
+      "d3d11/AdapterD3D11.cpp",
+      "d3d11/AdapterD3D11.h",
+      "d3d11/BackendD3D11.cpp",
+      "d3d11/BackendD3D11.h",
+      "d3d11/D3D11Backend.cpp",
+      "d3d11/DeviceInfoD3D11.cpp",
+      "d3d11/DeviceInfoD3D11.h",
+      "d3d11/PlatformFunctionsD3D11.cpp",
+      "d3d11/PlatformFunctionsD3D11.h",
+    ]
+  }
+
   if (dawn_enable_d3d12) {
     libs += [ "dxguid.lib" ]
     sources += [
diff --git a/src/dawn/native/CMakeLists.txt b/src/dawn/native/CMakeLists.txt
index 9b8fc63..7c479a0 100644
--- a/src/dawn/native/CMakeLists.txt
+++ b/src/dawn/native/CMakeLists.txt
@@ -251,14 +251,16 @@
     target_link_libraries(dawn_native PRIVATE debug dxgi.lib)
 endif()
 
-if (DAWN_ENABLE_D3D12)
+if (DAWN_ENABLE_D3D11 OR DAWN_ENABLE_D3D12)
     target_sources(dawn_native PRIVATE
+        "${DAWN_INCLUDE_DIR}/dawn/native/D3DBackend.h"
         "d3d/AdapterD3D.cpp"
         "d3d/AdapterD3D.h"
         "d3d/BackendD3D.cpp"
         "d3d/BackendD3D.h"
         "d3d/BlobD3D.cpp"
         "d3d/BlobD3D.h"
+        "d3d/D3DBackend.cpp"
         "d3d/D3DCompilationRequest.h"
         "d3d/D3DError.cpp"
         "d3d/D3DError.h"
@@ -275,6 +277,22 @@
     )
 endif()
 
+if (DAWN_ENABLE_D3D11)
+    target_sources(dawn_native PRIVATE
+        "${DAWN_INCLUDE_DIR}/dawn/native/D3D11Backend.h"
+        "d3d11/AdapterD3D11.cpp"
+        "d3d11/AdapterD3D11.h"
+        "d3d11/BackendD3D11.cpp"
+        "d3d11/BackendD3D11.h"
+        "d3d11/D3D11Backend.cpp"
+        "d3d11/DeviceInfoD3D11.cpp"
+        "d3d11/DeviceInfoD3D11.h"
+        "d3d11/PlatformFunctionsD3D11.cpp"
+        "d3d11/PlatformFunctionsD3D11.h"
+
+    )
+endif()
+
 if (DAWN_ENABLE_D3D12)
     target_sources(dawn_native PRIVATE
         "${DAWN_INCLUDE_DIR}/dawn/native/D3D12Backend.h"
diff --git a/src/dawn/native/Instance.cpp b/src/dawn/native/Instance.cpp
index 6b82486..0db04bc 100644
--- a/src/dawn/native/Instance.cpp
+++ b/src/dawn/native/Instance.cpp
@@ -44,6 +44,11 @@
 
 // Forward definitions of each backend's "Connect" function that creates new BackendConnection.
 // Conditionally compiled declarations are used to avoid using static constructors instead.
+#if defined(DAWN_ENABLE_BACKEND_D3D11)
+namespace d3d11 {
+BackendConnection* Connect(InstanceBase* instance);
+}
+#endif  // defined(DAWN_ENABLE_BACKEND_D3D11)
 #if defined(DAWN_ENABLE_BACKEND_D3D12)
 namespace d3d12 {
 BackendConnection* Connect(InstanceBase* instance);
@@ -77,6 +82,9 @@
 #if defined(DAWN_ENABLE_BACKEND_NULL)
     enabledBackends.set(wgpu::BackendType::Null);
 #endif  // defined(DAWN_ENABLE_BACKEND_NULL)
+#if defined(DAWN_ENABLE_BACKEND_D3D11)
+    enabledBackends.set(wgpu::BackendType::D3D11);
+#endif  // defined(DAWN_ENABLE_BACKEND_D3D11)
 #if defined(DAWN_ENABLE_BACKEND_D3D12)
     enabledBackends.set(wgpu::BackendType::D3D12);
 #endif  // defined(DAWN_ENABLE_BACKEND_D3D12)
@@ -372,6 +380,12 @@
             break;
 #endif  // defined(DAWN_ENABLE_BACKEND_NULL)
 
+#if defined(DAWN_ENABLE_BACKEND_D3D11)
+        case wgpu::BackendType::D3D11:
+            Register(d3d11::Connect(this), wgpu::BackendType::D3D11);
+            break;
+#endif  // defined(DAWN_ENABLE_BACKEND_D3D11)
+
 #if defined(DAWN_ENABLE_BACKEND_D3D12)
         case wgpu::BackendType::D3D12:
             Register(d3d12::Connect(this), wgpu::BackendType::D3D12);
diff --git a/src/dawn/native/d3d/AdapterD3D.cpp b/src/dawn/native/d3d/AdapterD3D.cpp
index 5e3fb92..b2e3746 100644
--- a/src/dawn/native/d3d/AdapterD3D.cpp
+++ b/src/dawn/native/d3d/AdapterD3D.cpp
@@ -14,8 +14,10 @@
 
 #include "dawn/native/d3d/AdapterD3D.h"
 
+#include <string>
 #include <utility>
 
+#include "dawn/common/WindowsUtils.h"
 #include "dawn/native/d3d/BackendD3D.h"
 
 namespace dawn::native::d3d {
@@ -38,4 +40,35 @@
     return mBackend;
 }
 
+MaybeError Adapter::InitializeImpl() {
+    DXGI_ADAPTER_DESC1 adapterDesc;
+    GetHardwareAdapter()->GetDesc1(&adapterDesc);
+
+    mDeviceId = adapterDesc.DeviceId;
+    mVendorId = adapterDesc.VendorId;
+    mName = WCharToUTF8(adapterDesc.Description);
+
+    if (adapterDesc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
+        mAdapterType = wgpu::AdapterType::CPU;
+    } else {
+        // Assume it is a discrete GPU. If it is an integrated GPU, it will be overwritten later.
+        mAdapterType = wgpu::AdapterType::DiscreteGPU;
+    }
+
+    // Convert the adapter's D3D11 driver version to a readable string like "24.21.13.9793".
+    LARGE_INTEGER umdVersion;
+    if (GetHardwareAdapter()->CheckInterfaceSupport(__uuidof(IDXGIDevice), &umdVersion) !=
+        DXGI_ERROR_UNSUPPORTED) {
+        uint64_t encodedVersion = umdVersion.QuadPart;
+        uint16_t mask = 0xFFFF;
+        mDriverVersion = {static_cast<uint16_t>((encodedVersion >> 48) & mask),
+                          static_cast<uint16_t>((encodedVersion >> 32) & mask),
+                          static_cast<uint16_t>((encodedVersion >> 16) & mask),
+                          static_cast<uint16_t>(encodedVersion & mask)};
+        mDriverDescription = std::string("D3D11 driver version ") + mDriverVersion.ToString();
+    }
+
+    return {};
+}
+
 }  // namespace dawn::native::d3d
diff --git a/src/dawn/native/d3d/AdapterD3D.h b/src/dawn/native/d3d/AdapterD3D.h
index 26c9045..da5ceee 100644
--- a/src/dawn/native/d3d/AdapterD3D.h
+++ b/src/dawn/native/d3d/AdapterD3D.h
@@ -34,6 +34,9 @@
     IDXGIAdapter3* GetHardwareAdapter() const;
     Backend* GetBackend() const;
 
+  protected:
+    MaybeError InitializeImpl() override;
+
   private:
     ComPtr<IDXGIAdapter3> mHardwareAdapter;
     Backend* mBackend;
diff --git a/src/dawn/native/d3d/BackendD3D.cpp b/src/dawn/native/d3d/BackendD3D.cpp
index 07dc4f1..2fd5b7b 100644
--- a/src/dawn/native/d3d/BackendD3D.cpp
+++ b/src/dawn/native/d3d/BackendD3D.cpp
@@ -17,6 +17,7 @@
 #include <utility>
 
 #include "dawn/common/Log.h"
+#include "dawn/native/D3DBackend.h"
 #include "dawn/native/Instance.h"
 #include "dawn/native/d3d/D3DError.h"
 #include "dawn/native/d3d/PlatformFunctions.h"
@@ -237,4 +238,50 @@
     return mFunctions.get();
 }
 
+std::vector<Ref<AdapterBase>> Backend::DiscoverDefaultAdapters(const TogglesState& adapterToggles) {
+    AdapterDiscoveryOptions options(ToAPI(GetType()), nullptr);
+    std::vector<Ref<AdapterBase>> adapters;
+    if (GetInstance()->ConsumedError(DiscoverAdapters(&options, adapterToggles), &adapters)) {
+        return {};
+    }
+    return adapters;
+}
+
+ResultOrError<std::vector<Ref<AdapterBase>>> Backend::DiscoverAdapters(
+    const AdapterDiscoveryOptionsBase* optionsBase,
+    const TogglesState& adapterToggles) {
+    ASSERT(optionsBase->backendType == ToAPI(GetType()));
+    const AdapterDiscoveryOptions* options =
+        static_cast<const AdapterDiscoveryOptions*>(optionsBase);
+
+    std::vector<Ref<AdapterBase>> adapters;
+    if (options->dxgiAdapter != nullptr) {
+        // |dxgiAdapter| was provided. Discover just that adapter.
+        Ref<AdapterBase> adapter;
+        DAWN_TRY_ASSIGN(adapter,
+                        CreateAdapterFromIDXGIAdapter(options->dxgiAdapter, adapterToggles));
+        adapters.push_back(std::move(adapter));
+        return std::move(adapters);
+    }
+
+    // Enumerate and discover all available adapters.
+    for (uint32_t adapterIndex = 0;; ++adapterIndex) {
+        ComPtr<IDXGIAdapter1> dxgiAdapter = nullptr;
+        if (GetFactory()->EnumAdapters1(adapterIndex, &dxgiAdapter) == DXGI_ERROR_NOT_FOUND) {
+            break;  // No more adapters to enumerate.
+        }
+
+        ASSERT(dxgiAdapter != nullptr);
+        Ref<AdapterBase> adapter;
+        if (GetInstance()->ConsumedError(CreateAdapterFromIDXGIAdapter(dxgiAdapter, adapterToggles),
+                                         &adapter)) {
+            continue;
+        }
+
+        adapters.push_back(std::move(adapter));
+    }
+
+    return adapters;
+}
+
 }  // namespace dawn::native::d3d
diff --git a/src/dawn/native/d3d/BackendD3D.h b/src/dawn/native/d3d/BackendD3D.h
index fb179db..efb53bc 100644
--- a/src/dawn/native/d3d/BackendD3D.h
+++ b/src/dawn/native/d3d/BackendD3D.h
@@ -18,6 +18,7 @@
 #include <memory>
 #include <string>
 #include <variant>
+#include <vector>
 
 #include "dawn/native/BackendConnection.h"
 
@@ -74,6 +75,17 @@
 
     const PlatformFunctions* GetFunctions() const;
 
+    std::vector<Ref<AdapterBase>> DiscoverDefaultAdapters(
+        const TogglesState& adapterToggles) override;
+    ResultOrError<std::vector<Ref<AdapterBase>>> DiscoverAdapters(
+        const AdapterDiscoveryOptionsBase* optionsBase,
+        const TogglesState& adapterToggles) override;
+
+  protected:
+    virtual ResultOrError<Ref<AdapterBase>> CreateAdapterFromIDXGIAdapter(
+        ComPtr<IDXGIAdapter> dxgiAdapter,
+        const TogglesState& adapterToggles) = 0;
+
   private:
     // Acquiring DXC version information and store the result in mDxcVersionInfo. This function
     // should be called only once, during startup in `Initialize`.
diff --git a/src/dawn/native/d3d/D3DBackend.cpp b/src/dawn/native/d3d/D3DBackend.cpp
new file mode 100644
index 0000000..5ad4300
--- /dev/null
+++ b/src/dawn/native/d3d/D3DBackend.cpp
@@ -0,0 +1,28 @@
+// Copyright 2023 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// D3D12Backend.cpp: contains the definition of symbols exported by D3D12Backend.h so that they
+// can be compiled twice: once export (shared library), once not exported (static library)
+
+#include "dawn/native/D3DBackend.h"
+
+#include <utility>
+
+namespace dawn::native::d3d {
+
+AdapterDiscoveryOptions::AdapterDiscoveryOptions(WGPUBackendType type,
+                                                 Microsoft::WRL::ComPtr<IDXGIAdapter> adapter)
+    : AdapterDiscoveryOptionsBase(type), dxgiAdapter(std::move(adapter)) {}
+
+}  // namespace dawn::native::d3d
diff --git a/src/dawn/native/d3d/d3d_platform.h b/src/dawn/native/d3d/d3d_platform.h
index ac7b9d3..a9a4a5a 100644
--- a/src/dawn/native/d3d/d3d_platform.h
+++ b/src/dawn/native/d3d/d3d_platform.h
@@ -21,7 +21,7 @@
 // NOLINTNEXTLINE(build/include_order)
 #include "dawn/common/windows_with_undefs.h"
 
-#include <d3d11_2.h>  // NOLINT(build/include_order)
+#include <d3d11_4.h>  // NOLINT(build/include_order)
 #include <dxcapi.h>   // NOLINT(build/include_order)
 #include <dxgi1_4.h>  // NOLINT(build/include_order)
 #include <wrl.h>      // NOLINT(build/include_order)
diff --git a/src/dawn/native/d3d11/AdapterD3D11.cpp b/src/dawn/native/d3d11/AdapterD3D11.cpp
new file mode 100644
index 0000000..9906936
--- /dev/null
+++ b/src/dawn/native/d3d11/AdapterD3D11.cpp
@@ -0,0 +1,169 @@
+// Copyright 2023 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dawn/native/d3d11/AdapterD3D11.h"
+
+#include <string>
+#include <utility>
+
+#include "dawn/common/Constants.h"
+#include "dawn/native/Instance.h"
+#include "dawn/native/d3d/D3DError.h"
+#include "dawn/native/d3d11/BackendD3D11.h"
+#include "dawn/native/d3d11/PlatformFunctionsD3D11.h"
+
+namespace dawn::native::d3d11 {
+
+Adapter::Adapter(Backend* backend,
+                 ComPtr<IDXGIAdapter3> hardwareAdapter,
+                 const TogglesState& adapterToggles)
+    : Base(backend, std::move(hardwareAdapter), wgpu::BackendType::D3D11, adapterToggles) {}
+
+Adapter::~Adapter() = default;
+
+bool Adapter::SupportsExternalImages() const {
+    // TODO(dawn:1724): Implement external images on D3D11.
+    return false;
+}
+
+const DeviceInfo& Adapter::GetDeviceInfo() const {
+    return mDeviceInfo;
+}
+
+ComPtr<ID3D11Device> Adapter::GetD3D11Device() const {
+    return mD3d11Device;
+}
+
+MaybeError Adapter::InitializeImpl() {
+    DAWN_TRY(Base::InitializeImpl());
+    // D3D11 cannot check for feature support without a device.
+    // Create the device to populate the adapter properties then reuse it when needed for actual
+    // rendering.
+    const PlatformFunctions* functions = static_cast<Backend*>(GetBackend())->GetFunctions();
+    const D3D_FEATURE_LEVEL featureLevels[] = {D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0};
+
+    UINT flags = 0;
+    if (GetInstance()->IsBackendValidationEnabled()) {
+        flags |= D3D11_CREATE_DEVICE_DEBUG;
+    }
+
+    DAWN_TRY(CheckHRESULT(functions->d3d11CreateDevice(
+                              GetHardwareAdapter(), D3D_DRIVER_TYPE_UNKNOWN, /*Software=*/nullptr,
+                              flags, featureLevels, std::size(featureLevels), D3D11_SDK_VERSION,
+                              &mD3d11Device, &mFeatureLevel, /*[out] ppImmediateContext=*/nullptr),
+                          "D3D11CreateDevice failed"));
+
+    DAWN_TRY_ASSIGN(mDeviceInfo, GatherDeviceInfo(*this));
+
+    // Base::InitializeImpl() cannot distinguish between discrete and integrated GPUs, so we need to
+    // overwrite it.
+    if (mAdapterType == wgpu::AdapterType::DiscreteGPU && mDeviceInfo.isUMA) {
+        mAdapterType = wgpu::AdapterType::IntegratedGPU;
+    }
+
+    return {};
+}
+
+void Adapter::InitializeSupportedFeaturesImpl() {
+    EnableFeature(Feature::TextureCompressionBC);
+}
+
+MaybeError Adapter::InitializeSupportedLimitsImpl(CombinedLimits* limits) {
+    GetDefaultLimits(&limits->v1);
+
+    // // https://docs.microsoft.com/en-us/windows/win32/direct3d12/hardware-feature-levels
+
+    // Limits that are the same across D3D feature levels
+    limits->v1.maxTextureDimension1D = D3D11_REQ_TEXTURE1D_U_DIMENSION;
+    limits->v1.maxTextureDimension2D = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+    limits->v1.maxTextureDimension3D = D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
+    limits->v1.maxTextureArrayLayers = D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
+    // Slot values can be 0-15, inclusive:
+    // https://docs.microsoft.com/en-ca/windows/win32/api/d3d11/ns-d3d11-d3d11_input_element_desc
+    limits->v1.maxVertexBuffers = 16;
+    limits->v1.maxVertexAttributes = D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT;
+
+    uint32_t maxUAVsAllStages = mFeatureLevel == D3D_FEATURE_LEVEL_11_1
+                                    ? D3D11_1_UAV_SLOT_COUNT
+                                    : D3D11_PS_CS_UAV_REGISTER_COUNT;
+    ASSERT(maxUAVsAllStages / 4 > limits->v1.maxStorageTexturesPerShaderStage);
+    ASSERT(maxUAVsAllStages / 4 > limits->v1.maxStorageBuffersPerShaderStage);
+    uint32_t maxUAVsPerStage = maxUAVsAllStages / 2;
+
+    // Reserve one slot for builtin constants.
+    constexpr uint32_t kReservedCBVSlots = 1;
+    limits->v1.maxUniformBuffersPerShaderStage =
+        D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - kReservedCBVSlots;
+
+    // Allocate half of the UAVs to storage buffers, and half to storage textures.
+    limits->v1.maxStorageTexturesPerShaderStage = maxUAVsPerStage / 2;
+    limits->v1.maxStorageBuffersPerShaderStage = maxUAVsPerStage - maxUAVsPerStage / 2;
+    limits->v1.maxSampledTexturesPerShaderStage = D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
+    limits->v1.maxSamplersPerShaderStage = D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
+    limits->v1.maxColorAttachments = D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;
+
+    // TODO(dawn:1721): support dynamic uniform buffers and storage buffers?
+    limits->v1.maxDynamicUniformBuffersPerPipelineLayout = 0;
+    limits->v1.maxDynamicStorageBuffersPerPipelineLayout = 0;
+
+    // https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-attributes-numthreads
+    limits->v1.maxComputeWorkgroupSizeX = D3D11_CS_THREAD_GROUP_MAX_X;
+    limits->v1.maxComputeWorkgroupSizeY = D3D11_CS_THREAD_GROUP_MAX_Y;
+    limits->v1.maxComputeWorkgroupSizeZ = D3D11_CS_THREAD_GROUP_MAX_Z;
+    limits->v1.maxComputeInvocationsPerWorkgroup = D3D11_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP;
+
+    // https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-dispatch
+    limits->v1.maxComputeWorkgroupsPerDimension = D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION;
+
+    // https://docs.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-devices-downlevel-compute-shaders
+    // Thread Group Shared Memory is limited to 16Kb on downlevel hardware. This is less than
+    // the 32Kb that is available to Direct3D 11 hardware. D3D12 is also 32kb.
+    limits->v1.maxComputeWorkgroupStorageSize = 32768;
+
+    // Max number of "constants" where each constant is a 16-byte float4
+    limits->v1.maxUniformBufferBindingSize = D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 16;
+    // D3D11 has no documented limit on the size of a storage buffer binding.
+    limits->v1.maxStorageBufferBindingSize = 4294967295;
+    // D3D11 has no documented limit on the buffer size.
+    limits->v1.maxBufferSize = kAssumedMaxBufferSize;
+
+    return {};
+}
+
+MaybeError Adapter::ValidateFeatureSupportedWithTogglesImpl(wgpu::FeatureName feature,
+                                                            const TogglesState& toggles) const {
+    return {};
+}
+
+void Adapter::SetupBackendDeviceToggles(TogglesState* deviceToggles) const {}
+
+ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor,
+                                                         const TogglesState& deviceToggles) {
+    // TODO(dawn:1705): Implement D3D11 backend.
+    return DAWN_UNIMPLEMENTED_ERROR("D3D11 backend is not implemented yet");
+}
+
+// Resets the backend device and creates a new one. If any D3D11 objects belonging to the
+// current ID3D11Device have not been destroyed, a non-zero value will be returned upon Reset()
+// and the subequent call to CreateDevice will return a handle the existing device instead of
+// creating a new one.
+MaybeError Adapter::ResetInternalDeviceForTestingImpl() {
+    [[maybe_unused]] auto refCount = mD3d11Device.Reset();
+    ASSERT(refCount == 0);
+    DAWN_TRY(Initialize());
+
+    return {};
+}
+
+}  // namespace dawn::native::d3d11
diff --git a/src/dawn/native/d3d11/AdapterD3D11.h b/src/dawn/native/d3d11/AdapterD3D11.h
new file mode 100644
index 0000000..51f4540
--- /dev/null
+++ b/src/dawn/native/d3d11/AdapterD3D11.h
@@ -0,0 +1,64 @@
+// Copyright 2023 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_DAWN_NATIVE_D3D11_ADAPTERD3D11_H_
+#define SRC_DAWN_NATIVE_D3D11_ADAPTERD3D11_H_
+
+#include "dawn/native/d3d/AdapterD3D.h"
+
+#include "dawn/native/d3d/d3d_platform.h"
+#include "dawn/native/d3d11/DeviceInfoD3D11.h"
+
+namespace dawn::native::d3d11 {
+
+class Backend;
+
+class Adapter : public d3d::Adapter {
+  public:
+    Adapter(Backend* backend,
+            ComPtr<IDXGIAdapter3> hardwareAdapter,
+            const TogglesState& adapterToggles);
+    ~Adapter() override;
+
+    // AdapterBase Implementation
+    bool SupportsExternalImages() const override;
+
+    const DeviceInfo& GetDeviceInfo() const;
+    ComPtr<ID3D11Device> GetD3D11Device() const;
+
+  private:
+    using Base = d3d::Adapter;
+
+    void SetupBackendDeviceToggles(TogglesState* deviceToggles) const override;
+
+    ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(const DeviceDescriptor* descriptor,
+                                                    const TogglesState& deviceToggles) override;
+
+    MaybeError ResetInternalDeviceForTestingImpl() override;
+
+    MaybeError InitializeImpl() override;
+    void InitializeSupportedFeaturesImpl() override;
+    MaybeError InitializeSupportedLimitsImpl(CombinedLimits* limits) override;
+
+    MaybeError ValidateFeatureSupportedWithTogglesImpl(wgpu::FeatureName feature,
+                                                       const TogglesState& toggles) const override;
+    ComPtr<ID3D11Device> mD3d11Device;
+    D3D_FEATURE_LEVEL mFeatureLevel;
+
+    DeviceInfo mDeviceInfo = {};
+};
+
+}  // namespace dawn::native::d3d11
+
+#endif  // SRC_DAWN_NATIVE_D3D11_ADAPTERD3D11_H_
diff --git a/src/dawn/native/d3d11/BackendD3D11.cpp b/src/dawn/native/d3d11/BackendD3D11.cpp
new file mode 100644
index 0000000..4340ee2
--- /dev/null
+++ b/src/dawn/native/d3d11/BackendD3D11.cpp
@@ -0,0 +1,66 @@
+// Copyright 2023 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dawn/native/d3d11/BackendD3D11.h"
+
+#include <memory>
+#include <utility>
+
+#include "dawn/common/Log.h"
+#include "dawn/native/D3D11Backend.h"
+#include "dawn/native/Instance.h"
+#include "dawn/native/d3d/D3DError.h"
+#include "dawn/native/d3d11/AdapterD3D11.h"
+#include "dawn/native/d3d11/PlatformFunctionsD3D11.h"
+
+namespace dawn::native::d3d11 {
+
+Backend::Backend(InstanceBase* instance) : Base(instance, wgpu::BackendType::D3D11) {}
+
+MaybeError Backend::Initialize() {
+    auto functions = std::make_unique<PlatformFunctions>();
+    DAWN_TRY(functions->LoadFunctions());
+
+    DAWN_TRY(Base::Initialize(std::move(functions)));
+
+    return {};
+}
+
+const PlatformFunctions* Backend::GetFunctions() const {
+    return static_cast<const PlatformFunctions*>(Base::GetFunctions());
+}
+
+ResultOrError<Ref<AdapterBase>> Backend::CreateAdapterFromIDXGIAdapter(
+    ComPtr<IDXGIAdapter> dxgiAdapter,
+    const TogglesState& adapterToggles) {
+    ComPtr<IDXGIAdapter3> dxgiAdapter3;
+    DAWN_TRY(CheckHRESULT(dxgiAdapter.As(&dxgiAdapter3), "DXGIAdapter retrieval"));
+    Ref<Adapter> adapter = AcquireRef(new Adapter(this, std::move(dxgiAdapter3), adapterToggles));
+    DAWN_TRY(adapter->Initialize());
+
+    return {std::move(adapter)};
+}
+
+BackendConnection* Connect(InstanceBase* instance) {
+    Backend* backend = new Backend(instance);
+
+    if (instance->ConsumedError(backend->Initialize())) {
+        delete backend;
+        return nullptr;
+    }
+
+    return backend;
+}
+
+}  // namespace dawn::native::d3d11
diff --git a/src/dawn/native/d3d11/BackendD3D11.h b/src/dawn/native/d3d11/BackendD3D11.h
new file mode 100644
index 0000000..422aff6
--- /dev/null
+++ b/src/dawn/native/d3d11/BackendD3D11.h
@@ -0,0 +1,44 @@
+// Copyright 2023 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_DAWN_NATIVE_D3D11_BACKENDD3D11_H_
+#define SRC_DAWN_NATIVE_D3D11_BACKENDD3D11_H_
+
+#include <vector>
+
+#include "dawn/native/d3d/BackendD3D.h"
+
+namespace dawn::native::d3d11 {
+
+class PlatformFunctions;
+
+class Backend : public d3d::Backend {
+  public:
+    explicit Backend(InstanceBase* instance);
+
+    MaybeError Initialize();
+    const PlatformFunctions* GetFunctions() const;
+
+  protected:
+    ResultOrError<Ref<AdapterBase>> CreateAdapterFromIDXGIAdapter(
+        ComPtr<IDXGIAdapter> dxgiAdapter,
+        const TogglesState& adapterToggles) override;
+
+  private:
+    using Base = d3d::Backend;
+};
+
+}  // namespace dawn::native::d3d11
+
+#endif  // SRC_DAWN_NATIVE_D3D11_BACKENDD3D11_H_
diff --git a/src/dawn/native/d3d11/D3D11Backend.cpp b/src/dawn/native/d3d11/D3D11Backend.cpp
new file mode 100644
index 0000000..e166e6a
--- /dev/null
+++ b/src/dawn/native/d3d11/D3D11Backend.cpp
@@ -0,0 +1,31 @@
+// Copyright 2023 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// D3D11Backend.cpp: contains the definition of symbols exported by D3D11Backend.h so that they
+// can be compiled twice: once export (shared library), once not exported (static library)
+
+#include "dawn/native/D3D11Backend.h"
+
+#include <utility>
+
+#include "dawn/native/d3d/d3d_platform.h"
+
+namespace dawn::native::d3d11 {
+
+AdapterDiscoveryOptions::AdapterDiscoveryOptions() : AdapterDiscoveryOptions(nullptr) {}
+
+AdapterDiscoveryOptions::AdapterDiscoveryOptions(ComPtr<IDXGIAdapter> adapter)
+    : d3d::AdapterDiscoveryOptions(WGPUBackendType_D3D11, std::move(adapter)) {}
+
+}  // namespace dawn::native::d3d11
diff --git a/src/dawn/native/d3d11/DeviceInfoD3D11.cpp b/src/dawn/native/d3d11/DeviceInfoD3D11.cpp
new file mode 100644
index 0000000..d15b7bb
--- /dev/null
+++ b/src/dawn/native/d3d11/DeviceInfoD3D11.cpp
@@ -0,0 +1,45 @@
+// Copyright 2023 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dawn/native/d3d11/DeviceInfoD3D11.h"
+
+#include <utility>
+
+#include "dawn/native/d3d/D3DError.h"
+#include "dawn/native/d3d11/AdapterD3D11.h"
+#include "dawn/native/d3d11/PlatformFunctionsD3D11.h"
+
+namespace dawn::native::d3d11 {
+
+ResultOrError<DeviceInfo> GatherDeviceInfo(const Adapter& adapter) {
+    DeviceInfo info = {};
+
+    D3D11_FEATURE_DATA_D3D11_OPTIONS2 options2;
+    DAWN_TRY(CheckHRESULT(adapter.GetD3D11Device()->CheckFeatureSupport(
+                              D3D11_FEATURE_D3D11_OPTIONS2, &options2, sizeof(options2)),
+                          "D3D11_FEATURE_D3D11_OPTIONS2"));
+
+    info.isUMA = options2.UnifiedMemoryArchitecture;
+
+    info.shaderModel = 50;
+    // Profiles are always <stage>s_<minor>_<major> so we build the s_<minor>_major and add
+    // it to each of the stage's suffix.
+    info.shaderProfiles[SingleShaderStage::Vertex] = L"vs_5_0";
+    info.shaderProfiles[SingleShaderStage::Fragment] = L"ps_5_0";
+    info.shaderProfiles[SingleShaderStage::Compute] = L"cs_5_0";
+
+    return std::move(info);
+}
+
+}  // namespace dawn::native::d3d11
diff --git a/src/dawn/native/d3d11/DeviceInfoD3D11.h b/src/dawn/native/d3d11/DeviceInfoD3D11.h
new file mode 100644
index 0000000..66ffd7b
--- /dev/null
+++ b/src/dawn/native/d3d11/DeviceInfoD3D11.h
@@ -0,0 +1,38 @@
+// Copyright 2023 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_DAWN_NATIVE_D3D11_DEVICEINFOD3D11_H_
+#define SRC_DAWN_NATIVE_D3D11_DEVICEINFOD3D11_H_
+
+#include "dawn/native/Error.h"
+#include "dawn/native/PerStage.h"
+#include "dawn/native/d3d/d3d_platform.h"
+
+namespace dawn::native::d3d11 {
+
+class Adapter;
+
+struct DeviceInfo {
+    bool isUMA;
+
+    // shaderModel indicates the maximum supported shader model, for example, the value 62
+    // indicates that current driver supports the maximum shader model is shader model 6.2.
+    uint32_t shaderModel;
+    PerStage<std::wstring> shaderProfiles;
+};
+
+ResultOrError<DeviceInfo> GatherDeviceInfo(const Adapter& adapter);
+}  // namespace dawn::native::d3d11
+
+#endif  // SRC_DAWN_NATIVE_D3D11_DEVICEINFOD3D11_H_
diff --git a/src/dawn/native/d3d11/PlatformFunctionsD3D11.cpp b/src/dawn/native/d3d11/PlatformFunctionsD3D11.cpp
new file mode 100644
index 0000000..6439f84
--- /dev/null
+++ b/src/dawn/native/d3d11/PlatformFunctionsD3D11.cpp
@@ -0,0 +1,45 @@
+// Copyright 2023 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dawn/native/d3d11/PlatformFunctionsD3D11.h"
+
+#include <string>
+
+namespace dawn::native::d3d11 {
+
+PlatformFunctions::PlatformFunctions() = default;
+PlatformFunctions::~PlatformFunctions() = default;
+
+MaybeError PlatformFunctions::LoadFunctions() {
+    DAWN_TRY(Base::LoadFunctions());
+
+    DAWN_TRY(LoadD3D11());
+    return {};
+}
+
+MaybeError PlatformFunctions::LoadD3D11() {
+#if DAWN_PLATFORM_IS(WINUWP)
+    d3d11CreateDevice = &D3D11CreateDevice;
+#else
+    std::string error;
+    if (!mD3D11Lib.Open("d3d11.dll", &error) ||
+        !mD3D11Lib.GetProc(&d3d11CreateDevice, "D3D11CreateDevice", &error)) {
+        return DAWN_INTERNAL_ERROR(error.c_str());
+    }
+#endif
+
+    return {};
+}
+
+}  // namespace dawn::native::d3d11
diff --git a/src/dawn/native/d3d11/PlatformFunctionsD3D11.h b/src/dawn/native/d3d11/PlatformFunctionsD3D11.h
new file mode 100644
index 0000000..62b687d
--- /dev/null
+++ b/src/dawn/native/d3d11/PlatformFunctionsD3D11.h
@@ -0,0 +1,43 @@
+// Copyright 2023 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_DAWN_NATIVE_D3D11_PLATFORMFUNCTIONSD3D11_H_
+#define SRC_DAWN_NATIVE_D3D11_PLATFORMFUNCTIONSD3D11_H_
+
+#include "dawn/native/d3d/PlatformFunctions.h"
+#include "dawn/native/d3d/d3d_platform.h"
+
+namespace dawn::native::d3d11 {
+
+class PlatformFunctions final : public d3d::PlatformFunctions {
+  public:
+    PlatformFunctions();
+    ~PlatformFunctions() override;
+
+    MaybeError LoadFunctions();
+
+    // Functions from D3D11.dll
+    PFN_D3D11_CREATE_DEVICE d3d11CreateDevice = nullptr;
+
+  private:
+    using Base = d3d::PlatformFunctions;
+
+    MaybeError LoadD3D11();
+
+    DynamicLib mD3D11Lib;
+};
+
+}  // namespace dawn::native::d3d11
+
+#endif  // SRC_DAWN_NATIVE_D3D11_PLATFORMFUNCTIONSD3D11_H_
diff --git a/src/dawn/native/d3d12/AdapterD3D12.cpp b/src/dawn/native/d3d12/AdapterD3D12.cpp
index ccd42bf..497fa20 100644
--- a/src/dawn/native/d3d12/AdapterD3D12.cpp
+++ b/src/dawn/native/d3d12/AdapterD3D12.cpp
@@ -56,6 +56,7 @@
 }
 
 MaybeError Adapter::InitializeImpl() {
+    DAWN_TRY(Base::InitializeImpl());
     // D3D12 cannot check for feature support without a device.
     // Create the device to populate the adapter properties then reuse it when needed for actual
     // rendering.
@@ -67,33 +68,12 @@
 
     DAWN_TRY(InitializeDebugLayerFilters());
 
-    DXGI_ADAPTER_DESC1 adapterDesc;
-    GetHardwareAdapter()->GetDesc1(&adapterDesc);
-
-    mDeviceId = adapterDesc.DeviceId;
-    mVendorId = adapterDesc.VendorId;
-    mName = WCharToUTF8(adapterDesc.Description);
-
     DAWN_TRY_ASSIGN(mDeviceInfo, GatherDeviceInfo(*this));
 
-    if (adapterDesc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
-        mAdapterType = wgpu::AdapterType::CPU;
-    } else {
-        mAdapterType =
-            (mDeviceInfo.isUMA) ? wgpu::AdapterType::IntegratedGPU : wgpu::AdapterType::DiscreteGPU;
-    }
-
-    // Convert the adapter's D3D12 driver version to a readable string like "24.21.13.9793".
-    LARGE_INTEGER umdVersion;
-    if (GetHardwareAdapter()->CheckInterfaceSupport(__uuidof(IDXGIDevice), &umdVersion) !=
-        DXGI_ERROR_UNSUPPORTED) {
-        uint64_t encodedVersion = umdVersion.QuadPart;
-        uint16_t mask = 0xFFFF;
-        mDriverVersion = {static_cast<uint16_t>((encodedVersion >> 48) & mask),
-                          static_cast<uint16_t>((encodedVersion >> 32) & mask),
-                          static_cast<uint16_t>((encodedVersion >> 16) & mask),
-                          static_cast<uint16_t>(encodedVersion & mask)};
-        mDriverDescription = std::string("D3D12 driver version ") + mDriverVersion.ToString();
+    // Base::InitializeImpl() cannot distinguish between discrete and integrated GPUs, so we need to
+    // overwrite it here.
+    if (mAdapterType == wgpu::AdapterType::DiscreteGPU && mDeviceInfo.isUMA) {
+        mAdapterType = wgpu::AdapterType::IntegratedGPU;
     }
 
     if (GetInstance()->IsAdapterBlocklistEnabled()) {
@@ -316,7 +296,7 @@
     limits->v1.maxComputeWorkgroupSizeZ = D3D12_CS_THREAD_GROUP_MAX_Z;
     limits->v1.maxComputeInvocationsPerWorkgroup = D3D12_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP;
 
-    // https://docs.maxComputeWorkgroupSizeXmicrosoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_dispatch_arguments
+    // https://docs.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_dispatch_arguments
     limits->v1.maxComputeWorkgroupsPerDimension = D3D12_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION;
 
     // https://docs.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-devices-downlevel-compute-shaders
@@ -610,7 +590,8 @@
 // and the subequent call to CreateDevice will return a handle the existing device instead of
 // creating a new one.
 MaybeError Adapter::ResetInternalDeviceForTestingImpl() {
-    ASSERT(mD3d12Device.Reset() == 0);
+    [[maybe_unused]] auto refCount = mD3d12Device.Reset();
+    ASSERT(refCount == 0);
     DAWN_TRY(Initialize());
 
     return {};
diff --git a/src/dawn/native/d3d12/BackendD3D12.cpp b/src/dawn/native/d3d12/BackendD3D12.cpp
index cbd0eb4..b0ccf6a 100644
--- a/src/dawn/native/d3d12/BackendD3D12.cpp
+++ b/src/dawn/native/d3d12/BackendD3D12.cpp
@@ -26,21 +26,6 @@
 #include "dawn/native/d3d12/UtilsD3D12.h"
 
 namespace dawn::native::d3d12 {
-namespace {
-
-ResultOrError<Ref<AdapterBase>> CreateAdapterFromIDXGIAdapter(Backend* backend,
-                                                              ComPtr<IDXGIAdapter> dxgiAdapter,
-                                                              const TogglesState& adapterToggles) {
-    ComPtr<IDXGIAdapter3> dxgiAdapter3;
-    DAWN_TRY(CheckHRESULT(dxgiAdapter.As(&dxgiAdapter3), "DXGIAdapter retrieval"));
-    Ref<Adapter> adapter =
-        AcquireRef(new Adapter(backend, std::move(dxgiAdapter3), adapterToggles));
-    DAWN_TRY(adapter->Initialize());
-
-    return {std::move(adapter)};
-}
-
-}  // namespace
 
 Backend::Backend(InstanceBase* instance) : Base(instance, wgpu::BackendType::D3D12) {}
 
@@ -78,52 +63,15 @@
     return static_cast<const PlatformFunctions*>(Base::GetFunctions());
 }
 
-std::vector<Ref<AdapterBase>> Backend::DiscoverDefaultAdapters(const TogglesState& adapterToggles) {
-    AdapterDiscoveryOptions options;
-    auto result = DiscoverAdapters(&options, adapterToggles);
-    if (result.IsError()) {
-        GetInstance()->ConsumedError(result.AcquireError());
-        return {};
-    }
-    return result.AcquireSuccess();
-}
-
-ResultOrError<std::vector<Ref<AdapterBase>>> Backend::DiscoverAdapters(
-    const AdapterDiscoveryOptionsBase* optionsBase,
+ResultOrError<Ref<AdapterBase>> Backend::CreateAdapterFromIDXGIAdapter(
+    ComPtr<IDXGIAdapter> dxgiAdapter,
     const TogglesState& adapterToggles) {
-    ASSERT(optionsBase->backendType == WGPUBackendType_D3D12);
-    const AdapterDiscoveryOptions* options =
-        static_cast<const AdapterDiscoveryOptions*>(optionsBase);
+    ComPtr<IDXGIAdapter3> dxgiAdapter3;
+    DAWN_TRY(CheckHRESULT(dxgiAdapter.As(&dxgiAdapter3), "DXGIAdapter retrieval"));
+    Ref<Adapter> adapter = AcquireRef(new Adapter(this, std::move(dxgiAdapter3), adapterToggles));
+    DAWN_TRY(adapter->Initialize());
 
-    std::vector<Ref<AdapterBase>> adapters;
-    if (options->dxgiAdapter != nullptr) {
-        // |dxgiAdapter| was provided. Discover just that adapter.
-        Ref<AdapterBase> adapter;
-        DAWN_TRY_ASSIGN(adapter,
-                        CreateAdapterFromIDXGIAdapter(this, options->dxgiAdapter, adapterToggles));
-        adapters.push_back(std::move(adapter));
-        return std::move(adapters);
-    }
-
-    // Enumerate and discover all available adapters.
-    for (uint32_t adapterIndex = 0;; ++adapterIndex) {
-        ComPtr<IDXGIAdapter1> dxgiAdapter = nullptr;
-        if (GetFactory()->EnumAdapters1(adapterIndex, &dxgiAdapter) == DXGI_ERROR_NOT_FOUND) {
-            break;  // No more adapters to enumerate.
-        }
-
-        ASSERT(dxgiAdapter != nullptr);
-        ResultOrError<Ref<AdapterBase>> adapter =
-            CreateAdapterFromIDXGIAdapter(this, dxgiAdapter, adapterToggles);
-        if (adapter.IsError()) {
-            GetInstance()->ConsumedError(adapter.AcquireError());
-            continue;
-        }
-
-        adapters.push_back(adapter.AcquireSuccess());
-    }
-
-    return adapters;
+    return {std::move(adapter)};
 }
 
 BackendConnection* Connect(InstanceBase* instance) {
diff --git a/src/dawn/native/d3d12/BackendD3D12.h b/src/dawn/native/d3d12/BackendD3D12.h
index 2038767..8342084 100644
--- a/src/dawn/native/d3d12/BackendD3D12.h
+++ b/src/dawn/native/d3d12/BackendD3D12.h
@@ -34,10 +34,9 @@
 
     const PlatformFunctions* GetFunctions() const;
 
-    std::vector<Ref<AdapterBase>> DiscoverDefaultAdapters(
-        const TogglesState& adapterToggles) override;
-    ResultOrError<std::vector<Ref<AdapterBase>>> DiscoverAdapters(
-        const AdapterDiscoveryOptionsBase* optionsBase,
+  protected:
+    ResultOrError<Ref<AdapterBase>> CreateAdapterFromIDXGIAdapter(
+        ComPtr<IDXGIAdapter> dxgiAdapter,
         const TogglesState& adapterToggles) override;
 
   private:
diff --git a/src/dawn/native/d3d12/D3D12Backend.cpp b/src/dawn/native/d3d12/D3D12Backend.cpp
index 736af5f..d7e3139 100644
--- a/src/dawn/native/d3d12/D3D12Backend.cpp
+++ b/src/dawn/native/d3d12/D3D12Backend.cpp
@@ -112,9 +112,9 @@
         memorySegment, requestedReservationSize);
 }
 
-AdapterDiscoveryOptions::AdapterDiscoveryOptions()
-    : AdapterDiscoveryOptionsBase(WGPUBackendType_D3D12), dxgiAdapter(nullptr) {}
+AdapterDiscoveryOptions::AdapterDiscoveryOptions() : AdapterDiscoveryOptions(nullptr) {}
 
 AdapterDiscoveryOptions::AdapterDiscoveryOptions(ComPtr<IDXGIAdapter> adapter)
-    : AdapterDiscoveryOptionsBase(WGPUBackendType_D3D12), dxgiAdapter(std::move(adapter)) {}
+    : d3d::AdapterDiscoveryOptions(WGPUBackendType_D3D12, std::move(adapter)) {}
+
 }  // namespace dawn::native::d3d12