From 2d0007ca8fc037ec3c99fc3fc62cf990d2fada72 Mon Sep 17 00:00:00 2001 From: Austin Eng Date: Thu, 2 Dec 2021 18:12:57 +0000 Subject: [PATCH] Don't connect to backends that aren't needed Change backend connection in Instance.cpp to store a bitset of backends that have been connected. This lets us only connect to a single backend if AdapterDiscoveryOptions are passed explicitly, and track which connections have/have not been made. Later, we can connect to the rest of the backends if more are requested. This is part of some improvements to the existing code so we can selectively discover adapters and control discovery of the high-performance, low-power, and fallback WebGPU adapters. Bug: chromium:1266550 Change-Id: Iceb0d3f71751f5aac6218996ace3cf89deda8a29 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/69521 Commit-Queue: Austin Eng Reviewed-by: Corentin Wallez --- .../templates/dawn_native/dawn_platform.h | 10 ++ src/dawn_native/Instance.cpp | 125 +++++++++++++----- src/dawn_native/Instance.h | 8 +- src/dawn_native/dawn_platform.h | 7 + 4 files changed, 117 insertions(+), 33 deletions(-) diff --git a/generator/templates/dawn_native/dawn_platform.h b/generator/templates/dawn_native/dawn_platform.h index af42e034d9..0690064fa1 100644 --- a/generator/templates/dawn_native/dawn_platform.h +++ b/generator/templates/dawn_native/dawn_platform.h @@ -59,6 +59,16 @@ namespace dawn_native { return reinterpret_cast<{{as_cppType(type.name)}}Base*>(rhs); } {% endfor %} + + template + struct EnumCount; + + {% for e in by_category["enum"] if e.contiguousFromZero %} + template<> + struct EnumCount { + static constexpr uint32_t value = {{len(e.values)}}; + }; + {% endfor %} } #endif // DAWNNATIVE_DAWN_PLATFORM_AUTOGEN_H_ \ No newline at end of file diff --git a/src/dawn_native/Instance.cpp b/src/dawn_native/Instance.cpp index f2b08c7dc6..7415c16823 100644 --- a/src/dawn_native/Instance.cpp +++ b/src/dawn_native/Instance.cpp @@ -18,6 +18,7 @@ #include "common/Log.h" #include "dawn_native/ErrorData.h" #include "dawn_native/Surface.h" +#include "dawn_native/ValidationUtils_autogen.h" #include "dawn_platform/DawnPlatform.h" #if defined(DAWN_USE_X11) @@ -54,6 +55,34 @@ namespace dawn_native { } #endif // defined(DAWN_ENABLE_BACKEND_VULKAN) + namespace { + + BackendsBitset GetEnabledBackends() { + BackendsBitset enabledBackends; +#if defined(DAWN_ENABLE_BACKEND_NULL) + enabledBackends.set(wgpu::BackendType::Null); +#endif // defined(DAWN_ENABLE_BACKEND_NULL) +#if defined(DAWN_ENABLE_BACKEND_D3D12) + enabledBackends.set(wgpu::BackendType::D3D12); +#endif // defined(DAWN_ENABLE_BACKEND_D3D12) +#if defined(DAWN_ENABLE_BACKEND_METAL) + enabledBackends.set(wgpu::BackendType::Metal); +#endif // defined(DAWN_ENABLE_BACKEND_METAL) +#if defined(DAWN_ENABLE_BACKEND_VULKAN) + enabledBackends.set(wgpu::BackendType::Vulkan); +#endif // defined(DAWN_ENABLE_BACKEND_VULKAN) +#if defined(DAWN_ENABLE_BACKEND_DESKTOP_GL) + enabledBackends.set(wgpu::BackendType::OpenGL); +#endif // defined(DAWN_ENABLE_BACKEND_DESKTOP_GL) +#if defined(DAWN_ENABLE_BACKEND_OPENGLES) + enabledBackends.set(wgpu::BackendType::OpenGLES); +#endif // defined(DAWN_ENABLE_BACKEND_OPENGLES) + + return enabledBackends; + } + + } // anonymous namespace + // InstanceBase // static @@ -71,7 +100,9 @@ namespace dawn_native { } void InstanceBase::DiscoverDefaultAdapters() { - EnsureBackendConnections(); + for (wgpu::BackendType b : IterateBitSet(GetEnabledBackends())) { + EnsureBackendConnection(b); + } if (mDiscoveredDefaultAdapters) { return; @@ -122,8 +153,8 @@ namespace dawn_native { return mAdapters; } - void InstanceBase::EnsureBackendConnections() { - if (mBackendsConnected) { + void InstanceBase::EnsureBackendConnection(wgpu::BackendType backendType) { + if (mBackendsConnected[backendType]) { return; } @@ -135,42 +166,74 @@ namespace dawn_native { } }; -#if defined(DAWN_ENABLE_BACKEND_D3D12) - Register(d3d12::Connect(this), wgpu::BackendType::D3D12); -#endif // defined(DAWN_ENABLE_BACKEND_D3D12) -#if defined(DAWN_ENABLE_BACKEND_METAL) - Register(metal::Connect(this), wgpu::BackendType::Metal); -#endif // defined(DAWN_ENABLE_BACKEND_METAL) -#if defined(DAWN_ENABLE_BACKEND_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_DESKTOP_GL) - Register(opengl::Connect(this, wgpu::BackendType::OpenGL), wgpu::BackendType::OpenGL); -#endif // defined(DAWN_ENABLE_BACKEND_DESKTOP_GL) -#if defined(DAWN_ENABLE_BACKEND_OPENGLES) - Register(opengl::Connect(this, wgpu::BackendType::OpenGLES), wgpu::BackendType::OpenGLES); -#endif // defined(DAWN_ENABLE_BACKEND_OPENGLES) + switch (backendType) { #if defined(DAWN_ENABLE_BACKEND_NULL) - Register(null::Connect(this), wgpu::BackendType::Null); + case wgpu::BackendType::Null: + Register(null::Connect(this), wgpu::BackendType::Null); + break; #endif // defined(DAWN_ENABLE_BACKEND_NULL) - mBackendsConnected = true; +#if defined(DAWN_ENABLE_BACKEND_D3D12) + case wgpu::BackendType::D3D12: + Register(d3d12::Connect(this), wgpu::BackendType::D3D12); + break; +#endif // defined(DAWN_ENABLE_BACKEND_D3D12) + +#if defined(DAWN_ENABLE_BACKEND_METAL) + case wgpu::BackendType::Metal: + Register(metal::Connect(this), wgpu::BackendType::Metal); + break; +#endif // defined(DAWN_ENABLE_BACKEND_METAL) + +#if defined(DAWN_ENABLE_BACKEND_VULKAN) + case 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) + break; +#endif // defined(DAWN_ENABLE_BACKEND_VULKAN) + +#if defined(DAWN_ENABLE_BACKEND_DESKTOP_GL) + case wgpu::BackendType::OpenGL: + Register(opengl::Connect(this, wgpu::BackendType::OpenGL), + wgpu::BackendType::OpenGL); + break; +#endif // defined(DAWN_ENABLE_BACKEND_DESKTOP_GL) + +#if defined(DAWN_ENABLE_BACKEND_OPENGLES) + case wgpu::BackendType::OpenGLES: + Register(opengl::Connect(this, wgpu::BackendType::OpenGLES), + wgpu::BackendType::OpenGLES); + break; +#endif // defined(DAWN_ENABLE_BACKEND_OPENGLES) + + default: + UNREACHABLE(); + } + + mBackendsConnected.set(backendType); } MaybeError InstanceBase::DiscoverAdaptersInternal(const AdapterDiscoveryOptionsBase* options) { - EnsureBackendConnections(); + wgpu::BackendType backendType = static_cast(options->backendType); + DAWN_TRY(ValidateBackendType(backendType)); + + if (!GetEnabledBackends()[backendType]) { + return DAWN_FORMAT_VALIDATION_ERROR("%s not supported.", backendType); + } + + EnsureBackendConnection(backendType); bool foundBackend = false; for (std::unique_ptr& backend : mBackends) { - if (backend->GetType() != static_cast(options->backendType)) { + if (backend->GetType() != backendType) { continue; } foundBackend = true; @@ -185,7 +248,7 @@ namespace dawn_native { } } - DAWN_INVALID_IF(!foundBackend, "No matching backend found."); + DAWN_INVALID_IF(!foundBackend, "%s not available.", backendType); return {}; } diff --git a/src/dawn_native/Instance.h b/src/dawn_native/Instance.h index 3451967bc6..a636875b25 100644 --- a/src/dawn_native/Instance.h +++ b/src/dawn_native/Instance.h @@ -16,6 +16,7 @@ #define DAWNNATIVE_INSTANCE_H_ #include "common/RefCounted.h" +#include "common/ityp_bitset.h" #include "dawn_native/Adapter.h" #include "dawn_native/BackendConnection.h" #include "dawn_native/Features.h" @@ -36,6 +37,8 @@ namespace dawn_native { class Surface; class XlibXcbFunctions; + using BackendsBitset = ityp::bitset>; + // This is called InstanceBase for consistency across the frontend, even if the backends don't // specialize this class. class InstanceBase final : public RefCounted { @@ -87,11 +90,12 @@ namespace dawn_native { bool Initialize(const InstanceDescriptor* descriptor); // Lazily creates connections to all backends that have been compiled. - void EnsureBackendConnections(); + void EnsureBackendConnection(wgpu::BackendType backendType); MaybeError DiscoverAdaptersInternal(const AdapterDiscoveryOptionsBase* options); - bool mBackendsConnected = false; + BackendsBitset mBackendsConnected; + bool mDiscoveredDefaultAdapters = false; bool mBeginCaptureOnStartup = false; diff --git a/src/dawn_native/dawn_platform.h b/src/dawn_native/dawn_platform.h index d4dfec1524..de9ef50920 100644 --- a/src/dawn_native/dawn_platform.h +++ b/src/dawn_native/dawn_platform.h @@ -21,6 +21,13 @@ #include namespace dawn_native { + + // kEnumCount is a constant specifying the number of enums in a WebGPU enum type, + // if the enums are contiguous, making it suitable for iteration. + // It is defined in dawn_platform_autogen.h + template + constexpr uint32_t kEnumCount = EnumCount::value; + // Extra buffer usages // Add an extra buffer usage and an extra binding type for binding the buffers with QueryResolve // usage as storage buffer in the internal pipeline.