Fixes Dawn to use custom Vulkan loader on Linux systems.
- Adds system utility to get the module directory for dawn native.
- Updates Vulkan backend to use the module directory to find loader.
- Test ran on NVIDIA GTX 1660 here: https://chromium-swarm.appspot.com/task?id=576d77991add7c10.
Bug: dawn:1191
Change-Id: I7c577008b5252ac94f38c8cdb56f7e8d8a0aa956
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/70860
Commit-Queue: Loko Kung <lokokung@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/scripts/dawn_features.gni b/scripts/dawn_features.gni
index 5a80f4d..03d3449 100644
--- a/scripts/dawn_features.gni
+++ b/scripts/dawn_features.gni
@@ -15,8 +15,8 @@
import("//build_overrides/build.gni")
if (build_with_chromium) {
- import("//build/config/sanitizers/sanitizers.gni")
import("//build/config/ozone.gni")
+ import("//build/config/sanitizers/sanitizers.gni")
dawn_use_x11 = ozone_platform_x11
} else {
@@ -97,7 +97,8 @@
# Uses our built version of the Vulkan loader on platforms where we can't
# assume to have one present at the system level.
- dawn_enable_vulkan_loader = dawn_enable_vulkan && is_mac
+ dawn_enable_vulkan_loader =
+ dawn_enable_vulkan && (is_mac || (is_linux && !is_android))
}
# UWP only supports CoreWindow for windowing
diff --git a/scripts/dawn_overrides_with_defaults.gni b/scripts/dawn_overrides_with_defaults.gni
index 4b30ec2..eb3de8e 100644
--- a/scripts/dawn_overrides_with_defaults.gni
+++ b/scripts/dawn_overrides_with_defaults.gni
@@ -63,8 +63,7 @@
}
if (!defined(dawn_vulkan_loader_dir)) {
- # Default to the Vulkan loader not being available.
- dawn_vulkan_loader_dir = ""
+ dawn_vulkan_loader_dir = "//third_party/vulkan-deps/vulkan-loader/src"
}
if (!defined(dawn_vulkan_validation_layers_dir)) {
diff --git a/src/common/SystemUtils.cpp b/src/common/SystemUtils.cpp
index b56a08c..9dc066a 100644
--- a/src/common/SystemUtils.cpp
+++ b/src/common/SystemUtils.cpp
@@ -21,10 +21,12 @@
# include <Windows.h>
# include <vector>
#elif defined(DAWN_PLATFORM_LINUX)
+# include <dlfcn.h>
# include <limits.h>
# include <unistd.h>
# include <cstdlib>
#elif defined(DAWN_PLATFORM_MACOS) || defined(DAWN_PLATFORM_IOS)
+# include <dlfcn.h>
# include <mach-o/dyld.h>
# include <vector>
#endif
@@ -136,6 +138,45 @@
return lastPathSepLoc != std::string::npos ? exePath.substr(0, lastPathSepLoc + 1) : "";
}
+#if defined(DAWN_PLATFORM_LINUX) || defined(DAWN_PLATFORM_MACOS) || defined(DAWN_PLATFORM_IOS)
+std::string GetModulePath() {
+ static int placeholderSymbol = 0;
+ Dl_info dlInfo;
+ if (dladdr(&placeholderSymbol, &dlInfo) == 0) {
+ return "";
+ }
+
+ std::array<char, PATH_MAX> absolutePath;
+ if (realpath(dlInfo.dli_fname, absolutePath.data()) == NULL) {
+ return "";
+ }
+ return absolutePath.data();
+}
+#elif defined(DAWN_PLATFORM_WINDOWS)
+std::string GetModulePath() {
+ UNREACHABLE();
+ return "";
+}
+#elif defined(DAWN_PLATFORM_FUCHSIA)
+std::string GetModulePath() {
+ UNREACHABLE();
+ return "";
+}
+#elif defined(DAWN_PLATFORM_EMSCRIPTEN)
+std::string GetModulePath() {
+ UNREACHABLE();
+ return "";
+}
+#else
+# error "Implement GetModulePath for your platform."
+#endif
+
+std::string GetModuleDirectory() {
+ std::string modPath = GetModulePath();
+ size_t lastPathSepLoc = modPath.find_last_of(GetPathSeparator());
+ return lastPathSepLoc != std::string::npos ? modPath.substr(0, lastPathSepLoc + 1) : "";
+}
+
// ScopedEnvironmentVar
ScopedEnvironmentVar::ScopedEnvironmentVar(const char* variableName, const char* value)
diff --git a/src/common/SystemUtils.h b/src/common/SystemUtils.h
index 63cf541..875c5aa 100644
--- a/src/common/SystemUtils.h
+++ b/src/common/SystemUtils.h
@@ -24,7 +24,9 @@
// was present.
std::pair<std::string, bool> GetEnvironmentVar(const char* variableName);
bool SetEnvironmentVar(const char* variableName, const char* value);
+// Directories are always returned with a trailing path separator.
std::string GetExecutableDirectory();
+std::string GetModuleDirectory();
#ifdef DAWN_PLATFORM_MACOS
void GetMacOSVersion(int32_t* majorVersion, int32_t* minorVersion = nullptr);
diff --git a/src/dawn_native/BUILD.gn b/src/dawn_native/BUILD.gn
index 465aa0a..cd977fa 100644
--- a/src/dawn_native/BUILD.gn
+++ b/src/dawn_native/BUILD.gn
@@ -679,6 +679,7 @@
}
if (enable_vulkan_loader) {
data_deps += [ "${dawn_vulkan_loader_dir}:libvulkan" ]
+ defines += [ "DAWN_ENABLE_VULKAN_LOADER" ]
}
if (use_swiftshader) {
data_deps += [
diff --git a/src/dawn_native/vulkan/BackendVk.cpp b/src/dawn_native/vulkan/BackendVk.cpp
index 484c246..c0552490 100644
--- a/src/dawn_native/vulkan/BackendVk.cpp
+++ b/src/dawn_native/vulkan/BackendVk.cpp
@@ -111,13 +111,25 @@
}
MaybeError Backend::LoadVulkan(bool useSwiftshader) {
- // First try to load the system Vulkan driver, if that fails,
- // try to load with Swiftshader. Note: The system driver could potentially be Swiftshader
- // if it was installed.
- if (mVulkanLib.Open(kVulkanLibName)) {
+ // First try to load the system Vulkan driver, if that fails, try to load with Swiftshader.
+ // Note: The system driver could potentially be Swiftshader if it was installed.
+#if defined(DAWN_ENABLE_VULKAN_LOADER)
+ // If enabled, we use our own built Vulkan loader by specifying an absolute path to the
+ // shared library. Note that when we are currently getting the absolute path for the custom
+ // loader by getting the path to the dawn native library and traversing relative from there.
+ // This has implications for dawn tests because some of them are linking statically to
+ // dawn_native which means the "module" is actually the test as well. If the directory
+ // location of the tests change w.r.t the shared lib then this may break. Essentially we are
+ // assuming that our custom built Vulkan loader will always be in the same directory as the
+ // shared dawn native library and all test binaries that link statically.
+ const std::string resolvedVulkanLibPath = GetModuleDirectory() + kVulkanLibName;
+#else
+ const std::string resolvedVulkanLibPath = kVulkanLibName;
+#endif // defined(DAWN_ENABLE_VULKAN_LOADER)
+ if (mVulkanLib.Open(resolvedVulkanLibPath)) {
return {};
}
- dawn::WarningLog() << std::string("Couldn't open ") + kVulkanLibName;
+ dawn::WarningLog() << std::string("Couldn't open ") + resolvedVulkanLibPath;
// If |useSwiftshader == true|, fallback and try to directly load the Swiftshader
// library.