Directly load Swiftshader if no Vulkan driver is available

This may be a short term solution before linking our own version
of the Vulkan Loader.

Bug: dawn:283
Change-Id: Ifeddeaa5170bccc912c61059071a83c2b5fd9524
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/15121
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index 0bfede2..7bae973 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -543,9 +543,14 @@
     }
 
     if (use_swiftshader) {
-      data_deps += [ "${dawn_swiftshader_dir}/src/Vulkan:icd_file" ]
-      defines +=
-          [ "DAWN_SWIFTSHADER_VK_ICD_JSON=\"${swiftshader_icd_file_name}\"" ]
+      data_deps += [
+        "${dawn_swiftshader_dir}/src/Vulkan:icd_file",
+        "${dawn_swiftshader_dir}/src/Vulkan:swiftshader_libvulkan",
+      ]
+      defines += [
+        "DAWN_ENABLE_SWIFTSHADER",
+        "DAWN_SWIFTSHADER_VK_ICD_JSON=\"${swiftshader_icd_file_name}\"",
+      ]
     }
   }
 
diff --git a/src/dawn_native/vulkan/BackendVk.cpp b/src/dawn_native/vulkan/BackendVk.cpp
index e1ef3d2..75402dd 100644
--- a/src/dawn_native/vulkan/BackendVk.cpp
+++ b/src/dawn_native/vulkan/BackendVk.cpp
@@ -21,16 +21,31 @@
 #include "dawn_native/vulkan/AdapterVk.h"
 #include "dawn_native/vulkan/VulkanError.h"
 
+// TODO(crbug.com/dawn/283): Link against the Vulkan Loader and remove this.
+#if defined(DAWN_ENABLE_SWIFTSHADER)
+#    if defined(DAWN_PLATFORM_LINUX) || defined(DAWN_PLATFORM_FUSCHIA)
+constexpr char kSwiftshaderLibName[] = "libvk_swiftshader.so";
+#    elif defined(DAWN_PLATFORM_WINDOWS)
+constexpr char kSwiftshaderLibName[] = "vk_swiftshader.dll";
+#    elif defined(DAWN_PLATFORM_MAC)
+constexpr char kSwiftshaderLibName[] = "libvk_swiftshader.dylib";
+#    else
+#        error "Unimplemented Swiftshader Vulkan backend platform"
+#    endif
+#endif
+
 #if defined(DAWN_PLATFORM_LINUX)
 #    if defined(DAWN_PLATFORM_ANDROID)
-const char kVulkanLibName[] = "libvulkan.so";
+constexpr char kVulkanLibName[] = "libvulkan.so";
 #    else
-const char kVulkanLibName[] = "libvulkan.so.1";
+constexpr char kVulkanLibName[] = "libvulkan.so.1";
 #    endif
 #elif defined(DAWN_PLATFORM_WINDOWS)
-const char kVulkanLibName[] = "vulkan-1.dll";
+constexpr char kVulkanLibName[] = "vulkan-1.dll";
 #elif defined(DAWN_PLATFORM_FUCHSIA)
-const char kVulkanLibName[] = "libvulkan.so";
+constexpr char kVulkanLibName[] = "libvulkan.so";
+#elif defined(DAWN_ENABLE_SWIFTSHADER)
+const char* kVulkanLibName = kSwiftshaderLibName;
 #else
 #    error "Unimplemented Vulkan backend platform"
 #endif
@@ -66,7 +81,7 @@
         return mGlobalInfo;
     }
 
-    MaybeError Backend::Initialize() {
+    MaybeError Backend::LoadVulkan() {
 #if defined(DAWN_ENABLE_VULKAN_VALIDATION_LAYERS)
         if (GetInstance()->IsBackendValidationEnabled()) {
             std::string vkDataDir = GetExecutableDirectory() + DAWN_VK_DATA_DIR;
@@ -83,9 +98,25 @@
         }
 #endif
 
-        if (!mVulkanLib.Open(kVulkanLibName)) {
-            return DAWN_DEVICE_LOST_ERROR(std::string("Couldn't open ") + kVulkanLibName);
+        if (mVulkanLib.Open(kVulkanLibName)) {
+            return {};
         }
+        dawn::WarningLog() << std::string("Couldn't open ") + kVulkanLibName;
+
+#if defined(DAWN_ENABLE_SWIFTSHADER)
+        if (strcmp(kVulkanLibName, kSwiftshaderLibName) != 0) {
+            if (mVulkanLib.Open(kSwiftshaderLibName)) {
+                return {};
+            }
+            dawn::WarningLog() << std::string("Couldn't open ") + kSwiftshaderLibName;
+        }
+#endif
+
+        return DAWN_DEVICE_LOST_ERROR("Couldn't load Vulkan");
+    }
+
+    MaybeError Backend::Initialize() {
+        DAWN_TRY(LoadVulkan());
 
         DAWN_TRY(mFunctions.LoadGlobalProcs(mVulkanLib));
 
diff --git a/src/dawn_native/vulkan/BackendVk.h b/src/dawn_native/vulkan/BackendVk.h
index a0606b7..57a25b2 100644
--- a/src/dawn_native/vulkan/BackendVk.h
+++ b/src/dawn_native/vulkan/BackendVk.h
@@ -37,6 +37,7 @@
         std::vector<std::unique_ptr<AdapterBase>> DiscoverDefaultAdapters() override;
 
       private:
+        MaybeError LoadVulkan();
         ResultOrError<VulkanGlobalKnobs> CreateInstance();
 
         MaybeError RegisterDebugReport();