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>
This commit is contained in:
Austin Eng 2020-05-08 19:31:00 +00:00 committed by Commit Bot service account
parent 818c6b7082
commit 562255a943
4 changed files with 70 additions and 48 deletions

View File

@ -45,7 +45,7 @@ namespace dawn_native {
#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 @@ namespace dawn_native {
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,21 +156,15 @@ namespace dawn_native {
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));
@ -172,7 +174,11 @@ namespace dawn_native {
ASSERT(adapter->GetInstance() == this);
mAdapters.push_back(std::move(adapter));
}
}
if (!foundBackend) {
return DAWN_VALIDATION_ERROR("Backend isn't present.");
}
return {};
}

View File

@ -81,9 +81,6 @@ namespace dawn_native {
// 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;

View File

@ -81,43 +81,62 @@ namespace dawn_native { namespace vulkan {
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");
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 (mVulkanLib.Open(kSwiftshaderLibName)) {
return {};
}
#endif
dawn::WarningLog() << std::string("Couldn't open ") + kSwiftshaderLibName;
#else
UNREACHABLE();
#endif // defined(DAWN_ENABLE_SWIFTSHADER)
}
return DAWN_INTERNAL_ERROR("Couldn't load Vulkan");
}
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 (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;
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
return DAWN_INTERNAL_ERROR("Couldn't load Vulkan");
}
MaybeError Backend::Initialize() {
DAWN_TRY(LoadVulkan());
DAWN_TRY(mFunctions.LoadGlobalProcs(mVulkanLib));
DAWN_TRY_ASSIGN(mGlobalInfo, GatherGlobalInfo(*this));
@ -300,10 +319,10 @@ namespace dawn_native { namespace vulkan {
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;
}

View File

@ -32,12 +32,12 @@ namespace dawn_native { namespace vulkan {
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();