Allow using swiftshader with the Vulkan backend

This adds swiftshader as a dependency of Dawn, and when it is present
dawn_use_swiftshader=true will force usage of it. (due to a Vulkan
loader limitation we can't have both regular drivers and swiftshader in
the same VkInstance).

BUG=dawn:283

Change-Id: Ib94f4dcca652eb380e994f007cdcfb145b1a5102
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/13440
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/.gitignore b/.gitignore
index c27c509..ceead6e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,6 +19,7 @@
 third_party/llvm-build
 third_party/markupsafe/
 third_party/shaderc/
+third_party/swiftshader/
 third_party/spirv-cross/
 third_party/spirv-headers/
 third_party/vulkan-headers/
diff --git a/BUILD.gn b/BUILD.gn
index 7d7933d..26cdf68 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -21,6 +21,16 @@
 
 import("//testing/test.gni")
 
+# Swiftshader is an optional dependency of Dawn so we only use it if the path
+# to it has been set.
+use_swiftshader = dawn_use_swiftshader && dawn_swiftshader_dir != ""
+
+if (use_swiftshader) {
+  assert(dawn_enable_vulkan,
+         "dawn_use_swiftshader requires dawn_enable_vulkan=true")
+  import("${dawn_swiftshader_dir}/src/Vulkan/vulkan.gni")
+}
+
 ###############################################################################
 # dawn_platform
 ###############################################################################
@@ -128,9 +138,10 @@
     "third_party:spirv_cross",
   ]
   defines = []
+  libs = []
+  data_deps = []
 
   configs += [ ":libdawn_native_internal" ]
-  libs = []
 
   # Dependencies that are needed to compile libdawn_native entry points in
   # FooBackend.cpp need to be public deps so they are propagated to the
@@ -511,6 +522,12 @@
         "DAWN_VK_DATA_DIR=\"$vulkan_data_subdir\"",
       ]
     }
+
+    if (use_swiftshader) {
+      data_deps += [ "${dawn_swiftshader_dir}/src/Vulkan:icd_file" ]
+      defines +=
+          [ "DAWN_SWIFTSHADER_VK_ICD_JSON=\"${swiftshader_icd_file_name}\"" ]
+    }
   }
 }
 
diff --git a/DEPS b/DEPS
index b6a2883..913d781 100644
--- a/DEPS
+++ b/DEPS
@@ -5,6 +5,7 @@
   'chromium_git': 'https://chromium.googlesource.com',
   'dawn_git': 'https://dawn.googlesource.com',
   'github_git': 'https://github.com',
+  'swiftshader_git': 'https://swiftshader.googlesource.com',
 
   'dawn_standalone': True,
 }
@@ -112,6 +113,12 @@
     'url': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@9fba37afae13a11bd49ae942bf82e5bf1098e381',
     'condition': 'dawn_standalone',
   },
+
+  'third_party/swiftshader': {
+    'url': '{swiftshader_git}/SwiftShader@e7ce4e53915d026720005ca2c1831a5c28f77b3f',
+    'condition': 'dawn_standalone',
+  },
+
 }
 
 hooks = [
diff --git a/build_overrides/dawn.gni b/build_overrides/dawn.gni
index 968d43b..0d44f3b 100644
--- a/build_overrides/dawn.gni
+++ b/build_overrides/dawn.gni
@@ -31,4 +31,5 @@
 dawn_shaderc_dir = "//third_party/shaderc"
 dawn_spirv_tools_dir = "//third_party/SPIRV-Tools"
 dawn_spirv_cross_dir = "//third_party/spirv-cross"
+dawn_swiftshader_dir = "//third_party/swiftshader"
 dawn_vulkan_validation_layers_dir = "//third_party/vulkan-validation-layers"
diff --git a/build_overrides/swiftshader.gni b/build_overrides/swiftshader.gni
new file mode 100644
index 0000000..4153f72
--- /dev/null
+++ b/build_overrides/swiftshader.gni
@@ -0,0 +1,22 @@
+# 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.
+
+# We are building SwiftShader inside Dawn
+swiftshader_standalone = false
+
+# Path to SwiftShader
+swiftshader_dir = "//third_party/swiftshader"
+
+# Paths to SwiftShader dependencies in Dawn
+swiftshader_spirv_tools_dir = "//third_party/SPIRV-Tools"
diff --git a/scripts/dawn_features.gni b/scripts/dawn_features.gni
index 84ac2bb..2de3260 100644
--- a/scripts/dawn_features.gni
+++ b/scripts/dawn_features.gni
@@ -44,14 +44,20 @@
   # GLSL/HLSL/MSL compiler. This implicitly pulls in the GLSL
   # compiler, since it is a sub-class of if.
   dawn_enable_cross_reflection = false
+
+  # Enables usage of swiftshader on the Vulkan backend.
+  # Note that this will only work in standalone and in projects that set the
+  # dawn_swiftshader_dir variable in build_overrides/dawn.gni
+  # Because of how the Vulkan loader works, setting this make Dawn only able
+  # to find the Swiftshader ICD and not the others.
+  dawn_use_swiftshader = false
 }
 
 # GN does not allow reading a variable defined in the same declare_args().
 # Put them in two separate declare_args() when setting the value of one
 # argument based on another.
-if (dawn_enable_vulkan) {
-  declare_args() {
-    # Uses our built version of Vulkan validation layers
-    dawn_enable_vulkan_validation_layers = (is_linux && !is_chromeos) || is_win
-  }
+declare_args() {
+  # Uses our built version of Vulkan validation layers
+  dawn_enable_vulkan_validation_layers =
+      dawn_enable_vulkan && ((is_linux && !is_chromeos) || is_win)
 }
diff --git a/scripts/dawn_overrides_with_defaults.gni b/scripts/dawn_overrides_with_defaults.gni
index 2e69e76..b7eaee1 100644
--- a/scripts/dawn_overrides_with_defaults.gni
+++ b/scripts/dawn_overrides_with_defaults.gni
@@ -57,6 +57,11 @@
   dawn_spirv_tools_dir = "//third_party/SPIRV-Tools"
 }
 
+if (!defined(dawn_swiftshader_dir)) {
+  # Default to swiftshader not being available.
+  dawn_swiftshader_dir = ""
+}
+
 if (!defined(dawn_vulkan_validaion_layers_dir)) {
   dawn_vulkan_validaion_layers_dir = "//third_party/vulkan-validation-layers"
 }
diff --git a/src/dawn_native/vulkan/BackendVk.cpp b/src/dawn_native/vulkan/BackendVk.cpp
index 9ac3224..02b5b3a 100644
--- a/src/dawn_native/vulkan/BackendVk.cpp
+++ b/src/dawn_native/vulkan/BackendVk.cpp
@@ -67,11 +67,18 @@
         if (GetInstance()->IsBackendValidationEnabled()) {
             std::string vkDataDir = GetExecutableDirectory() + DAWN_VK_DATA_DIR;
             if (!SetEnvironmentVar("VK_LAYER_PATH", vkDataDir.c_str())) {
-                return DAWN_DEVICE_LOST_ERROR(std::string("Couldn't set VK_LAYER_PATH with ") +
-                                              vkDataDir);
+                return DAWN_DEVICE_LOST_ERROR("Couldn't set VK_LAYER_PATH");
             }
         }
 #endif
+#if defined(DAWN_SWIFTSHADER_VK_ICD_JSON)
+        std::string fullSwiftshaderICDPath =
+            GetExecutableDirectory() + DAWN_SWIFTSHADER_VK_ICD_JSON;
+        if (!SetEnvironmentVar("VK_ICD_FILENAMES", fullSwiftshaderICDPath.c_str())) {
+            return DAWN_DEVICE_LOST_ERROR("Couldn't set VK_ICD_FILENAMES");
+        }
+#endif
+
         if (!mVulkanLib.Open(kVulkanLibName)) {
             return DAWN_DEVICE_LOST_ERROR(std::string("Couldn't open ") + kVulkanLibName);
         }