Simplify BackendBinding following adapters.

It doesn't need to care about device creation anymore, except for the
GLFW window hints and creating a GL context to discover the adapter.

Also remove the non-adapter GetPCIInfo.

BUG=dawn:29

Change-Id: I9bc8232536a55d2f973463ae0f2e0548dfc35456
Reviewed-on: https://dawn-review.googlesource.com/c/4381
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
diff --git a/examples/SampleUtils.cpp b/examples/SampleUtils.cpp
index 7e1e731..87f4982 100644
--- a/examples/SampleUtils.cpp
+++ b/examples/SampleUtils.cpp
@@ -27,6 +27,7 @@
 #include <dawn_wire/WireServer.h>
 #include "GLFW/glfw3.h"
 
+#include <algorithm>
 #include <cstring>
 #include <iostream>
 
@@ -59,6 +60,7 @@
 #endif
 
 static CmdBufType cmdBufType = CmdBufType::Terrible;
+static std::unique_ptr<dawn_native::Instance> instance;
 static utils::BackendBinding* binding = nullptr;
 
 static GLFWwindow* window = nullptr;
@@ -69,29 +71,45 @@
 static utils::TerribleCommandBuffer* s2cBuf = nullptr;
 
 dawn::Device CreateCppDawnDevice() {
-    binding = utils::CreateBinding(backendType);
-    if (binding == nullptr) {
-        return dawn::Device();
-    }
-
     glfwSetErrorCallback(PrintGLFWError);
     if (!glfwInit()) {
         return dawn::Device();
     }
 
-    binding->SetupGLFWWindowHints();
+    // Create the test window and discover adapters using it (esp. for OpenGL)
+    utils::SetupGLFWWindowHintsForBackend(backendType);
     window = glfwCreateWindow(640, 480, "Dawn window", nullptr, nullptr);
     if (!window) {
         return dawn::Device();
     }
 
-    binding->SetWindow(window);
+    instance = std::make_unique<dawn_native::Instance>();
+    utils::DiscoverAdapter(instance.get(), window, backendType);
 
-    dawnDevice backendDevice = binding->CreateDevice();
+    // Get an adapter for the backend to use, and create the device.
+    dawn_native::Adapter backendAdapter;
+    {
+        std::vector<dawn_native::Adapter> adapters = instance->GetAdapters();
+        auto adapterIt = std::find_if(adapters.begin(), adapters.end(),
+                                      [](const dawn_native::Adapter adapter) -> bool {
+            return adapter.GetBackendType() == backendType;
+        });
+        ASSERT(adapterIt != adapters.end());
+        backendAdapter = *adapterIt;
+    }
+
+    dawnDevice backendDevice = backendAdapter.CreateDevice();
     dawnProcTable backendProcs = dawn_native::GetProcs();
 
+    binding = utils::CreateBinding(backendType, window, backendDevice);
+    if (binding == nullptr) {
+        return dawn::Device();
+    }
+
+    // Choose whether to use the backend procs and devices directly, or set up the wire.
     dawnDevice cDevice = nullptr;
     dawnProcTable procs;
+
     switch (cmdBufType) {
         case CmdBufType::None:
             procs = backendProcs;
diff --git a/src/dawn_native/DawnNative.cpp b/src/dawn_native/DawnNative.cpp
index d10e8cb..5464d0d 100644
--- a/src/dawn_native/DawnNative.cpp
+++ b/src/dawn_native/DawnNative.cpp
@@ -26,11 +26,6 @@
         return GetProcsAutogen();
     }
 
-    const PCIInfo& GetPCIInfo(dawnDevice device) {
-        DeviceBase* deviceBase = reinterpret_cast<DeviceBase*>(device);
-        return deviceBase->GetPCIInfo();
-    }
-
     // Adapter
 
     Adapter::Adapter() = default;
@@ -50,6 +45,10 @@
         return mImpl->GetPCIInfo();
     }
 
+    Adapter::operator bool() const {
+        return mImpl != nullptr;
+    }
+
     dawnDevice Adapter::CreateDevice() {
         return reinterpret_cast<dawnDevice>(mImpl->CreateDevice());
     }
diff --git a/src/dawn_native/Device.cpp b/src/dawn_native/Device.cpp
index f0f879c..8b33268 100644
--- a/src/dawn_native/Device.cpp
+++ b/src/dawn_native/Device.cpp
@@ -102,11 +102,6 @@
         mCaches->bindGroupLayouts.erase(obj);
     }
 
-    const PCIInfo& DeviceBase::GetPCIInfo() const {
-        ASSERT(mAdapter != nullptr);
-        return mAdapter->GetPCIInfo();
-    }
-
     // Object creation API methods
 
     BindGroupBase* DeviceBase::CreateBindGroup(const BindGroupDescriptor* descriptor) {
diff --git a/src/dawn_native/Device.h b/src/dawn_native/Device.h
index 977ba73..83c40c4 100644
--- a/src/dawn_native/Device.h
+++ b/src/dawn_native/Device.h
@@ -114,8 +114,6 @@
             return nullptr;
         }
 
-        virtual const PCIInfo& GetPCIInfo() const;
-
         virtual ResultOrError<std::unique_ptr<StagingBufferBase>> CreateStagingBuffer(
             size_t size) = 0;
         virtual MaybeError CopyFromStagingToBuffer(StagingBufferBase* source,
diff --git a/src/include/dawn_native/DawnNative.h b/src/include/dawn_native/DawnNative.h
index c1c439e..e71e948 100644
--- a/src/include/dawn_native/DawnNative.h
+++ b/src/include/dawn_native/DawnNative.h
@@ -55,6 +55,8 @@
         BackendType GetBackendType() const;
         const PCIInfo& GetPCIInfo() const;
 
+        explicit operator bool() const;
+
         // Create a device on this adapter, note that the interface will change to include at least
         // a device descriptor and a pointer to backend specific options.
         // On an error, nullptr is returned.
@@ -104,8 +106,6 @@
     // Backend-agnostic API for dawn_native
     DAWN_NATIVE_EXPORT dawnProcTable GetProcs();
 
-    DAWN_NATIVE_EXPORT const PCIInfo& GetPCIInfo(dawnDevice device);
-
 }  // namespace dawn_native
 
 #endif  // DAWNNATIVE_DAWNNATIVE_H_
diff --git a/src/tests/DawnTest.cpp b/src/tests/DawnTest.cpp
index 357c090..e82a327 100644
--- a/src/tests/DawnTest.cpp
+++ b/src/tests/DawnTest.cpp
@@ -26,6 +26,7 @@
 #include "utils/SystemUtils.h"
 #include "utils/TerribleCommandBuffer.h"
 
+#include <algorithm>
 #include <iostream>
 #include <unordered_map>
 #include "GLFW/glfw3.h"
@@ -55,7 +56,7 @@
     std::unordered_map<dawn_native::BackendType, GLFWwindow*> windows;
 
     // Creates a GLFW window set up for use with a given backend.
-    GLFWwindow* GetWindowForBackend(utils::BackendBinding* binding, dawn_native::BackendType type) {
+    GLFWwindow* GetWindowForBackend(dawn_native::BackendType type) {
         GLFWwindow** window = &windows[type];
 
         if (*window != nullptr) {
@@ -67,7 +68,7 @@
         }
 
         glfwDefaultWindowHints();
-        binding->SetupGLFWWindowHints();
+        utils::SetupGLFWWindowHintsForBackend(type);
 
         std::string windowName = "Dawn " + ParamName(type) + " test window";
         *window = glfwCreateWindow(400, 400, windowName.c_str(), nullptr, nullptr);
@@ -174,17 +175,35 @@
 bool gTestUsesWire = false;
 
 void DawnTest::SetUp() {
-    mBinding.reset(utils::CreateBinding(GetParam()));
-    DAWN_ASSERT(mBinding != nullptr);
-
-    GLFWwindow* testWindow = GetWindowForBackend(mBinding.get(), GetParam());
+    // Create the test window and discover adapters using it (esp. for OpenGL)
+    GLFWwindow* testWindow = GetWindowForBackend(GetParam());
     DAWN_ASSERT(testWindow != nullptr);
 
-    mBinding->SetWindow(testWindow);
+    mInstance = std::make_unique<dawn_native::Instance>();
+    utils::DiscoverAdapter(mInstance.get(), testWindow, GetParam());
 
-    dawnDevice backendDevice = mBinding->CreateDevice();
+    // Get an adapter for the backend to use, and create the device.
+    dawn_native::Adapter backendAdapter;
+    {
+        std::vector<dawn_native::Adapter> adapters = mInstance->GetAdapters();
+        auto adapterIt = std::find_if(adapters.begin(), adapters.end(),
+                                      [this](const dawn_native::Adapter adapter) -> bool {
+                                          // Chromium's GTest harness has GetParam() as a regular
+                                          // function and not a member function of this.
+                                          DAWN_UNUSED(this);
+                                          return adapter.GetBackendType() == GetParam();
+                                      });
+        ASSERT(adapterIt != adapters.end());
+        backendAdapter = *adapterIt;
+    }
+
+    mPCIInfo = backendAdapter.GetPCIInfo();
+    dawnDevice backendDevice = backendAdapter.CreateDevice();
     dawnProcTable backendProcs = dawn_native::GetProcs();
 
+    mBinding.reset(utils::CreateBinding(GetParam(), testWindow, backendDevice));
+    DAWN_ASSERT(mBinding != nullptr);
+
     // Choose whether to use the backend procs and devices directly, or set up the wire.
     dawnDevice cDevice = nullptr;
     dawnProcTable procs;
@@ -225,8 +244,6 @@
 
     // The end2end tests should never cause validation errors. These should be tested in unittests.
     device.SetErrorCallback(DeviceErrorCauseTestFailure, 0);
-
-    mPCIInfo = dawn_native::GetPCIInfo(backendDevice);
 }
 
 void DawnTest::TearDown() {
diff --git a/src/tests/DawnTest.h b/src/tests/DawnTest.h
index 7bce5ec..6dc6699 100644
--- a/src/tests/DawnTest.h
+++ b/src/tests/DawnTest.h
@@ -177,6 +177,7 @@
     // Assuming the data is mapped, checks all expectations
     void ResolveExpectations();
 
+    std::unique_ptr<dawn_native::Instance> mInstance;
     std::unique_ptr<utils::BackendBinding> mBinding;
 
     dawn_native::PCIInfo mPCIInfo;
diff --git a/src/utils/BackendBinding.cpp b/src/utils/BackendBinding.cpp
index 3145856..3e2b808 100644
--- a/src/utils/BackendBinding.cpp
+++ b/src/utils/BackendBinding.cpp
@@ -14,55 +14,92 @@
 
 #include "utils/BackendBinding.h"
 
-#include "common/Assert.h"
+#include "common/Compiler.h"
+
+#include "GLFW/glfw3.h"
+
+#if defined(DAWN_ENABLE_BACKEND_OPENGL)
+#    include "dawn_native/OpenGLBackend.h"
+#endif  // defined(DAWN_ENABLE_BACKEND_OPENGL)
 
 namespace utils {
 
 #if defined(DAWN_ENABLE_BACKEND_D3D12)
-    BackendBinding* CreateD3D12Binding();
+    BackendBinding* CreateD3D12Binding(GLFWwindow* window, dawnDevice device);
 #endif
 #if defined(DAWN_ENABLE_BACKEND_METAL)
-    BackendBinding* CreateMetalBinding();
+    BackendBinding* CreateMetalBinding(GLFWwindow* window, dawnDevice device);
 #endif
 #if defined(DAWN_ENABLE_BACKEND_NULL)
-    BackendBinding* CreateNullBinding();
+    BackendBinding* CreateNullBinding(GLFWwindow* window, dawnDevice device);
 #endif
 #if defined(DAWN_ENABLE_BACKEND_OPENGL)
-    BackendBinding* CreateOpenGLBinding();
+    BackendBinding* CreateOpenGLBinding(GLFWwindow* window, dawnDevice device);
 #endif
 #if defined(DAWN_ENABLE_BACKEND_VULKAN)
-    BackendBinding* CreateVulkanBinding();
+    BackendBinding* CreateVulkanBinding(GLFWwindow* window, dawnDevice device);
 #endif
 
-    void BackendBinding::SetWindow(GLFWwindow* window) {
-        mWindow = window;
+    BackendBinding::BackendBinding(GLFWwindow* window, dawnDevice device)
+        : mWindow(window), mDevice(device) {
     }
 
-    BackendBinding* CreateBinding(dawn_native::BackendType type) {
+    void SetupGLFWWindowHintsForBackend(dawn_native::BackendType type) {
+        if (type == dawn_native::BackendType::OpenGL) {
+            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
+            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
+            glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
+            glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+        } else {
+            glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
+        }
+    }
+
+    void DiscoverAdapter(dawn_native::Instance* instance,
+                         GLFWwindow* window,
+                         dawn_native::BackendType type) {
+        DAWN_UNUSED(type);
+        DAWN_UNUSED(window);
+
+        if (type == dawn_native::BackendType::OpenGL) {
+#if defined(DAWN_ENABLE_BACKEND_OPENGL)
+            glfwMakeContextCurrent(window);
+            dawn_native::opengl::AdapterDiscoveryOptions adapterOptions;
+            adapterOptions.getProc = reinterpret_cast<void* (*)(const char*)>(glfwGetProcAddress);
+            instance->DiscoverAdapters(&adapterOptions);
+#endif  // defined(DAWN_ENABLE_BACKEND_OPENGL)
+        } else {
+            instance->DiscoverDefaultAdapters();
+        }
+    }
+
+    BackendBinding* CreateBinding(dawn_native::BackendType type,
+                                  GLFWwindow* window,
+                                  dawnDevice device) {
         switch (type) {
 #if defined(DAWN_ENABLE_BACKEND_D3D12)
             case dawn_native::BackendType::D3D12:
-                return CreateD3D12Binding();
+                return CreateD3D12Binding(window, device);
 #endif
 
 #if defined(DAWN_ENABLE_BACKEND_METAL)
             case dawn_native::BackendType::Metal:
-                return CreateMetalBinding();
+                return CreateMetalBinding(window, device);
 #endif
 
 #if defined(DAWN_ENABLE_BACKEND_NULL)
             case dawn_native::BackendType::Null:
-                return CreateNullBinding();
+                return CreateNullBinding(window, device);
 #endif
 
 #if defined(DAWN_ENABLE_BACKEND_OPENGL)
             case dawn_native::BackendType::OpenGL:
-                return CreateOpenGLBinding();
+                return CreateOpenGLBinding(window, device);
 #endif
 
 #if defined(DAWN_ENABLE_BACKEND_VULKAN)
             case dawn_native::BackendType::Vulkan:
-                return CreateVulkanBinding();
+                return CreateVulkanBinding(window, device);
 #endif
 
             default:
diff --git a/src/utils/BackendBinding.h b/src/utils/BackendBinding.h
index 44b7eb4..9cf3158 100644
--- a/src/utils/BackendBinding.h
+++ b/src/utils/BackendBinding.h
@@ -15,11 +15,10 @@
 #ifndef UTILS_BACKENDBINDING_H_
 #define UTILS_BACKENDBINDING_H_
 
-#include <dawn_native/DawnNative.h>
+#include "dawn/dawncpp.h"
+#include "dawn_native/DawnNative.h"
 
 struct GLFWwindow;
-typedef struct dawnProcTable_s dawnProcTable;
-typedef struct dawnDeviceImpl* dawnDevice;
 
 namespace utils {
 
@@ -27,18 +26,23 @@
       public:
         virtual ~BackendBinding() = default;
 
-        virtual void SetupGLFWWindowHints() = 0;
-        virtual dawnDevice CreateDevice() = 0;
         virtual uint64_t GetSwapChainImplementation() = 0;
         virtual dawnTextureFormat GetPreferredSwapChainTextureFormat() = 0;
 
-        void SetWindow(GLFWwindow* window);
-
       protected:
+        BackendBinding(GLFWwindow* window, dawnDevice device);
+
         GLFWwindow* mWindow = nullptr;
+        dawnDevice mDevice = nullptr;
     };
 
-    BackendBinding* CreateBinding(dawn_native::BackendType type);
+    void SetupGLFWWindowHintsForBackend(dawn_native::BackendType type);
+    void DiscoverAdapter(dawn_native::Instance* instance,
+                         GLFWwindow* window,
+                         dawn_native::BackendType type);
+    BackendBinding* CreateBinding(dawn_native::BackendType type,
+                                  GLFWwindow* window,
+                                  dawnDevice device);
 
 }  // namespace utils
 
diff --git a/src/utils/D3D12Binding.cpp b/src/utils/D3D12Binding.cpp
index e1c8687..8f6ec28 100644
--- a/src/utils/D3D12Binding.cpp
+++ b/src/utils/D3D12Binding.cpp
@@ -27,30 +27,14 @@
 
     class D3D12Binding : public BackendBinding {
       public:
-        void SetupGLFWWindowHints() override {
-            glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
-        }
-
-        dawnDevice CreateDevice() override {
-            // 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();
+        D3D12Binding(GLFWwindow* window, dawnDevice device) : BackendBinding(window, device) {
         }
 
         uint64_t GetSwapChainImplementation() override {
             if (mSwapchainImpl.userData == nullptr) {
                 HWND win32Window = glfwGetWin32Window(mWindow);
                 mSwapchainImpl =
-                    dawn_native::d3d12::CreateNativeSwapChainImpl(mBackendDevice, win32Window);
+                    dawn_native::d3d12::CreateNativeSwapChainImpl(mDevice, win32Window);
             }
             return reinterpret_cast<uint64_t>(&mSwapchainImpl);
         }
@@ -61,13 +45,11 @@
         }
 
       private:
-        std::unique_ptr<dawn_native::Instance> mInstance;
-        dawnDevice mBackendDevice = nullptr;
         dawnSwapChainImplementation mSwapchainImpl = {};
     };
 
-    BackendBinding* CreateD3D12Binding() {
-        return new D3D12Binding;
+    BackendBinding* CreateD3D12Binding(GLFWwindow* window, dawnDevice device) {
+        return new D3D12Binding(window, device);
     }
 
 }  // namespace utils
diff --git a/src/utils/MetalBinding.mm b/src/utils/MetalBinding.mm
index 5137253..bdc7d6e 100644
--- a/src/utils/MetalBinding.mm
+++ b/src/utils/MetalBinding.mm
@@ -110,26 +110,7 @@
 
     class MetalBinding : public BackendBinding {
       public:
-        void SetupGLFWWindowHints() override {
-            glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
-        }
-
-        dawnDevice CreateDevice() override {
-            // Make an instance and find a Metal 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::Metal) {
-                    dawnDevice device = adapter.CreateDevice();
-                    mMetalDevice = dawn_native::metal::GetMetalDevice(device);
-                    return device;
-                }
-            }
-
-            UNREACHABLE();
-            return {};
+        MetalBinding(GLFWwindow* window, dawnDevice device) : BackendBinding(window, device) {
         }
 
         uint64_t GetSwapChainImplementation() override {
@@ -145,12 +126,10 @@
         }
 
       private:
-        std::unique_ptr<dawn_native::Instance> mInstance;
-        id<MTLDevice> mMetalDevice = nil;
         dawnSwapChainImplementation mSwapchainImpl = {};
     };
 
-    BackendBinding* CreateMetalBinding() {
-        return new MetalBinding;
+    BackendBinding* CreateMetalBinding(GLFWwindow* window, dawnDevice device) {
+        return new MetalBinding(window, device);
     }
 }
diff --git a/src/utils/NullBinding.cpp b/src/utils/NullBinding.cpp
index 213cca7..92c48b47 100644
--- a/src/utils/NullBinding.cpp
+++ b/src/utils/NullBinding.cpp
@@ -23,23 +23,9 @@
 
     class NullBinding : public BackendBinding {
       public:
-        void SetupGLFWWindowHints() override {
+        NullBinding(GLFWwindow* window, dawnDevice device) : BackendBinding(window, device) {
         }
-        dawnDevice CreateDevice() override {
-            // Make an instance and find the null 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::Null) {
-                    return adapter.CreateDevice();
-                }
-            }
-
-            UNREACHABLE();
-            return {};
-        }
         uint64_t GetSwapChainImplementation() override {
             if (mSwapchainImpl.userData == nullptr) {
                 mSwapchainImpl = dawn_native::null::CreateNativeSwapChainImpl();
@@ -51,12 +37,11 @@
         }
 
       private:
-        std::unique_ptr<dawn_native::Instance> mInstance;
         dawnSwapChainImplementation mSwapchainImpl = {};
     };
 
-    BackendBinding* CreateNullBinding() {
-        return new NullBinding;
+    BackendBinding* CreateNullBinding(GLFWwindow* window, dawnDevice device) {
+        return new NullBinding(window, device);
     }
 
 }  // namespace utils
diff --git a/src/utils/OpenGLBinding.cpp b/src/utils/OpenGLBinding.cpp
index 146cfbe..0818101 100644
--- a/src/utils/OpenGLBinding.cpp
+++ b/src/utils/OpenGLBinding.cpp
@@ -95,36 +95,9 @@
 
     class OpenGLBinding : public BackendBinding {
       public:
-        void SetupGLFWWindowHints() override {
-#if defined(DAWN_PLATFORM_APPLE)
-            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
-            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
-            glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
-            glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-#else
-            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
-            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
-            glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
-            glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-#endif
-        }
-
-        dawnDevice CreateDevice() override {
-            glfwMakeContextCurrent(mWindow);
+        OpenGLBinding(GLFWwindow* window, dawnDevice device) : BackendBinding(window, device) {
             // Load the GL entry points in our copy of the glad static library
             gladLoadGLLoader(reinterpret_cast<GLADloadproc>(glfwGetProcAddress));
-
-            // Make an instance and "discover" an OpenGL adapter with glfw's getProc
-            mInstance = std::make_unique<dawn_native::Instance>();
-
-            dawn_native::opengl::AdapterDiscoveryOptions adapterOptions;
-            adapterOptions.getProc = reinterpret_cast<void* (*)(const char*)>(glfwGetProcAddress);
-            mInstance->DiscoverAdapters(&adapterOptions);
-
-            std::vector<dawn_native::Adapter> adapters = mInstance->GetAdapters();
-            ASSERT(adapters.size() == 1);
-
-            return adapters[0].CreateDevice();
         }
 
         uint64_t GetSwapChainImplementation() override {
@@ -139,12 +112,11 @@
         }
 
       private:
-        std::unique_ptr<dawn_native::Instance> mInstance;
         dawnSwapChainImplementation mSwapchainImpl = {};
     };
 
-    BackendBinding* CreateOpenGLBinding() {
-        return new OpenGLBinding;
+    BackendBinding* CreateOpenGLBinding(GLFWwindow* window, dawnDevice device) {
+        return new OpenGLBinding(window, device);
     }
 
 }  // namespace utils
diff --git a/src/utils/VulkanBinding.cpp b/src/utils/VulkanBinding.cpp
index c071415..fe4d943 100644
--- a/src/utils/VulkanBinding.cpp
+++ b/src/utils/VulkanBinding.cpp
@@ -26,25 +26,9 @@
 
     class VulkanBinding : public BackendBinding {
       public:
-        void SetupGLFWWindowHints() override {
-            glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
+        VulkanBinding(GLFWwindow* window, dawnDevice device) : BackendBinding(window, device) {
         }
-        dawnDevice CreateDevice() override {
-            // Make an instance and find a Vulkan 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::Vulkan) {
-                    mDevice = adapter.CreateDevice();
-                    return mDevice;
-                }
-            }
-
-            UNREACHABLE();
-            return {};
-        }
         uint64_t GetSwapChainImplementation() override {
             if (mSwapchainImpl.userData == nullptr) {
                 VkSurfaceKHR surface = VK_NULL_HANDLE;
@@ -63,13 +47,11 @@
         }
 
       private:
-        std::unique_ptr<dawn_native::Instance> mInstance;
-        dawnDevice mDevice = nullptr;
         dawnSwapChainImplementation mSwapchainImpl = {};
     };
 
-    BackendBinding* CreateVulkanBinding() {
-        return new VulkanBinding;
+    BackendBinding* CreateVulkanBinding(GLFWwindow* window, dawnDevice device) {
+        return new VulkanBinding(window, device);
     }
 
 }  // namespace utils