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.