| Index: src/gpu/GrResourceCache.cpp
|
| diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp
|
| index e6afa81b79de1104c7328549d05cef0a340f5807..9462a7384d73d45d3a5a857060ab7755d7082903 100644
|
| --- a/src/gpu/GrResourceCache.cpp
|
| +++ b/src/gpu/GrResourceCache.cpp
|
| @@ -57,22 +57,13 @@
|
| };
|
|
|
| //////////////////////////////////////////////////////////////////////////////
|
| -constexpr int GrResourceCache::kStrategyScoreMin;
|
| -constexpr int GrResourceCache::kStrategyScoreMax;
|
| -constexpr int GrResourceCache::kInitialStrategyScore;
|
| +
|
|
|
| GrResourceCache::GrResourceCache(const GrCaps* caps)
|
| : fTimestamp(0)
|
| , fMaxCount(kDefaultMaxCount)
|
| , fMaxBytes(kDefaultMaxSize)
|
| , fMaxUnusedFlushes(kDefaultMaxUnusedFlushes)
|
| - , fStrategy(ReplacementStrategy::kLRU)
|
| - , fStrategyScore(kInitialStrategyScore)
|
| - , fTotalMissesThisFlush(0)
|
| - , fMissesThisFlushPurgedRecently(0)
|
| - , fUniqueKeysPurgedThisFlushStorage {new SkChunkAlloc(8*sizeof(GrUniqueKey)),
|
| - new SkChunkAlloc(8*sizeof(GrUniqueKey))}
|
| - , fFlushParity(0)
|
| #if GR_CACHE_STATS
|
| , fHighWaterCount(0)
|
| , fHighWaterBytes(0)
|
| @@ -82,8 +73,8 @@
|
| , fBytes(0)
|
| , fBudgetedCount(0)
|
| , fBudgetedBytes(0)
|
| + , fRequestFlush(false)
|
| , fExternalFlushCnt(0)
|
| - , fIsPurging(false)
|
| , fPreferVRAMUseOverFlushes(caps->preferVRAMUseOverFlushes()) {
|
| SkDEBUGCODE(fCount = 0;)
|
| SkDEBUGCODE(fNewlyPurgeableResourceForValidation = nullptr;)
|
| @@ -91,8 +82,6 @@
|
|
|
| GrResourceCache::~GrResourceCache() {
|
| this->releaseAll();
|
| - delete fUniqueKeysPurgedThisFlushStorage[0];
|
| - delete fUniqueKeysPurgedThisFlushStorage[1];
|
| }
|
|
|
| void GrResourceCache::setLimits(int count, size_t bytes, int maxUnusedFlushes) {
|
| @@ -238,10 +227,8 @@
|
| GrGpuResource* GrResourceCache::findAndRefScratchResource(const GrScratchKey& scratchKey,
|
| size_t resourceSize,
|
| uint32_t flags) {
|
| - // We don't currently track misses for scratch resources for selecting the replacement policy.
|
| - // The reason is that it is common to look for a scratch resource before creating a texture
|
| - // that will immediately become uniquely keyed.
|
| SkASSERT(scratchKey.isValid());
|
| +
|
| GrGpuResource* resource;
|
| if (flags & (kPreferNoPendingIO_ScratchFlag | kRequireNoPendingIO_ScratchFlag)) {
|
| resource = fScratchMap.find(scratchKey, AvailableForScratchUse(true));
|
| @@ -267,25 +254,6 @@
|
| this->validate();
|
| }
|
| return resource;
|
| -}
|
| -
|
| -GrGpuResource* GrResourceCache::findAndRefUniqueResource(const GrUniqueKey& key) {
|
| - GrGpuResource* resource = fUniqueHash.find(key);
|
| - if (resource) {
|
| - this->refAndMakeResourceMRU(resource);
|
| - } else {
|
| - this->recordKeyMiss(key);
|
| - }
|
| - return resource;
|
| -}
|
| -
|
| -void GrResourceCache::recordKeyMiss(const GrUniqueKey& key) {
|
| - // If a resource with this key was purged either this flush or the previous flush, consider it
|
| - // a recent purge.
|
| - if (fUniqueKeysPurgedThisFlush[0].find(key) || fUniqueKeysPurgedThisFlush[1].find(key)) {
|
| - ++fMissesThisFlushPurgedRecently;
|
| - }
|
| - ++fTotalMissesThisFlush;
|
| }
|
|
|
| void GrResourceCache::willRemoveScratchKey(const GrGpuResource* resource) {
|
| @@ -412,12 +380,9 @@
|
| } else {
|
| // Purge the resource immediately if we're over budget
|
| // Also purge if the resource has neither a valid scratch key nor a unique key.
|
| - bool hasKey = resource->resourcePriv().getScratchKey().isValid() ||
|
| - resource->getUniqueKey().isValid();
|
| - if (hasKey) {
|
| - if (this->overBudget()) {
|
| - this->purgeAsNeeded();
|
| - }
|
| + bool noKey = !resource->resourcePriv().getScratchKey().isValid() &&
|
| + !resource->getUniqueKey().isValid();
|
| + if (!this->overBudget() && !noKey) {
|
| return;
|
| }
|
| }
|
| @@ -477,36 +442,7 @@
|
| this->validate();
|
| }
|
|
|
| -void GrResourceCache::recordPurgedKey(GrGpuResource* resource) {
|
| - // This maximum exists to avoid allocating too much space for key tracking.
|
| - static constexpr int kMaxTrackedKeys = 256;
|
| - if (fUniqueKeysPurgedThisFlush[fFlushParity].count() >= kMaxTrackedKeys) {
|
| - return;
|
| - }
|
| - if (resource->getUniqueKey().isValid() &&
|
| - !fUniqueKeysPurgedThisFlush[fFlushParity].find(resource->getUniqueKey())) {
|
| - void* p = fUniqueKeysPurgedThisFlushStorage[fFlushParity]->allocThrow(sizeof(GrUniqueKey));
|
| - GrUniqueKey* copy = new (p) GrUniqueKey;
|
| - *copy = resource->getUniqueKey();
|
| - fUniqueKeysPurgedThisFlush[fFlushParity].add(copy);
|
| - }
|
| -}
|
| -
|
| -GrGpuResource* GrResourceCache::selectResourceUsingStrategy() {
|
| - switch (fStrategy) {
|
| - case ReplacementStrategy::kLRU:
|
| - return fPurgeableQueue.peek();
|
| - case ReplacementStrategy::kRandom:
|
| - return fPurgeableQueue.at(fRandom.nextULessThan(fPurgeableQueue.count()));
|
| - }
|
| - return nullptr;
|
| -}
|
| -
|
| -void GrResourceCache::internalPurgeAsNeeded(bool fromFlushNotification) {
|
| - if (fIsPurging) {
|
| - return;
|
| - }
|
| - fIsPurging = true;
|
| +void GrResourceCache::purgeAsNeeded() {
|
| SkTArray<GrUniqueKeyInvalidatedMessage> invalidKeyMsgs;
|
| fInvalidUniqueKeyInbox.poll(&invalidKeyMsgs);
|
| if (invalidKeyMsgs.count()) {
|
| @@ -534,31 +470,26 @@
|
| }
|
| GrGpuResource* resource = fPurgeableQueue.peek();
|
| SkASSERT(resource->isPurgeable());
|
| - this->recordPurgedKey(resource);
|
| resource->cacheAccess().release();
|
| }
|
| }
|
| - }
|
| -
|
| - if (ReplacementStrategy::kRandom == fStrategy && !fromFlushNotification) {
|
| - // Wait until after the requested flush when all the pending IO resources will be eligible
|
| - // for the draft.
|
| - SkASSERT(!this->overBudget() || this->requestsFlush());
|
| - fIsPurging = false;
|
| - return;
|
| }
|
|
|
| bool stillOverbudget = this->overBudget();
|
| while (stillOverbudget && fPurgeableQueue.count()) {
|
| - GrGpuResource* resource = this->selectResourceUsingStrategy();
|
| + GrGpuResource* resource = fPurgeableQueue.peek();
|
| SkASSERT(resource->isPurgeable());
|
| - this->recordPurgedKey(resource);
|
| resource->cacheAccess().release();
|
| stillOverbudget = this->overBudget();
|
| }
|
|
|
| this->validate();
|
| - fIsPurging = false;
|
| +
|
| + if (stillOverbudget) {
|
| + // Set this so that GrDrawingManager will issue a flush to free up resources with pending
|
| + // IO that we were unable to purge in this pass.
|
| + fRequestFlush = true;
|
| + }
|
| }
|
|
|
| void GrResourceCache::purgeAllUnlocked() {
|
| @@ -618,6 +549,7 @@
|
| *sortedPurgeableResources.append() = fPurgeableQueue.peek();
|
| fPurgeableQueue.pop();
|
| }
|
| +
|
| SkTQSort(fNonpurgeableResources.begin(), fNonpurgeableResources.end() - 1,
|
| CompareTimestamp);
|
|
|
| @@ -668,25 +600,10 @@
|
| case FlushType::kImmediateMode:
|
| break;
|
| case FlushType::kCacheRequested:
|
| + SkASSERT(fRequestFlush);
|
| + fRequestFlush = false;
|
| break;
|
| - case FlushType::kExternal: {
|
| - int scoreDelta = 1;
|
| - if (fMissesThisFlushPurgedRecently) {
|
| - // If > 60% of our cache misses were things we purged in the last two flushes
|
| - // then we move closer towards selecting random replacement.
|
| - if ((float)fMissesThisFlushPurgedRecently / fTotalMissesThisFlush > 0.6f) {
|
| - scoreDelta = -1;
|
| - }
|
| - }
|
| - fStrategyScore = SkTPin(fStrategyScore + scoreDelta, kStrategyScoreMin,
|
| - kStrategyScoreMax);
|
| - fStrategy = fStrategyScore < 0 ? ReplacementStrategy::kRandom
|
| - : ReplacementStrategy::kLRU;
|
| - fMissesThisFlushPurgedRecently = 0;
|
| - fTotalMissesThisFlush = 0;
|
| - fFlushParity = -(fFlushParity - 1);
|
| - fUniqueKeysPurgedThisFlush[fFlushParity].reset();
|
| - fUniqueKeysPurgedThisFlushStorage[fFlushParity]->rewind();
|
| + case FlushType::kExternal:
|
| ++fExternalFlushCnt;
|
| if (0 == fExternalFlushCnt) {
|
| // When this wraps just reset all the purgeable resources' last used flush state.
|
| @@ -695,9 +612,8 @@
|
| }
|
| }
|
| break;
|
| - }
|
| - }
|
| - this->internalPurgeAsNeeded(true);
|
| + }
|
| + this->purgeAsNeeded();
|
| }
|
|
|
| void GrResourceCache::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
|
|
|