Load Swiftshader Vulkan separately from the system Vulkan
This enables both Swiftshader Vulkan and the system Vulkan drivers
to be discovered and used simultaneously.
Bug: dawn:396, dawn:283
Change-Id: I580ca26c12296fe13c0331c4faf6e7a4520664e4
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/21041
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn_native/Instance.cpp b/src/dawn_native/Instance.cpp
index 982c979..c7a1e31 100644
--- a/src/dawn_native/Instance.cpp
+++ b/src/dawn_native/Instance.cpp
@@ -45,7 +45,7 @@
#endif // defined(DAWN_ENABLE_BACKEND_OPENGL)
#if defined(DAWN_ENABLE_BACKEND_VULKAN)
namespace vulkan {
- BackendConnection* Connect(InstanceBase* instance);
+ BackendConnection* Connect(InstanceBase* instance, bool useSwiftshader);
}
#endif // defined(DAWN_ENABLE_BACKEND_VULKAN)
@@ -136,7 +136,15 @@
Register(metal::Connect(this), wgpu::BackendType::Metal);
#endif // defined(DAWN_ENABLE_BACKEND_METAL)
#if defined(DAWN_ENABLE_BACKEND_VULKAN)
- Register(vulkan::Connect(this), wgpu::BackendType::Vulkan);
+ // TODO(https://github.com/KhronosGroup/Vulkan-Loader/issues/287):
+ // When we can load SwiftShader in parallel with the system driver, we should create the
+ // backend only once and expose SwiftShader as an additional adapter. For now, we create two
+ // VkInstances, one from SwiftShader, and one from the system. Note: If the Vulkan driver
+ // *is* SwiftShader, then this would load SwiftShader twice.
+ Register(vulkan::Connect(this, false), wgpu::BackendType::Vulkan);
+# if defined(DAWN_ENABLE_SWIFTSHADER)
+ Register(vulkan::Connect(this, true), wgpu::BackendType::Vulkan);
+# endif // defined(DAWN_ENABLE_SWIFTSHADER)
#endif // defined(DAWN_ENABLE_BACKEND_VULKAN)
#if defined(DAWN_ENABLE_BACKEND_OPENGL)
Register(opengl::Connect(this), wgpu::BackendType::OpenGL);
@@ -148,31 +156,29 @@
mBackendsConnected = true;
}
- ResultOrError<BackendConnection*> InstanceBase::FindBackend(wgpu::BackendType type) {
- for (std::unique_ptr<BackendConnection>& backend : mBackends) {
- if (backend->GetType() == type) {
- return backend.get();
- }
- }
-
- return DAWN_VALIDATION_ERROR("Backend isn't present.");
- }
-
MaybeError InstanceBase::DiscoverAdaptersInternal(const AdapterDiscoveryOptionsBase* options) {
EnsureBackendConnections();
- BackendConnection* backend;
- DAWN_TRY_ASSIGN(backend, FindBackend(static_cast<wgpu::BackendType>(options->backendType)));
+ bool foundBackend = false;
+ for (std::unique_ptr<BackendConnection>& backend : mBackends) {
+ if (backend->GetType() != static_cast<wgpu::BackendType>(options->backendType)) {
+ continue;
+ }
+ foundBackend = true;
- std::vector<std::unique_ptr<AdapterBase>> newAdapters;
- DAWN_TRY_ASSIGN(newAdapters, backend->DiscoverAdapters(options));
+ std::vector<std::unique_ptr<AdapterBase>> newAdapters;
+ DAWN_TRY_ASSIGN(newAdapters, backend->DiscoverAdapters(options));
- for (std::unique_ptr<AdapterBase>& adapter : newAdapters) {
- ASSERT(adapter->GetBackendType() == backend->GetType());
- ASSERT(adapter->GetInstance() == this);
- mAdapters.push_back(std::move(adapter));
+ for (std::unique_ptr<AdapterBase>& adapter : newAdapters) {
+ ASSERT(adapter->GetBackendType() == backend->GetType());
+ ASSERT(adapter->GetInstance() == this);
+ mAdapters.push_back(std::move(adapter));
+ }
}
+ if (!foundBackend) {
+ return DAWN_VALIDATION_ERROR("Backend isn't present.");
+ }
return {};
}
diff --git a/src/dawn_native/Instance.h b/src/dawn_native/Instance.h
index f297c03..0ade98b 100644
--- a/src/dawn_native/Instance.h
+++ b/src/dawn_native/Instance.h
@@ -81,9 +81,6 @@
// Lazily creates connections to all backends that have been compiled.
void EnsureBackendConnections();
- // Finds the BackendConnection for `type` or returns an error.
- ResultOrError<BackendConnection*> FindBackend(wgpu::BackendType type);
-
MaybeError DiscoverAdaptersInternal(const AdapterDiscoveryOptionsBase* options);
bool mBackendsConnected = false;
diff --git a/src/dawn_native/vulkan/BackendVk.cpp b/src/dawn_native/vulkan/BackendVk.cpp
index d03bffd..eef62e8 100644
--- a/src/dawn_native/vulkan/BackendVk.cpp
+++ b/src/dawn_native/vulkan/BackendVk.cpp
@@ -81,42 +81,61 @@
return mGlobalInfo;
}
- MaybeError Backend::LoadVulkan() {
-#if defined(DAWN_ENABLE_VULKAN_VALIDATION_LAYERS)
- if (GetInstance()->IsBackendValidationEnabled()) {
- std::string vkDataDir = GetExecutableDirectory() + DAWN_VK_DATA_DIR;
- if (!SetEnvironmentVar("VK_LAYER_PATH", vkDataDir.c_str())) {
- return DAWN_INTERNAL_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_INTERNAL_ERROR("Couldn't set VK_ICD_FILENAMES");
- }
-#endif
-
+ 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)) {
return {};
}
dawn::WarningLog() << std::string("Couldn't open ") + kVulkanLibName;
+ // If |useSwiftshader == true|, fallback and try to directly load the Swiftshader
+ // library.
+ if (useSwiftshader) {
#if defined(DAWN_ENABLE_SWIFTSHADER)
- if (strcmp(kVulkanLibName, kSwiftshaderLibName) != 0) {
if (mVulkanLib.Open(kSwiftshaderLibName)) {
return {};
}
dawn::WarningLog() << std::string("Couldn't open ") + kSwiftshaderLibName;
+#else
+ UNREACHABLE();
+#endif // defined(DAWN_ENABLE_SWIFTSHADER)
}
-#endif
return DAWN_INTERNAL_ERROR("Couldn't load Vulkan");
}
- MaybeError Backend::Initialize() {
- DAWN_TRY(LoadVulkan());
+ MaybeError Backend::Initialize(bool useSwiftshader) {
+ DAWN_TRY(LoadVulkan(useSwiftshader));
+
+ // TODO(crbug.com/dawn/406): In order to not modify the environment variables of
+ // the rest of an application embedding Dawn, we should set these only
+ // in the scope of this function. See ANGLE's ScopedVkLoaderEnvironment
+ if (useSwiftshader) {
+#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_INTERNAL_ERROR("Couldn't set VK_ICD_FILENAMES");
+ }
+#else
+ dawn::WarningLog() << "Swiftshader enabled but Dawn was not built with "
+ "DAWN_SWIFTSHADER_VK_ICD_JSON.";
+#endif
+ }
+
+ if (GetInstance()->IsBackendValidationEnabled()) {
+#if defined(DAWN_ENABLE_VULKAN_VALIDATION_LAYERS)
+ std::string vkDataDir = GetExecutableDirectory() + DAWN_VK_DATA_DIR;
+ if (!SetEnvironmentVar("VK_LAYER_PATH", vkDataDir.c_str())) {
+ return DAWN_INTERNAL_ERROR("Couldn't set VK_LAYER_PATH");
+ }
+#else
+ dawn::WarningLog() << "Backend validation enabled but Dawn was not built with "
+ "DAWN_ENABLE_VULKAN_VALIDATION_LAYERS.";
+#endif
+ }
DAWN_TRY(mFunctions.LoadGlobalProcs(mVulkanLib));
@@ -300,10 +319,10 @@
return VK_FALSE;
}
- BackendConnection* Connect(InstanceBase* instance) {
+ BackendConnection* Connect(InstanceBase* instance, bool useSwiftshader) {
Backend* backend = new Backend(instance);
- if (instance->ConsumedError(backend->Initialize())) {
+ if (instance->ConsumedError(backend->Initialize(useSwiftshader))) {
delete backend;
return nullptr;
}
diff --git a/src/dawn_native/vulkan/BackendVk.h b/src/dawn_native/vulkan/BackendVk.h
index 57a25b2..7d22b67 100644
--- a/src/dawn_native/vulkan/BackendVk.h
+++ b/src/dawn_native/vulkan/BackendVk.h
@@ -32,12 +32,12 @@
VkInstance GetVkInstance() const;
const VulkanGlobalInfo& GetGlobalInfo() const;
- MaybeError Initialize();
+ MaybeError Initialize(bool useSwiftshader);
std::vector<std::unique_ptr<AdapterBase>> DiscoverDefaultAdapters() override;
private:
- MaybeError LoadVulkan();
+ MaybeError LoadVulkan(bool useSwiftshader);
ResultOrError<VulkanGlobalKnobs> CreateInstance();
MaybeError RegisterDebugReport();