Index: src/gpu/GrResourceCache.cpp |
diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp |
index 529f87c124880bbefd0c724bd2e48016841d4cd9..9462a7384d73d45d3a5a857060ab7755d7082903 100644 |
--- a/src/gpu/GrResourceCache.cpp |
+++ b/src/gpu/GrResourceCache.cpp |
@@ -74,49 +74,23 @@ GrResourceCache::GrResourceCache(const GrCaps* caps) |
, fBudgetedCount(0) |
, fBudgetedBytes(0) |
, fRequestFlush(false) |
- , fFlushTimestamps(nullptr) |
- , fLastFlushTimestampIndex(0) |
+ , fExternalFlushCnt(0) |
, fPreferVRAMUseOverFlushes(caps->preferVRAMUseOverFlushes()) { |
SkDEBUGCODE(fCount = 0;) |
SkDEBUGCODE(fNewlyPurgeableResourceForValidation = nullptr;) |
- this->resetFlushTimestamps(); |
} |
GrResourceCache::~GrResourceCache() { |
this->releaseAll(); |
- delete[] fFlushTimestamps; |
} |
void GrResourceCache::setLimits(int count, size_t bytes, int maxUnusedFlushes) { |
fMaxCount = count; |
fMaxBytes = bytes; |
fMaxUnusedFlushes = maxUnusedFlushes; |
- this->resetFlushTimestamps(); |
this->purgeAsNeeded(); |
} |
-void GrResourceCache::resetFlushTimestamps() { |
- delete[] fFlushTimestamps; |
- |
- // We assume this number is a power of two when wrapping indices into the timestamp array. |
- fMaxUnusedFlushes = SkNextPow2(fMaxUnusedFlushes); |
- |
- // Since our implementation is to store the timestamps of the last fMaxUnusedFlushes flush calls |
- // we just turn the feature off if that array would be large. |
- static const int kMaxSupportedTimestampHistory = 128; |
- |
- if (fMaxUnusedFlushes > kMaxSupportedTimestampHistory) { |
- fFlushTimestamps = nullptr; |
- return; |
- } |
- |
- fFlushTimestamps = new uint32_t[fMaxUnusedFlushes]; |
- fLastFlushTimestampIndex = 0; |
- // Set all the historical flush timestamps to initially be at the beginning of time (timestamp |
- // 0). |
- sk_bzero(fFlushTimestamps, fMaxUnusedFlushes * sizeof(uint32_t)); |
-} |
- |
void GrResourceCache::insertResource(GrGpuResource* resource) { |
SkASSERT(resource); |
SkASSERT(!this->isInCache(resource)); |
@@ -390,6 +364,7 @@ void GrResourceCache::notifyCntReachedZero(GrGpuResource* resource, uint32_t fla |
SkASSERT(resource->isPurgeable()); |
this->removeFromNonpurgeableArray(resource); |
fPurgeableQueue.insert(resource); |
+ resource->cacheAccess().setFlushCntWhenResourceBecamePurgeable(fExternalFlushCnt); |
if (SkBudgeted::kNo == resource->resourcePriv().isBudgeted()) { |
// Check whether this resource could still be used as a scratch resource. |
@@ -474,20 +449,29 @@ void GrResourceCache::purgeAsNeeded() { |
this->processInvalidUniqueKeys(invalidKeyMsgs); |
} |
- if (fFlushTimestamps) { |
- // Assuming kNumFlushesToDeleteUnusedResource is a power of 2. |
- SkASSERT(SkIsPow2(fMaxUnusedFlushes)); |
- int oldestFlushIndex = (fLastFlushTimestampIndex + 1) & (fMaxUnusedFlushes - 1); |
- |
- uint32_t oldestAllowedTimestamp = fFlushTimestamps[oldestFlushIndex]; |
- while (fPurgeableQueue.count()) { |
- uint32_t oldestResourceTimestamp = fPurgeableQueue.peek()->cacheAccess().timestamp(); |
- if (oldestAllowedTimestamp < oldestResourceTimestamp) { |
- break; |
+ if (fMaxUnusedFlushes > 0) { |
+ // We want to know how many complete flushes have occurred without the resource being used. |
+ // If the resource was tagged when fExternalFlushCnt was N then this means it became |
+ // purgeable during activity that became the N+1th flush. So when the flush count is N+2 |
+ // it has sat in the purgeable queue for one entire flush. |
+ uint32_t oldestAllowedFlushCnt = fExternalFlushCnt - fMaxUnusedFlushes - 1; |
+ // check for underflow |
+ if (oldestAllowedFlushCnt < fExternalFlushCnt) { |
+ while (fPurgeableQueue.count()) { |
+ uint32_t flushWhenResourceBecamePurgeable = |
+ fPurgeableQueue.peek()->cacheAccess().flushCntWhenResourceBecamePurgeable(); |
+ if (oldestAllowedFlushCnt < flushWhenResourceBecamePurgeable) { |
+ // Resources were given both LRU timestamps and tagged with a flush cnt 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 flush count >= to this |
+ // one. |
+ break; |
+ } |
+ GrGpuResource* resource = fPurgeableQueue.peek(); |
+ SkASSERT(resource->isPurgeable()); |
+ resource->cacheAccess().release(); |
} |
- GrGpuResource* resource = fPurgeableQueue.peek(); |
- SkASSERT(resource->isPurgeable()); |
- resource->cacheAccess().release(); |
} |
} |
@@ -566,13 +550,8 @@ uint32_t GrResourceCache::getNextTimestamp() { |
fPurgeableQueue.pop(); |
} |
- struct Less { |
- bool operator()(GrGpuResource* a, GrGpuResource* b) { |
- return CompareTimestamp(a,b); |
- } |
- }; |
- Less less; |
- SkTQSort(fNonpurgeableResources.begin(), fNonpurgeableResources.end() - 1, less); |
+ SkTQSort(fNonpurgeableResources.begin(), fNonpurgeableResources.end() - 1, |
+ CompareTimestamp); |
// Pick resources out of the purgeable and non-purgeable arrays based on lowest |
// timestamp and assign new timestamps. |
@@ -611,9 +590,6 @@ uint32_t GrResourceCache::getNextTimestamp() { |
// count should be the next timestamp we return. |
SkASSERT(fTimestamp == SkToU32(count)); |
- |
- // The historical timestamps of flushes are now invalid. |
- this->resetFlushTimestamps(); |
} |
} |
return fTimestamp++; |
@@ -628,13 +604,12 @@ void GrResourceCache::notifyFlushOccurred(FlushType type) { |
fRequestFlush = false; |
break; |
case FlushType::kExternal: |
- if (fFlushTimestamps) { |
- SkASSERT(SkIsPow2(fMaxUnusedFlushes)); |
- fLastFlushTimestampIndex = (fLastFlushTimestampIndex + 1) & (fMaxUnusedFlushes - 1); |
- // get the timestamp before accessing fFlushTimestamps because getNextTimestamp will |
- // reallocate fFlushTimestamps on timestamp overflow. |
- uint32_t timestamp = this->getNextTimestamp(); |
- fFlushTimestamps[fLastFlushTimestampIndex] = timestamp; |
+ ++fExternalFlushCnt; |
+ if (0 == fExternalFlushCnt) { |
+ // When this wraps just reset all the purgeable resources' last used flush state. |
+ for (int i = 0; i < fPurgeableQueue.count(); ++i) { |
+ fPurgeableQueue.at(i)->cacheAccess().setFlushCntWhenResourceBecamePurgeable(0); |
+ } |
} |
break; |
} |