1 // Copyright 2018 The Dawn Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "dawn_native/Instance.h" 16 17 #include "common/Assert.h" 18 #include "common/Log.h" 19 #include "dawn_native/ErrorData.h" 20 #include "dawn_native/Surface.h" 21 22 namespace dawn_native { 23 24 // Forward definitions of each backend's "Connect" function that creates new BackendConnection. 25 // Conditionally compiled declarations are used to avoid using static constructors instead. 26 #if defined(DAWN_ENABLE_BACKEND_D3D12) 27 namespace d3d12 { 28 BackendConnection* Connect(InstanceBase* instance); 29 } 30 #endif // defined(DAWN_ENABLE_BACKEND_D3D12) 31 #if defined(DAWN_ENABLE_BACKEND_METAL) 32 namespace metal { 33 BackendConnection* Connect(InstanceBase* instance); 34 } 35 #endif // defined(DAWN_ENABLE_BACKEND_METAL) 36 #if defined(DAWN_ENABLE_BACKEND_NULL) 37 namespace null { 38 BackendConnection* Connect(InstanceBase* instance); 39 } 40 #endif // defined(DAWN_ENABLE_BACKEND_NULL) 41 #if defined(DAWN_ENABLE_BACKEND_OPENGL) 42 namespace opengl { 43 BackendConnection* Connect(InstanceBase* instance); 44 } 45 #endif // defined(DAWN_ENABLE_BACKEND_OPENGL) 46 #if defined(DAWN_ENABLE_BACKEND_VULKAN) 47 namespace vulkan { 48 BackendConnection* Connect(InstanceBase* instance); 49 } 50 #endif // defined(DAWN_ENABLE_BACKEND_VULKAN) 51 52 // InstanceBase 53 54 // static Create(const InstanceDescriptor * descriptor)55 InstanceBase* InstanceBase::Create(const InstanceDescriptor* descriptor) { 56 Ref<InstanceBase> instance = AcquireRef(new InstanceBase); 57 if (!instance->Initialize(descriptor)) { 58 return nullptr; 59 } 60 return instance.Detach(); 61 } 62 Initialize(const InstanceDescriptor *)63 bool InstanceBase::Initialize(const InstanceDescriptor*) { 64 return true; 65 } 66 DiscoverDefaultAdapters()67 void InstanceBase::DiscoverDefaultAdapters() { 68 EnsureBackendConnections(); 69 70 if (mDiscoveredDefaultAdapters) { 71 return; 72 } 73 74 // Query and merge all default adapters for all backends 75 for (std::unique_ptr<BackendConnection>& backend : mBackends) { 76 std::vector<std::unique_ptr<AdapterBase>> backendAdapters = 77 backend->DiscoverDefaultAdapters(); 78 79 for (std::unique_ptr<AdapterBase>& adapter : backendAdapters) { 80 ASSERT(adapter->GetBackendType() == backend->GetType()); 81 ASSERT(adapter->GetInstance() == this); 82 mAdapters.push_back(std::move(adapter)); 83 } 84 } 85 86 mDiscoveredDefaultAdapters = true; 87 } 88 89 // This is just a wrapper around the real logic that uses Error.h error handling. DiscoverAdapters(const AdapterDiscoveryOptionsBase * options)90 bool InstanceBase::DiscoverAdapters(const AdapterDiscoveryOptionsBase* options) { 91 return !ConsumedError(DiscoverAdaptersInternal(options)); 92 } 93 GetToggleInfo(const char * toggleName)94 const ToggleInfo* InstanceBase::GetToggleInfo(const char* toggleName) { 95 return mTogglesInfo.GetToggleInfo(toggleName); 96 } 97 ToggleNameToEnum(const char * toggleName)98 Toggle InstanceBase::ToggleNameToEnum(const char* toggleName) { 99 return mTogglesInfo.ToggleNameToEnum(toggleName); 100 } 101 GetExtensionInfo(const char * extensionName)102 const ExtensionInfo* InstanceBase::GetExtensionInfo(const char* extensionName) { 103 return mExtensionsInfo.GetExtensionInfo(extensionName); 104 } 105 ExtensionNameToEnum(const char * extensionName)106 Extension InstanceBase::ExtensionNameToEnum(const char* extensionName) { 107 return mExtensionsInfo.ExtensionNameToEnum(extensionName); 108 } 109 ExtensionNamesToExtensionsSet(const std::vector<const char * > & requiredExtensions)110 ExtensionsSet InstanceBase::ExtensionNamesToExtensionsSet( 111 const std::vector<const char*>& requiredExtensions) { 112 return mExtensionsInfo.ExtensionNamesToExtensionsSet(requiredExtensions); 113 } 114 GetAdapters() const115 const std::vector<std::unique_ptr<AdapterBase>>& InstanceBase::GetAdapters() const { 116 return mAdapters; 117 } 118 EnsureBackendConnections()119 void InstanceBase::EnsureBackendConnections() { 120 if (mBackendsConnected) { 121 return; 122 } 123 124 auto Register = [this](BackendConnection* connection, wgpu::BackendType expectedType) { 125 if (connection != nullptr) { 126 ASSERT(connection->GetType() == expectedType); 127 ASSERT(connection->GetInstance() == this); 128 mBackends.push_back(std::unique_ptr<BackendConnection>(connection)); 129 } 130 }; 131 132 #if defined(DAWN_ENABLE_BACKEND_D3D12) 133 Register(d3d12::Connect(this), wgpu::BackendType::D3D12); 134 #endif // defined(DAWN_ENABLE_BACKEND_D3D12) 135 #if defined(DAWN_ENABLE_BACKEND_METAL) 136 Register(metal::Connect(this), wgpu::BackendType::Metal); 137 #endif // defined(DAWN_ENABLE_BACKEND_METAL) 138 #if defined(DAWN_ENABLE_BACKEND_VULKAN) 139 Register(vulkan::Connect(this), wgpu::BackendType::Vulkan); 140 #endif // defined(DAWN_ENABLE_BACKEND_VULKAN) 141 #if defined(DAWN_ENABLE_BACKEND_OPENGL) 142 Register(opengl::Connect(this), wgpu::BackendType::OpenGL); 143 #endif // defined(DAWN_ENABLE_BACKEND_OPENGL) 144 #if defined(DAWN_ENABLE_BACKEND_NULL) 145 Register(null::Connect(this), wgpu::BackendType::Null); 146 #endif // defined(DAWN_ENABLE_BACKEND_NULL) 147 148 mBackendsConnected = true; 149 } 150 FindBackend(wgpu::BackendType type)151 ResultOrError<BackendConnection*> InstanceBase::FindBackend(wgpu::BackendType type) { 152 for (std::unique_ptr<BackendConnection>& backend : mBackends) { 153 if (backend->GetType() == type) { 154 return backend.get(); 155 } 156 } 157 158 return DAWN_VALIDATION_ERROR("Backend isn't present."); 159 } 160 DiscoverAdaptersInternal(const AdapterDiscoveryOptionsBase * options)161 MaybeError InstanceBase::DiscoverAdaptersInternal(const AdapterDiscoveryOptionsBase* options) { 162 EnsureBackendConnections(); 163 164 BackendConnection* backend; 165 DAWN_TRY_ASSIGN(backend, FindBackend(static_cast<wgpu::BackendType>(options->backendType))); 166 167 std::vector<std::unique_ptr<AdapterBase>> newAdapters; 168 DAWN_TRY_ASSIGN(newAdapters, backend->DiscoverAdapters(options)); 169 170 for (std::unique_ptr<AdapterBase>& adapter : newAdapters) { 171 ASSERT(adapter->GetBackendType() == backend->GetType()); 172 ASSERT(adapter->GetInstance() == this); 173 mAdapters.push_back(std::move(adapter)); 174 } 175 176 return {}; 177 } 178 ConsumedError(MaybeError maybeError)179 bool InstanceBase::ConsumedError(MaybeError maybeError) { 180 if (maybeError.IsError()) { 181 std::unique_ptr<ErrorData> error = maybeError.AcquireError(); 182 183 ASSERT(error != nullptr); 184 dawn::InfoLog() << error->GetMessage(); 185 186 return true; 187 } 188 return false; 189 } 190 EnableBackendValidation(bool enableBackendValidation)191 void InstanceBase::EnableBackendValidation(bool enableBackendValidation) { 192 mEnableBackendValidation = enableBackendValidation; 193 } 194 IsBackendValidationEnabled() const195 bool InstanceBase::IsBackendValidationEnabled() const { 196 return mEnableBackendValidation; 197 } 198 EnableBeginCaptureOnStartup(bool beginCaptureOnStartup)199 void InstanceBase::EnableBeginCaptureOnStartup(bool beginCaptureOnStartup) { 200 mBeginCaptureOnStartup = beginCaptureOnStartup; 201 } 202 IsBeginCaptureOnStartupEnabled() const203 bool InstanceBase::IsBeginCaptureOnStartupEnabled() const { 204 return mBeginCaptureOnStartup; 205 } 206 SetPlatform(dawn_platform::Platform * platform)207 void InstanceBase::SetPlatform(dawn_platform::Platform* platform) { 208 mPlatform = platform; 209 } 210 GetPlatform() const211 dawn_platform::Platform* InstanceBase::GetPlatform() const { 212 return mPlatform; 213 } 214 CreateSurface(const SurfaceDescriptor * descriptor)215 Surface* InstanceBase::CreateSurface(const SurfaceDescriptor* descriptor) { 216 if (ConsumedError(ValidateSurfaceDescriptor(this, descriptor))) { 217 return nullptr; 218 } 219 220 return new Surface(this, descriptor); 221 } 222 223 } // namespace dawn_native 224