Vulkan: Always request all VkSurfaceKHR-related extensions

The backend had a "requiredInstanceExtensions" parameter to device
creation so that we could request the right instance extensions to
support swapchains. When we have dawn_native::Instance we don't want to
require this information before we can use the Vulkan backend. Instead
we make the backend always require all VkSurfaceKHR extensions. This
should be safe because these extensions basically enable copying a
struct into an opaque VkSurfaceKHR object and not much else.

BUG=dawn:29

Change-Id: I7fc5426f5770b65bb35f02793a1319eb0653782c
Reviewed-on: https://dawn-review.googlesource.com/c/3662
Reviewed-by: Stephen White <senorblanco@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn_native/vulkan/DeviceVk.cpp b/src/dawn_native/vulkan/DeviceVk.cpp
index 725df61..8b88141 100644
--- a/src/dawn_native/vulkan/DeviceVk.cpp
+++ b/src/dawn_native/vulkan/DeviceVk.cpp
@@ -54,8 +54,8 @@
 
 namespace dawn_native { namespace vulkan {
 
-    dawnDevice CreateDevice(const std::vector<const char*>& requiredInstanceExtensions) {
-        return reinterpret_cast<dawnDevice>(new Device(requiredInstanceExtensions));
+    dawnDevice CreateDevice() {
+        return reinterpret_cast<dawnDevice>(new Device());
     }
 
     VkInstance GetInstance(dawnDevice device) {
@@ -87,8 +87,8 @@
 
     // Device
 
-    Device::Device(const std::vector<const char*>& requiredInstanceExtensions) {
-        MaybeError maybeError = Initialize(requiredInstanceExtensions);
+    Device::Device() {
+        MaybeError maybeError = Initialize();
 
         // In device initialization, the error callback can't have been set yet.
         // So it's too early to use ConsumedError - consume the error manually.
@@ -101,7 +101,7 @@
         }
     }
 
-    MaybeError Device::Initialize(const std::vector<const char*>& requiredInstanceExtensions) {
+    MaybeError Device::Initialize() {
         if (!mVulkanLib.Open(kVulkanLibName)) {
             return DAWN_CONTEXT_LOST_ERROR(std::string("Couldn't open ") + kVulkanLibName);
         }
@@ -112,7 +112,7 @@
         DAWN_TRY_ASSIGN(mGlobalInfo, GatherGlobalInfo(*this));
 
         VulkanGlobalKnobs usedGlobalKnobs = {};
-        DAWN_TRY_ASSIGN(usedGlobalKnobs, CreateInstance(requiredInstanceExtensions));
+        DAWN_TRY_ASSIGN(usedGlobalKnobs, CreateInstance());
         *static_cast<VulkanGlobalKnobs*>(&mGlobalInfo) = usedGlobalKnobs;
 
         DAWN_TRY(functions->LoadInstanceProcs(mInstance, mGlobalInfo));
@@ -421,22 +421,11 @@
         mWaitSemaphores.push_back(semaphore);
     }
 
-    ResultOrError<VulkanGlobalKnobs> Device::CreateInstance(
-        const std::vector<const char*>& requiredExtensions) {
+    ResultOrError<VulkanGlobalKnobs> Device::CreateInstance() {
         VulkanGlobalKnobs usedKnobs = {};
 
         std::vector<const char*> layersToRequest;
-        std::vector<const char*> extensionsToRequest = requiredExtensions;
-
-        auto AddExtensionIfNotPresent = [](std::vector<const char*>* extensions,
-                                           const char* extension) {
-            for (const char* present : *extensions) {
-                if (strcmp(present, extension) == 0) {
-                    return;
-                }
-            }
-            extensions->push_back(extension);
-        };
+        std::vector<const char*> extensionsToRequest;
 
         // vktrace works by instering a layer, but we hide it behind a macro due to the vktrace
         // layer crashes when used without vktrace server started, see this vktrace issue:
@@ -463,14 +452,36 @@
             usedKnobs.standardValidation = true;
         }
         if (mGlobalInfo.debugReport) {
-            AddExtensionIfNotPresent(&extensionsToRequest, kExtensionNameExtDebugReport);
+            extensionsToRequest.push_back(kExtensionNameExtDebugReport);
             usedKnobs.debugReport = true;
         }
 #endif
+        // Always request all extensions used to create VkSurfaceKHR objects so that they are
+        // always available for embedders looking to create VkSurfaceKHR on our VkInstance.
+        if (mGlobalInfo.macosSurface) {
+            extensionsToRequest.push_back(kExtensionNameMvkMacosSurface);
+            usedKnobs.macosSurface = true;
+        }
         if (mGlobalInfo.surface) {
-            AddExtensionIfNotPresent(&extensionsToRequest, kExtensionNameKhrSurface);
+            extensionsToRequest.push_back(kExtensionNameKhrSurface);
             usedKnobs.surface = true;
         }
+        if (mGlobalInfo.waylandSurface) {
+            extensionsToRequest.push_back(kExtensionNameKhrWaylandSurface);
+            usedKnobs.waylandSurface = true;
+        }
+        if (mGlobalInfo.win32Surface) {
+            extensionsToRequest.push_back(kExtensionNameKhrWin32Surface);
+            usedKnobs.win32Surface = true;
+        }
+        if (mGlobalInfo.xcbSurface) {
+            extensionsToRequest.push_back(kExtensionNameKhrXcbSurface);
+            usedKnobs.xcbSurface = true;
+        }
+        if (mGlobalInfo.xlibSurface) {
+            extensionsToRequest.push_back(kExtensionNameKhrXlibSurface);
+            usedKnobs.xlibSurface = true;
+        }
 
         VkApplicationInfo appInfo;
         appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
diff --git a/src/dawn_native/vulkan/DeviceVk.h b/src/dawn_native/vulkan/DeviceVk.h
index 4ff27d41..b3af48a 100644
--- a/src/dawn_native/vulkan/DeviceVk.h
+++ b/src/dawn_native/vulkan/DeviceVk.h
@@ -38,7 +38,7 @@
 
     class Device : public DeviceBase {
       public:
-        Device(const std::vector<const char*>& requiredInstanceExtensions);
+        Device();
         ~Device();
 
         // Contains all the Vulkan entry points, vkDoFoo is called via device->fn.DoFoo.
@@ -96,9 +96,8 @@
             TextureBase* texture,
             const TextureViewDescriptor* descriptor) override;
 
-        MaybeError Initialize(const std::vector<const char*>& requiredInstanceExtensions);
-        ResultOrError<VulkanGlobalKnobs> CreateInstance(
-            const std::vector<const char*>& requiredExtensions);
+        MaybeError Initialize();
+        ResultOrError<VulkanGlobalKnobs> CreateInstance();
         ResultOrError<VulkanDeviceKnobs> CreateDevice();
         void GatherQueueFromDevice();
 
diff --git a/src/dawn_native/vulkan/VulkanInfo.cpp b/src/dawn_native/vulkan/VulkanInfo.cpp
index 625d7c1..c8c11a8 100644
--- a/src/dawn_native/vulkan/VulkanInfo.cpp
+++ b/src/dawn_native/vulkan/VulkanInfo.cpp
@@ -35,8 +35,13 @@
     const char kLayerNameRenderDocCapture[] = "VK_LAYER_RENDERDOC_Capture";
 
     const char kExtensionNameExtDebugReport[] = "VK_EXT_debug_report";
+    const char kExtensionNameMvkMacosSurface[] = "VK_MVK_macos_surface";
     const char kExtensionNameKhrSurface[] = "VK_KHR_surface";
     const char kExtensionNameKhrSwapchain[] = "VK_KHR_swapchain";
+    const char kExtensionNameKhrWaylandSurface[] = "VK_KHR_wayland_surface";
+    const char kExtensionNameKhrWin32Surface[] = "VK_KHR_win32_surface";
+    const char kExtensionNameKhrXcbSurface[] = "VK_KHR_xcb_surface";
+    const char kExtensionNameKhrXlibSurface[] = "VK_KHR_xlib_surface";
 
     ResultOrError<VulkanGlobalInfo> GatherGlobalInfo(const Device& device) {
         VulkanGlobalInfo info = {};
@@ -91,9 +96,24 @@
                 if (IsExtensionName(extension, kExtensionNameExtDebugReport)) {
                     info.debugReport = true;
                 }
+                if (IsExtensionName(extension, kExtensionNameMvkMacosSurface)) {
+                    info.macosSurface = true;
+                }
                 if (IsExtensionName(extension, kExtensionNameKhrSurface)) {
                     info.surface = true;
                 }
+                if (IsExtensionName(extension, kExtensionNameKhrWaylandSurface)) {
+                    info.waylandSurface = true;
+                }
+                if (IsExtensionName(extension, kExtensionNameKhrWin32Surface)) {
+                    info.win32Surface = true;
+                }
+                if (IsExtensionName(extension, kExtensionNameKhrXcbSurface)) {
+                    info.xcbSurface = true;
+                }
+                if (IsExtensionName(extension, kExtensionNameKhrXlibSurface)) {
+                    info.xlibSurface = true;
+                }
             }
         }
 
diff --git a/src/dawn_native/vulkan/VulkanInfo.h b/src/dawn_native/vulkan/VulkanInfo.h
index 383ea9b..fee253b 100644
--- a/src/dawn_native/vulkan/VulkanInfo.h
+++ b/src/dawn_native/vulkan/VulkanInfo.h
@@ -29,8 +29,13 @@
     extern const char kLayerNameRenderDocCapture[];
 
     extern const char kExtensionNameExtDebugReport[];
+    extern const char kExtensionNameMvkMacosSurface[];
     extern const char kExtensionNameKhrSurface[];
     extern const char kExtensionNameKhrSwapchain[];
+    extern const char kExtensionNameKhrWaylandSurface[];
+    extern const char kExtensionNameKhrWin32Surface[];
+    extern const char kExtensionNameKhrXcbSurface[];
+    extern const char kExtensionNameKhrXlibSurface[];
 
     // Global information - gathered before the instance is created
     struct VulkanGlobalKnobs {
@@ -41,7 +46,12 @@
 
         // Extensions
         bool debugReport = false;
+        bool macosSurface = false;
         bool surface = false;
+        bool waylandSurface = false;
+        bool win32Surface = false;
+        bool xcbSurface = false;
+        bool xlibSurface = false;
     };
 
     struct VulkanGlobalInfo : VulkanGlobalKnobs {
diff --git a/src/include/dawn_native/VulkanBackend.h b/src/include/dawn_native/VulkanBackend.h
index e52e0ce..9bf7a2a 100644
--- a/src/include/dawn_native/VulkanBackend.h
+++ b/src/include/dawn_native/VulkanBackend.h
@@ -24,8 +24,7 @@
 #include <vector>
 
 namespace dawn_native { namespace vulkan {
-    DAWN_NATIVE_EXPORT dawnDevice
-    CreateDevice(const std::vector<const char*>& requiredInstanceExtensions);
+    DAWN_NATIVE_EXPORT dawnDevice CreateDevice();
 
     DAWN_NATIVE_EXPORT VkInstance GetInstance(dawnDevice device);
 
diff --git a/src/utils/VulkanBinding.cpp b/src/utils/VulkanBinding.cpp
index bc3f62b..7cae7b4 100644
--- a/src/utils/VulkanBinding.cpp
+++ b/src/utils/VulkanBinding.cpp
@@ -28,13 +28,7 @@
             glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
         }
         dawnDevice CreateDevice() override {
-            uint32_t extensionCount = 0;
-            const char** glfwInstanceExtensions =
-                glfwGetRequiredInstanceExtensions(&extensionCount);
-            std::vector<const char*> requiredExtensions(glfwInstanceExtensions,
-                                                        glfwInstanceExtensions + extensionCount);
-
-            mDevice = dawn_native::vulkan::CreateDevice(requiredExtensions);
+            mDevice = dawn_native::vulkan::CreateDevice();
             return mDevice;
         }
         uint64_t GetSwapChainImplementation() override {