// Copyright 2018 The Dawn Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "dawn_native/Instance.h" #include "common/Assert.h" #include "dawn_native/ErrorData.h" #include namespace dawn_native { // Forward definitions of each backend's "Connect" function that creates new BackendConnection. // Conditionally compiled declarations are used to avoid using static constructors instead. #if defined(DAWN_ENABLE_BACKEND_D3D12) namespace d3d12 { BackendConnection* Connect(InstanceBase* instance); } #endif // defined(DAWN_ENABLE_BACKEND_D3D12) #if defined(DAWN_ENABLE_BACKEND_METAL) namespace metal { BackendConnection* Connect(InstanceBase* instance); } #endif // defined(DAWN_ENABLE_BACKEND_METAL) #if defined(DAWN_ENABLE_BACKEND_NULL) namespace null { BackendConnection* Connect(InstanceBase* instance); } #endif // defined(DAWN_ENABLE_BACKEND_NULL) #if defined(DAWN_ENABLE_BACKEND_OPENGL) namespace opengl { BackendConnection* Connect(InstanceBase* instance); } #endif // defined(DAWN_ENABLE_BACKEND_OPENGL) #if defined(DAWN_ENABLE_BACKEND_VULKAN) namespace vulkan { BackendConnection* Connect(InstanceBase* instance); } #endif // defined(DAWN_ENABLE_BACKEND_VULKAN) // InstanceBase void InstanceBase::DiscoverDefaultAdapters() { EnsureBackendConnections(); if (mDiscoveredDefaultAdapters) { return; } // Query and merge all default adapters for all backends for (std::unique_ptr& backend : mBackends) { std::vector> backendAdapters = backend->DiscoverDefaultAdapters(); for (std::unique_ptr& adapter : backendAdapters) { ASSERT(adapter->GetBackendType() == backend->GetType()); ASSERT(adapter->GetInstance() == this); mAdapters.push_back(std::move(adapter)); } } mDiscoveredDefaultAdapters = true; } // This is just a wrapper around the real logic that uses Error.h error handling. bool InstanceBase::DiscoverAdapters(const AdapterDiscoveryOptionsBase* options) { return !ConsumedError(DiscoverAdaptersInternal(options)); } const ToggleInfo* InstanceBase::GetToggleInfo(const char* toggleName) { return mTogglesInfo.GetToggleInfo(toggleName); } Toggle InstanceBase::ToggleNameToEnum(const char* toggleName) { return mTogglesInfo.ToggleNameToEnum(toggleName); } const ExtensionInfo* InstanceBase::GetExtensionInfo(const char* extensionName) { return mExtensionsInfo.GetExtensionInfo(extensionName); } Extension InstanceBase::ExtensionNameToEnum(const char* extensionName) { return mExtensionsInfo.ExtensionNameToEnum(extensionName); } ExtensionsSet InstanceBase::ExtensionNamesToExtensionsSet( const std::vector& requiredExtensions) { return mExtensionsInfo.ExtensionNamesToExtensionsSet(requiredExtensions); } const std::vector>& InstanceBase::GetAdapters() const { return mAdapters; } void InstanceBase::EnsureBackendConnections() { if (mBackendsConnected) { return; } auto Register = [this](BackendConnection* connection, BackendType expectedType) { if (connection != nullptr) { ASSERT(connection->GetType() == expectedType); ASSERT(connection->GetInstance() == this); mBackends.push_back(std::unique_ptr(connection)); } }; #if defined(DAWN_ENABLE_BACKEND_D3D12) Register(d3d12::Connect(this), BackendType::D3D12); #endif // defined(DAWN_ENABLE_BACKEND_D3D12) #if defined(DAWN_ENABLE_BACKEND_METAL) Register(metal::Connect(this), BackendType::Metal); #endif // defined(DAWN_ENABLE_BACKEND_METAL) #if defined(DAWN_ENABLE_BACKEND_VULKAN) Register(vulkan::Connect(this), BackendType::Vulkan); #endif // defined(DAWN_ENABLE_BACKEND_VULKAN) #if defined(DAWN_ENABLE_BACKEND_OPENGL) Register(opengl::Connect(this), BackendType::OpenGL); #endif // defined(DAWN_ENABLE_BACKEND_OPENGL) #if defined(DAWN_ENABLE_BACKEND_NULL) Register(null::Connect(this), BackendType::Null); #endif // defined(DAWN_ENABLE_BACKEND_NULL) mBackendsConnected = true; } ResultOrError InstanceBase::FindBackend(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(options->backendType)); 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)); } return {}; } bool InstanceBase::ConsumedError(MaybeError maybeError) { if (maybeError.IsError()) { ErrorData* error = maybeError.AcquireError(); ASSERT(error != nullptr); std::cout << error->GetMessage() << std::endl; delete error; return true; } return false; } void InstanceBase::EnableBackendValidation(bool enableBackendValidation) { mEnableBackendValidation = enableBackendValidation; } bool InstanceBase::IsBackendValidationEnabled() const { return mEnableBackendValidation; } void InstanceBase::EnableBeginCaptureOnStartup(bool beginCaptureOnStartup) { mBeginCaptureOnStartup = beginCaptureOnStartup; } bool InstanceBase::IsBeginCaptureOnStartupEnabled() const { return mBeginCaptureOnStartup; } } // namespace dawn_native