D3D12: Implement the backend connection and adapter.

BUG=dawn:29

Change-Id: Id4497b4a91ba58b79d1cd976a52df5a0fa5d60a8
Reviewed-on: https://dawn-review.googlesource.com/c/3844
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index 4604f8a..92370be 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -506,6 +506,10 @@
   if (dawn_enable_d3d12) {
     libs += [ "dxguid.lib" ]
     sources += [
+      "src/dawn_native/d3d12/AdapterD3D12.cpp",
+      "src/dawn_native/d3d12/AdapterD3D12.h",
+      "src/dawn_native/d3d12/BackendD3D12.cpp",
+      "src/dawn_native/d3d12/BackendD3D12.h",
       "src/dawn_native/d3d12/BindGroupD3D12.cpp",
       "src/dawn_native/d3d12/BindGroupD3D12.h",
       "src/dawn_native/d3d12/BindGroupLayoutD3D12.cpp",
diff --git a/src/dawn_native/Device.cpp b/src/dawn_native/Device.cpp
index c5f6993..f0f879c 100644
--- a/src/dawn_native/Device.cpp
+++ b/src/dawn_native/Device.cpp
@@ -70,6 +70,10 @@
         mErrorUserdata = userdata;
     }
 
+    AdapterBase* DeviceBase::GetAdapter() const {
+        return mAdapter;
+    }
+
     DeviceBase* DeviceBase::GetDevice() {
         return this;
     }
diff --git a/src/dawn_native/Device.h b/src/dawn_native/Device.h
index fc79075..977ba73 100644
--- a/src/dawn_native/Device.h
+++ b/src/dawn_native/Device.h
@@ -49,6 +49,8 @@
             return false;
         }
 
+        AdapterBase* GetAdapter() const;
+
         // Used by autogenerated code, returns itself
         DeviceBase* GetDevice();
 
diff --git a/src/dawn_native/d3d12/AdapterD3D12.cpp b/src/dawn_native/d3d12/AdapterD3D12.cpp
new file mode 100644
index 0000000..f1d4630
--- /dev/null
+++ b/src/dawn_native/d3d12/AdapterD3D12.cpp
@@ -0,0 +1,55 @@
+// Copyright 2019 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/d3d12/AdapterD3D12.h"
+
+#include "dawn_native/d3d12/BackendD3D12.h"
+#include "dawn_native/d3d12/DeviceD3D12.h"
+#include "dawn_native/d3d12/PlatformFunctions.h"
+
+#include <locale>
+
+namespace dawn_native { namespace d3d12 {
+
+    Adapter::Adapter(Backend* backend, ComPtr<IDXGIAdapter1> hardwareAdapter)
+        : AdapterBase(backend->GetInstance(), BackendType::D3D12),
+          mHardwareAdapter(hardwareAdapter),
+          mBackend(backend) {
+        DXGI_ADAPTER_DESC1 adapterDesc;
+        mHardwareAdapter->GetDesc1(&adapterDesc);
+
+        mPCIInfo.deviceId = adapterDesc.DeviceId;
+        mPCIInfo.vendorId = adapterDesc.VendorId;
+
+        std::wstring_convert<std::codecvt<wchar_t, char, std::mbstate_t>> converter(
+            "Error converting");
+        mPCIInfo.name = converter.to_bytes(adapterDesc.Description);
+    }
+
+    Backend* Adapter::GetBackend() const {
+        return mBackend;
+    }
+
+    ResultOrError<DeviceBase*> Adapter::CreateDeviceImpl() {
+        ComPtr<ID3D12Device> d3d12Device;
+        if (FAILED(mBackend->GetFunctions()->d3d12CreateDevice(
+                mHardwareAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&d3d12Device)))) {
+            return DAWN_CONTEXT_LOST_ERROR("D3D12CreateDevice failed");
+        }
+
+        ASSERT(d3d12Device != nullptr);
+        return new Device(this, d3d12Device);
+    }
+
+}}  // namespace dawn_native::d3d12
diff --git a/src/dawn_native/d3d12/AdapterD3D12.h b/src/dawn_native/d3d12/AdapterD3D12.h
new file mode 100644
index 0000000..1ff8b6d
--- /dev/null
+++ b/src/dawn_native/d3d12/AdapterD3D12.h
@@ -0,0 +1,42 @@
+// Copyright 2019 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 DAWNNATIVE_D3D12_ADAPTERD3D12_H_
+#define DAWNNATIVE_D3D12_ADAPTERD3D12_H_
+
+#include "dawn_native/Adapter.h"
+
+#include "dawn_native/d3d12/d3d12_platform.h"
+
+namespace dawn_native { namespace d3d12 {
+
+    class Backend;
+
+    class Adapter : public AdapterBase {
+      public:
+        Adapter(Backend* backend, ComPtr<IDXGIAdapter1> hardwareAdapter);
+        virtual ~Adapter() = default;
+
+        Backend* GetBackend() const;
+
+      private:
+        ResultOrError<DeviceBase*> CreateDeviceImpl() override;
+
+        ComPtr<IDXGIAdapter1> mHardwareAdapter;
+        Backend* mBackend;
+    };
+
+}}  // namespace dawn_native::d3d12
+
+#endif  // DAWNNATIVE_D3D12_ADAPTERD3D12_H_
\ No newline at end of file
diff --git a/src/dawn_native/d3d12/BackendD3D12.cpp b/src/dawn_native/d3d12/BackendD3D12.cpp
new file mode 100644
index 0000000..4db3527
--- /dev/null
+++ b/src/dawn_native/d3d12/BackendD3D12.cpp
@@ -0,0 +1,111 @@
+// Copyright 2019 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/d3d12/BackendD3D12.h"
+
+#include "dawn_native/D3D12Backend.h"
+#include "dawn_native/Instance.h"
+#include "dawn_native/d3d12/AdapterD3D12.h"
+#include "dawn_native/d3d12/PlatformFunctions.h"
+
+namespace dawn_native { namespace d3d12 {
+
+    namespace {
+
+        ResultOrError<ComPtr<IDXGIFactory4>> CreateFactory(const PlatformFunctions* functions) {
+            ComPtr<IDXGIFactory4> factory;
+
+            uint32_t dxgiFactoryFlags = 0;
+#if defined(DAWN_ENABLE_ASSERTS)
+            // Enable the debug layer (requires the Graphics Tools "optional feature").
+            {
+                ComPtr<ID3D12Debug> debugController;
+                if (SUCCEEDED(functions->d3d12GetDebugInterface(IID_PPV_ARGS(&debugController)))) {
+                    ASSERT(debugController != nullptr);
+                    debugController->EnableDebugLayer();
+
+                    // Enable additional debug layers.
+                    dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
+                }
+
+                ComPtr<IDXGIDebug1> dxgiDebug;
+                if (SUCCEEDED(functions->dxgiGetDebugInterface1(0, IID_PPV_ARGS(&dxgiDebug)))) {
+                    ASSERT(dxgiDebug != nullptr);
+                    dxgiDebug->ReportLiveObjects(DXGI_DEBUG_ALL,
+                                                 DXGI_DEBUG_RLO_FLAGS(DXGI_DEBUG_RLO_ALL));
+                }
+            }
+#endif  // defined(DAWN_ENABLE_ASSERTS)
+
+            if (FAILED(functions->createDxgiFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&factory)))) {
+                return DAWN_CONTEXT_LOST_ERROR("Failed to create a DXGI factory");
+            }
+
+            ASSERT(factory != nullptr);
+            return factory;
+        }
+
+    }  // anonymous namespace
+
+    Backend::Backend(InstanceBase* instance) : BackendConnection(instance, BackendType::D3D12) {
+    }
+
+    MaybeError Backend::Initialize() {
+        mFunctions = std::make_unique<PlatformFunctions>();
+        DAWN_TRY(mFunctions->LoadFunctions());
+
+        DAWN_TRY_ASSIGN(mFactory, CreateFactory(mFunctions.get()));
+
+        return {};
+    }
+
+    ComPtr<IDXGIFactory4> Backend::GetFactory() const {
+        return mFactory;
+    }
+
+    const PlatformFunctions* Backend::GetFunctions() const {
+        return mFunctions.get();
+    }
+
+    std::vector<std::unique_ptr<AdapterBase>> Backend::DiscoverDefaultAdapters() {
+        std::vector<std::unique_ptr<AdapterBase>> adapters;
+
+        for (uint32_t adapterIndex = 0;; ++adapterIndex) {
+            ComPtr<IDXGIAdapter1> dxgiAdapter = nullptr;
+            if (mFactory->EnumAdapters1(adapterIndex, &dxgiAdapter) == DXGI_ERROR_NOT_FOUND) {
+                break;  // No more adapters to enumerate.
+            }
+
+            ASSERT(dxgiAdapter != nullptr);
+            if (SUCCEEDED(mFunctions->d3d12CreateDevice(dxgiAdapter.Get(), D3D_FEATURE_LEVEL_11_0,
+                                                        _uuidof(ID3D12Device), nullptr))) {
+                adapters.push_back(std::make_unique<Adapter>(this, dxgiAdapter));
+            }
+        }
+
+        return adapters;
+    }
+
+    BackendConnection* Connect(InstanceBase* instance) {
+        Backend* backend = new Backend(instance);
+
+        if (instance->ConsumedError(backend->Initialize())) {
+            delete backend;
+            return nullptr;
+        }
+
+        return backend;
+    }
+
+}}  // namespace dawn_native::d3d12
diff --git a/src/dawn_native/d3d12/BackendD3D12.h b/src/dawn_native/d3d12/BackendD3D12.h
new file mode 100644
index 0000000..3161048
--- /dev/null
+++ b/src/dawn_native/d3d12/BackendD3D12.h
@@ -0,0 +1,46 @@
+// Copyright 2019 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 DAWNNATIVE_D3D12_BACKENDD3D12_H_
+#define DAWNNATIVE_D3D12_BACKENDD3D12_H_
+
+#include "dawn_native/BackendConnection.h"
+
+#include "dawn_native/d3d12/d3d12_platform.h"
+
+namespace dawn_native { namespace d3d12 {
+
+    class PlatformFunctions;
+
+    class Backend : public BackendConnection {
+      public:
+        Backend(InstanceBase* instance);
+
+        MaybeError Initialize();
+
+        ComPtr<IDXGIFactory4> GetFactory() const;
+        const PlatformFunctions* GetFunctions() const;
+
+        std::vector<std::unique_ptr<AdapterBase>> DiscoverDefaultAdapters() override;
+
+      private:
+        // Keep mFunctions as the first member so that in the destructor it is freed last. Otherwise
+        // the D3D12 DLLs are unloaded before we are done using them.
+        std::unique_ptr<PlatformFunctions> mFunctions;
+        ComPtr<IDXGIFactory4> mFactory;
+    };
+
+}}  // namespace dawn_native::d3d12
+
+#endif  // DAWNNATIVE_D3D12_BACKENDD3D12_H_
\ No newline at end of file
diff --git a/src/dawn_native/d3d12/D3D12Backend.cpp b/src/dawn_native/d3d12/D3D12Backend.cpp
index 2195f61..0f09bbe 100644
--- a/src/dawn_native/d3d12/D3D12Backend.cpp
+++ b/src/dawn_native/d3d12/D3D12Backend.cpp
@@ -23,10 +23,6 @@
 
 namespace dawn_native { namespace d3d12 {
 
-    dawnDevice CreateDevice() {
-        return reinterpret_cast<dawnDevice>(new Device());
-    }
-
     dawnSwapChainImplementation CreateNativeSwapChainImpl(dawnDevice device, HWND window) {
         Device* backendDevice = reinterpret_cast<Device*>(device);
 
diff --git a/src/dawn_native/d3d12/DeviceD3D12.cpp b/src/dawn_native/d3d12/DeviceD3D12.cpp
index 0ad3f4d..9f5920c 100644
--- a/src/dawn_native/d3d12/DeviceD3D12.cpp
+++ b/src/dawn_native/d3d12/DeviceD3D12.cpp
@@ -17,6 +17,8 @@
 #include "common/Assert.h"
 #include "dawn_native/BackendConnection.h"
 #include "dawn_native/DynamicUploader.h"
+#include "dawn_native/d3d12/AdapterD3D12.h"
+#include "dawn_native/d3d12/BackendD3D12.h"
 #include "dawn_native/d3d12/BindGroupD3D12.h"
 #include "dawn_native/d3d12/BindGroupLayoutD3D12.h"
 #include "dawn_native/d3d12/BufferD3D12.h"
@@ -37,88 +39,14 @@
 #include "dawn_native/d3d12/SwapChainD3D12.h"
 #include "dawn_native/d3d12/TextureD3D12.h"
 
-#include <locale>
-
 namespace dawn_native { namespace d3d12 {
 
     void ASSERT_SUCCESS(HRESULT hr) {
         ASSERT(SUCCEEDED(hr));
     }
 
-    BackendConnection* Connect(InstanceBase* instance) {
-        return nullptr;
-    }
-
-    namespace {
-        ComPtr<IDXGIFactory4> CreateFactory(const PlatformFunctions* functions) {
-            ComPtr<IDXGIFactory4> factory;
-
-            uint32_t dxgiFactoryFlags = 0;
-#if defined(DAWN_ENABLE_ASSERTS)
-            // Enable the debug layer (requires the Graphics Tools "optional feature").
-            {
-                ComPtr<ID3D12Debug> debugController;
-                if (SUCCEEDED(functions->d3d12GetDebugInterface(IID_PPV_ARGS(&debugController)))) {
-                    debugController->EnableDebugLayer();
-
-                    // Enable additional debug layers.
-                    dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
-                }
-
-                ComPtr<IDXGIDebug1> dxgiDebug;
-                if (SUCCEEDED(functions->dxgiGetDebugInterface1(0, IID_PPV_ARGS(&dxgiDebug)))) {
-                    dxgiDebug->ReportLiveObjects(DXGI_DEBUG_ALL,
-                                                 DXGI_DEBUG_RLO_FLAGS(DXGI_DEBUG_RLO_ALL));
-                }
-            }
-#endif  // defined(DAWN_ENABLE_ASSERTS)
-
-            ASSERT_SUCCESS(functions->createDxgiFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&factory)));
-            return factory;
-        }
-
-        ComPtr<IDXGIAdapter1> GetHardwareAdapter(ComPtr<IDXGIFactory4> factory,
-                                                 const PlatformFunctions* functions) {
-            for (uint32_t adapterIndex = 0;; ++adapterIndex) {
-                IDXGIAdapter1* adapter = nullptr;
-                if (factory->EnumAdapters1(adapterIndex, &adapter) == DXGI_ERROR_NOT_FOUND) {
-                    break;  // No more adapters to enumerate.
-                }
-
-                // Check to see if the adapter supports Direct3D 12, but don't create the actual
-                // device yet.
-                if (SUCCEEDED(functions->d3d12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0,
-                                                           _uuidof(ID3D12Device), nullptr))) {
-                    return adapter;
-                }
-                adapter->Release();
-            }
-            return nullptr;
-        }
-
-    }  // anonymous namespace
-
-    Device::Device() : DeviceBase(nullptr) {
-        mFunctions = std::make_unique<PlatformFunctions>();
-
-        {
-            MaybeError status = mFunctions->LoadFunctions();
-            ASSERT(status.IsSuccess());
-        }
-
-        // Create the connection to DXGI and the D3D12 device
-        mFactory = CreateFactory(mFunctions.get());
-        ASSERT(mFactory.Get() != nullptr);
-
-        mHardwareAdapter = GetHardwareAdapter(mFactory, mFunctions.get());
-        ASSERT(mHardwareAdapter.Get() != nullptr);
-
-        ASSERT_SUCCESS(mFunctions->d3d12CreateDevice(mHardwareAdapter.Get(), D3D_FEATURE_LEVEL_11_0,
-                                                     IID_PPV_ARGS(&mD3d12Device)));
-
-        // Collect GPU information
-        CollectPCIInfo();
-
+    Device::Device(Adapter* adapter, ComPtr<ID3D12Device> d3d12Device)
+        : DeviceBase(adapter), mD3d12Device(d3d12Device) {
         // Create device-global objects
         D3D12_COMMAND_QUEUE_DESC queueDesc = {};
         queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
@@ -149,31 +77,31 @@
         ASSERT(mPendingCommands.commandList == nullptr);
     }
 
-    ComPtr<IDXGIFactory4> Device::GetFactory() {
-        return mFactory;
-    }
-
-    ComPtr<ID3D12Device> Device::GetD3D12Device() {
+    ComPtr<ID3D12Device> Device::GetD3D12Device() const {
         return mD3d12Device;
     }
 
-    ComPtr<ID3D12CommandQueue> Device::GetCommandQueue() {
+    ComPtr<ID3D12CommandQueue> Device::GetCommandQueue() const {
         return mCommandQueue;
     }
 
-    DescriptorHeapAllocator* Device::GetDescriptorHeapAllocator() {
+    DescriptorHeapAllocator* Device::GetDescriptorHeapAllocator() const {
         return mDescriptorHeapAllocator.get();
     }
 
-    const PlatformFunctions* Device::GetFunctions() {
-        return mFunctions.get();
+    ComPtr<IDXGIFactory4> Device::GetFactory() const {
+        return ToBackend(GetAdapter())->GetBackend()->GetFactory();
+    }
+
+    const PlatformFunctions* Device::GetFunctions() const {
+        return ToBackend(GetAdapter())->GetBackend()->GetFunctions();
     }
 
     MapRequestTracker* Device::GetMapRequestTracker() const {
         return mMapRequestTracker.get();
     }
 
-    ResourceAllocator* Device::GetResourceAllocator() {
+    ResourceAllocator* Device::GetResourceAllocator() const {
         return mResourceAllocator.get();
     }
 
@@ -225,10 +153,6 @@
         NextSerial();
     }
 
-    const dawn_native::PCIInfo& Device::GetPCIInfo() const {
-        return mPCIInfo;
-    }
-
     void Device::NextSerial() {
         mLastSubmittedSerial++;
         ASSERT_SUCCESS(mCommandQueue->Signal(mFence.Get(), mLastSubmittedSerial));
@@ -319,20 +243,6 @@
         return new TextureView(texture, descriptor);
     }
 
-    void Device::CollectPCIInfo() {
-        memset(&mPCIInfo, 0, sizeof(mPCIInfo));
-
-        DXGI_ADAPTER_DESC1 adapterDesc;
-        mHardwareAdapter->GetDesc1(&adapterDesc);
-
-        mPCIInfo.deviceId = adapterDesc.DeviceId;
-        mPCIInfo.vendorId = adapterDesc.VendorId;
-
-        std::wstring_convert<std::codecvt<wchar_t, char, std::mbstate_t>> converter(
-            "Error converting");
-        mPCIInfo.name = converter.to_bytes(adapterDesc.Description);
-    }
-
     ResultOrError<std::unique_ptr<StagingBufferBase>> Device::CreateStagingBuffer(size_t size) {
         std::unique_ptr<StagingBufferBase> stagingBuffer =
             std::make_unique<StagingBuffer>(size, this);
diff --git a/src/dawn_native/d3d12/DeviceD3D12.h b/src/dawn_native/d3d12/DeviceD3D12.h
index be489d9..7182ae1 100644
--- a/src/dawn_native/d3d12/DeviceD3D12.h
+++ b/src/dawn_native/d3d12/DeviceD3D12.h
@@ -37,7 +37,7 @@
     // Definition of backend types
     class Device : public DeviceBase {
       public:
-        Device();
+        Device(Adapter* adapter, ComPtr<ID3D12Device> d3d12Device);
         ~Device();
 
         CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) override;
@@ -50,16 +50,15 @@
         Serial GetLastSubmittedCommandSerial() const final override;
         void TickImpl() override;
 
-        const dawn_native::PCIInfo& GetPCIInfo() const override;
+        ComPtr<ID3D12Device> GetD3D12Device() const;
+        ComPtr<ID3D12CommandQueue> GetCommandQueue() const;
 
-        ComPtr<IDXGIFactory4> GetFactory();
-        ComPtr<ID3D12Device> GetD3D12Device();
-        ComPtr<ID3D12CommandQueue> GetCommandQueue();
-
-        DescriptorHeapAllocator* GetDescriptorHeapAllocator();
+        DescriptorHeapAllocator* GetDescriptorHeapAllocator() const;
         MapRequestTracker* GetMapRequestTracker() const;
-        const PlatformFunctions* GetFunctions();
-        ResourceAllocator* GetResourceAllocator();
+        ResourceAllocator* GetResourceAllocator() const;
+
+        const PlatformFunctions* GetFunctions() const;
+        ComPtr<IDXGIFactory4> GetFactory() const;
 
         void OpenCommandList(ComPtr<ID3D12GraphicsCommandList>* commandList);
         ComPtr<ID3D12GraphicsCommandList> GetPendingCommandList();
@@ -101,19 +100,12 @@
         ResultOrError<TextureViewBase*> CreateTextureViewImpl(
             TextureBase* texture,
             const TextureViewDescriptor* descriptor) override;
-        void CollectPCIInfo();
-
-        // Keep mFunctions as the first member so that in the destructor it is freed. Otherwise the
-        // D3D12 DLLs are unloaded before we are done using it.
-        std::unique_ptr<PlatformFunctions> mFunctions;
 
         Serial mCompletedSerial = 0;
         Serial mLastSubmittedSerial = 0;
         ComPtr<ID3D12Fence> mFence;
         HANDLE mFenceEvent;
 
-        ComPtr<IDXGIFactory4> mFactory;
-        ComPtr<IDXGIAdapter1> mHardwareAdapter;
         ComPtr<ID3D12Device> mD3d12Device;
         ComPtr<ID3D12CommandQueue> mCommandQueue;
 
diff --git a/src/dawn_native/opengl/BackendGL.h b/src/dawn_native/opengl/BackendGL.h
index eb5923a..e55cc52 100644
--- a/src/dawn_native/opengl/BackendGL.h
+++ b/src/dawn_native/opengl/BackendGL.h
@@ -12,6 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#ifndef DAWNNATIVE_OPENGL_BACKENDGL_H_
+#define DAWNNATIVE_OPENGL_BACKENDGL_H_
+
 #include "dawn_native/BackendConnection.h"
 
 namespace dawn_native { namespace opengl {
@@ -29,3 +32,5 @@
     };
 
 }}  // namespace dawn_native::opengl
+
+#endif  // DAWNNATIVE_OPENGL_BACKENDGL_H_
diff --git a/src/include/dawn_native/D3D12Backend.h b/src/include/dawn_native/D3D12Backend.h
index ddc3f12..5af3356 100644
--- a/src/include/dawn_native/D3D12Backend.h
+++ b/src/include/dawn_native/D3D12Backend.h
@@ -15,15 +15,12 @@
 #ifndef DAWNNATIVE_D3D12BACKEND_H_
 #define DAWNNATIVE_D3D12BACKEND_H_
 
-#include <dawn/dawn.h>
 #include <dawn/dawn_wsi.h>
-#include <dawn_native/dawn_native_export.h>
+#include <dawn_native/DawnNative.h>
 
 #include <windows.h>
 
 namespace dawn_native { namespace d3d12 {
-    DAWN_NATIVE_EXPORT dawnDevice CreateDevice();
-
     DAWN_NATIVE_EXPORT dawnSwapChainImplementation CreateNativeSwapChainImpl(dawnDevice device,
                                                                              HWND window);
     DAWN_NATIVE_EXPORT dawnTextureFormat
diff --git a/src/utils/D3D12Binding.cpp b/src/utils/D3D12Binding.cpp
index 7aa5722..c9a8f2a 100644
--- a/src/utils/D3D12Binding.cpp
+++ b/src/utils/D3D12Binding.cpp
@@ -30,8 +30,18 @@
         }
 
         dawnDevice CreateDevice() override {
-            mBackendDevice = dawn_native::d3d12::CreateDevice();
-            return mBackendDevice;
+            // Make an instance and find a D3D12 adapter
+            mInstance = std::make_unique<dawn_native::Instance>();
+            mInstance->DiscoverDefaultAdapters();
+
+            std::vector<dawn_native::Adapter> adapters = mInstance->GetAdapters();
+            for (dawn_native::Adapter adapter : adapters) {
+                if (adapter.GetBackendType() == dawn_native::BackendType::D3D12) {
+                    mBackendDevice = adapter.CreateDevice();
+                    return mBackendDevice;
+                }
+            }
+            UNREACHABLE();
         }
 
         uint64_t GetSwapChainImplementation() override {
@@ -49,6 +59,7 @@
         }
 
       private:
+        std::unique_ptr<dawn_native::Instance> mInstance;
         dawnDevice mBackendDevice = nullptr;
         dawnSwapChainImplementation mSwapchainImpl = {};
     };