|  | // 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 "common/Log.h" | 
|  | #include "dawn_native/ErrorData.h" | 
|  |  | 
|  | 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<BackendConnection>& backend : mBackends) { | 
|  | std::vector<std::unique_ptr<AdapterBase>> backendAdapters = | 
|  | backend->DiscoverDefaultAdapters(); | 
|  |  | 
|  | for (std::unique_ptr<AdapterBase>& 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<const char*>& requiredExtensions) { | 
|  | return mExtensionsInfo.ExtensionNamesToExtensionsSet(requiredExtensions); | 
|  | } | 
|  |  | 
|  | const std::vector<std::unique_ptr<AdapterBase>>& 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<BackendConnection>(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<BackendConnection*> InstanceBase::FindBackend(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(options->backendType)); | 
|  |  | 
|  | std::vector<std::unique_ptr<AdapterBase>> newAdapters; | 
|  | DAWN_TRY_ASSIGN(newAdapters, backend->DiscoverAdapters(options)); | 
|  |  | 
|  | for (std::unique_ptr<AdapterBase>& 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); | 
|  | dawn::InfoLog() << error->GetMessage(); | 
|  | 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; | 
|  | } | 
|  |  | 
|  | void InstanceBase::SetPlatform(dawn_platform::Platform* platform) { | 
|  | mPlatform = platform; | 
|  | } | 
|  |  | 
|  | dawn_platform::Platform* InstanceBase::GetPlatform() const { | 
|  | return mPlatform; | 
|  | } | 
|  |  | 
|  | }  // namespace dawn_native |