dawn-cmake/src/dawn_native/Device.h

415 lines
20 KiB
C
Raw Normal View History

// Copyright 2017 The Dawn Authors
2017-05-31 00:03:44 +00:00
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef DAWNNATIVE_DEVICE_H_
#define DAWNNATIVE_DEVICE_H_
2017-05-31 00:03:44 +00:00
#include "dawn_native/Commands.h"
2018-07-24 11:53:51 +00:00
#include "dawn_native/Error.h"
#include "dawn_native/Extensions.h"
#include "dawn_native/Format.h"
2018-07-24 11:53:51 +00:00
#include "dawn_native/Forward.h"
#include "dawn_native/ObjectBase.h"
#include "dawn_native/Toggles.h"
2017-05-31 00:03:44 +00:00
#include "dawn_native/DawnNative.h"
#include "dawn_native/dawn_platform.h"
2017-05-31 00:03:44 +00:00
#include <memory>
namespace dawn_native {
class AdapterBase;
class AttachmentState;
class AttachmentStateBlueprint;
class BindGroupLayoutBase;
class CreatePipelineAsyncTracker;
class DynamicUploader;
class ErrorScopeStack;
class ExternalTextureBase;
class PersistentCache;
class StagingBufferBase;
struct InternalPipelineStore;
struct ShaderModuleParseResult;
class DeviceBase : public RefCounted {
2017-11-24 18:59:42 +00:00
public:
DeviceBase(AdapterBase* adapter, const DeviceDescriptor* descriptor);
2017-11-24 18:59:42 +00:00
virtual ~DeviceBase();
void HandleError(InternalErrorType type, const char* message);
2017-11-24 18:59:42 +00:00
bool ConsumedError(MaybeError maybeError) {
if (DAWN_UNLIKELY(maybeError.IsError())) {
ConsumeError(maybeError.AcquireError());
return true;
}
return false;
}
template <typename T>
bool ConsumedError(ResultOrError<T> resultOrError, T* result) {
if (DAWN_UNLIKELY(resultOrError.IsError())) {
ConsumeError(resultOrError.AcquireError());
return true;
}
*result = resultOrError.AcquireSuccess();
return false;
}
MaybeError ValidateObject(const ObjectBase* object) const;
AdapterBase* GetAdapter() const;
dawn_platform::Platform* GetPlatform() const;
// Returns the Format corresponding to the wgpu::TextureFormat or an error if the format
// isn't a valid wgpu::TextureFormat or isn't supported by this device.
// The pointer returned has the same lifetime as the device.
ResultOrError<const Format*> GetInternalFormat(wgpu::TextureFormat format) const;
// Returns the Format corresponding to the wgpu::TextureFormat and assumes the format is
// valid and supported.
// The reference returned has the same lifetime as the device.
const Format& GetValidInternalFormat(wgpu::TextureFormat format) const;
virtual ResultOrError<Ref<CommandBufferBase>> CreateCommandBuffer(
CommandEncoder* encoder,
const CommandBufferDescriptor* descriptor) = 0;
2017-11-24 18:59:42 +00:00
ExecutionSerial GetCompletedCommandSerial() const;
ExecutionSerial GetLastSubmittedCommandSerial() const;
ExecutionSerial GetFutureSerial() const;
ExecutionSerial GetPendingCommandSerial() const;
2017-11-24 18:59:42 +00:00
2018-07-18 13:28:38 +00:00
// Many Dawn objects are completely immutable once created which means that if two
// creations are given the same arguments, they can return the same object. Reusing
2017-11-24 18:59:42 +00:00
// objects will help make comparisons between objects by a single pointer comparison.
//
// Technically no object is immutable as they have a reference count, and an
// application with reference-counting issues could "see" that objects are reused.
// This is solved by automatic-reference counting, and also the fact that when using
// the client-server wire every creation will get a different proxy object, with a
// different reference count.
//
// When trying to create an object, we give both the descriptor and an example of what
// the created object will be, the "blueprint". The blueprint is just a FooBase object
2017-11-24 18:59:42 +00:00
// instead of a backend Foo object. If the blueprint doesn't match an object in the
// cache, then the descriptor is used to make a new object.
ResultOrError<Ref<BindGroupLayoutBase>> GetOrCreateBindGroupLayout(
const BindGroupLayoutDescriptor* descriptor);
2017-11-24 18:59:42 +00:00
void UncacheBindGroupLayout(BindGroupLayoutBase* obj);
BindGroupLayoutBase* GetEmptyBindGroupLayout();
ResultOrError<Ref<ComputePipelineBase>> GetOrCreateComputePipeline(
const ComputePipelineDescriptor* descriptor);
void UncacheComputePipeline(ComputePipelineBase* obj);
ResultOrError<Ref<PipelineLayoutBase>> GetOrCreatePipelineLayout(
const PipelineLayoutDescriptor* descriptor);
void UncachePipelineLayout(PipelineLayoutBase* obj);
ResultOrError<Ref<RenderPipelineBase>> GetOrCreateRenderPipeline(
const RenderPipelineDescriptor2* descriptor);
void UncacheRenderPipeline(RenderPipelineBase* obj);
ResultOrError<Ref<SamplerBase>> GetOrCreateSampler(const SamplerDescriptor* descriptor);
void UncacheSampler(SamplerBase* obj);
ResultOrError<Ref<ShaderModuleBase>> GetOrCreateShaderModule(
const ShaderModuleDescriptor* descriptor,
ShaderModuleParseResult* parseResult);
void UncacheShaderModule(ShaderModuleBase* obj);
Ref<AttachmentState> GetOrCreateAttachmentState(AttachmentStateBlueprint* blueprint);
Ref<AttachmentState> GetOrCreateAttachmentState(
const RenderBundleEncoderDescriptor* descriptor);
Ref<AttachmentState> GetOrCreateAttachmentState(const RenderPipelineDescriptor* descriptor);
Ref<AttachmentState> GetOrCreateAttachmentState(
const RenderPipelineDescriptor2* descriptor);
Ref<AttachmentState> GetOrCreateAttachmentState(const RenderPassDescriptor* descriptor);
void UncacheAttachmentState(AttachmentState* obj);
2018-07-18 13:20:28 +00:00
// Dawn API
BindGroupBase* APICreateBindGroup(const BindGroupDescriptor* descriptor);
BindGroupLayoutBase* APICreateBindGroupLayout(const BindGroupLayoutDescriptor* descriptor);
BufferBase* APICreateBuffer(const BufferDescriptor* descriptor);
CommandEncoder* APICreateCommandEncoder(const CommandEncoderDescriptor* descriptor);
ComputePipelineBase* APICreateComputePipeline(const ComputePipelineDescriptor* descriptor);
PipelineLayoutBase* APICreatePipelineLayout(const PipelineLayoutDescriptor* descriptor);
QuerySetBase* APICreateQuerySet(const QuerySetDescriptor* descriptor);
void APICreateComputePipelineAsync(const ComputePipelineDescriptor* descriptor,
WGPUCreateComputePipelineAsyncCallback callback,
void* userdata);
void APICreateRenderPipelineAsync(const RenderPipelineDescriptor2* descriptor,
WGPUCreateRenderPipelineAsyncCallback callback,
void* userdata);
RenderBundleEncoder* APICreateRenderBundleEncoder(
const RenderBundleEncoderDescriptor* descriptor);
RenderPipelineBase* APICreateRenderPipeline(const RenderPipelineDescriptor* descriptor);
RenderPipelineBase* APICreateRenderPipeline2(const RenderPipelineDescriptor2* descriptor);
ExternalTextureBase* APICreateExternalTexture(const ExternalTextureDescriptor* descriptor);
SamplerBase* APICreateSampler(const SamplerDescriptor* descriptor);
ShaderModuleBase* APICreateShaderModule(const ShaderModuleDescriptor* descriptor);
SwapChainBase* APICreateSwapChain(Surface* surface, const SwapChainDescriptor* descriptor);
TextureBase* APICreateTexture(const TextureDescriptor* descriptor);
TextureViewBase* CreateTextureView(TextureBase* texture,
const TextureViewDescriptor* descriptor);
InternalPipelineStore* GetInternalPipelineStore();
2017-11-24 18:59:42 +00:00
// For Dawn Wire
BufferBase* APICreateErrorBuffer();
// TODO(dawn:22): Remove once the deprecation period is finished.
QueueBase* APIGetDefaultQueue();
QueueBase* APIGetQueue();
void APIInjectError(wgpu::ErrorType type, const char* message);
bool APITick();
void APISetDeviceLostCallback(wgpu::DeviceLostCallback callback, void* userdata);
void APISetUncapturedErrorCallback(wgpu::ErrorCallback callback, void* userdata);
void APIPushErrorScope(wgpu::ErrorFilter filter);
bool APIPopErrorScope(wgpu::ErrorCallback callback, void* userdata);
MaybeError ValidateIsAlive() const;
PersistentCache* GetPersistentCache();
virtual ResultOrError<std::unique_ptr<StagingBufferBase>> CreateStagingBuffer(
size_t size) = 0;
virtual MaybeError CopyFromStagingToBuffer(StagingBufferBase* source,
uint64_t sourceOffset,
BufferBase* destination,
uint64_t destinationOffset,
uint64_t size) = 0;
virtual MaybeError CopyFromStagingToTexture(const StagingBufferBase* source,
const TextureDataLayout& src,
TextureCopy* dst,
const Extent3D& copySizePixels) = 0;
DynamicUploader* GetDynamicUploader() const;
Simplify the device lifecycle. What was previously the Device's loss status is now a state that also contains the "being created" state. Its transitions are entirely handled in the frontend which enforces somewhat uniform lifecycles between backends. The backend devices' ShutDownImpl() function is now guaranteed to be called only during the destructor, which leads to further simplification. Previously Destroy() could also be called when the device was first lost. This require complications because, for example, a WGPUBuffer could still exist, and would want to call some resource allocator service after the call to Destroy(). Now destruction of the device's backing API objects is deferred to the destructor. (that's ok as long as the application can't submit any more work). WaitForCompletion is now guaranteed to be called before ShutDownImpl() iff the call to DeviceBase::Initialize was succesful and the backing device not lost. The idea is that after DeviceBase::Initialize, the GPU can have some work enqueued and we need to wait for it to complete before deleting backing API objects. In the future we might also have backend be reentrant, using WebGPU itself to implement parts of the backend. Reentrant calls would only be allowed after DeviceBase::Initialize. Also the DynamicUploader that was special-cased in all backends is now handled entirely by the frontend. Bug: dawn:373 Change-Id: I985417d67727ea3bc11849c999c5ef0e02403223 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/18801 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org>
2020-04-07 16:19:47 +00:00
// The device state which is a combination of creation state and loss state.
//
// - BeingCreated: the device didn't finish creation yet and the frontend cannot be used
// (both for the application calling WebGPU, or re-entrant calls). No work exists on
// the GPU timeline.
// - Alive: the device is usable and might have work happening on the GPU timeline.
// - BeingDisconnected: the device is no longer usable because we are waiting for all
// work on the GPU timeline to finish. (this is to make validation prevent the
// application from adding more work during the transition from Available to
// Disconnected)
// - Disconnected: there is no longer work happening on the GPU timeline and the CPU data
// structures can be safely destroyed without additional synchronization.
enum class State {
BeingCreated,
Alive,
BeingDisconnected,
Disconnected,
};
State GetState() const;
bool IsLost() const;
std::vector<const char*> GetEnabledExtensions() const;
std::vector<const char*> GetTogglesUsed() const;
bool IsExtensionEnabled(Extension extension) const;
bool IsToggleEnabled(Toggle toggle) const;
bool IsValidationEnabled() const;
bool IsRobustnessEnabled() const;
size_t GetLazyClearCountForTesting();
void IncrementLazyClearCountForTesting();
size_t GetDeprecationWarningCountForTesting();
void EmitDeprecationWarning(const char* warning);
void APILoseForTesting();
QueueBase* GetQueue() const;
// AddFutureSerial is used to update the mFutureSerial with the max serial needed to be
// ticked in order to clean up all pending callback work or to execute asynchronous resource
// writes. It should be given the serial that a callback is tracked with, so that once that
// serial is completed, it can be resolved and cleaned up. This is so that when there is no
// gpu work (the last submitted serial has not moved beyond the completed serial), Tick can
// still check if we have pending work to take care of, rather than hanging and never
// reaching the serial the work will be executed on.
void AddFutureSerial(ExecutionSerial serial);
// Check for passed fences and set the new completed serial
void CheckPassedSerials();
MaybeError Tick();
virtual uint32_t GetOptimalBytesPerRowAlignment() const = 0;
virtual uint64_t GetOptimalBufferToTextureCopyOffsetAlignment() const = 0;
virtual float GetTimestampPeriodInNS() const = 0;
protected:
void SetToggle(Toggle toggle, bool isEnabled);
void ForceSetToggle(Toggle toggle, bool isEnabled);
MaybeError Initialize(QueueBase* defaultQueue);
Simplify the device lifecycle. What was previously the Device's loss status is now a state that also contains the "being created" state. Its transitions are entirely handled in the frontend which enforces somewhat uniform lifecycles between backends. The backend devices' ShutDownImpl() function is now guaranteed to be called only during the destructor, which leads to further simplification. Previously Destroy() could also be called when the device was first lost. This require complications because, for example, a WGPUBuffer could still exist, and would want to call some resource allocator service after the call to Destroy(). Now destruction of the device's backing API objects is deferred to the destructor. (that's ok as long as the application can't submit any more work). WaitForCompletion is now guaranteed to be called before ShutDownImpl() iff the call to DeviceBase::Initialize was succesful and the backing device not lost. The idea is that after DeviceBase::Initialize, the GPU can have some work enqueued and we need to wait for it to complete before deleting backing API objects. In the future we might also have backend be reentrant, using WebGPU itself to implement parts of the backend. Reentrant calls would only be allowed after DeviceBase::Initialize. Also the DynamicUploader that was special-cased in all backends is now handled entirely by the frontend. Bug: dawn:373 Change-Id: I985417d67727ea3bc11849c999c5ef0e02403223 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/18801 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org>
2020-04-07 16:19:47 +00:00
void ShutDownBase();
// Incrememt mLastSubmittedSerial when we submit the next serial
void IncrementLastSubmittedCommandSerial();
2017-11-24 18:59:42 +00:00
private:
virtual ResultOrError<Ref<BindGroupBase>> CreateBindGroupImpl(
const BindGroupDescriptor* descriptor) = 0;
virtual ResultOrError<Ref<BindGroupLayoutBase>> CreateBindGroupLayoutImpl(
const BindGroupLayoutDescriptor* descriptor) = 0;
virtual ResultOrError<Ref<BufferBase>> CreateBufferImpl(
const BufferDescriptor* descriptor) = 0;
virtual ResultOrError<Ref<ComputePipelineBase>> CreateComputePipelineImpl(
const ComputePipelineDescriptor* descriptor) = 0;
virtual ResultOrError<Ref<PipelineLayoutBase>> CreatePipelineLayoutImpl(
const PipelineLayoutDescriptor* descriptor) = 0;
virtual ResultOrError<Ref<QuerySetBase>> CreateQuerySetImpl(
const QuerySetDescriptor* descriptor) = 0;
virtual ResultOrError<Ref<RenderPipelineBase>> CreateRenderPipelineImpl(
const RenderPipelineDescriptor2* descriptor) = 0;
virtual ResultOrError<Ref<SamplerBase>> CreateSamplerImpl(
const SamplerDescriptor* descriptor) = 0;
virtual ResultOrError<Ref<ShaderModuleBase>> CreateShaderModuleImpl(
const ShaderModuleDescriptor* descriptor,
ShaderModuleParseResult* parseResult) = 0;
virtual ResultOrError<Ref<SwapChainBase>> CreateSwapChainImpl(
const SwapChainDescriptor* descriptor) = 0;
// Note that previousSwapChain may be nullptr, or come from a different backend.
virtual ResultOrError<Ref<NewSwapChainBase>> CreateSwapChainImpl(
Surface* surface,
NewSwapChainBase* previousSwapChain,
const SwapChainDescriptor* descriptor) = 0;
virtual ResultOrError<Ref<TextureBase>> CreateTextureImpl(
const TextureDescriptor* descriptor) = 0;
virtual ResultOrError<Ref<TextureViewBase>> CreateTextureViewImpl(
TextureBase* texture,
const TextureViewDescriptor* descriptor) = 0;
virtual MaybeError TickImpl() = 0;
ResultOrError<Ref<BindGroupLayoutBase>> CreateEmptyBindGroupLayout();
ResultOrError<Ref<BindGroupBase>> CreateBindGroupInternal(
const BindGroupDescriptor* descriptor);
ResultOrError<Ref<BindGroupLayoutBase>> CreateBindGroupLayoutInternal(
const BindGroupLayoutDescriptor* descriptor);
ResultOrError<Ref<BufferBase>> CreateBufferInternal(const BufferDescriptor* descriptor);
ResultOrError<Ref<ComputePipelineBase>> CreateComputePipelineInternal(
const ComputePipelineDescriptor* descriptor);
ResultOrError<Ref<PipelineLayoutBase>> CreatePipelineLayoutInternal(
const PipelineLayoutDescriptor* descriptor);
ResultOrError<Ref<ExternalTextureBase>> CreateExternalTextureInternal(
const ExternalTextureDescriptor* descriptor);
ResultOrError<Ref<QuerySetBase>> CreateQuerySetInternal(
const QuerySetDescriptor* descriptor);
ResultOrError<Ref<RenderBundleEncoder>> CreateRenderBundleEncoderInternal(
const RenderBundleEncoderDescriptor* descriptor);
ResultOrError<Ref<RenderPipelineBase>> CreateRenderPipelineInternal(
const RenderPipelineDescriptor2* descriptor);
ResultOrError<Ref<SamplerBase>> CreateSamplerInternal(const SamplerDescriptor* descriptor);
ResultOrError<Ref<ShaderModuleBase>> CreateShaderModuleInternal(
const ShaderModuleDescriptor* descriptor);
ResultOrError<Ref<SwapChainBase>> CreateSwapChainInternal(
Surface* surface,
const SwapChainDescriptor* descriptor);
ResultOrError<Ref<TextureBase>> CreateTextureInternal(const TextureDescriptor* descriptor);
ResultOrError<Ref<TextureViewBase>> CreateTextureViewInternal(
TextureBase* texture,
const TextureViewDescriptor* descriptor);
void ApplyToggleOverrides(const DeviceDescriptor* deviceDescriptor);
void ApplyExtensions(const DeviceDescriptor* deviceDescriptor);
void SetDefaultToggles();
void ConsumeError(std::unique_ptr<ErrorData> error);
// Each backend should implement to check their passed fences if there are any and return a
// completed serial. Return 0 should indicate no fences to check.
virtual ExecutionSerial CheckAndUpdateCompletedSerials() = 0;
// During shut down of device, some operations might have been started since the last submit
// and waiting on a serial that doesn't have a corresponding fence enqueued. Fake serials to
// make all commands look completed.
void AssumeCommandsComplete();
bool IsDeviceIdle();
// mCompletedSerial tracks the last completed command serial that the fence has returned.
// mLastSubmittedSerial tracks the last submitted command serial.
// During device removal, the serials could be artificially incremented
// to make it appear as if commands have been compeleted. They can also be artificially
// incremented when no work is being done in the GPU so CPU operations don't have to wait on
// stale serials.
// mFutureSerial tracks the largest serial we need to tick to for asynchronous commands or
// callbacks to fire
ExecutionSerial mCompletedSerial = ExecutionSerial(0);
ExecutionSerial mLastSubmittedSerial = ExecutionSerial(0);
ExecutionSerial mFutureSerial = ExecutionSerial(0);
Simplify the device lifecycle. What was previously the Device's loss status is now a state that also contains the "being created" state. Its transitions are entirely handled in the frontend which enforces somewhat uniform lifecycles between backends. The backend devices' ShutDownImpl() function is now guaranteed to be called only during the destructor, which leads to further simplification. Previously Destroy() could also be called when the device was first lost. This require complications because, for example, a WGPUBuffer could still exist, and would want to call some resource allocator service after the call to Destroy(). Now destruction of the device's backing API objects is deferred to the destructor. (that's ok as long as the application can't submit any more work). WaitForCompletion is now guaranteed to be called before ShutDownImpl() iff the call to DeviceBase::Initialize was succesful and the backing device not lost. The idea is that after DeviceBase::Initialize, the GPU can have some work enqueued and we need to wait for it to complete before deleting backing API objects. In the future we might also have backend be reentrant, using WebGPU itself to implement parts of the backend. Reentrant calls would only be allowed after DeviceBase::Initialize. Also the DynamicUploader that was special-cased in all backends is now handled entirely by the frontend. Bug: dawn:373 Change-Id: I985417d67727ea3bc11849c999c5ef0e02403223 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/18801 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org>
2020-04-07 16:19:47 +00:00
// ShutDownImpl is used to clean up and release resources used by device, does not wait for
// GPU or check errors.
virtual void ShutDownImpl() = 0;
// WaitForIdleForDestruction waits for GPU to finish, checks errors and gets ready for
// destruction. This is only used when properly destructing the device. For a real
// device loss, this function doesn't need to be called since the driver already closed all
// resources.
virtual MaybeError WaitForIdleForDestruction() = 0;
wgpu::ErrorCallback mUncapturedErrorCallback = nullptr;
void* mUncapturedErrorUserdata = nullptr;
wgpu::DeviceLostCallback mDeviceLostCallback = nullptr;
Simplify the device lifecycle. What was previously the Device's loss status is now a state that also contains the "being created" state. Its transitions are entirely handled in the frontend which enforces somewhat uniform lifecycles between backends. The backend devices' ShutDownImpl() function is now guaranteed to be called only during the destructor, which leads to further simplification. Previously Destroy() could also be called when the device was first lost. This require complications because, for example, a WGPUBuffer could still exist, and would want to call some resource allocator service after the call to Destroy(). Now destruction of the device's backing API objects is deferred to the destructor. (that's ok as long as the application can't submit any more work). WaitForCompletion is now guaranteed to be called before ShutDownImpl() iff the call to DeviceBase::Initialize was succesful and the backing device not lost. The idea is that after DeviceBase::Initialize, the GPU can have some work enqueued and we need to wait for it to complete before deleting backing API objects. In the future we might also have backend be reentrant, using WebGPU itself to implement parts of the backend. Reentrant calls would only be allowed after DeviceBase::Initialize. Also the DynamicUploader that was special-cased in all backends is now handled entirely by the frontend. Bug: dawn:373 Change-Id: I985417d67727ea3bc11849c999c5ef0e02403223 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/18801 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org>
2020-04-07 16:19:47 +00:00
void* mDeviceLostUserdata = nullptr;
std::unique_ptr<ErrorScopeStack> mErrorScopeStack;
// The Device keeps a ref to the Instance so that any live Device keeps the Instance alive.
// The Instance shouldn't need to ref child objects so this shouldn't introduce ref cycles.
// The Device keeps a simple pointer to the Adapter because the Adapter is owned by the
// Instance.
Ref<InstanceBase> mInstance;
AdapterBase* mAdapter = nullptr;
2017-11-24 18:59:42 +00:00
// The object caches aren't exposed in the header as they would require a lot of
// additional includes.
struct Caches;
std::unique_ptr<Caches> mCaches;
2017-11-24 18:59:42 +00:00
Ref<BindGroupLayoutBase> mEmptyBindGroupLayout;
Simplify the device lifecycle. What was previously the Device's loss status is now a state that also contains the "being created" state. Its transitions are entirely handled in the frontend which enforces somewhat uniform lifecycles between backends. The backend devices' ShutDownImpl() function is now guaranteed to be called only during the destructor, which leads to further simplification. Previously Destroy() could also be called when the device was first lost. This require complications because, for example, a WGPUBuffer could still exist, and would want to call some resource allocator service after the call to Destroy(). Now destruction of the device's backing API objects is deferred to the destructor. (that's ok as long as the application can't submit any more work). WaitForCompletion is now guaranteed to be called before ShutDownImpl() iff the call to DeviceBase::Initialize was succesful and the backing device not lost. The idea is that after DeviceBase::Initialize, the GPU can have some work enqueued and we need to wait for it to complete before deleting backing API objects. In the future we might also have backend be reentrant, using WebGPU itself to implement parts of the backend. Reentrant calls would only be allowed after DeviceBase::Initialize. Also the DynamicUploader that was special-cased in all backends is now handled entirely by the frontend. Bug: dawn:373 Change-Id: I985417d67727ea3bc11849c999c5ef0e02403223 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/18801 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org>
2020-04-07 16:19:47 +00:00
std::unique_ptr<DynamicUploader> mDynamicUploader;
std::unique_ptr<CreatePipelineAsyncTracker> mCreatePipelineAsyncTracker;
Ref<QueueBase> mQueue;
struct DeprecationWarnings;
std::unique_ptr<DeprecationWarnings> mDeprecationWarnings;
Simplify the device lifecycle. What was previously the Device's loss status is now a state that also contains the "being created" state. Its transitions are entirely handled in the frontend which enforces somewhat uniform lifecycles between backends. The backend devices' ShutDownImpl() function is now guaranteed to be called only during the destructor, which leads to further simplification. Previously Destroy() could also be called when the device was first lost. This require complications because, for example, a WGPUBuffer could still exist, and would want to call some resource allocator service after the call to Destroy(). Now destruction of the device's backing API objects is deferred to the destructor. (that's ok as long as the application can't submit any more work). WaitForCompletion is now guaranteed to be called before ShutDownImpl() iff the call to DeviceBase::Initialize was succesful and the backing device not lost. The idea is that after DeviceBase::Initialize, the GPU can have some work enqueued and we need to wait for it to complete before deleting backing API objects. In the future we might also have backend be reentrant, using WebGPU itself to implement parts of the backend. Reentrant calls would only be allowed after DeviceBase::Initialize. Also the DynamicUploader that was special-cased in all backends is now handled entirely by the frontend. Bug: dawn:373 Change-Id: I985417d67727ea3bc11849c999c5ef0e02403223 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/18801 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org>
2020-04-07 16:19:47 +00:00
State mState = State::BeingCreated;
FormatTable mFormatTable;
TogglesSet mEnabledToggles;
TogglesSet mOverridenToggles;
size_t mLazyClearCountForTesting = 0;
ExtensionsSet mEnabledExtensions;
std::unique_ptr<InternalPipelineStore> mInternalPipelineStore;
std::unique_ptr<PersistentCache> mPersistentCache;
2017-05-31 00:03:44 +00:00
};
} // namespace dawn_native
2017-05-31 00:03:44 +00:00
#endif // DAWNNATIVE_DEVICE_H_