Track TextureViews in Textures so that they can be chain-destroyed.
- Adds Prepend function to LinkedList to avoid directly using the insert functions on the LinkNodes. (And tests for this as well.) - Adds ApiObjectList class for tracking lists of objects for destruction. - Renames and virtualizes some tracking interfaces so that they can be overriden for the TextureView/Texture cases. - Removes explicit destroying of TextureViews from Device since destroying Textures will destroy TextureViews now. Fixed: dawn:1355 Change-Id: I3522383ea7724d6e41ac0c805793a6c34d9bec27 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/101762 Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Loko Kung <lokokung@google.com> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
parent
9c07d3c52c
commit
18dfc4797c
|
@ -185,6 +185,9 @@ class LinkedList {
|
||||||
// Appends |e| to the end of the linked list.
|
// Appends |e| to the end of the linked list.
|
||||||
void Append(LinkNode<T>* e) { e->InsertBefore(&root_); }
|
void Append(LinkNode<T>* e) { e->InsertBefore(&root_); }
|
||||||
|
|
||||||
|
// Prepends |e| to the front og the linked list.
|
||||||
|
void Prepend(LinkNode<T>* e) { e->InsertAfter(&root_); }
|
||||||
|
|
||||||
// Moves all elements (in order) of the list and appends them into |l| leaving the list empty.
|
// Moves all elements (in order) of the list and appends them into |l| leaving the list empty.
|
||||||
void MoveInto(LinkedList<T>* l) {
|
void MoveInto(LinkedList<T>* l) {
|
||||||
if (empty()) {
|
if (empty()) {
|
||||||
|
|
|
@ -450,11 +450,11 @@ BindGroupBase::BindGroupBase(DeviceBase* device,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
BindGroupBase::BindGroupBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {
|
BindGroupBase::BindGroupBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
BindGroupBase::~BindGroupBase() = default;
|
BindGroupBase::~BindGroupBase() = default;
|
||||||
|
|
|
@ -481,7 +481,7 @@ BindGroupLayoutBase::BindGroupLayoutBase(DeviceBase* device,
|
||||||
const BindGroupLayoutDescriptor* descriptor,
|
const BindGroupLayoutDescriptor* descriptor,
|
||||||
PipelineCompatibilityToken pipelineCompatibilityToken)
|
PipelineCompatibilityToken pipelineCompatibilityToken)
|
||||||
: BindGroupLayoutBase(device, descriptor, pipelineCompatibilityToken, kUntrackedByDevice) {
|
: BindGroupLayoutBase(device, descriptor, pipelineCompatibilityToken, kUntrackedByDevice) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
BindGroupLayoutBase::BindGroupLayoutBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
BindGroupLayoutBase::BindGroupLayoutBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
||||||
|
@ -489,7 +489,7 @@ BindGroupLayoutBase::BindGroupLayoutBase(DeviceBase* device, ObjectBase::ErrorTa
|
||||||
|
|
||||||
BindGroupLayoutBase::BindGroupLayoutBase(DeviceBase* device)
|
BindGroupLayoutBase::BindGroupLayoutBase(DeviceBase* device)
|
||||||
: ApiObjectBase(device, kLabelNotImplemented) {
|
: ApiObjectBase(device, kLabelNotImplemented) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
BindGroupLayoutBase::~BindGroupLayoutBase() = default;
|
BindGroupLayoutBase::~BindGroupLayoutBase() = default;
|
||||||
|
|
|
@ -68,7 +68,7 @@ class ErrorBuffer final : public BufferBase {
|
||||||
}
|
}
|
||||||
// Since error buffers in this case may allocate memory, we need to track them
|
// Since error buffers in this case may allocate memory, we need to track them
|
||||||
// for destruction on the device.
|
// for destruction on the device.
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ BufferBase::BufferBase(DeviceBase* device, const BufferDescriptor* descriptor)
|
||||||
mUsage |= kInternalStorageBuffer;
|
mUsage |= kInternalStorageBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferBase::BufferBase(DeviceBase* device,
|
BufferBase::BufferBase(DeviceBase* device,
|
||||||
|
@ -171,7 +171,7 @@ BufferBase::BufferBase(DeviceBase* device,
|
||||||
|
|
||||||
BufferBase::BufferBase(DeviceBase* device, BufferState state)
|
BufferBase::BufferBase(DeviceBase* device, BufferState state)
|
||||||
: ApiObjectBase(device, kLabelNotImplemented), mState(state) {
|
: ApiObjectBase(device, kLabelNotImplemented), mState(state) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferBase::~BufferBase() {
|
BufferBase::~BufferBase() {
|
||||||
|
|
|
@ -30,12 +30,12 @@ CommandBufferBase::CommandBufferBase(CommandEncoder* encoder,
|
||||||
: ApiObjectBase(encoder->GetDevice(), descriptor->label),
|
: ApiObjectBase(encoder->GetDevice(), descriptor->label),
|
||||||
mCommands(encoder->AcquireCommands()),
|
mCommands(encoder->AcquireCommands()),
|
||||||
mResourceUsages(encoder->AcquireResourceUsages()) {
|
mResourceUsages(encoder->AcquireResourceUsages()) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandBufferBase::CommandBufferBase(DeviceBase* device)
|
CommandBufferBase::CommandBufferBase(DeviceBase* device)
|
||||||
: ApiObjectBase(device, kLabelNotImplemented) {
|
: ApiObjectBase(device, kLabelNotImplemented) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandBufferBase::CommandBufferBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
CommandBufferBase::CommandBufferBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
||||||
|
|
|
@ -718,7 +718,7 @@ CommandEncoder* CommandEncoder::MakeError(DeviceBase* device) {
|
||||||
|
|
||||||
CommandEncoder::CommandEncoder(DeviceBase* device, const CommandEncoderDescriptor* descriptor)
|
CommandEncoder::CommandEncoder(DeviceBase* device, const CommandEncoderDescriptor* descriptor)
|
||||||
: ApiObjectBase(device, descriptor->label), mEncodingContext(device, this) {
|
: ApiObjectBase(device, descriptor->label), mEncodingContext(device, this) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
|
|
||||||
const DawnEncoderInternalUsageDescriptor* internalUsageDesc = nullptr;
|
const DawnEncoderInternalUsageDescriptor* internalUsageDesc = nullptr;
|
||||||
FindInChain(descriptor->nextInChain, &internalUsageDesc);
|
FindInChain(descriptor->nextInChain, &internalUsageDesc);
|
||||||
|
|
|
@ -114,7 +114,7 @@ ComputePassEncoder::ComputePassEncoder(DeviceBase* device,
|
||||||
EncodingContext* encodingContext)
|
EncodingContext* encodingContext)
|
||||||
: ProgrammableEncoder(device, descriptor->label, encodingContext),
|
: ProgrammableEncoder(device, descriptor->label, encodingContext),
|
||||||
mCommandEncoder(commandEncoder) {
|
mCommandEncoder(commandEncoder) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
|
|
@ -47,14 +47,14 @@ ComputePipelineBase::ComputePipelineBase(DeviceBase* device,
|
||||||
{{SingleShaderStage::Compute, descriptor->compute.module, descriptor->compute.entryPoint,
|
{{SingleShaderStage::Compute, descriptor->compute.module, descriptor->compute.entryPoint,
|
||||||
descriptor->compute.constantCount, descriptor->compute.constants}}) {
|
descriptor->compute.constantCount, descriptor->compute.constants}}) {
|
||||||
SetContentHash(ComputeContentHash());
|
SetContentHash(ComputeContentHash());
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
|
|
||||||
// Initialize the cache key to include the cache type and device information.
|
// Initialize the cache key to include the cache type and device information.
|
||||||
StreamIn(&mCacheKey, CacheKey::Type::ComputePipeline, device->GetCacheKey());
|
StreamIn(&mCacheKey, CacheKey::Type::ComputePipeline, device->GetCacheKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
ComputePipelineBase::ComputePipelineBase(DeviceBase* device) : PipelineBase(device) {
|
ComputePipelineBase::ComputePipelineBase(DeviceBase* device) : PipelineBase(device) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ComputePipelineBase::ComputePipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
ComputePipelineBase::ComputePipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
||||||
|
|
|
@ -338,7 +338,7 @@ void DeviceBase::DestroyObjects() {
|
||||||
// can destroy the frontend cache.
|
// can destroy the frontend cache.
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static constexpr std::array<ObjectType, 19> kObjectTypeDependencyOrder = {
|
static constexpr std::array<ObjectType, 18> kObjectTypeDependencyOrder = {
|
||||||
ObjectType::ComputePassEncoder,
|
ObjectType::ComputePassEncoder,
|
||||||
ObjectType::RenderPassEncoder,
|
ObjectType::RenderPassEncoder,
|
||||||
ObjectType::RenderBundleEncoder,
|
ObjectType::RenderBundleEncoder,
|
||||||
|
@ -353,26 +353,15 @@ void DeviceBase::DestroyObjects() {
|
||||||
ObjectType::BindGroupLayout,
|
ObjectType::BindGroupLayout,
|
||||||
ObjectType::ShaderModule,
|
ObjectType::ShaderModule,
|
||||||
ObjectType::ExternalTexture,
|
ObjectType::ExternalTexture,
|
||||||
ObjectType::TextureView,
|
ObjectType::Texture, // Note that Textures own the TextureViews.
|
||||||
ObjectType::Texture,
|
|
||||||
ObjectType::QuerySet,
|
ObjectType::QuerySet,
|
||||||
ObjectType::Sampler,
|
ObjectType::Sampler,
|
||||||
ObjectType::Buffer,
|
ObjectType::Buffer,
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
// 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) {
|
for (ObjectType type : kObjectTypeDependencyOrder) {
|
||||||
ApiObjectList& objList = mObjectLists[type];
|
mObjectLists[type].Destroy();
|
||||||
const std::lock_guard<std::mutex> lock(objList.mutex);
|
|
||||||
objList.objects.MoveInto(&objects);
|
|
||||||
}
|
|
||||||
while (!objects.empty()) {
|
|
||||||
// The destroy call should also remove the object from the list.
|
|
||||||
objects.head()->value()->Destroy();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -685,14 +674,8 @@ bool DeviceBase::IsLost() const {
|
||||||
return mState != State::Alive;
|
return mState != State::Alive;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceBase::TrackObject(ApiObjectBase* object) {
|
ApiObjectList* DeviceBase::GetObjectTrackingList(ObjectType type) {
|
||||||
ApiObjectList& objectList = mObjectLists[object->GetType()];
|
return &mObjectLists[type];
|
||||||
std::lock_guard<std::mutex> lock(objectList.mutex);
|
|
||||||
object->InsertBefore(objectList.objects.head());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::mutex* DeviceBase::GetObjectListMutex(ObjectType type) {
|
|
||||||
return &mObjectLists[type].mutex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AdapterBase* DeviceBase::GetAdapter() const {
|
AdapterBase* DeviceBase::GetAdapter() const {
|
||||||
|
|
|
@ -333,8 +333,7 @@ class DeviceBase : public RefCountedWithExternalCount {
|
||||||
};
|
};
|
||||||
State GetState() const;
|
State GetState() const;
|
||||||
bool IsLost() const;
|
bool IsLost() const;
|
||||||
void TrackObject(ApiObjectBase* object);
|
ApiObjectList* GetObjectTrackingList(ObjectType type);
|
||||||
std::mutex* GetObjectListMutex(ObjectType type);
|
|
||||||
|
|
||||||
std::vector<const char*> GetTogglesUsed() const;
|
std::vector<const char*> GetTogglesUsed() const;
|
||||||
WGSLExtensionSet GetWGSLExtensionAllowList() const;
|
WGSLExtensionSet GetWGSLExtensionAllowList() const;
|
||||||
|
@ -548,12 +547,6 @@ class DeviceBase : public RefCountedWithExternalCount {
|
||||||
|
|
||||||
State mState = State::BeingCreated;
|
State mState = State::BeingCreated;
|
||||||
|
|
||||||
// Encompasses the mutex and the actual list that contains all live objects "owned" by the
|
|
||||||
// device.
|
|
||||||
struct ApiObjectList {
|
|
||||||
std::mutex mutex;
|
|
||||||
LinkedList<ApiObjectBase> objects;
|
|
||||||
};
|
|
||||||
PerObjectType<ApiObjectList> mObjectLists;
|
PerObjectType<ApiObjectList> mObjectLists;
|
||||||
|
|
||||||
FormatTable mFormatTable;
|
FormatTable mFormatTable;
|
||||||
|
|
|
@ -115,12 +115,12 @@ ResultOrError<Ref<ExternalTextureBase>> ExternalTextureBase::Create(
|
||||||
ExternalTextureBase::ExternalTextureBase(DeviceBase* device,
|
ExternalTextureBase::ExternalTextureBase(DeviceBase* device,
|
||||||
const ExternalTextureDescriptor* descriptor)
|
const ExternalTextureDescriptor* descriptor)
|
||||||
: ApiObjectBase(device, descriptor->label), mState(ExternalTextureState::Alive) {
|
: ApiObjectBase(device, descriptor->label), mState(ExternalTextureState::Alive) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExternalTextureBase::ExternalTextureBase(DeviceBase* device)
|
ExternalTextureBase::ExternalTextureBase(DeviceBase* device)
|
||||||
: ApiObjectBase(device, kLabelNotImplemented), mState(ExternalTextureState::Alive) {
|
: ApiObjectBase(device, kLabelNotImplemented), mState(ExternalTextureState::Alive) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error external texture cannot be used in bind group.
|
// Error external texture cannot be used in bind group.
|
||||||
|
|
|
@ -37,6 +37,31 @@ DeviceBase* ObjectBase::GetDevice() const {
|
||||||
return mDevice.Get();
|
return mDevice.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ApiObjectList::Track(ApiObjectBase* object) {
|
||||||
|
if (mMarkedDestroyed) {
|
||||||
|
object->DestroyImpl();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
|
mObjects.Prepend(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ApiObjectList::Untrack(ApiObjectBase* object) {
|
||||||
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
|
return object->RemoveFromList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApiObjectList::Destroy() {
|
||||||
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
|
mMarkedDestroyed = true;
|
||||||
|
while (!mObjects.empty()) {
|
||||||
|
auto* head = mObjects.head();
|
||||||
|
bool removed = head->RemoveFromList();
|
||||||
|
ASSERT(removed);
|
||||||
|
head->value()->DestroyImpl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
@ -71,14 +96,18 @@ void ApiObjectBase::DeleteThis() {
|
||||||
RefCounted::DeleteThis();
|
RefCounted::DeleteThis();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiObjectBase::TrackInDevice() {
|
ApiObjectList* ApiObjectBase::GetObjectTrackingList() {
|
||||||
ASSERT(GetDevice() != nullptr);
|
ASSERT(GetDevice() != nullptr);
|
||||||
GetDevice()->TrackObject(this);
|
return GetDevice()->GetObjectTrackingList(GetType());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiObjectBase::Destroy() {
|
void ApiObjectBase::Destroy() {
|
||||||
const std::lock_guard<std::mutex> lock(*GetDevice()->GetObjectListMutex(GetType()));
|
if (!IsAlive()) {
|
||||||
if (RemoveFromList()) {
|
return;
|
||||||
|
}
|
||||||
|
ApiObjectList* list = GetObjectTrackingList();
|
||||||
|
ASSERT(list != nullptr);
|
||||||
|
if (list->Untrack(this)) {
|
||||||
DestroyImpl();
|
DestroyImpl();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#ifndef SRC_DAWN_NATIVE_OBJECTBASE_H_
|
#ifndef SRC_DAWN_NATIVE_OBJECTBASE_H_
|
||||||
#define SRC_DAWN_NATIVE_OBJECTBASE_H_
|
#define SRC_DAWN_NATIVE_OBJECTBASE_H_
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "dawn/common/LinkedList.h"
|
#include "dawn/common/LinkedList.h"
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
|
|
||||||
namespace dawn::native {
|
namespace dawn::native {
|
||||||
|
|
||||||
|
class ApiObjectBase;
|
||||||
class DeviceBase;
|
class DeviceBase;
|
||||||
|
|
||||||
class ErrorMonad : public RefCounted {
|
class ErrorMonad : public RefCounted {
|
||||||
|
@ -48,6 +50,26 @@ class ObjectBase : public ErrorMonad {
|
||||||
Ref<DeviceBase> mDevice;
|
Ref<DeviceBase> mDevice;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Generic object list with a mutex for tracking for destruction.
|
||||||
|
class ApiObjectList {
|
||||||
|
public:
|
||||||
|
// Tracks an object if the list is not destroyed. If the list is destroyed, destroys the object.
|
||||||
|
void Track(ApiObjectBase* object);
|
||||||
|
|
||||||
|
// Returns true iff the object was removed from the list.
|
||||||
|
bool Untrack(ApiObjectBase* object);
|
||||||
|
|
||||||
|
// Destroys and removes all the objects tracked in the list.
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Boolean used to mark the list so that on subsequent calls to Untrack, we don't need to
|
||||||
|
// reaquire the lock, and Track on new objects immediately destroys them.
|
||||||
|
bool mMarkedDestroyed = false;
|
||||||
|
std::mutex mMutex;
|
||||||
|
LinkedList<ApiObjectBase> mObjects;
|
||||||
|
};
|
||||||
|
|
||||||
class ApiObjectBase : public ObjectBase, public LinkNode<ApiObjectBase> {
|
class ApiObjectBase : public ObjectBase, public LinkNode<ApiObjectBase> {
|
||||||
public:
|
public:
|
||||||
struct LabelNotImplementedTag {};
|
struct LabelNotImplementedTag {};
|
||||||
|
@ -85,7 +107,11 @@ class ApiObjectBase : public ObjectBase, public LinkNode<ApiObjectBase> {
|
||||||
// and they should ensure that their overriding versions call this underlying version
|
// and they should ensure that their overriding versions call this underlying version
|
||||||
// somewhere.
|
// somewhere.
|
||||||
void DeleteThis() override;
|
void DeleteThis() override;
|
||||||
void TrackInDevice();
|
|
||||||
|
// Returns the list where this object may be tracked for future destruction. This can be
|
||||||
|
// overrided to create hierarchical object tracking ownership:
|
||||||
|
// i.e. Device -[tracks]-> Texture -[tracks]-> TextureView.
|
||||||
|
virtual ApiObjectList* GetObjectTrackingList();
|
||||||
|
|
||||||
// Sub-classes may override this function multiple times. Whenever overriding this function,
|
// Sub-classes may override this function multiple times. Whenever overriding this function,
|
||||||
// however, users should be sure to call their parent's version in the new override to make
|
// however, users should be sure to call their parent's version in the new override to make
|
||||||
|
@ -94,6 +120,8 @@ class ApiObjectBase : public ObjectBase, public LinkNode<ApiObjectBase> {
|
||||||
virtual void DestroyImpl() = 0;
|
virtual void DestroyImpl() = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend class ApiObjectList;
|
||||||
|
|
||||||
virtual void SetLabelImpl();
|
virtual void SetLabelImpl();
|
||||||
|
|
||||||
std::string mLabel;
|
std::string mLabel;
|
||||||
|
|
|
@ -71,12 +71,12 @@ PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device,
|
||||||
PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device,
|
PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device,
|
||||||
const PipelineLayoutDescriptor* descriptor)
|
const PipelineLayoutDescriptor* descriptor)
|
||||||
: PipelineLayoutBase(device, descriptor, kUntrackedByDevice) {
|
: PipelineLayoutBase(device, descriptor, kUntrackedByDevice) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device)
|
PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device)
|
||||||
: ApiObjectBase(device, kLabelNotImplemented) {
|
: ApiObjectBase(device, kLabelNotImplemented) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
||||||
|
|
|
@ -107,11 +107,11 @@ QuerySetBase::QuerySetBase(DeviceBase* device, const QuerySetDescriptor* descrip
|
||||||
}
|
}
|
||||||
|
|
||||||
mQueryAvailability.resize(descriptor->count);
|
mQueryAvailability.resize(descriptor->count);
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
QuerySetBase::QuerySetBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {
|
QuerySetBase::QuerySetBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
QuerySetBase::QuerySetBase(DeviceBase* device,
|
QuerySetBase::QuerySetBase(DeviceBase* device,
|
||||||
|
|
|
@ -39,7 +39,7 @@ RenderBundleBase::RenderBundleBase(RenderBundleEncoder* encoder,
|
||||||
mStencilReadOnly(stencilReadOnly),
|
mStencilReadOnly(stencilReadOnly),
|
||||||
mDrawCount(encoder->GetDrawCount()),
|
mDrawCount(encoder->GetDrawCount()),
|
||||||
mResourceUsage(std::move(resourceUsage)) {
|
mResourceUsage(std::move(resourceUsage)) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderBundleBase::DestroyImpl() {
|
void RenderBundleBase::DestroyImpl() {
|
||||||
|
|
|
@ -100,7 +100,7 @@ RenderBundleEncoder::RenderBundleEncoder(DeviceBase* device,
|
||||||
descriptor->depthReadOnly,
|
descriptor->depthReadOnly,
|
||||||
descriptor->stencilReadOnly),
|
descriptor->stencilReadOnly),
|
||||||
mBundleEncodingContext(device, this) {
|
mBundleEncodingContext(device, this) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderBundleEncoder::RenderBundleEncoder(DeviceBase* device, ErrorTag errorTag)
|
RenderBundleEncoder::RenderBundleEncoder(DeviceBase* device, ErrorTag errorTag)
|
||||||
|
|
|
@ -76,7 +76,7 @@ RenderPassEncoder::RenderPassEncoder(DeviceBase* device,
|
||||||
if (maxDrawCountInfo) {
|
if (maxDrawCountInfo) {
|
||||||
mMaxDrawCount = maxDrawCountInfo->maxDrawCount;
|
mMaxDrawCount = maxDrawCountInfo->maxDrawCount;
|
||||||
}
|
}
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
|
|
@ -616,14 +616,14 @@ RenderPipelineBase::RenderPipelineBase(DeviceBase* device,
|
||||||
}
|
}
|
||||||
|
|
||||||
SetContentHash(ComputeContentHash());
|
SetContentHash(ComputeContentHash());
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
|
|
||||||
// Initialize the cache key to include the cache type and device information.
|
// Initialize the cache key to include the cache type and device information.
|
||||||
StreamIn(&mCacheKey, CacheKey::Type::RenderPipeline, device->GetCacheKey());
|
StreamIn(&mCacheKey, CacheKey::Type::RenderPipeline, device->GetCacheKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderPipelineBase::RenderPipelineBase(DeviceBase* device) : PipelineBase(device) {
|
RenderPipelineBase::RenderPipelineBase(DeviceBase* device) : PipelineBase(device) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderPipelineBase::RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
RenderPipelineBase::RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
||||||
|
|
|
@ -86,11 +86,11 @@ SamplerBase::SamplerBase(DeviceBase* device,
|
||||||
|
|
||||||
SamplerBase::SamplerBase(DeviceBase* device, const SamplerDescriptor* descriptor)
|
SamplerBase::SamplerBase(DeviceBase* device, const SamplerDescriptor* descriptor)
|
||||||
: SamplerBase(device, descriptor, kUntrackedByDevice) {
|
: SamplerBase(device, descriptor, kUntrackedByDevice) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
SamplerBase::SamplerBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {
|
SamplerBase::SamplerBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
SamplerBase::SamplerBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
SamplerBase::SamplerBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
||||||
|
|
|
@ -1089,12 +1089,12 @@ ShaderModuleBase::ShaderModuleBase(DeviceBase* device,
|
||||||
|
|
||||||
ShaderModuleBase::ShaderModuleBase(DeviceBase* device, const ShaderModuleDescriptor* descriptor)
|
ShaderModuleBase::ShaderModuleBase(DeviceBase* device, const ShaderModuleDescriptor* descriptor)
|
||||||
: ShaderModuleBase(device, descriptor, kUntrackedByDevice) {
|
: ShaderModuleBase(device, descriptor, kUntrackedByDevice) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderModuleBase::ShaderModuleBase(DeviceBase* device)
|
ShaderModuleBase::ShaderModuleBase(DeviceBase* device)
|
||||||
: ApiObjectBase(device, kLabelNotImplemented) {
|
: ApiObjectBase(device, kLabelNotImplemented) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderModuleBase::ShaderModuleBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
ShaderModuleBase::ShaderModuleBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
||||||
|
|
|
@ -117,7 +117,7 @@ TextureDescriptor GetSwapChainBaseTextureDescriptor(NewSwapChainBase* swapChain)
|
||||||
// SwapChainBase
|
// SwapChainBase
|
||||||
|
|
||||||
SwapChainBase::SwapChainBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {
|
SwapChainBase::SwapChainBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
SwapChainBase::SwapChainBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
SwapChainBase::SwapChainBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
||||||
|
|
|
@ -552,7 +552,7 @@ TextureBase::TextureBase(DeviceBase* device,
|
||||||
if (internalUsageDesc != nullptr) {
|
if (internalUsageDesc != nullptr) {
|
||||||
mInternalUsage |= internalUsageDesc->internalUsage;
|
mInternalUsage |= internalUsageDesc->internalUsage;
|
||||||
}
|
}
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureBase::~TextureBase() = default;
|
TextureBase::~TextureBase() = default;
|
||||||
|
@ -561,7 +561,7 @@ static constexpr Format kUnusedFormat;
|
||||||
|
|
||||||
TextureBase::TextureBase(DeviceBase* device, TextureState state)
|
TextureBase::TextureBase(DeviceBase* device, TextureState state)
|
||||||
: ApiObjectBase(device, kLabelNotImplemented), mFormat(kUnusedFormat), mState(state) {
|
: ApiObjectBase(device, kLabelNotImplemented), mFormat(kUnusedFormat), mState(state) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureBase::TextureBase(DeviceBase* device,
|
TextureBase::TextureBase(DeviceBase* device,
|
||||||
|
@ -578,6 +578,9 @@ TextureBase::TextureBase(DeviceBase* device,
|
||||||
|
|
||||||
void TextureBase::DestroyImpl() {
|
void TextureBase::DestroyImpl() {
|
||||||
mState = TextureState::Destroyed;
|
mState = TextureState::Destroyed;
|
||||||
|
|
||||||
|
// Destroy all of the views associated with the texture as well.
|
||||||
|
mTextureViews.Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
@ -766,6 +769,10 @@ ResultOrError<Ref<TextureViewBase>> TextureBase::CreateView(
|
||||||
return GetDevice()->CreateTextureView(this, descriptor);
|
return GetDevice()->CreateTextureView(this, descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ApiObjectList* TextureBase::GetViewTrackingList() {
|
||||||
|
return &mTextureViews;
|
||||||
|
}
|
||||||
|
|
||||||
TextureViewBase* TextureBase::APICreateView(const TextureViewDescriptor* descriptor) {
|
TextureViewBase* TextureBase::APICreateView(const TextureViewDescriptor* descriptor) {
|
||||||
DeviceBase* device = GetDevice();
|
DeviceBase* device = GetDevice();
|
||||||
|
|
||||||
|
@ -831,14 +838,14 @@ TextureViewBase::TextureViewBase(TextureBase* texture, const TextureViewDescript
|
||||||
mRange({ConvertViewAspect(mFormat, descriptor->aspect),
|
mRange({ConvertViewAspect(mFormat, descriptor->aspect),
|
||||||
{descriptor->baseArrayLayer, descriptor->arrayLayerCount},
|
{descriptor->baseArrayLayer, descriptor->arrayLayerCount},
|
||||||
{descriptor->baseMipLevel, descriptor->mipLevelCount}}) {
|
{descriptor->baseMipLevel, descriptor->mipLevelCount}}) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureViewBase::TextureViewBase(TextureBase* texture)
|
TextureViewBase::TextureViewBase(TextureBase* texture)
|
||||||
: ApiObjectBase(texture->GetDevice(), kLabelNotImplemented),
|
: ApiObjectBase(texture->GetDevice(), kLabelNotImplemented),
|
||||||
mTexture(texture),
|
mTexture(texture),
|
||||||
mFormat(kUnusedFormat) {
|
mFormat(kUnusedFormat) {
|
||||||
TrackInDevice();
|
GetObjectTrackingList()->Track(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureViewBase::TextureViewBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
TextureViewBase::TextureViewBase(DeviceBase* device, ObjectBase::ErrorTag tag)
|
||||||
|
@ -907,4 +914,9 @@ const SubresourceRange& TextureViewBase::GetSubresourceRange() const {
|
||||||
return mRange;
|
return mRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ApiObjectList* TextureViewBase::GetObjectTrackingList() {
|
||||||
|
ASSERT(!IsError());
|
||||||
|
return mTexture->GetViewTrackingList();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dawn::native
|
} // namespace dawn::native
|
||||||
|
|
|
@ -92,6 +92,7 @@ class TextureBase : public ApiObjectBase {
|
||||||
|
|
||||||
ResultOrError<Ref<TextureViewBase>> CreateView(
|
ResultOrError<Ref<TextureViewBase>> CreateView(
|
||||||
const TextureViewDescriptor* descriptor = nullptr);
|
const TextureViewDescriptor* descriptor = nullptr);
|
||||||
|
ApiObjectList* GetViewTrackingList();
|
||||||
|
|
||||||
// Dawn API
|
// Dawn API
|
||||||
TextureViewBase* APICreateView(const TextureViewDescriptor* descriptor = nullptr);
|
TextureViewBase* APICreateView(const TextureViewDescriptor* descriptor = nullptr);
|
||||||
|
@ -129,6 +130,10 @@ class TextureBase : public ApiObjectBase {
|
||||||
TextureState mState;
|
TextureState mState;
|
||||||
wgpu::TextureFormat mFormatEnumForReflection;
|
wgpu::TextureFormat mFormatEnumForReflection;
|
||||||
|
|
||||||
|
// Textures track texture views created from them so that they can be destroyed when the texture
|
||||||
|
// is destroyed.
|
||||||
|
ApiObjectList mTextureViews;
|
||||||
|
|
||||||
// TODO(crbug.com/dawn/845): Use a more optimized data structure to save space
|
// TODO(crbug.com/dawn/845): Use a more optimized data structure to save space
|
||||||
std::vector<bool> mIsSubresourceContentInitializedAtIndex;
|
std::vector<bool> mIsSubresourceContentInitializedAtIndex;
|
||||||
};
|
};
|
||||||
|
@ -162,6 +167,8 @@ class TextureViewBase : public ApiObjectBase {
|
||||||
private:
|
private:
|
||||||
TextureViewBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
TextureViewBase(DeviceBase* device, ObjectBase::ErrorTag tag);
|
||||||
|
|
||||||
|
ApiObjectList* GetObjectTrackingList() override;
|
||||||
|
|
||||||
Ref<TextureBase> mTexture;
|
Ref<TextureBase> mTexture;
|
||||||
|
|
||||||
const Format& mFormat;
|
const Format& mFormat;
|
||||||
|
|
|
@ -117,6 +117,41 @@ TEST(LinkedList, Append) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(LinkedList, Prepend) {
|
||||||
|
LinkedList<Node> list;
|
||||||
|
ExpectListContents(list, 0, nullptr);
|
||||||
|
|
||||||
|
Node n1(1);
|
||||||
|
list.Prepend(&n1);
|
||||||
|
|
||||||
|
EXPECT_EQ(&n1, list.head());
|
||||||
|
EXPECT_EQ(&n1, list.tail());
|
||||||
|
{
|
||||||
|
const int expected[] = {1};
|
||||||
|
ExpectListContents(list, 1, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node n2(2);
|
||||||
|
list.Prepend(&n2);
|
||||||
|
|
||||||
|
EXPECT_EQ(&n2, list.head());
|
||||||
|
EXPECT_EQ(&n1, list.tail());
|
||||||
|
{
|
||||||
|
const int expected[] = {2, 1};
|
||||||
|
ExpectListContents(list, 2, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node n3(3);
|
||||||
|
list.Prepend(&n3);
|
||||||
|
|
||||||
|
EXPECT_EQ(&n3, list.head());
|
||||||
|
EXPECT_EQ(&n1, list.tail());
|
||||||
|
{
|
||||||
|
const int expected[] = {3, 2, 1};
|
||||||
|
ExpectListContents(list, 3, expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST(LinkedList, RemoveFromList) {
|
TEST(LinkedList, RemoveFromList) {
|
||||||
LinkedList<Node> list;
|
LinkedList<Node> list;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue