Add scratch-only version of performDeferredCleanup
Change-Id: I5707d1da1b69ab1ffaa77d7a391a187ac3e8eba1
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/417267
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrDirectContext.cpp b/src/gpu/GrDirectContext.cpp
index 3a2ae7e..36b5c52 100644
--- a/src/gpu/GrDirectContext.cpp
+++ b/src/gpu/GrDirectContext.cpp
@@ -193,7 +193,7 @@
this->drawingManager()->freeGpuResources();
- fResourceCache->purgeAllUnlocked();
+ fResourceCache->purgeUnlockedResources();
}
bool GrDirectContext::init() {
@@ -317,7 +317,8 @@
fGpu->releaseUnlockedBackendObjects();
}
-void GrDirectContext::performDeferredCleanup(std::chrono::milliseconds msNotUsed) {
+void GrDirectContext::performDeferredCleanup(std::chrono::milliseconds msNotUsed,
+ bool scratchResourcesOnly) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
ASSERT_SINGLE_OWNER
@@ -331,7 +332,7 @@
auto purgeTime = GrStdSteadyClock::now() - msNotUsed;
fResourceCache->purgeAsNeeded();
- fResourceCache->purgeResourcesNotUsedSince(purgeTime);
+ fResourceCache->purgeResourcesNotUsedSince(purgeTime, scratchResourcesOnly);
// The textBlob Cache doesn't actually hold any GPU resource but this is a convenient
// place to purge stale blobs
diff --git a/src/gpu/GrDirectContextPriv.cpp b/src/gpu/GrDirectContextPriv.cpp
index 66917a1..b00a1a2 100644
--- a/src/gpu/GrDirectContextPriv.cpp
+++ b/src/gpu/GrDirectContextPriv.cpp
@@ -185,10 +185,6 @@
SkColorInfo(colorType, kPremul_SkAlphaType, nullptr));
}
-void GrDirectContextPriv::testingOnly_purgeAllUnlockedResources() {
- fContext->fResourceCache->purgeAllUnlocked();
-}
-
void GrDirectContextPriv::testingOnly_flushAndRemoveOnFlushCallbackObject(
GrOnFlushCallbackObject* cb) {
fContext->flushAndSubmit();
diff --git a/src/gpu/GrDirectContextPriv.h b/src/gpu/GrDirectContextPriv.h
index fd205d0..fd8f9af 100644
--- a/src/gpu/GrDirectContextPriv.h
+++ b/src/gpu/GrDirectContextPriv.h
@@ -187,13 +187,6 @@
if it gets cached or used more generally. */
sk_sp<SkImage> testingOnly_getFontAtlasImage(GrMaskFormat format, unsigned int index = 0);
- /**
- * Purge all the unlocked resources from the cache.
- * This entry point is mainly meant for timing texture uploads
- * and is not defined in normal builds of Skia.
- */
- void testingOnly_purgeAllUnlockedResources();
-
void testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject*);
#endif
diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp
index 64d470c..2a96973 100644
--- a/src/gpu/GrResourceCache.cpp
+++ b/src/gpu/GrResourceCache.cpp
@@ -564,19 +564,43 @@
this->validate();
}
-void GrResourceCache::purgeUnlockedResources(bool scratchResourcesOnly) {
+void GrResourceCache::purgeUnlockedResources(const GrStdSteadyClock::time_point* purgeTime,
+ bool scratchResourcesOnly) {
if (!scratchResourcesOnly) {
- fThreadSafeCache->dropUniqueRefs(nullptr);
+ if (purgeTime) {
+ fThreadSafeCache->dropUniqueRefsOlderThan(*purgeTime);
+ } else {
+ fThreadSafeCache->dropUniqueRefs(nullptr);
+ }
// We could disable maintaining the heap property here, but it would add a lot of
// complexity. Moreover, this is rarely called.
while (fPurgeableQueue.count()) {
GrGpuResource* resource = fPurgeableQueue.peek();
+
+ const GrStdSteadyClock::time_point resourceTime =
+ resource->cacheAccess().timeWhenResourceBecamePurgeable();
+ if (purgeTime && resourceTime >= *purgeTime) {
+ // Resources were given both LRU timestamps and tagged with a frame number when
+ // they first became purgeable. The LRU timestamp won't change again until the
+ // resource is made non-purgeable again. So, at this point all the remaining
+ // resources in the timestamp-sorted queue will have a frame number >= to this
+ // one.
+ break;
+ }
+
SkASSERT(resource->resourcePriv().isPurgeable());
resource->cacheAccess().release();
}
} else {
+ // Early out if the very first item is too new to purge to avoid sorting the queue when
+ // nothing will be deleted.
+ if (purgeTime && fPurgeableQueue.count() &&
+ fPurgeableQueue.peek()->cacheAccess().timeWhenResourceBecamePurgeable() >= *purgeTime) {
+ return;
+ }
+
// Sort the queue
fPurgeableQueue.sort();
@@ -584,6 +608,13 @@
SkTDArray<GrGpuResource*> scratchResources;
for (int i = 0; i < fPurgeableQueue.count(); i++) {
GrGpuResource* resource = fPurgeableQueue.at(i);
+
+ const GrStdSteadyClock::time_point resourceTime =
+ resource->cacheAccess().timeWhenResourceBecamePurgeable();
+ if (purgeTime && resourceTime >= *purgeTime) {
+ // scratch or not, all later iterations will be too recently used to purge.
+ break;
+ }
SkASSERT(resource->resourcePriv().isPurgeable());
if (!resource->getUniqueKey().isValid()) {
*scratchResources.append() = resource;
@@ -600,26 +631,6 @@
this->validate();
}
-void GrResourceCache::purgeResourcesNotUsedSince(GrStdSteadyClock::time_point purgeTime) {
- fThreadSafeCache->dropUniqueRefsOlderThan(purgeTime);
-
- while (fPurgeableQueue.count()) {
- const GrStdSteadyClock::time_point resourceTime =
- fPurgeableQueue.peek()->cacheAccess().timeWhenResourceBecamePurgeable();
- if (resourceTime >= purgeTime) {
- // Resources were given both LRU timestamps and tagged with a frame number when
- // they first became purgeable. The LRU timestamp won't change again until the
- // resource is made non-purgeable again. So, at this point all the remaining
- // resources in the timestamp-sorted queue will have a frame number >= to this
- // one.
- break;
- }
- GrGpuResource* resource = fPurgeableQueue.peek();
- SkASSERT(resource->resourcePriv().isPurgeable());
- resource->cacheAccess().release();
- }
-}
-
bool GrResourceCache::purgeToMakeHeadroom(size_t desiredHeadroomBytes) {
AutoValidate av(this);
if (desiredHeadroomBytes > fMaxBytes) {
diff --git a/src/gpu/GrResourceCache.h b/src/gpu/GrResourceCache.h
index eb52ca2..198ace2 100644
--- a/src/gpu/GrResourceCache.h
+++ b/src/gpu/GrResourceCache.h
@@ -154,16 +154,20 @@
keys. */
void purgeAsNeeded();
- /** Purges all resources that don't have external owners. */
- void purgeAllUnlocked() { this->purgeUnlockedResources(false); }
-
// Purge unlocked resources. If 'scratchResourcesOnly' is true the purgeable resources
// containing persistent data are spared. If it is false then all purgeable resources will
// be deleted.
- void purgeUnlockedResources(bool scratchResourcesOnly);
+ void purgeUnlockedResources(bool scratchResourcesOnly=false) {
+ this->purgeUnlockedResources(/*purgeTime=*/nullptr, scratchResourcesOnly);
+ }
- /** Purge all resources not used since the passed in time. */
- void purgeResourcesNotUsedSince(GrStdSteadyClock::time_point);
+ // Purge unlocked resources not used since the passed point in time. If 'scratchResourcesOnly'
+ // is true the purgeable resources containing persistent data are spared. If it is false then
+ // all purgeable resources older than 'purgeTime' will be deleted.
+ void purgeResourcesNotUsedSince(GrStdSteadyClock::time_point purgeTime,
+ bool scratchResourcesOnly=false) {
+ this->purgeUnlockedResources(&purgeTime, scratchResourcesOnly);
+ }
/** If it's possible to purge enough resources to get the provided amount of budget
headroom, do so and return true. If it's not possible, do nothing and return false.
@@ -273,6 +277,9 @@
uint32_t getNextTimestamp();
+ void purgeUnlockedResources(const GrStdSteadyClock::time_point* purgeTime,
+ bool scratchResourcesOnly);
+
#ifdef SK_DEBUG
bool isInCache(const GrGpuResource* r) const;
void validate() const;