• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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