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