• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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 #ifndef DAWNNATIVE_DEVICE_H_
16 #define DAWNNATIVE_DEVICE_H_
17 
18 #include "dawn_native/Commands.h"
19 #include "dawn_native/ComputePipeline.h"
20 #include "dawn_native/Error.h"
21 #include "dawn_native/Features.h"
22 #include "dawn_native/Format.h"
23 #include "dawn_native/Forward.h"
24 #include "dawn_native/Limits.h"
25 #include "dawn_native/ObjectBase.h"
26 #include "dawn_native/ObjectType_autogen.h"
27 #include "dawn_native/StagingBuffer.h"
28 #include "dawn_native/Toggles.h"
29 
30 #include "dawn_native/DawnNative.h"
31 #include "dawn_native/dawn_platform.h"
32 
33 #include <mutex>
34 #include <utility>
35 
36 namespace dawn_platform {
37     class WorkerTaskPool;
38 }  // namespace dawn_platform
39 
40 namespace dawn_native {
41     class AdapterBase;
42     class AsyncTaskManager;
43     class AttachmentState;
44     class AttachmentStateBlueprint;
45     class BindGroupLayoutBase;
46     class CallbackTaskManager;
47     class DynamicUploader;
48     class ErrorScopeStack;
49     class ExternalTextureBase;
50     class OwnedCompilationMessages;
51     class PersistentCache;
52     class StagingBufferBase;
53     struct CallbackTask;
54     struct InternalPipelineStore;
55     struct ShaderModuleParseResult;
56 
57     class DeviceBase : public RefCounted {
58       public:
59         DeviceBase(AdapterBase* adapter, const DawnDeviceDescriptor* descriptor);
60         virtual ~DeviceBase();
61 
62         void HandleError(InternalErrorType type, const char* message);
63 
ConsumedError(MaybeError maybeError)64         bool ConsumedError(MaybeError maybeError) {
65             if (DAWN_UNLIKELY(maybeError.IsError())) {
66                 ConsumeError(maybeError.AcquireError());
67                 return true;
68             }
69             return false;
70         }
71 
72         template <typename T>
ConsumedError(ResultOrError<T> resultOrError,T * result)73         bool ConsumedError(ResultOrError<T> resultOrError, T* result) {
74             if (DAWN_UNLIKELY(resultOrError.IsError())) {
75                 ConsumeError(resultOrError.AcquireError());
76                 return true;
77             }
78             *result = resultOrError.AcquireSuccess();
79             return false;
80         }
81 
82         template <typename... Args>
ConsumedError(MaybeError maybeError,const char * formatStr,const Args &...args)83         bool ConsumedError(MaybeError maybeError, const char* formatStr, const Args&... args) {
84             if (DAWN_UNLIKELY(maybeError.IsError())) {
85                 std::unique_ptr<ErrorData> error = maybeError.AcquireError();
86                 if (error->GetType() == InternalErrorType::Validation) {
87                     std::string out;
88                     absl::UntypedFormatSpec format(formatStr);
89                     if (absl::FormatUntyped(&out, format, {absl::FormatArg(args)...})) {
90                         error->AppendContext(std::move(out));
91                     } else {
92                         error->AppendContext(
93                             absl::StrFormat("[Failed to format error: \"%s\"]", formatStr));
94                     }
95                 }
96                 ConsumeError(std::move(error));
97                 return true;
98             }
99             return false;
100         }
101 
102         template <typename T, typename... Args>
ConsumedError(ResultOrError<T> resultOrError,T * result,const char * formatStr,const Args &...args)103         bool ConsumedError(ResultOrError<T> resultOrError,
104                            T* result,
105                            const char* formatStr,
106                            const Args&... args) {
107             if (DAWN_UNLIKELY(resultOrError.IsError())) {
108                 std::unique_ptr<ErrorData> error = resultOrError.AcquireError();
109                 if (error->GetType() == InternalErrorType::Validation) {
110                     std::string out;
111                     absl::UntypedFormatSpec format(formatStr);
112                     if (absl::FormatUntyped(&out, format, {absl::FormatArg(args)...})) {
113                         error->AppendContext(std::move(out));
114                     } else {
115                         error->AppendContext(
116                             absl::StrFormat("[Failed to format error: \"%s\"]", formatStr));
117                     }
118                 }
119                 ConsumeError(std::move(error));
120                 return true;
121             }
122             *result = resultOrError.AcquireSuccess();
123             return false;
124         }
125 
126         MaybeError ValidateObject(const ApiObjectBase* object) const;
127 
128         AdapterBase* GetAdapter() const;
129         dawn_platform::Platform* GetPlatform() const;
130 
131         // Returns the Format corresponding to the wgpu::TextureFormat or an error if the format
132         // isn't a valid wgpu::TextureFormat or isn't supported by this device.
133         // The pointer returned has the same lifetime as the device.
134         ResultOrError<const Format*> GetInternalFormat(wgpu::TextureFormat format) const;
135 
136         // Returns the Format corresponding to the wgpu::TextureFormat and assumes the format is
137         // valid and supported.
138         // The reference returned has the same lifetime as the device.
139         const Format& GetValidInternalFormat(wgpu::TextureFormat format) const;
140 
141         virtual ResultOrError<Ref<CommandBufferBase>> CreateCommandBuffer(
142             CommandEncoder* encoder,
143             const CommandBufferDescriptor* descriptor) = 0;
144 
145         ExecutionSerial GetCompletedCommandSerial() const;
146         ExecutionSerial GetLastSubmittedCommandSerial() const;
147         ExecutionSerial GetFutureSerial() const;
148         ExecutionSerial GetPendingCommandSerial() const;
149 
150         // Many Dawn objects are completely immutable once created which means that if two
151         // creations are given the same arguments, they can return the same object. Reusing
152         // objects will help make comparisons between objects by a single pointer comparison.
153         //
154         // Technically no object is immutable as they have a reference count, and an
155         // application with reference-counting issues could "see" that objects are reused.
156         // This is solved by automatic-reference counting, and also the fact that when using
157         // the client-server wire every creation will get a different proxy object, with a
158         // different reference count.
159         //
160         // When trying to create an object, we give both the descriptor and an example of what
161         // the created object will be, the "blueprint". The blueprint is just a FooBase object
162         // instead of a backend Foo object. If the blueprint doesn't match an object in the
163         // cache, then the descriptor is used to make a new object.
164         ResultOrError<Ref<BindGroupLayoutBase>> GetOrCreateBindGroupLayout(
165             const BindGroupLayoutDescriptor* descriptor,
166             PipelineCompatibilityToken pipelineCompatibilityToken = PipelineCompatibilityToken(0));
167         void UncacheBindGroupLayout(BindGroupLayoutBase* obj);
168 
169         BindGroupLayoutBase* GetEmptyBindGroupLayout();
170 
171         void UncacheComputePipeline(ComputePipelineBase* obj);
172 
173         ResultOrError<Ref<PipelineLayoutBase>> GetOrCreatePipelineLayout(
174             const PipelineLayoutDescriptor* descriptor);
175         void UncachePipelineLayout(PipelineLayoutBase* obj);
176 
177         void UncacheRenderPipeline(RenderPipelineBase* obj);
178 
179         ResultOrError<Ref<SamplerBase>> GetOrCreateSampler(const SamplerDescriptor* descriptor);
180         void UncacheSampler(SamplerBase* obj);
181 
182         ResultOrError<Ref<ShaderModuleBase>> GetOrCreateShaderModule(
183             const ShaderModuleDescriptor* descriptor,
184             ShaderModuleParseResult* parseResult,
185             OwnedCompilationMessages* compilationMessages);
186         void UncacheShaderModule(ShaderModuleBase* obj);
187 
188         Ref<AttachmentState> GetOrCreateAttachmentState(AttachmentStateBlueprint* blueprint);
189         Ref<AttachmentState> GetOrCreateAttachmentState(
190             const RenderBundleEncoderDescriptor* descriptor);
191         Ref<AttachmentState> GetOrCreateAttachmentState(const RenderPipelineDescriptor* descriptor);
192         Ref<AttachmentState> GetOrCreateAttachmentState(const RenderPassDescriptor* descriptor);
193         void UncacheAttachmentState(AttachmentState* obj);
194 
195         // Object creation methods that be used in a reentrant manner.
196         ResultOrError<Ref<BindGroupBase>> CreateBindGroup(const BindGroupDescriptor* descriptor);
197         ResultOrError<Ref<BindGroupLayoutBase>> CreateBindGroupLayout(
198             const BindGroupLayoutDescriptor* descriptor,
199             bool allowInternalBinding = false);
200         ResultOrError<Ref<BufferBase>> CreateBuffer(const BufferDescriptor* descriptor);
201         ResultOrError<Ref<ComputePipelineBase>> CreateComputePipeline(
202             const ComputePipelineDescriptor* descriptor);
203         MaybeError CreateComputePipelineAsync(
204             const ComputePipelineDescriptor* descriptor,
205             WGPUCreateComputePipelineAsyncCallback callback,
206             void* userdata);
207         ResultOrError<Ref<ExternalTextureBase>> CreateExternalTexture(
208             const ExternalTextureDescriptor* descriptor);
209         ResultOrError<Ref<PipelineLayoutBase>> CreatePipelineLayout(
210             const PipelineLayoutDescriptor* descriptor);
211         ResultOrError<Ref<QuerySetBase>> CreateQuerySet(const QuerySetDescriptor* descriptor);
212         ResultOrError<Ref<RenderBundleEncoder>> CreateRenderBundleEncoder(
213             const RenderBundleEncoderDescriptor* descriptor);
214         ResultOrError<Ref<RenderPipelineBase>> CreateRenderPipeline(
215             const RenderPipelineDescriptor* descriptor);
216         MaybeError CreateRenderPipelineAsync(const RenderPipelineDescriptor* descriptor,
217                                              WGPUCreateRenderPipelineAsyncCallback callback,
218                                              void* userdata);
219         ResultOrError<Ref<SamplerBase>> CreateSampler(const SamplerDescriptor* descriptor);
220         ResultOrError<Ref<ShaderModuleBase>> CreateShaderModule(
221             const ShaderModuleDescriptor* descriptor,
222             OwnedCompilationMessages* compilationMessages = nullptr);
223         ResultOrError<Ref<SwapChainBase>> CreateSwapChain(Surface* surface,
224                                                           const SwapChainDescriptor* descriptor);
225         ResultOrError<Ref<TextureBase>> CreateTexture(const TextureDescriptor* descriptor);
226         ResultOrError<Ref<TextureViewBase>> CreateTextureView(
227             TextureBase* texture,
228             const TextureViewDescriptor* descriptor);
229 
230         // Implementation of API object creation methods. DO NOT use them in a reentrant manner.
231         BindGroupBase* APICreateBindGroup(const BindGroupDescriptor* descriptor);
232         BindGroupLayoutBase* APICreateBindGroupLayout(const BindGroupLayoutDescriptor* descriptor);
233         BufferBase* APICreateBuffer(const BufferDescriptor* descriptor);
234         CommandEncoder* APICreateCommandEncoder(const CommandEncoderDescriptor* descriptor);
235         ComputePipelineBase* APICreateComputePipeline(const ComputePipelineDescriptor* descriptor);
236         PipelineLayoutBase* APICreatePipelineLayout(const PipelineLayoutDescriptor* descriptor);
237         QuerySetBase* APICreateQuerySet(const QuerySetDescriptor* descriptor);
238         void APICreateComputePipelineAsync(const ComputePipelineDescriptor* descriptor,
239                                            WGPUCreateComputePipelineAsyncCallback callback,
240                                            void* userdata);
241         void APICreateRenderPipelineAsync(const RenderPipelineDescriptor* descriptor,
242                                           WGPUCreateRenderPipelineAsyncCallback callback,
243                                           void* userdata);
244         RenderBundleEncoder* APICreateRenderBundleEncoder(
245             const RenderBundleEncoderDescriptor* descriptor);
246         RenderPipelineBase* APICreateRenderPipeline(const RenderPipelineDescriptor* descriptor);
247         ExternalTextureBase* APICreateExternalTexture(const ExternalTextureDescriptor* descriptor);
248         SamplerBase* APICreateSampler(const SamplerDescriptor* descriptor);
249         ShaderModuleBase* APICreateShaderModule(const ShaderModuleDescriptor* descriptor);
250         SwapChainBase* APICreateSwapChain(Surface* surface, const SwapChainDescriptor* descriptor);
251         TextureBase* APICreateTexture(const TextureDescriptor* descriptor);
252 
253         InternalPipelineStore* GetInternalPipelineStore();
254 
255         // For Dawn Wire
256         BufferBase* APICreateErrorBuffer();
257 
258         QueueBase* APIGetQueue();
259 
260         bool APIGetLimits(SupportedLimits* limits);
261         void APIInjectError(wgpu::ErrorType type, const char* message);
262         bool APITick();
263 
264         void APISetDeviceLostCallback(wgpu::DeviceLostCallback callback, void* userdata);
265         void APISetUncapturedErrorCallback(wgpu::ErrorCallback callback, void* userdata);
266         void APISetLoggingCallback(wgpu::LoggingCallback callback, void* userdata);
267         void APIPushErrorScope(wgpu::ErrorFilter filter);
268         bool APIPopErrorScope(wgpu::ErrorCallback callback, void* userdata);
269 
270         MaybeError ValidateIsAlive() const;
271 
272         PersistentCache* GetPersistentCache();
273 
274         virtual ResultOrError<std::unique_ptr<StagingBufferBase>> CreateStagingBuffer(
275             size_t size) = 0;
276         virtual MaybeError CopyFromStagingToBuffer(StagingBufferBase* source,
277                                                    uint64_t sourceOffset,
278                                                    BufferBase* destination,
279                                                    uint64_t destinationOffset,
280                                                    uint64_t size) = 0;
281         virtual MaybeError CopyFromStagingToTexture(const StagingBufferBase* source,
282                                                     const TextureDataLayout& src,
283                                                     TextureCopy* dst,
284                                                     const Extent3D& copySizePixels) = 0;
285 
286         DynamicUploader* GetDynamicUploader() const;
287 
288         // The device state which is a combination of creation state and loss state.
289         //
290         //   - BeingCreated: the device didn't finish creation yet and the frontend cannot be used
291         //     (both for the application calling WebGPU, or re-entrant calls). No work exists on
292         //     the GPU timeline.
293         //   - Alive: the device is usable and might have work happening on the GPU timeline.
294         //   - BeingDisconnected: the device is no longer usable because we are waiting for all
295         //     work on the GPU timeline to finish. (this is to make validation prevent the
296         //     application from adding more work during the transition from Available to
297         //     Disconnected)
298         //   - Disconnected: there is no longer work happening on the GPU timeline and the CPU data
299         //     structures can be safely destroyed without additional synchronization.
300         //   - Destroyed: the device is disconnected and resources have been reclaimed.
301         enum class State {
302             BeingCreated,
303             Alive,
304             BeingDisconnected,
305             Disconnected,
306             Destroyed,
307         };
308         State GetState() const;
309         bool IsLost() const;
310         void TrackObject(ApiObjectBase* object);
311         std::mutex* GetObjectListMutex(ObjectType type);
312 
313         std::vector<const char*> GetEnabledFeatures() const;
314         std::vector<const char*> GetTogglesUsed() const;
315         bool IsFeatureEnabled(Feature feature) const;
316         bool IsToggleEnabled(Toggle toggle) const;
317         bool IsValidationEnabled() const;
318         bool IsRobustnessEnabled() const;
319         size_t GetLazyClearCountForTesting();
320         void IncrementLazyClearCountForTesting();
321         size_t GetDeprecationWarningCountForTesting();
322         void EmitDeprecationWarning(const char* warning);
323         void EmitLog(const char* message);
324         void EmitLog(WGPULoggingType loggingType, const char* message);
325         void APILoseForTesting();
326         QueueBase* GetQueue() const;
327 
328         // AddFutureSerial is used to update the mFutureSerial with the max serial needed to be
329         // ticked in order to clean up all pending callback work or to execute asynchronous resource
330         // writes. It should be given the serial that a callback is tracked with, so that once that
331         // serial is completed, it can be resolved and cleaned up. This is so that when there is no
332         // gpu work (the last submitted serial has not moved beyond the completed serial), Tick can
333         // still check if we have pending work to take care of, rather than hanging and never
334         // reaching the serial the work will be executed on.
335         void AddFutureSerial(ExecutionSerial serial);
336         // Check for passed fences and set the new completed serial
337         MaybeError CheckPassedSerials();
338 
339         MaybeError Tick();
340 
341         // TODO(crbug.com/dawn/839): Organize the below backend-specific parameters into the struct
342         // BackendMetadata that we can query from the device.
343         virtual uint32_t GetOptimalBytesPerRowAlignment() const = 0;
344         virtual uint64_t GetOptimalBufferToTextureCopyOffsetAlignment() const = 0;
345 
346         virtual float GetTimestampPeriodInNS() const = 0;
347 
348         virtual bool ShouldDuplicateNumWorkgroupsForDispatchIndirect(
349             ComputePipelineBase* computePipeline) const;
350 
351         const CombinedLimits& GetLimits() const;
352 
353         AsyncTaskManager* GetAsyncTaskManager() const;
354         CallbackTaskManager* GetCallbackTaskManager() const;
355         dawn_platform::WorkerTaskPool* GetWorkerTaskPool() const;
356 
357         void AddComputePipelineAsyncCallbackTask(Ref<ComputePipelineBase> pipeline,
358                                                  std::string errorMessage,
359                                                  WGPUCreateComputePipelineAsyncCallback callback,
360                                                  void* userdata);
361         void AddRenderPipelineAsyncCallbackTask(Ref<RenderPipelineBase> pipeline,
362                                                 std::string errorMessage,
363                                                 WGPUCreateRenderPipelineAsyncCallback callback,
364                                                 void* userdata);
365 
366         PipelineCompatibilityToken GetNextPipelineCompatibilityToken();
367 
368         const std::string& GetLabel() const;
369         void APISetLabel(const char* label);
370         void APIDestroy();
371 
372       protected:
373         // Constructor used only for mocking and testing.
374         DeviceBase();
375 
376         void SetToggle(Toggle toggle, bool isEnabled);
377         void ForceSetToggle(Toggle toggle, bool isEnabled);
378 
379         MaybeError Initialize(QueueBase* defaultQueue);
380         void DestroyObjects();
381         void Destroy();
382 
383         // Incrememt mLastSubmittedSerial when we submit the next serial
384         void IncrementLastSubmittedCommandSerial();
385 
386       private:
387         virtual ResultOrError<Ref<BindGroupBase>> CreateBindGroupImpl(
388             const BindGroupDescriptor* descriptor) = 0;
389         virtual ResultOrError<Ref<BindGroupLayoutBase>> CreateBindGroupLayoutImpl(
390             const BindGroupLayoutDescriptor* descriptor,
391             PipelineCompatibilityToken pipelineCompatibilityToken) = 0;
392         virtual ResultOrError<Ref<BufferBase>> CreateBufferImpl(
393             const BufferDescriptor* descriptor) = 0;
394         virtual ResultOrError<Ref<PipelineLayoutBase>> CreatePipelineLayoutImpl(
395             const PipelineLayoutDescriptor* descriptor) = 0;
396         virtual ResultOrError<Ref<QuerySetBase>> CreateQuerySetImpl(
397             const QuerySetDescriptor* descriptor) = 0;
398         virtual ResultOrError<Ref<SamplerBase>> CreateSamplerImpl(
399             const SamplerDescriptor* descriptor) = 0;
400         virtual ResultOrError<Ref<ShaderModuleBase>> CreateShaderModuleImpl(
401             const ShaderModuleDescriptor* descriptor,
402             ShaderModuleParseResult* parseResult) = 0;
403         virtual ResultOrError<Ref<SwapChainBase>> CreateSwapChainImpl(
404             const SwapChainDescriptor* descriptor) = 0;
405         // Note that previousSwapChain may be nullptr, or come from a different backend.
406         virtual ResultOrError<Ref<NewSwapChainBase>> CreateSwapChainImpl(
407             Surface* surface,
408             NewSwapChainBase* previousSwapChain,
409             const SwapChainDescriptor* descriptor) = 0;
410         virtual ResultOrError<Ref<TextureBase>> CreateTextureImpl(
411             const TextureDescriptor* descriptor) = 0;
412         virtual ResultOrError<Ref<TextureViewBase>> CreateTextureViewImpl(
413             TextureBase* texture,
414             const TextureViewDescriptor* descriptor) = 0;
415         virtual Ref<ComputePipelineBase> CreateUninitializedComputePipelineImpl(
416             const ComputePipelineDescriptor* descriptor) = 0;
417         virtual Ref<RenderPipelineBase> CreateUninitializedRenderPipelineImpl(
418             const RenderPipelineDescriptor* descriptor) = 0;
419         virtual void SetLabelImpl();
420 
421         virtual MaybeError TickImpl() = 0;
422         void FlushCallbackTaskQueue();
423 
424         ResultOrError<Ref<BindGroupLayoutBase>> CreateEmptyBindGroupLayout();
425 
426         Ref<ComputePipelineBase> GetCachedComputePipeline(
427             ComputePipelineBase* uninitializedComputePipeline);
428         Ref<RenderPipelineBase> GetCachedRenderPipeline(
429             RenderPipelineBase* uninitializedRenderPipeline);
430         Ref<ComputePipelineBase> AddOrGetCachedComputePipeline(
431             Ref<ComputePipelineBase> computePipeline);
432         Ref<RenderPipelineBase> AddOrGetCachedRenderPipeline(
433             Ref<RenderPipelineBase> renderPipeline);
434         virtual void InitializeComputePipelineAsyncImpl(
435             Ref<ComputePipelineBase> computePipeline,
436             WGPUCreateComputePipelineAsyncCallback callback,
437             void* userdata);
438         virtual void InitializeRenderPipelineAsyncImpl(
439             Ref<RenderPipelineBase> renderPipeline,
440             WGPUCreateRenderPipelineAsyncCallback callback,
441             void* userdata);
442 
443         void ApplyToggleOverrides(const DawnDeviceDescriptor* deviceDescriptor);
444         void ApplyFeatures(const DawnDeviceDescriptor* deviceDescriptor);
445 
446         void SetDefaultToggles();
447 
448         void ConsumeError(std::unique_ptr<ErrorData> error);
449 
450         // Each backend should implement to check their passed fences if there are any and return a
451         // completed serial. Return 0 should indicate no fences to check.
452         virtual ResultOrError<ExecutionSerial> CheckAndUpdateCompletedSerials() = 0;
453         // During shut down of device, some operations might have been started since the last submit
454         // and waiting on a serial that doesn't have a corresponding fence enqueued. Fake serials to
455         // make all commands look completed.
456         void AssumeCommandsComplete();
457         bool IsDeviceIdle();
458 
459         // mCompletedSerial tracks the last completed command serial that the fence has returned.
460         // mLastSubmittedSerial tracks the last submitted command serial.
461         // During device removal, the serials could be artificially incremented
462         // to make it appear as if commands have been compeleted. They can also be artificially
463         // incremented when no work is being done in the GPU so CPU operations don't have to wait on
464         // stale serials.
465         // mFutureSerial tracks the largest serial we need to tick to for asynchronous commands or
466         // callbacks to fire
467         ExecutionSerial mCompletedSerial = ExecutionSerial(0);
468         ExecutionSerial mLastSubmittedSerial = ExecutionSerial(0);
469         ExecutionSerial mFutureSerial = ExecutionSerial(0);
470 
471         // DestroyImpl is used to clean up and release resources used by device, does not wait for
472         // GPU or check errors.
473         virtual void DestroyImpl() = 0;
474 
475         // WaitForIdleForDestruction waits for GPU to finish, checks errors and gets ready for
476         // destruction. This is only used when properly destructing the device. For a real
477         // device loss, this function doesn't need to be called since the driver already closed all
478         // resources.
479         virtual MaybeError WaitForIdleForDestruction() = 0;
480 
481         wgpu::ErrorCallback mUncapturedErrorCallback = nullptr;
482         void* mUncapturedErrorUserdata = nullptr;
483 
484         wgpu::LoggingCallback mLoggingCallback = nullptr;
485         void* mLoggingUserdata = nullptr;
486 
487         wgpu::DeviceLostCallback mDeviceLostCallback = nullptr;
488         void* mDeviceLostUserdata = nullptr;
489 
490         std::unique_ptr<ErrorScopeStack> mErrorScopeStack;
491 
492         // The Device keeps a ref to the Instance so that any live Device keeps the Instance alive.
493         // The Instance shouldn't need to ref child objects so this shouldn't introduce ref cycles.
494         // The Device keeps a simple pointer to the Adapter because the Adapter is owned by the
495         // Instance.
496         Ref<InstanceBase> mInstance;
497         AdapterBase* mAdapter = nullptr;
498 
499         // The object caches aren't exposed in the header as they would require a lot of
500         // additional includes.
501         struct Caches;
502         std::unique_ptr<Caches> mCaches;
503 
504         Ref<BindGroupLayoutBase> mEmptyBindGroupLayout;
505 
506         std::unique_ptr<DynamicUploader> mDynamicUploader;
507         std::unique_ptr<AsyncTaskManager> mAsyncTaskManager;
508         Ref<QueueBase> mQueue;
509 
510         struct DeprecationWarnings;
511         std::unique_ptr<DeprecationWarnings> mDeprecationWarnings;
512 
513         State mState = State::BeingCreated;
514 
515         // Encompasses the mutex and the actual list that contains all live objects "owned" by the
516         // device.
517         struct ApiObjectList {
518             std::mutex mutex;
519             LinkedList<ApiObjectBase> objects;
520         };
521         PerObjectType<ApiObjectList> mObjectLists;
522 
523         FormatTable mFormatTable;
524 
525         TogglesSet mEnabledToggles;
526         TogglesSet mOverridenToggles;
527         size_t mLazyClearCountForTesting = 0;
528         std::atomic_uint64_t mNextPipelineCompatibilityToken;
529 
530         CombinedLimits mLimits;
531         FeaturesSet mEnabledFeatures;
532 
533         std::unique_ptr<InternalPipelineStore> mInternalPipelineStore;
534 
535         std::unique_ptr<PersistentCache> mPersistentCache;
536 
537         std::unique_ptr<CallbackTaskManager> mCallbackTaskManager;
538         std::unique_ptr<dawn_platform::WorkerTaskPool> mWorkerTaskPool;
539         std::string mLabel;
540     };
541 
542 }  // namespace dawn_native
543 
544 #endif  // DAWNNATIVE_DEVICE_H_
545