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