Add Instance and CreateInstance to webgpu.h

This is the first step in making the API before WGPUDevice creation
match webgpu.h and is necessary to implement WGPUSwapChain.

BUG=dawn:269

Change-Id: If92ced42d7683d79e67c02738949ff8b483d22c4
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/14061
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
diff --git a/dawn.json b/dawn.json
index 30dbbef..3e3fdd9 100644
--- a/dawn.json
+++ b/dawn.json
@@ -738,6 +738,14 @@
             {"value": 1, "name": "uint32"}
         ]
     },
+    "instance": {
+        "category": "object"
+    },
+    "instance descriptor": {
+        "category": "structure",
+        "extensible": true,
+        "members": []
+    },
     "vertex attribute descriptor": {
         "category": "structure",
         "extensible": false,
diff --git a/generator/templates/dawn_native/ProcTable.cpp b/generator/templates/dawn_native/ProcTable.cpp
index 9088ce3..1713ac2 100644
--- a/generator/templates/dawn_native/ProcTable.cpp
+++ b/generator/templates/dawn_native/ProcTable.cpp
@@ -92,6 +92,12 @@
         static constexpr size_t sProcMapSize = sizeof(sProcMap) / sizeof(sProcMap[0]);
     }
 
+    WGPUInstance NativeCreateInstance(WGPUInstanceDescriptor const* cDescriptor) {
+        const dawn_native::InstanceDescriptor* descriptor =
+            reinterpret_cast<const dawn_native::InstanceDescriptor*>(cDescriptor);
+        return reinterpret_cast<WGPUInstance>(InstanceBase::Create(descriptor));
+    }
+
     WGPUProc NativeGetProcAddress(WGPUDevice, const char* procName) {
         if (procName == nullptr) {
             return nullptr;
@@ -107,10 +113,15 @@
             return entry->proc;
         }
 
+        // Special case the two free-standing functions of the API.
         if (strcmp(procName, "wgpuGetProcAddress") == 0) {
             return reinterpret_cast<WGPUProc>(NativeGetProcAddress);
         }
 
+        if (strcmp(procName, "wgpuCreateInstance") == 0) {
+            return reinterpret_cast<WGPUProc>(NativeCreateInstance);
+        }
+
         return nullptr;
     }
 
@@ -126,6 +137,7 @@
     DawnProcTable GetProcsAutogen() {
         DawnProcTable table;
         table.getProcAddress = NativeGetProcAddress;
+        table.createInstance = NativeCreateInstance;
         {% for type in by_category["object"] %}
             {% for method in c_methods(type) %}
                 table.{{as_varName(type.name, method.name)}} = Native{{as_MethodSuffix(type.name, method.name)}};
diff --git a/generator/templates/dawn_proc.c b/generator/templates/dawn_proc.c
index 6d6153d..9d77755 100644
--- a/generator/templates/dawn_proc.c
+++ b/generator/templates/dawn_proc.c
@@ -26,6 +26,10 @@
     }
 }
 
+WGPUInstance wgpuCreateInstance(WGPUInstanceDescriptor const * descriptor) {
+    return procs.createInstance(descriptor);
+}
+
 WGPUProc wgpuGetProcAddress(WGPUDevice device, const char* procName) {
     return procs.getProcAddress(device, procName);
 }
diff --git a/generator/templates/dawn_proc_table.h b/generator/templates/dawn_proc_table.h
index 75304b8..197f300 100644
--- a/generator/templates/dawn_proc_table.h
+++ b/generator/templates/dawn_proc_table.h
@@ -19,6 +19,7 @@
 
 typedef struct DawnProcTable {
     WGPUProcGetProcAddress getProcAddress;
+    WGPUProcCreateInstance createInstance;
 
     {% for type in by_category["object"] %}
         {% for method in c_methods(type) %}
diff --git a/generator/templates/dawn_wire/client/ApiProcs.cpp b/generator/templates/dawn_wire/client/ApiProcs.cpp
index 054d2af..121e983 100644
--- a/generator/templates/dawn_wire/client/ApiProcs.cpp
+++ b/generator/templates/dawn_wire/client/ApiProcs.cpp
@@ -94,6 +94,11 @@
     {% endfor %}
 
     namespace {
+        WGPUInstance ClientCreateInstance(WGPUInstanceDescriptor const* descriptor) {
+            UNREACHABLE();
+            return nullptr;
+        }
+
         struct ProcEntry {
             WGPUProc proc;
             const char* name;
@@ -121,10 +126,15 @@
             return entry->proc;
         }
 
+        // Special case the two free-standing functions of the API.
         if (strcmp(procName, "wgpuGetProcAddress") == 0) {
             return reinterpret_cast<WGPUProc>(ClientGetProcAddress);
         }
 
+        if (strcmp(procName, "wgpuCreateInstance") == 0) {
+            return reinterpret_cast<WGPUProc>(ClientCreateInstance);
+        }
+
         return nullptr;
     }
 
@@ -145,6 +155,7 @@
     DawnProcTable GetProcs() {
         DawnProcTable table;
         table.getProcAddress = ClientGetProcAddress;
+        table.createInstance = ClientCreateInstance;
         {% for type in by_category["object"] %}
             {% for method in c_methods(type) %}
                 {% set suffix = as_MethodSuffix(type.name, method.name) %}
diff --git a/generator/templates/webgpu.h b/generator/templates/webgpu.h
index dbbe36a..d1fcb32 100644
--- a/generator/templates/webgpu.h
+++ b/generator/templates/webgpu.h
@@ -101,6 +101,7 @@
 
 #if !defined(WGPU_SKIP_PROCS)
 
+typedef WGPUInstance (*WGPUProcCreateInstance)(WGPUInstanceDescriptor const * descriptor);
 typedef WGPUProc (*WGPUProcGetProcAddress)(WGPUDevice device, char const * procName);
 
 {% for type in by_category["object"] if len(c_methods(type)) > 0 %}
@@ -119,6 +120,7 @@
 
 #if !defined(WGPU_SKIP_DECLARATIONS)
 
+WGPU_EXPORT WGPUInstance wgpuCreateInstance(WGPUInstanceDescriptor const * descriptor);
 WGPU_EXPORT WGPUProc wgpuGetProcAddress(WGPUDevice device, char const * procName);
 
 {% for type in by_category["object"] if len(c_methods(type)) > 0 %}
diff --git a/generator/templates/webgpu_cpp.cpp b/generator/templates/webgpu_cpp.cpp
index 1f4bbc7..0bfcbd4 100644
--- a/generator/templates/webgpu_cpp.cpp
+++ b/generator/templates/webgpu_cpp.cpp
@@ -125,6 +125,12 @@
 
     {% endfor %}
 
+    Instance CreateInstance(const InstanceDescriptor* descriptor) {
+        const WGPUInstanceDescriptor* cDescriptor =
+            reinterpret_cast<const WGPUInstanceDescriptor*>(descriptor);
+        return Instance::Acquire(wgpuCreateInstance(cDescriptor));
+    }
+
     Proc GetProcAddress(Device const& device, const char* procName) {
         return reinterpret_cast<Proc>(wgpuGetProcAddress(device.Get(), procName));
     }
diff --git a/generator/templates/webgpu_cpp.h b/generator/templates/webgpu_cpp.h
index b110f56..14b5a2e 100644
--- a/generator/templates/webgpu_cpp.h
+++ b/generator/templates/webgpu_cpp.h
@@ -183,6 +183,7 @@
 
     {% endfor %}
 
+    Instance CreateInstance(InstanceDescriptor const * descriptor = nullptr);
     Proc GetProcAddress(Device const& device, const char* procName);
 
     {% for type in by_category["structure"] %}
diff --git a/src/dawn_native/DawnNative.cpp b/src/dawn_native/DawnNative.cpp
index f058d78..857d0d2 100644
--- a/src/dawn_native/DawnNative.cpp
+++ b/src/dawn_native/DawnNative.cpp
@@ -80,12 +80,14 @@
 
     // Instance
 
-    Instance::Instance() : mImpl(new InstanceBase()) {
+    Instance::Instance() : mImpl(InstanceBase::Create()) {
     }
 
     Instance::~Instance() {
-        delete mImpl;
-        mImpl = nullptr;
+        if (mImpl != nullptr) {
+            mImpl->Release();
+            mImpl = nullptr;
+        }
     }
 
     void Instance::DiscoverDefaultAdapters() {
@@ -121,6 +123,10 @@
         mImpl->SetPlatform(platform);
     }
 
+    WGPUInstance Instance::Get() const {
+        return reinterpret_cast<WGPUInstance>(mImpl);
+    }
+
     size_t GetLazyClearCountForTesting(WGPUDevice device) {
         dawn_native::DeviceBase* deviceBase = reinterpret_cast<dawn_native::DeviceBase*>(device);
         return deviceBase->GetLazyClearCountForTesting();
diff --git a/src/dawn_native/Instance.cpp b/src/dawn_native/Instance.cpp
index d758987..c26d597 100644
--- a/src/dawn_native/Instance.cpp
+++ b/src/dawn_native/Instance.cpp
@@ -50,6 +50,19 @@
 
     // InstanceBase
 
+    // static
+    InstanceBase* InstanceBase::Create(const InstanceDescriptor* descriptor) {
+        Ref<InstanceBase> instance = AcquireRef(new InstanceBase);
+        if (!instance->Initialize(descriptor)) {
+            return nullptr;
+        }
+        return instance.Detach();
+    }
+
+    bool InstanceBase::Initialize(const InstanceDescriptor*) {
+        return true;
+    }
+
     void InstanceBase::DiscoverDefaultAdapters() {
         EnsureBackendConnections();
 
diff --git a/src/dawn_native/Instance.h b/src/dawn_native/Instance.h
index 1e704e0..0881d01 100644
--- a/src/dawn_native/Instance.h
+++ b/src/dawn_native/Instance.h
@@ -18,7 +18,9 @@
 #include "dawn_native/Adapter.h"
 #include "dawn_native/BackendConnection.h"
 #include "dawn_native/Extensions.h"
+#include "dawn_native/RefCounted.h"
 #include "dawn_native/Toggles.h"
+#include "dawn_native/dawn_platform.h"
 
 #include <array>
 #include <memory>
@@ -29,13 +31,9 @@
 
     // This is called InstanceBase for consistency across the frontend, even if the backends don't
     // specialize this class.
-    class InstanceBase final {
+    class InstanceBase final : public RefCounted {
       public:
-        InstanceBase() = default;
-        ~InstanceBase() = default;
-
-        InstanceBase(const InstanceBase& other) = delete;
-        InstanceBase& operator=(const InstanceBase& other) = delete;
+        static InstanceBase* Create(const InstanceDescriptor* descriptor = nullptr);
 
         void DiscoverDefaultAdapters();
         bool DiscoverAdapters(const AdapterDiscoveryOptionsBase* options);
@@ -67,6 +65,14 @@
         dawn_platform::Platform* GetPlatform() const;
 
       private:
+        InstanceBase() = default;
+        ~InstanceBase() = default;
+
+        InstanceBase(const InstanceBase& other) = delete;
+        InstanceBase& operator=(const InstanceBase& other) = delete;
+
+        bool Initialize(const InstanceDescriptor* descriptor);
+
         // Lazily creates connections to all backends that have been compiled.
         void EnsureBackendConnections();
 
diff --git a/src/include/dawn_native/DawnNative.h b/src/include/dawn_native/DawnNative.h
index a7e8d6c..17ed5e3 100644
--- a/src/include/dawn_native/DawnNative.h
+++ b/src/include/dawn_native/DawnNative.h
@@ -146,6 +146,9 @@
 
         void SetPlatform(dawn_platform::Platform* platform);
 
+        // Returns the underlying WGPUInstance object.
+        WGPUInstance Get() const;
+
       private:
         InstanceBase* mImpl = nullptr;
     };
diff --git a/src/tests/unittests/ExtensionTests.cpp b/src/tests/unittests/ExtensionTests.cpp
index 4e2a81c..2805e11 100644
--- a/src/tests/unittests/ExtensionTests.cpp
+++ b/src/tests/unittests/ExtensionTests.cpp
@@ -20,7 +20,10 @@
 
 class ExtensionTests : public testing::Test {
   public:
-    ExtensionTests() : testing::Test(), mInstanceBase(), mAdapterBase(&mInstanceBase) {
+    ExtensionTests()
+        : testing::Test(),
+          mInstanceBase(dawn_native::InstanceBase::Create()),
+          mAdapterBase(mInstanceBase.Get()) {
     }
 
     std::vector<const char*> GetAllExtensionNames() {
@@ -35,7 +38,7 @@
         static_cast<size_t>(dawn_native::Extension::EnumCount);
 
   protected:
-    dawn_native::InstanceBase mInstanceBase;
+    dawn_native::Ref<dawn_native::InstanceBase> mInstanceBase;
     dawn_native::null::Adapter mAdapterBase;
 };
 
diff --git a/src/tests/unittests/GetProcAddressTests.cpp b/src/tests/unittests/GetProcAddressTests.cpp
index 0d6c209..e18309c 100644
--- a/src/tests/unittests/GetProcAddressTests.cpp
+++ b/src/tests/unittests/GetProcAddressTests.cpp
@@ -51,8 +51,8 @@
       public:
         GetProcAddressTests()
             : testing::TestWithParam<DawnFlavor>(),
-              mNativeInstance(),
-              mNativeAdapter(&mNativeInstance) {
+              mNativeInstance(dawn_native::InstanceBase::Create()),
+              mNativeAdapter(mNativeInstance.Get()) {
         }
 
         void SetUp() override {
@@ -90,7 +90,7 @@
         }
 
       protected:
-        dawn_native::InstanceBase mNativeInstance;
+        dawn_native::Ref<dawn_native::InstanceBase> mNativeInstance;
         dawn_native::null::Adapter mNativeAdapter;
 
         std::unique_ptr<utils::TerribleCommandBuffer> mC2sBuf;
@@ -136,13 +136,17 @@
         ASSERT_EQ(mProcs.getProcAddress(mDevice.Get(), "0"), nullptr);
     }
 
-    // Test that GetProcAddress supports itself: it is handled specially because it is a
-    // freestanding function and not a method on an object.
-    TEST_P(GetProcAddressTests, GetProcAddressItself) {
+    // Test that GetProcAddress supports freestanding function that are handled specially
+    TEST_P(GetProcAddressTests, FreeStandingFunctions) {
         ASSERT_EQ(mProcs.getProcAddress(nullptr, "wgpuGetProcAddress"),
                   reinterpret_cast<WGPUProc>(mProcs.getProcAddress));
         ASSERT_EQ(mProcs.getProcAddress(mDevice.Get(), "wgpuGetProcAddress"),
                   reinterpret_cast<WGPUProc>(mProcs.getProcAddress));
+
+        ASSERT_EQ(mProcs.getProcAddress(nullptr, "wgpuCreateInstance"),
+                  reinterpret_cast<WGPUProc>(mProcs.createInstance));
+        ASSERT_EQ(mProcs.getProcAddress(mDevice.Get(), "wgpuCreateInstance"),
+                  reinterpret_cast<WGPUProc>(mProcs.createInstance));
     }
 
     INSTANTIATE_TEST_SUITE_P(,