mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-06-23 15:03:43 +00:00
Adds remaining setup logic to implement destroy in Device and ObjectBase.
- Renames some of the Device functions to be consistent with documentation - Reverts change in https://dawn-review.googlesource.com/c/dawn/+/64820 for overloading mDevice == nullptr to determine if objects are alive because device is needed for error propagation. Instead, use list existence to determine if objects are alive - Updates destroy api to return bool upwards in case we need to further process the extending objects - Adds tracking functions in ObjectBase - Adds final tag to all backend Device implementations - Adds MoveInto LinkedList support to move list elements in O(1) Bug: dawn:628 Change-Id: Iff70f4f7d55f46ee52d1bd0e02e3671819f2eed4 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/65861 Commit-Queue: Loko Kung <lokokung@google.com> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
e355bb8e65
commit
fc5a7d414f
@ -43,7 +43,7 @@ After this the device is set in the `Disconnected` state.
|
|||||||
If an `Alive` device is destroyed, then a similar flow to `LoseForTesting happens`.
|
If an `Alive` device is destroyed, then a similar flow to `LoseForTesting happens`.
|
||||||
|
|
||||||
All this ensures that during destruction or forceful disconnect of the device, it properly gets to the `Disconnected` state with no commands executing on the GPU.
|
All this ensures that during destruction or forceful disconnect of the device, it properly gets to the `Disconnected` state with no commands executing on the GPU.
|
||||||
After disconnecting, frontend will call `backend::Device::ShutDownImpl` so that it can properly free driver objects.
|
After disconnecting, frontend will call `backend::Device::DestroyImpl` so that it can properly free driver objects.
|
||||||
|
|
||||||
### Toggles
|
### Toggles
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
// modifications:
|
// modifications:
|
||||||
// - Added iterators for ranged based iterations
|
// - Added iterators for ranged based iterations
|
||||||
// - Added in list check before removing node to prevent segfault, now returns true iff removed
|
// - Added in list check before removing node to prevent segfault, now returns true iff removed
|
||||||
|
// - Added MoveInto functionality for moving list elements to another list
|
||||||
|
|
||||||
#ifndef COMMON_LINKED_LIST_H
|
#ifndef COMMON_LINKED_LIST_H
|
||||||
#define COMMON_LINKED_LIST_H
|
#define COMMON_LINKED_LIST_H
|
||||||
@ -89,6 +90,12 @@
|
|||||||
// needs to glue on the "next" and "previous" pointers using
|
// needs to glue on the "next" and "previous" pointers using
|
||||||
// some internal node type.
|
// some internal node type.
|
||||||
|
|
||||||
|
// Forward declarations of the types in order for recursive referencing and friending.
|
||||||
|
template <typename T>
|
||||||
|
class LinkNode;
|
||||||
|
template <typename T>
|
||||||
|
class LinkedList;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class LinkNode {
|
class LinkNode {
|
||||||
public:
|
public:
|
||||||
@ -165,6 +172,7 @@ class LinkNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend class LinkedList<T>;
|
||||||
LinkNode<T>* previous_;
|
LinkNode<T>* previous_;
|
||||||
LinkNode<T>* next_;
|
LinkNode<T>* next_;
|
||||||
};
|
};
|
||||||
@ -190,6 +198,20 @@ class LinkedList {
|
|||||||
e->InsertBefore(&root_);
|
e->InsertBefore(&root_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Moves all elements (in order) of the list and appends them into |l| leaving the list empty.
|
||||||
|
void MoveInto(LinkedList<T>* l) {
|
||||||
|
if (empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
l->root_.previous_->next_ = root_.next_;
|
||||||
|
root_.next_->previous_ = l->root_.previous_;
|
||||||
|
l->root_.previous_ = root_.previous_;
|
||||||
|
root_.previous_->next_ = &l->root_;
|
||||||
|
|
||||||
|
root_.next_ = &root_;
|
||||||
|
root_.previous_ = &root_;
|
||||||
|
}
|
||||||
|
|
||||||
LinkNode<T>* head() const {
|
LinkNode<T>* head() const {
|
||||||
return root_.next();
|
return root_.next();
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
#include "dawn_native/ValidationUtils_autogen.h"
|
#include "dawn_native/ValidationUtils_autogen.h"
|
||||||
#include "dawn_platform/DawnPlatform.h"
|
#include "dawn_platform/DawnPlatform.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
@ -262,7 +263,30 @@ namespace dawn_native {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceBase::ShutDownBase() {
|
void DeviceBase::DestroyObjects() {
|
||||||
|
// List of object types in reverse "dependency" order so we can iterate and delete the
|
||||||
|
// objects safely starting at leaf objects. We define dependent here such that if B has
|
||||||
|
// a ref to A, then B depends on A. We therefore try to destroy B before destroying A. Note
|
||||||
|
// that this only considers the immediate frontend dependencies, while backend objects could
|
||||||
|
// add complications and extra dependencies.
|
||||||
|
// TODO(dawn/628) Add types into the array as they are implemented.
|
||||||
|
static constexpr std::array<ObjectType, 0> kObjectTypeDependencyOrder = {};
|
||||||
|
|
||||||
|
// We first move all objects out from the tracking list into a separate list so that we can
|
||||||
|
// avoid locking the same mutex twice. We can then iterate across the separate list to call
|
||||||
|
// the actual destroy function.
|
||||||
|
LinkedList<ApiObjectBase> objects;
|
||||||
|
for (ObjectType type : kObjectTypeDependencyOrder) {
|
||||||
|
ApiObjectList& objList = mObjectLists[type];
|
||||||
|
const std::lock_guard<std::mutex> lock(objList.mutex);
|
||||||
|
objList.objects.MoveInto(&objects);
|
||||||
|
}
|
||||||
|
for (LinkNode<ApiObjectBase>* node : objects) {
|
||||||
|
node->value()->DestroyApiObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceBase::Destroy() {
|
||||||
// Skip handling device facilities if they haven't even been created (or failed doing so)
|
// Skip handling device facilities if they haven't even been created (or failed doing so)
|
||||||
if (mState != State::BeingCreated) {
|
if (mState != State::BeingCreated) {
|
||||||
// Call all the callbacks immediately as the device is about to shut down.
|
// Call all the callbacks immediately as the device is about to shut down.
|
||||||
@ -304,8 +328,8 @@ namespace dawn_native {
|
|||||||
if (mState != State::BeingCreated) {
|
if (mState != State::BeingCreated) {
|
||||||
// The GPU timeline is finished.
|
// The GPU timeline is finished.
|
||||||
// Tick the queue-related tasks since they should be complete. This must be done before
|
// Tick the queue-related tasks since they should be complete. This must be done before
|
||||||
// ShutDownImpl() it may relinquish resources that will be freed by backends in the
|
// DestroyImpl() it may relinquish resources that will be freed by backends in the
|
||||||
// ShutDownImpl() call.
|
// DestroyImpl() call.
|
||||||
mQueue->Tick(GetCompletedCommandSerial());
|
mQueue->Tick(GetCompletedCommandSerial());
|
||||||
// Call TickImpl once last time to clean up resources
|
// Call TickImpl once last time to clean up resources
|
||||||
// Ignore errors so that we can continue with destruction
|
// Ignore errors so that we can continue with destruction
|
||||||
@ -319,14 +343,15 @@ namespace dawn_native {
|
|||||||
mCallbackTaskManager = nullptr;
|
mCallbackTaskManager = nullptr;
|
||||||
mAsyncTaskManager = nullptr;
|
mAsyncTaskManager = nullptr;
|
||||||
mPersistentCache = nullptr;
|
mPersistentCache = nullptr;
|
||||||
|
|
||||||
mEmptyBindGroupLayout = nullptr;
|
mEmptyBindGroupLayout = nullptr;
|
||||||
|
|
||||||
mInternalPipelineStore = nullptr;
|
mInternalPipelineStore = nullptr;
|
||||||
|
|
||||||
AssumeCommandsComplete();
|
AssumeCommandsComplete();
|
||||||
// Tell the backend that it can free all the objects now that the GPU timeline is empty.
|
|
||||||
ShutDownImpl();
|
// Now that the GPU timeline is empty, destroy all objects owned by the device, and then the
|
||||||
|
// backend device.
|
||||||
|
DestroyObjects();
|
||||||
|
DestroyImpl();
|
||||||
|
|
||||||
mCaches = nullptr;
|
mCaches = nullptr;
|
||||||
}
|
}
|
||||||
@ -499,6 +524,12 @@ namespace dawn_native {
|
|||||||
return mState != State::Alive;
|
return mState != State::Alive;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeviceBase::TrackObject(ApiObjectBase* object) {
|
||||||
|
ApiObjectList& objectList = mObjectLists[object->GetType()];
|
||||||
|
std::lock_guard<std::mutex> lock(objectList.mutex);
|
||||||
|
object->InsertBefore(objectList.objects.head());
|
||||||
|
}
|
||||||
|
|
||||||
std::mutex* DeviceBase::GetObjectListMutex(ObjectType type) {
|
std::mutex* DeviceBase::GetObjectListMutex(ObjectType type) {
|
||||||
return &mObjectLists[type].mutex;
|
return &mObjectLists[type].mutex;
|
||||||
}
|
}
|
||||||
|
@ -298,6 +298,7 @@ namespace dawn_native {
|
|||||||
};
|
};
|
||||||
State GetState() const;
|
State GetState() const;
|
||||||
bool IsLost() const;
|
bool IsLost() const;
|
||||||
|
void TrackObject(ApiObjectBase* object);
|
||||||
std::mutex* GetObjectListMutex(ObjectType type);
|
std::mutex* GetObjectListMutex(ObjectType type);
|
||||||
|
|
||||||
std::vector<const char*> GetEnabledFeatures() const;
|
std::vector<const char*> GetEnabledFeatures() const;
|
||||||
@ -357,7 +358,8 @@ namespace dawn_native {
|
|||||||
void ForceSetToggle(Toggle toggle, bool isEnabled);
|
void ForceSetToggle(Toggle toggle, bool isEnabled);
|
||||||
|
|
||||||
MaybeError Initialize(QueueBase* defaultQueue);
|
MaybeError Initialize(QueueBase* defaultQueue);
|
||||||
void ShutDownBase();
|
void DestroyObjects();
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
// Incrememt mLastSubmittedSerial when we submit the next serial
|
// Incrememt mLastSubmittedSerial when we submit the next serial
|
||||||
void IncrementLastSubmittedCommandSerial();
|
void IncrementLastSubmittedCommandSerial();
|
||||||
@ -450,9 +452,9 @@ namespace dawn_native {
|
|||||||
ExecutionSerial mLastSubmittedSerial = ExecutionSerial(0);
|
ExecutionSerial mLastSubmittedSerial = ExecutionSerial(0);
|
||||||
ExecutionSerial mFutureSerial = ExecutionSerial(0);
|
ExecutionSerial mFutureSerial = ExecutionSerial(0);
|
||||||
|
|
||||||
// ShutDownImpl is used to clean up and release resources used by device, does not wait for
|
// DestroyImpl is used to clean up and release resources used by device, does not wait for
|
||||||
// GPU or check errors.
|
// GPU or check errors.
|
||||||
virtual void ShutDownImpl() = 0;
|
virtual void DestroyImpl() = 0;
|
||||||
|
|
||||||
// WaitForIdleForDestruction waits for GPU to finish, checks errors and gets ready for
|
// 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
|
// destruction. This is only used when properly destructing the device. For a real
|
||||||
|
@ -37,14 +37,6 @@ namespace dawn_native {
|
|||||||
return GetRefCountPayload() == kErrorPayload;
|
return GetRefCountPayload() == kErrorPayload;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjectBase::IsAlive() const {
|
|
||||||
return mDevice != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjectBase::DestroyObject() {
|
|
||||||
mDevice = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ApiObjectBase::ApiObjectBase(DeviceBase* device, const char* label) : ObjectBase(device) {
|
ApiObjectBase::ApiObjectBase(DeviceBase* device, const char* label) : ObjectBase(device) {
|
||||||
if (label) {
|
if (label) {
|
||||||
mLabel = label;
|
mLabel = label;
|
||||||
@ -58,6 +50,10 @@ namespace dawn_native {
|
|||||||
: ObjectBase(device) {
|
: ObjectBase(device) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ApiObjectBase::~ApiObjectBase() {
|
||||||
|
ASSERT(!IsAlive());
|
||||||
|
}
|
||||||
|
|
||||||
void ApiObjectBase::APISetLabel(const char* label) {
|
void ApiObjectBase::APISetLabel(const char* label) {
|
||||||
mLabel = label;
|
mLabel = label;
|
||||||
SetLabelImpl();
|
SetLabelImpl();
|
||||||
@ -70,4 +66,25 @@ namespace dawn_native {
|
|||||||
void ApiObjectBase::SetLabelImpl() {
|
void ApiObjectBase::SetLabelImpl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ApiObjectBase::IsAlive() const {
|
||||||
|
return IsInList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApiObjectBase::TrackInDevice() {
|
||||||
|
ASSERT(GetDevice() != nullptr);
|
||||||
|
GetDevice()->TrackObject(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ApiObjectBase::DestroyApiObject() {
|
||||||
|
const std::lock_guard<std::mutex> lock(*GetDevice()->GetObjectListMutex(GetType()));
|
||||||
|
if (!RemoveFromList()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DestroyApiObjectImpl();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApiObjectBase::DestroyApiObjectImpl() {
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dawn_native
|
} // namespace dawn_native
|
||||||
|
@ -35,12 +35,9 @@ namespace dawn_native {
|
|||||||
|
|
||||||
DeviceBase* GetDevice() const;
|
DeviceBase* GetDevice() const;
|
||||||
bool IsError() const;
|
bool IsError() const;
|
||||||
bool IsAlive() const;
|
|
||||||
void DestroyObject();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Pointer to owning device, if nullptr, that means that the object is no longer alive or
|
// Pointer to owning device.
|
||||||
// valid.
|
|
||||||
DeviceBase* mDevice;
|
DeviceBase* mDevice;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -52,13 +49,29 @@ namespace dawn_native {
|
|||||||
ApiObjectBase(DeviceBase* device, LabelNotImplementedTag tag);
|
ApiObjectBase(DeviceBase* device, LabelNotImplementedTag tag);
|
||||||
ApiObjectBase(DeviceBase* device, const char* label);
|
ApiObjectBase(DeviceBase* device, const char* label);
|
||||||
ApiObjectBase(DeviceBase* device, ErrorTag tag);
|
ApiObjectBase(DeviceBase* device, ErrorTag tag);
|
||||||
|
virtual ~ApiObjectBase() override;
|
||||||
|
|
||||||
virtual ObjectType GetType() const = 0;
|
virtual ObjectType GetType() const = 0;
|
||||||
const std::string& GetLabel() const;
|
const std::string& GetLabel() const;
|
||||||
|
|
||||||
|
// The ApiObjectBase is considered alive if it is tracked in a respective linked list owned
|
||||||
|
// by the owning device.
|
||||||
|
bool IsAlive() const;
|
||||||
|
|
||||||
|
// Allow virtual overriding of actual destroy call in order to allow for re-using of base
|
||||||
|
// destruction oerations. Classes that override this function should almost always call this
|
||||||
|
// class's implementation in the override. This needs to be public because it can be called
|
||||||
|
// from the device owning the object. Returns true iff destruction occurs. Upon any re-calls
|
||||||
|
// of the function it will return false to indicate no further operations should be taken.
|
||||||
|
virtual bool DestroyApiObject();
|
||||||
|
|
||||||
// Dawn API
|
// Dawn API
|
||||||
void APISetLabel(const char* label);
|
void APISetLabel(const char* label);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void TrackInDevice();
|
||||||
|
virtual void DestroyApiObjectImpl();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void SetLabelImpl();
|
virtual void SetLabelImpl();
|
||||||
|
|
||||||
|
@ -169,7 +169,7 @@ namespace dawn_native { namespace d3d12 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Device::~Device() {
|
Device::~Device() {
|
||||||
ShutDownBase();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
ID3D12Device* Device::GetD3D12Device() const {
|
ID3D12Device* Device::GetD3D12Device() const {
|
||||||
@ -601,7 +601,7 @@ namespace dawn_native { namespace d3d12 {
|
|||||||
return DAWN_INTERNAL_ERROR(messages.str());
|
return DAWN_INTERNAL_ERROR(messages.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::ShutDownImpl() {
|
void Device::DestroyImpl() {
|
||||||
ASSERT(GetState() == State::Disconnected);
|
ASSERT(GetState() == State::Disconnected);
|
||||||
|
|
||||||
// Immediately forget about all pending commands for the case where device is lost on its
|
// Immediately forget about all pending commands for the case where device is lost on its
|
||||||
|
@ -39,7 +39,7 @@ namespace dawn_native { namespace d3d12 {
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
// Definition of backend types
|
// Definition of backend types
|
||||||
class Device : public DeviceBase {
|
class Device final : public DeviceBase {
|
||||||
public:
|
public:
|
||||||
static ResultOrError<Device*> Create(Adapter* adapter, const DeviceDescriptor* descriptor);
|
static ResultOrError<Device*> Create(Adapter* adapter, const DeviceDescriptor* descriptor);
|
||||||
~Device() override;
|
~Device() override;
|
||||||
@ -181,7 +181,7 @@ namespace dawn_native { namespace d3d12 {
|
|||||||
WGPUCreateRenderPipelineAsyncCallback callback,
|
WGPUCreateRenderPipelineAsyncCallback callback,
|
||||||
void* userdata) override;
|
void* userdata) override;
|
||||||
|
|
||||||
void ShutDownImpl() override;
|
void DestroyImpl() override;
|
||||||
MaybeError WaitForIdleForDestruction() override;
|
MaybeError WaitForIdleForDestruction() override;
|
||||||
|
|
||||||
MaybeError CheckDebugLayerAndGenerateErrors();
|
MaybeError CheckDebugLayerAndGenerateErrors();
|
||||||
|
@ -36,7 +36,7 @@ namespace dawn_native { namespace metal {
|
|||||||
struct KalmanInfo;
|
struct KalmanInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Device : public DeviceBase {
|
class Device final : public DeviceBase {
|
||||||
public:
|
public:
|
||||||
static ResultOrError<Device*> Create(AdapterBase* adapter,
|
static ResultOrError<Device*> Create(AdapterBase* adapter,
|
||||||
NSPRef<id<MTLDevice>> mtlDevice,
|
NSPRef<id<MTLDevice>> mtlDevice,
|
||||||
@ -122,7 +122,7 @@ namespace dawn_native { namespace metal {
|
|||||||
void* userdata) override;
|
void* userdata) override;
|
||||||
|
|
||||||
void InitTogglesFromDriver();
|
void InitTogglesFromDriver();
|
||||||
void ShutDownImpl() override;
|
void DestroyImpl() override;
|
||||||
MaybeError WaitForIdleForDestruction() override;
|
MaybeError WaitForIdleForDestruction() override;
|
||||||
ResultOrError<ExecutionSerial> CheckAndUpdateCompletedSerials() override;
|
ResultOrError<ExecutionSerial> CheckAndUpdateCompletedSerials() override;
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ namespace dawn_native { namespace metal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Device::~Device() {
|
Device::~Device() {
|
||||||
ShutDownBase();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Device::Initialize() {
|
MaybeError Device::Initialize() {
|
||||||
@ -483,7 +483,7 @@ namespace dawn_native { namespace metal {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::ShutDownImpl() {
|
void Device::DestroyImpl() {
|
||||||
ASSERT(GetState() == State::Disconnected);
|
ASSERT(GetState() == State::Disconnected);
|
||||||
|
|
||||||
// Forget all pending commands.
|
// Forget all pending commands.
|
||||||
|
@ -87,7 +87,7 @@ namespace dawn_native { namespace null {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Device::~Device() {
|
Device::~Device() {
|
||||||
ShutDownBase();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Device::Initialize() {
|
MaybeError Device::Initialize() {
|
||||||
@ -164,7 +164,7 @@ namespace dawn_native { namespace null {
|
|||||||
return std::move(stagingBuffer);
|
return std::move(stagingBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::ShutDownImpl() {
|
void Device::DestroyImpl() {
|
||||||
ASSERT(GetState() == State::Disconnected);
|
ASSERT(GetState() == State::Disconnected);
|
||||||
|
|
||||||
// Clear pending operations before checking mMemoryUsage because some operations keep a
|
// Clear pending operations before checking mMemoryUsage because some operations keep a
|
||||||
|
@ -84,7 +84,7 @@ namespace dawn_native { namespace null {
|
|||||||
virtual void Execute() = 0;
|
virtual void Execute() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Device : public DeviceBase {
|
class Device final : public DeviceBase {
|
||||||
public:
|
public:
|
||||||
static ResultOrError<Device*> Create(Adapter* adapter, const DeviceDescriptor* descriptor);
|
static ResultOrError<Device*> Create(Adapter* adapter, const DeviceDescriptor* descriptor);
|
||||||
~Device() override;
|
~Device() override;
|
||||||
@ -156,7 +156,7 @@ namespace dawn_native { namespace null {
|
|||||||
|
|
||||||
ResultOrError<ExecutionSerial> CheckAndUpdateCompletedSerials() override;
|
ResultOrError<ExecutionSerial> CheckAndUpdateCompletedSerials() override;
|
||||||
|
|
||||||
void ShutDownImpl() override;
|
void DestroyImpl() override;
|
||||||
MaybeError WaitForIdleForDestruction() override;
|
MaybeError WaitForIdleForDestruction() override;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<PendingOperation>> mPendingOperations;
|
std::vector<std::unique_ptr<PendingOperation>> mPendingOperations;
|
||||||
|
@ -50,7 +50,7 @@ namespace dawn_native { namespace opengl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Device::~Device() {
|
Device::~Device() {
|
||||||
ShutDownBase();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError Device::Initialize() {
|
MaybeError Device::Initialize() {
|
||||||
@ -291,7 +291,7 @@ namespace dawn_native { namespace opengl {
|
|||||||
return DAWN_UNIMPLEMENTED_ERROR("Device unable to copy from staging buffer to texture.");
|
return DAWN_UNIMPLEMENTED_ERROR("Device unable to copy from staging buffer to texture.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::ShutDownImpl() {
|
void Device::DestroyImpl() {
|
||||||
ASSERT(GetState() == State::Disconnected);
|
ASSERT(GetState() == State::Disconnected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ typedef void* EGLImage;
|
|||||||
|
|
||||||
namespace dawn_native { namespace opengl {
|
namespace dawn_native { namespace opengl {
|
||||||
|
|
||||||
class Device : public DeviceBase {
|
class Device final : public DeviceBase {
|
||||||
public:
|
public:
|
||||||
static ResultOrError<Device*> Create(AdapterBase* adapter,
|
static ResultOrError<Device*> Create(AdapterBase* adapter,
|
||||||
const DeviceDescriptor* descriptor,
|
const DeviceDescriptor* descriptor,
|
||||||
@ -118,7 +118,7 @@ namespace dawn_native { namespace opengl {
|
|||||||
|
|
||||||
void InitTogglesFromDriver();
|
void InitTogglesFromDriver();
|
||||||
ResultOrError<ExecutionSerial> CheckAndUpdateCompletedSerials() override;
|
ResultOrError<ExecutionSerial> CheckAndUpdateCompletedSerials() override;
|
||||||
void ShutDownImpl() override;
|
void DestroyImpl() override;
|
||||||
MaybeError WaitForIdleForDestruction() override;
|
MaybeError WaitForIdleForDestruction() override;
|
||||||
|
|
||||||
std::queue<std::pair<GLsync, ExecutionSerial>> mFencesInFlight;
|
std::queue<std::pair<GLsync, ExecutionSerial>> mFencesInFlight;
|
||||||
|
@ -67,7 +67,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
// Two things are crucial if device initialization fails: the function pointers to destroy
|
// Two things are crucial if device initialization fails: the function pointers to destroy
|
||||||
// objects, and the fence deleter that calls these functions. Do not do anything before
|
// objects, and the fence deleter that calls these functions. Do not do anything before
|
||||||
// these two are set up, so that a failed initialization doesn't cause a crash in
|
// these two are set up, so that a failed initialization doesn't cause a crash in
|
||||||
// ShutDownImpl()
|
// DestroyImpl()
|
||||||
{
|
{
|
||||||
VkPhysicalDevice physicalDevice = ToBackend(GetAdapter())->GetPhysicalDevice();
|
VkPhysicalDevice physicalDevice = ToBackend(GetAdapter())->GetPhysicalDevice();
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Device::~Device() {
|
Device::~Device() {
|
||||||
ShutDownBase();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultOrError<Ref<BindGroupBase>> Device::CreateBindGroupImpl(
|
ResultOrError<Ref<BindGroupBase>> Device::CreateBindGroupImpl(
|
||||||
@ -912,7 +912,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::ShutDownImpl() {
|
void Device::DestroyImpl() {
|
||||||
ASSERT(GetState() == State::Disconnected);
|
ASSERT(GetState() == State::Disconnected);
|
||||||
|
|
||||||
// We failed during initialization so early that we don't even have a VkDevice. There is
|
// We failed during initialization so early that we don't even have a VkDevice. There is
|
||||||
|
@ -40,7 +40,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
class RenderPassCache;
|
class RenderPassCache;
|
||||||
class ResourceMemoryAllocator;
|
class ResourceMemoryAllocator;
|
||||||
|
|
||||||
class Device : public DeviceBase {
|
class Device final : public DeviceBase {
|
||||||
public:
|
public:
|
||||||
static ResultOrError<Device*> Create(Adapter* adapter, const DeviceDescriptor* descriptor);
|
static ResultOrError<Device*> Create(Adapter* adapter, const DeviceDescriptor* descriptor);
|
||||||
~Device() override;
|
~Device() override;
|
||||||
@ -152,7 +152,7 @@ namespace dawn_native { namespace vulkan {
|
|||||||
void InitTogglesFromDriver();
|
void InitTogglesFromDriver();
|
||||||
void ApplyDepth24PlusS8Toggle();
|
void ApplyDepth24PlusS8Toggle();
|
||||||
|
|
||||||
void ShutDownImpl() override;
|
void DestroyImpl() override;
|
||||||
MaybeError WaitForIdleForDestruction() override;
|
MaybeError WaitForIdleForDestruction() override;
|
||||||
|
|
||||||
// To make it easier to use fn it is a public const member. However
|
// To make it easier to use fn it is a public const member. However
|
||||||
|
@ -369,6 +369,51 @@ TEST(LinkedList, IsInList) {
|
|||||||
EXPECT_FALSE(n.RemoveFromList());
|
EXPECT_FALSE(n.RemoveFromList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(LinkedList, MoveInto) {
|
||||||
|
LinkedList<Node> l1;
|
||||||
|
LinkedList<Node> l2;
|
||||||
|
|
||||||
|
Node n1(1);
|
||||||
|
Node n2(2);
|
||||||
|
l1.Append(&n1);
|
||||||
|
l2.Append(&n2);
|
||||||
|
|
||||||
|
l2.MoveInto(&l1);
|
||||||
|
const int expected[] = {1, 2};
|
||||||
|
ExpectListContents(l1, 2, expected);
|
||||||
|
EXPECT_TRUE(l2.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(LinkedList, MoveEmptyListInto) {
|
||||||
|
LinkedList<Node> l1;
|
||||||
|
LinkedList<Node> l2;
|
||||||
|
|
||||||
|
Node n1(1);
|
||||||
|
Node n2(2);
|
||||||
|
l1.Append(&n1);
|
||||||
|
l1.Append(&n2);
|
||||||
|
|
||||||
|
l2.MoveInto(&l1);
|
||||||
|
const int expected[] = {1, 2};
|
||||||
|
ExpectListContents(l1, 2, expected);
|
||||||
|
EXPECT_TRUE(l2.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(LinkedList, MoveIntoEmpty) {
|
||||||
|
LinkedList<Node> l1;
|
||||||
|
LinkedList<Node> l2;
|
||||||
|
|
||||||
|
Node n1(1);
|
||||||
|
Node n2(2);
|
||||||
|
l2.Append(&n1);
|
||||||
|
l2.Append(&n2);
|
||||||
|
|
||||||
|
l2.MoveInto(&l1);
|
||||||
|
const int expected[] = {1, 2};
|
||||||
|
ExpectListContents(l1, 2, expected);
|
||||||
|
EXPECT_TRUE(l2.empty());
|
||||||
|
}
|
||||||
|
|
||||||
TEST(LinkedList, RangeBasedModify) {
|
TEST(LinkedList, RangeBasedModify) {
|
||||||
LinkedList<Node> list;
|
LinkedList<Node> list;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user