diff --git a/experimental/graphite/src/Resource.cpp b/experimental/graphite/src/Resource.cpp index 651fcf8aae..49cf7b9f70 100644 --- a/experimental/graphite/src/Resource.cpp +++ b/experimental/graphite/src/Resource.cpp @@ -9,7 +9,7 @@ namespace skgpu { -Resource::Resource(const Gpu* gpu) : fGpu(gpu) { +Resource::Resource(const Gpu* gpu) : fGpu(gpu), fUsageRefCnt(1), fCommandBufferRefCnt(0) { // Normally the array index will always be set before the cache tries to read so there isn't // a worry about this not being initialized. However, when we try to validate the cache in // debug builds we may try to read a resources index before it has actually been set by the @@ -22,7 +22,7 @@ Resource::~Resource() { SkASSERT(this->wasDestroyed()); } -void Resource::notifyARefCntIsZero(LastRemovedRef removedRef) const { +void Resource::notifyARefIsZero(LastRemovedRef removedRef) const { // TODO: Eventually we'll go through the cache to release the resource, but for now we just do // this immediately. SkASSERT(removedRef == LastRemovedRef::kUsageRef); diff --git a/experimental/graphite/src/Resource.h b/experimental/graphite/src/Resource.h index c5bfbc12d0..03613b562e 100644 --- a/experimental/graphite/src/Resource.h +++ b/experimental/graphite/src/Resource.h @@ -8,6 +8,7 @@ #ifndef skgpu_Resource_DEFINED #define skgpu_Resource_DEFINED +#include "experimental/graphite/src/ResourceTypes.h" #include "include/core/SkTypes.h" #include @@ -17,18 +18,14 @@ namespace skgpu { class Gpu; /** - * Base class for Resource. Provides the hooks for resources to interact with the cache. - * Separated out as a base class to isolate the ref-cnting behavior and provide friendship without - * exposing all of Resource. - * - * AFTER the ref count reaches zero DERIVED::notifyARefCntIsZero() will be called. + * Base class for objects that can be kept in the ResourceCache. */ -template class ResourceRef { +class Resource { public: - ResourceRef(const ResourceRef&) = delete; - ResourceRef(ResourceRef&&) = delete; - ResourceRef& operator=(const ResourceRef&) = delete; - ResourceRef& operator=(ResourceRef&&) = delete; + Resource(const Resource&) = delete; + Resource(Resource&&) = delete; + Resource& operator=(const Resource&) = delete; + Resource& operator=(Resource&&) = delete; // Adds a usage ref to the resource. Named ref so we can easily manage usage refs with sk_sp. void ref() const { @@ -38,12 +35,6 @@ public: (void)fUsageRefCnt.fetch_add(+1, std::memory_order_relaxed); } - // This enum is used to notify the ResourceCache which type of ref just dropped to zero. - enum class LastRemovedRef { - kUsageRef, - kCommandBufferRef, - }; - // Removes a usage ref from the resource void unref() const { SkASSERT(this->hasUsageRef()); @@ -64,13 +55,32 @@ public: SkASSERT(this->hasCommandBufferRef()); // A release here acts in place of all releases we "should" have been doing in ref(). if (1 == fCommandBufferRefCnt.fetch_add(-1, std::memory_order_acq_rel)) { - this->notifyARefIsZero(LastRemovedRef::kCommandBufferUsage); + this->notifyARefIsZero(LastRemovedRef::kCommandBufferRef); } } -protected: - ResourceRef() : fUsageRefCnt(1), fCommandBufferRefCnt(0) {} + /** + * Tests whether a object has been abandoned or released. All objects will be in this state + * after their creating Context is destroyed or abandoned. + * + * @return true if the object has been released or abandoned, + * false otherwise. + */ + bool wasDestroyed() const { return fGpu == nullptr; } + int* accessCacheIndex() const { return &fCacheArrayIndex; } + + uint32_t timestamp() const { return fTimestamp; } + void setTimestamp(uint32_t ts) { fTimestamp = ts; } + +protected: + Resource(const Gpu*); + virtual ~Resource(); + + /** Overridden to free GPU resources in the backend API. */ + virtual void onFreeGpuData() = 0; + +private: bool hasUsageRef() const { if (0 == fUsageRefCnt.load(std::memory_order_acquire)) { // The acquire barrier is only really needed if we return true. It @@ -98,45 +108,7 @@ protected: (void)fUsageRefCnt.fetch_add(+1, std::memory_order_relaxed); } -private: - void notifyARefIsZero(LastRemovedRef removedRef) const { - static_cast(this)->notifyARefCntIsZero(removedRef); - } - - mutable std::atomic fUsageRefCnt; - mutable std::atomic fCommandBufferRefCnt; -}; - -/** - * Base class for objects that can be kept in the ResourceCache. - */ -class Resource : public ResourceRef { -public: - /** - * Tests whether a object has been abandoned or released. All objects will be in this state - * after their creating Context is destroyed or abandoned. - * - * @return true if the object has been released or abandoned, - * false otherwise. - */ - bool wasDestroyed() const { return fGpu == nullptr; } - - int* accessCacheIndex() const { return &fCacheArrayIndex; } - - uint32_t timestamp() const { return fTimestamp; } - void setTimestamp(uint32_t ts) { fTimestamp = ts; } - -protected: - Resource(const Gpu*); - virtual ~Resource(); - - /** Overridden to free GPU resources in the backend API. */ - virtual void onFreeGpuData() = 0; - -private: - friend class ResourceRef; // to access notifyARefCntIsZero. - - void notifyARefCntIsZero(LastRemovedRef removedRef) const; + void notifyARefIsZero(LastRemovedRef removedRef) const; /** * Frees the object in the underlying 3D API. @@ -147,6 +119,9 @@ private: // destroyed. Those calls set will this to nullptr. const Gpu* fGpu; + mutable std::atomic fUsageRefCnt; + mutable std::atomic fCommandBufferRefCnt; + // An index into a heap when this resource is purgeable or an array when not. This is maintained // by the cache. mutable int fCacheArrayIndex; diff --git a/experimental/graphite/src/ResourceTypes.h b/experimental/graphite/src/ResourceTypes.h index b250d4a922..a3daf8287c 100644 --- a/experimental/graphite/src/ResourceTypes.h +++ b/experimental/graphite/src/ResourceTypes.h @@ -68,6 +68,12 @@ enum class Shareable : bool { kYes = true, }; +/** This enum is used to notify the ResourceCache which type of ref just dropped to zero. */ +enum class LastRemovedRef { + kUsageRef, + kCommandBufferRef, +}; + }; // namespace skgpu #endif // skgpu_ResourceTypes_DEFINED