diff --git a/src/dawn_native/Instance.cpp b/src/dawn_native/Instance.cpp index 982c979728..c7a1e310f3 100644 --- a/src/dawn_native/Instance.cpp +++ b/src/dawn_native/Instance.cpp @@ -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,31 +156,29 @@ namespace dawn_native { mBackendsConnected = true; } - ResultOrError InstanceBase::FindBackend(wgpu::BackendType type) { - for (std::unique_ptr& 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(options->backendType))); + bool foundBackend = false; + for (std::unique_ptr& backend : mBackends) { + if (backend->GetType() != static_cast(options->backendType)) { + continue; + } + foundBackend = true; - std::vector> newAdapters; - DAWN_TRY_ASSIGN(newAdapters, backend->DiscoverAdapters(options)); + std::vector> newAdapters; + DAWN_TRY_ASSIGN(newAdapters, backend->DiscoverAdapters(options)); - for (std::unique_ptr& adapter : newAdapters) { - ASSERT(adapter->GetBackendType() == backend->GetType()); - ASSERT(adapter->GetInstance() == this); - mAdapters.push_back(std::move(adapter)); + for (std::unique_ptr& 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 f297c03bd4..0ade98b4e6 100644 --- a/src/dawn_native/Instance.h +++ b/src/dawn_native/Instance.h @@ -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 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 d03bffd443..eef62e8d39 100644 --- a/src/dawn_native/vulkan/BackendVk.cpp +++ b/src/dawn_native/vulkan/BackendVk.cpp @@ -81,42 +81,61 @@ 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"); - } - } -#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 @@ 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; } diff --git a/src/dawn_native/vulkan/BackendVk.h b/src/dawn_native/vulkan/BackendVk.h index 57a25b21d0..7d22b671f9 100644 --- a/src/dawn_native/vulkan/BackendVk.h +++ b/src/dawn_native/vulkan/BackendVk.h @@ -32,12 +32,12 @@ namespace dawn_native { namespace vulkan { VkInstance GetVkInstance() const; const VulkanGlobalInfo& GetGlobalInfo() const; - MaybeError Initialize(); + MaybeError Initialize(bool useSwiftshader); std::vector> DiscoverDefaultAdapters() override; private: - MaybeError LoadVulkan(); + MaybeError LoadVulkan(bool useSwiftshader); ResultOrError CreateInstance(); MaybeError RegisterDebugReport();