[graphite] Merge Resource and ResourceRef together.

There really isn't anything we are gaining from keeping these class
separate. Originally the model was copied when porting over from Ganesh,
but I believe even in Ganesh the split mostly exists because GrResource
use to be public and we friended classes in it.. Since Resource is
internal and there are no plans to friend classes, the split is not
adding much value and just adds extra coding hopes.

Bug: skia:12754
Change-Id: I2e94b459d82b9295fa8450a94c612c593337fb98
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/508676
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
This commit is contained in:
Greg Daniel 2022-02-14 11:27:49 -05:00 committed by SkCQ
parent 9fae1e741e
commit e39cebef73
3 changed files with 41 additions and 60 deletions

View File

@ -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);

View File

@ -8,6 +8,7 @@
#ifndef skgpu_Resource_DEFINED
#define skgpu_Resource_DEFINED
#include "experimental/graphite/src/ResourceTypes.h"
#include "include/core/SkTypes.h"
#include <atomic>
@ -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 <typename DERIVED> 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<const DERIVED*>(this)->notifyARefCntIsZero(removedRef);
}
mutable std::atomic<int32_t> fUsageRefCnt;
mutable std::atomic<int32_t> fCommandBufferRefCnt;
};
/**
* Base class for objects that can be kept in the ResourceCache.
*/
class Resource : public ResourceRef<Resource> {
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<Resource>; // 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<int32_t> fUsageRefCnt;
mutable std::atomic<int32_t> 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;

View File

@ -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