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 #include "dawn_native/ValidationUtils_autogen.h" 22 #include "dawn_platform/DawnPlatform.h" 23 24 #if defined(DAWN_USE_X11) 25 # include "dawn_native/XlibXcbFunctions.h" 26 #endif // defined(DAWN_USE_X11) 27 28 namespace dawn_native { 29 30 // Forward definitions of each backend's "Connect" function that creates new BackendConnection. 31 // Conditionally compiled declarations are used to avoid using static constructors instead. 32 #if defined(DAWN_ENABLE_BACKEND_D3D12) 33 namespace d3d12 { 34 BackendConnection* Connect(InstanceBase* instance); 35 } 36 #endif // defined(DAWN_ENABLE_BACKEND_D3D12) 37 #if defined(DAWN_ENABLE_BACKEND_METAL) 38 namespace metal { 39 BackendConnection* Connect(InstanceBase* instance); 40 } 41 #endif // defined(DAWN_ENABLE_BACKEND_METAL) 42 #if defined(DAWN_ENABLE_BACKEND_NULL) 43 namespace null { 44 BackendConnection* Connect(InstanceBase* instance); 45 } 46 #endif // defined(DAWN_ENABLE_BACKEND_NULL) 47 #if defined(DAWN_ENABLE_BACKEND_OPENGL) 48 namespace opengl { 49 BackendConnection* Connect(InstanceBase* instance, wgpu::BackendType backendType); 50 } 51 #endif // defined(DAWN_ENABLE_BACKEND_OPENGL) 52 #if defined(DAWN_ENABLE_BACKEND_VULKAN) 53 namespace vulkan { 54 BackendConnection* Connect(InstanceBase* instance); 55 } 56 #endif // defined(DAWN_ENABLE_BACKEND_VULKAN) 57 58 namespace { 59 GetEnabledBackends()60 BackendsBitset GetEnabledBackends() { 61 BackendsBitset enabledBackends; 62 #if defined(DAWN_ENABLE_BACKEND_NULL) 63 enabledBackends.set(wgpu::BackendType::Null); 64 #endif // defined(DAWN_ENABLE_BACKEND_NULL) 65 #if defined(DAWN_ENABLE_BACKEND_D3D12) 66 enabledBackends.set(wgpu::BackendType::D3D12); 67 #endif // defined(DAWN_ENABLE_BACKEND_D3D12) 68 #if defined(DAWN_ENABLE_BACKEND_METAL) 69 enabledBackends.set(wgpu::BackendType::Metal); 70 #endif // defined(DAWN_ENABLE_BACKEND_METAL) 71 #if defined(DAWN_ENABLE_BACKEND_VULKAN) 72 enabledBackends.set(wgpu::BackendType::Vulkan); 73 #endif // defined(DAWN_ENABLE_BACKEND_VULKAN) 74 #if defined(DAWN_ENABLE_BACKEND_DESKTOP_GL) 75 enabledBackends.set(wgpu::BackendType::OpenGL); 76 #endif // defined(DAWN_ENABLE_BACKEND_DESKTOP_GL) 77 #if defined(DAWN_ENABLE_BACKEND_OPENGLES) 78 enabledBackends.set(wgpu::BackendType::OpenGLES); 79 #endif // defined(DAWN_ENABLE_BACKEND_OPENGLES) 80 81 return enabledBackends; 82 } 83 84 } // anonymous namespace 85 86 // InstanceBase 87 88 // static Create(const InstanceDescriptor * descriptor)89 InstanceBase* InstanceBase::Create(const InstanceDescriptor* descriptor) { 90 Ref<InstanceBase> instance = AcquireRef(new InstanceBase); 91 if (!instance->Initialize(descriptor)) { 92 return nullptr; 93 } 94 return instance.Detach(); 95 } 96 97 // TODO(crbug.com/dawn/832): make the platform an initialization parameter of the instance. Initialize(const InstanceDescriptor *)98 bool InstanceBase::Initialize(const InstanceDescriptor*) { 99 return true; 100 } 101 DiscoverDefaultAdapters()102 void InstanceBase::DiscoverDefaultAdapters() { 103 for (wgpu::BackendType b : IterateBitSet(GetEnabledBackends())) { 104 EnsureBackendConnection(b); 105 } 106 107 if (mDiscoveredDefaultAdapters) { 108 return; 109 } 110 111 // Query and merge all default adapters for all backends 112 for (std::unique_ptr<BackendConnection>& backend : mBackends) { 113 std::vector<std::unique_ptr<AdapterBase>> backendAdapters = 114 backend->DiscoverDefaultAdapters(); 115 116 for (std::unique_ptr<AdapterBase>& adapter : backendAdapters) { 117 ASSERT(adapter->GetBackendType() == backend->GetType()); 118 ASSERT(adapter->GetInstance() == this); 119 mAdapters.push_back(std::move(adapter)); 120 } 121 } 122 123 mDiscoveredDefaultAdapters = true; 124 } 125 126 // This is just a wrapper around the real logic that uses Error.h error handling. DiscoverAdapters(const AdapterDiscoveryOptionsBase * options)127 bool InstanceBase::DiscoverAdapters(const AdapterDiscoveryOptionsBase* options) { 128 return !ConsumedError(DiscoverAdaptersInternal(options)); 129 } 130 GetToggleInfo(const char * toggleName)131 const ToggleInfo* InstanceBase::GetToggleInfo(const char* toggleName) { 132 return mTogglesInfo.GetToggleInfo(toggleName); 133 } 134 ToggleNameToEnum(const char * toggleName)135 Toggle InstanceBase::ToggleNameToEnum(const char* toggleName) { 136 return mTogglesInfo.ToggleNameToEnum(toggleName); 137 } 138 GetFeatureInfo(const char * featureName)139 const FeatureInfo* InstanceBase::GetFeatureInfo(const char* featureName) { 140 return mFeaturesInfo.GetFeatureInfo(featureName); 141 } 142 FeatureNameToEnum(const char * featureName)143 Feature InstanceBase::FeatureNameToEnum(const char* featureName) { 144 return mFeaturesInfo.FeatureNameToEnum(featureName); 145 } 146 FeatureNamesToFeaturesSet(const std::vector<const char * > & requiredFeatures)147 FeaturesSet InstanceBase::FeatureNamesToFeaturesSet( 148 const std::vector<const char*>& requiredFeatures) { 149 return mFeaturesInfo.FeatureNamesToFeaturesSet(requiredFeatures); 150 } 151 GetAdapters() const152 const std::vector<std::unique_ptr<AdapterBase>>& InstanceBase::GetAdapters() const { 153 return mAdapters; 154 } 155 EnsureBackendConnection(wgpu::BackendType backendType)156 void InstanceBase::EnsureBackendConnection(wgpu::BackendType backendType) { 157 if (mBackendsConnected[backendType]) { 158 return; 159 } 160 161 auto Register = [this](BackendConnection* connection, wgpu::BackendType expectedType) { 162 if (connection != nullptr) { 163 ASSERT(connection->GetType() == expectedType); 164 ASSERT(connection->GetInstance() == this); 165 mBackends.push_back(std::unique_ptr<BackendConnection>(connection)); 166 } 167 }; 168 169 switch (backendType) { 170 #if defined(DAWN_ENABLE_BACKEND_NULL) 171 case wgpu::BackendType::Null: 172 Register(null::Connect(this), wgpu::BackendType::Null); 173 break; 174 #endif // defined(DAWN_ENABLE_BACKEND_NULL) 175 176 #if defined(DAWN_ENABLE_BACKEND_D3D12) 177 case wgpu::BackendType::D3D12: 178 Register(d3d12::Connect(this), wgpu::BackendType::D3D12); 179 break; 180 #endif // defined(DAWN_ENABLE_BACKEND_D3D12) 181 182 #if defined(DAWN_ENABLE_BACKEND_METAL) 183 case wgpu::BackendType::Metal: 184 Register(metal::Connect(this), wgpu::BackendType::Metal); 185 break; 186 #endif // defined(DAWN_ENABLE_BACKEND_METAL) 187 188 #if defined(DAWN_ENABLE_BACKEND_VULKAN) 189 case wgpu::BackendType::Vulkan: 190 Register(vulkan::Connect(this), wgpu::BackendType::Vulkan); 191 break; 192 #endif // defined(DAWN_ENABLE_BACKEND_VULKAN) 193 194 #if defined(DAWN_ENABLE_BACKEND_DESKTOP_GL) 195 case wgpu::BackendType::OpenGL: 196 Register(opengl::Connect(this, wgpu::BackendType::OpenGL), 197 wgpu::BackendType::OpenGL); 198 break; 199 #endif // defined(DAWN_ENABLE_BACKEND_DESKTOP_GL) 200 201 #if defined(DAWN_ENABLE_BACKEND_OPENGLES) 202 case wgpu::BackendType::OpenGLES: 203 Register(opengl::Connect(this, wgpu::BackendType::OpenGLES), 204 wgpu::BackendType::OpenGLES); 205 break; 206 #endif // defined(DAWN_ENABLE_BACKEND_OPENGLES) 207 208 default: 209 UNREACHABLE(); 210 } 211 212 mBackendsConnected.set(backendType); 213 } 214 DiscoverAdaptersInternal(const AdapterDiscoveryOptionsBase * options)215 MaybeError InstanceBase::DiscoverAdaptersInternal(const AdapterDiscoveryOptionsBase* options) { 216 wgpu::BackendType backendType = static_cast<wgpu::BackendType>(options->backendType); 217 DAWN_TRY(ValidateBackendType(backendType)); 218 219 if (!GetEnabledBackends()[backendType]) { 220 return DAWN_FORMAT_VALIDATION_ERROR("%s not supported.", backendType); 221 } 222 223 EnsureBackendConnection(backendType); 224 225 bool foundBackend = false; 226 for (std::unique_ptr<BackendConnection>& backend : mBackends) { 227 if (backend->GetType() != backendType) { 228 continue; 229 } 230 foundBackend = true; 231 232 std::vector<std::unique_ptr<AdapterBase>> newAdapters; 233 DAWN_TRY_ASSIGN(newAdapters, backend->DiscoverAdapters(options)); 234 235 for (std::unique_ptr<AdapterBase>& adapter : newAdapters) { 236 ASSERT(adapter->GetBackendType() == backend->GetType()); 237 ASSERT(adapter->GetInstance() == this); 238 mAdapters.push_back(std::move(adapter)); 239 } 240 } 241 242 DAWN_INVALID_IF(!foundBackend, "%s not available.", backendType); 243 return {}; 244 } 245 ConsumedError(MaybeError maybeError)246 bool InstanceBase::ConsumedError(MaybeError maybeError) { 247 if (maybeError.IsError()) { 248 std::unique_ptr<ErrorData> error = maybeError.AcquireError(); 249 250 ASSERT(error != nullptr); 251 dawn::InfoLog() << error->GetFormattedMessage(); 252 253 return true; 254 } 255 return false; 256 } 257 IsBackendValidationEnabled() const258 bool InstanceBase::IsBackendValidationEnabled() const { 259 return mBackendValidationLevel != BackendValidationLevel::Disabled; 260 } 261 SetBackendValidationLevel(BackendValidationLevel level)262 void InstanceBase::SetBackendValidationLevel(BackendValidationLevel level) { 263 mBackendValidationLevel = level; 264 } 265 GetBackendValidationLevel() const266 BackendValidationLevel InstanceBase::GetBackendValidationLevel() const { 267 return mBackendValidationLevel; 268 } 269 EnableBeginCaptureOnStartup(bool beginCaptureOnStartup)270 void InstanceBase::EnableBeginCaptureOnStartup(bool beginCaptureOnStartup) { 271 mBeginCaptureOnStartup = beginCaptureOnStartup; 272 } 273 IsBeginCaptureOnStartupEnabled() const274 bool InstanceBase::IsBeginCaptureOnStartupEnabled() const { 275 return mBeginCaptureOnStartup; 276 } 277 SetPlatform(dawn_platform::Platform * platform)278 void InstanceBase::SetPlatform(dawn_platform::Platform* platform) { 279 mPlatform = platform; 280 } 281 GetPlatform()282 dawn_platform::Platform* InstanceBase::GetPlatform() { 283 if (mPlatform != nullptr) { 284 return mPlatform; 285 } 286 287 if (mDefaultPlatform == nullptr) { 288 mDefaultPlatform = std::make_unique<dawn_platform::Platform>(); 289 } 290 return mDefaultPlatform.get(); 291 } 292 GetOrCreateXlibXcbFunctions()293 const XlibXcbFunctions* InstanceBase::GetOrCreateXlibXcbFunctions() { 294 #if defined(DAWN_USE_X11) 295 if (mXlibXcbFunctions == nullptr) { 296 mXlibXcbFunctions = std::make_unique<XlibXcbFunctions>(); 297 } 298 return mXlibXcbFunctions.get(); 299 #else 300 UNREACHABLE(); 301 #endif // defined(DAWN_USE_X11) 302 } 303 APICreateSurface(const SurfaceDescriptor * descriptor)304 Surface* InstanceBase::APICreateSurface(const SurfaceDescriptor* descriptor) { 305 if (ConsumedError(ValidateSurfaceDescriptor(this, descriptor))) { 306 return nullptr; 307 } 308 309 return new Surface(this, descriptor); 310 } 311 312 } // namespace dawn_native 313