Control access to adding ref to a GrGpuResource when it's ref count is zero.
We want GrResourceCache to be able to track which resources are held by refs (as opposed to pending IOs) so that it can track the affect of flushing on resource purgeability. Therefore, all cases that can add the first ref to a GrGpuResource must funnel through GrResourceCache. This lays the groundwork by restricting initial refs. No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: skia:8927 Change-Id: I1213c3db258d2412df6666e3222419211ceaa192 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/205482 Commit-Queue: Brian Salomon <bsalomon@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
parent
c1c686b4d4
commit
01ceae9352
@ -53,6 +53,8 @@ public:
|
||||
// refs (e.g. pending reads). We also don't require thread safety as GrCacheable objects are
|
||||
// not intended to cross thread boundaries.
|
||||
void ref() const {
|
||||
// Only the cache should be able to add the first ref to a resource.
|
||||
SkASSERT(fRefCnt > 0);
|
||||
this->validate();
|
||||
++fRefCnt;
|
||||
}
|
||||
@ -100,6 +102,12 @@ protected:
|
||||
bool internalHasRef() const { return SkToBool(fRefCnt); }
|
||||
bool internalHasUniqueRef() const { return fRefCnt == 1; }
|
||||
|
||||
// Privileged method that allows going from ref count = 0 to ref count = 1.
|
||||
void addInitialRef() const {
|
||||
this->validate();
|
||||
++fRefCnt;
|
||||
}
|
||||
|
||||
private:
|
||||
// This is for a unit test.
|
||||
template <typename T>
|
||||
@ -226,6 +234,12 @@ public:
|
||||
inline CacheAccess cacheAccess();
|
||||
inline const CacheAccess cacheAccess() const;
|
||||
|
||||
/**
|
||||
* Internal-only helper class used for manipulations of the resource by GrSurfaceProxy.
|
||||
*/
|
||||
class ProxyAccess;
|
||||
inline ProxyAccess proxyAccess();
|
||||
|
||||
/**
|
||||
* Internal-only helper class used for manipulations of the resource by internal code.
|
||||
*/
|
||||
@ -361,4 +375,24 @@ private:
|
||||
friend class GrIORef<GrGpuResource>; // to access notifyAllCntsAreZero and notifyRefCntIsZero.
|
||||
};
|
||||
|
||||
class GrGpuResource::ProxyAccess {
|
||||
private:
|
||||
ProxyAccess(GrGpuResource* resource) : fResource(resource) {}
|
||||
|
||||
/** Proxies are allowed to take a resource from no refs to one ref. */
|
||||
void ref() { fResource->addInitialRef(); }
|
||||
|
||||
// No taking addresses of this type.
|
||||
const CacheAccess* operator&() const = delete;
|
||||
CacheAccess* operator&() = delete;
|
||||
|
||||
GrGpuResource* fResource;
|
||||
|
||||
friend class GrGpuResource;
|
||||
friend class GrSurfaceProxy;
|
||||
friend class GrIORefProxy;
|
||||
};
|
||||
|
||||
inline GrGpuResource::ProxyAccess GrGpuResource::proxyAccess() { return ProxyAccess(this); }
|
||||
|
||||
#endif
|
||||
|
@ -18,7 +18,6 @@
|
||||
class GrCaps;
|
||||
class GrContext_Base;
|
||||
class GrOpList;
|
||||
class GrProxyProvider;
|
||||
class GrRecordingContext;
|
||||
class GrRenderTargetOpList;
|
||||
class GrRenderTargetProxy;
|
||||
@ -152,6 +151,15 @@ protected:
|
||||
// have forwarded on the unref call that got us here.
|
||||
}
|
||||
|
||||
// Privileged method that allows going from ref count = 0 to ref count = 1.
|
||||
void addInitialRef() const {
|
||||
this->validate();
|
||||
++fRefCnt;
|
||||
if (fTarget) {
|
||||
fTarget->proxyAccess().ref();
|
||||
}
|
||||
}
|
||||
|
||||
// This GrIORefProxy was deferred before but has just been instantiated. To
|
||||
// make all the reffing & unreffing work out we now need to transfer any deferred
|
||||
// refs & unrefs to the new GrSurface
|
||||
@ -458,6 +466,13 @@ public:
|
||||
inline GrSurfaceProxyPriv priv();
|
||||
inline const GrSurfaceProxyPriv priv() const;
|
||||
|
||||
/**
|
||||
* Provides privileged access to select callers to be able to add a ref to a GrSurfaceProxy
|
||||
* with zero refs.
|
||||
*/
|
||||
class FirstRefAccess;
|
||||
inline FirstRefAccess firstRefAccess();
|
||||
|
||||
GrInternalSurfaceFlags testingOnly_getFlags() const;
|
||||
|
||||
protected:
|
||||
@ -568,4 +583,25 @@ private:
|
||||
typedef GrIORefProxy INHERITED;
|
||||
};
|
||||
|
||||
class GrSurfaceProxy::FirstRefAccess {
|
||||
private:
|
||||
void ref() { fProxy->addInitialRef(); }
|
||||
|
||||
FirstRefAccess(GrSurfaceProxy* proxy) : fProxy(proxy) {}
|
||||
|
||||
// No taking addresses of this type.
|
||||
const FirstRefAccess* operator&() const = delete;
|
||||
FirstRefAccess* operator&() = delete;
|
||||
|
||||
GrSurfaceProxy* fProxy;
|
||||
|
||||
friend class GrSurfaceProxy;
|
||||
friend class GrProxyProvider;
|
||||
friend class GrDeinstantiateProxyTracker;
|
||||
};
|
||||
|
||||
inline GrSurfaceProxy::FirstRefAccess GrSurfaceProxy::firstRefAccess() {
|
||||
return FirstRefAccess(this);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -18,7 +18,8 @@ void GrDeinstantiateProxyTracker::addProxy(GrSurfaceProxy* proxy) {
|
||||
SkASSERT(proxy != fProxies[i].get());
|
||||
}
|
||||
#endif
|
||||
fProxies.push_back(sk_ref_sp(proxy));
|
||||
proxy->firstRefAccess().ref();
|
||||
fProxies.push_back(sk_sp<GrSurfaceProxy>(proxy));
|
||||
}
|
||||
|
||||
void GrDeinstantiateProxyTracker::deinstantiateAllProxies() {
|
||||
|
@ -20,6 +20,9 @@ namespace skiatest {
|
||||
*/
|
||||
class GrGpuResource::CacheAccess {
|
||||
private:
|
||||
/** The cache is allowed to go from no refs to 1 ref. */
|
||||
void ref() { fResource->addInitialRef(); }
|
||||
|
||||
/**
|
||||
* Is the resource currently cached as scratch? This means it is cached, has a valid scratch
|
||||
* key, and does not have a unique key.
|
||||
@ -78,8 +81,8 @@ private:
|
||||
CacheAccess& operator=(const CacheAccess&); // unimpl
|
||||
|
||||
// No taking addresses of this type.
|
||||
const CacheAccess* operator&() const;
|
||||
CacheAccess* operator&();
|
||||
const CacheAccess* operator&() const = delete;
|
||||
CacheAccess* operator&() = delete;
|
||||
|
||||
GrGpuResource* fResource;
|
||||
|
||||
|
@ -102,8 +102,11 @@ sk_sp<GrTextureProxy> GrProxyProvider::findProxyByUniqueKey(const GrUniqueKey& k
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
sk_sp<GrTextureProxy> result = sk_ref_sp(fUniquelyKeyedProxies.find(key));
|
||||
if (result) {
|
||||
GrTextureProxy* proxy = fUniquelyKeyedProxies.find(key);
|
||||
sk_sp<GrTextureProxy> result;
|
||||
if (proxy) {
|
||||
proxy->firstRefAccess().ref();
|
||||
result.reset(proxy);
|
||||
SkASSERT(result->origin() == origin);
|
||||
}
|
||||
return result;
|
||||
@ -790,15 +793,10 @@ void GrProxyProvider::processInvalidUniqueKey(const GrUniqueKey& key, GrTextureP
|
||||
// proxy's unique key. We must do it in this order because 'key' may alias the proxy's key.
|
||||
sk_sp<GrGpuResource> invalidGpuResource;
|
||||
if (InvalidateGPUResource::kYes == invalidateGPUResource) {
|
||||
if (proxy && proxy->isInstantiated()) {
|
||||
invalidGpuResource = sk_ref_sp(proxy->peekSurface());
|
||||
}
|
||||
if (!invalidGpuResource) {
|
||||
GrContext* direct = fImageContext->priv().asDirectContext();
|
||||
if (direct) {
|
||||
GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
|
||||
invalidGpuResource = resourceProvider->findByUniqueKey<GrGpuResource>(key);
|
||||
}
|
||||
GrContext* direct = fImageContext->priv().asDirectContext();
|
||||
if (direct) {
|
||||
GrResourceProvider* resourceProvider = direct->priv().resourceProvider();
|
||||
invalidGpuResource = resourceProvider->findByUniqueKey<GrGpuResource>(key);
|
||||
}
|
||||
SkASSERT(!invalidGpuResource || invalidGpuResource->getUniqueKey() == key);
|
||||
}
|
||||
|
@ -410,7 +410,7 @@ void GrResourceCache::refAndMakeResourceMRU(GrGpuResource* resource) {
|
||||
fPurgeableQueue.remove(resource);
|
||||
this->addToNonpurgeableArray(resource);
|
||||
}
|
||||
resource->ref();
|
||||
resource->cacheAccess().ref();
|
||||
|
||||
resource->cacheAccess().setTimestamp(this->getNextTimestamp());
|
||||
this->validate();
|
||||
|
@ -337,7 +337,8 @@ private:
|
||||
*testExecuteValue = 1;
|
||||
return {};
|
||||
}
|
||||
return rp->createTexture(desc, SkBudgeted::kNo);
|
||||
return {rp->createTexture(desc, SkBudgeted::kNo),
|
||||
GrSurfaceProxy::LazyInstantiationKeyMode::kUnsynced};
|
||||
},
|
||||
format, desc, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo, SkBackingFit::kExact,
|
||||
SkBudgeted::kNo);
|
||||
|
Loading…
Reference in New Issue
Block a user