OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 | 8 |
9 #include "GrResourceCache.h" | 9 #include "GrResourceCache.h" |
10 | 10 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 | 50 |
51 class GrResourceCache::AutoValidate : ::SkNoncopyable { | 51 class GrResourceCache::AutoValidate : ::SkNoncopyable { |
52 public: | 52 public: |
53 AutoValidate(GrResourceCache* cache) : fCache(cache) { cache->validate(); } | 53 AutoValidate(GrResourceCache* cache) : fCache(cache) { cache->validate(); } |
54 ~AutoValidate() { fCache->validate(); } | 54 ~AutoValidate() { fCache->validate(); } |
55 private: | 55 private: |
56 GrResourceCache* fCache; | 56 GrResourceCache* fCache; |
57 }; | 57 }; |
58 | 58 |
59 ////////////////////////////////////////////////////////////////////////////// | 59 ////////////////////////////////////////////////////////////////////////////// |
60 | 60 constexpr int GrResourceCache::kStrategyScoreMin; |
| 61 constexpr int GrResourceCache::kStrategyScoreMax; |
| 62 constexpr int GrResourceCache::kInitialStrategyScore; |
61 | 63 |
62 GrResourceCache::GrResourceCache(const GrCaps* caps) | 64 GrResourceCache::GrResourceCache(const GrCaps* caps) |
63 : fTimestamp(0) | 65 : fTimestamp(0) |
64 , fMaxCount(kDefaultMaxCount) | 66 , fMaxCount(kDefaultMaxCount) |
65 , fMaxBytes(kDefaultMaxSize) | 67 , fMaxBytes(kDefaultMaxSize) |
66 , fMaxUnusedFlushes(kDefaultMaxUnusedFlushes) | 68 , fMaxUnusedFlushes(kDefaultMaxUnusedFlushes) |
| 69 , fStrategy(ReplacementStrategy::kLRU) |
| 70 , fStrategyScore(kInitialStrategyScore) |
| 71 , fTotalMissesThisFlush(0) |
| 72 , fMissesThisFlushPurgedRecently(0) |
| 73 , fUniqueKeysPurgedThisFlushStorage {new SkChunkAlloc(8*sizeof(GrUniqueKey))
, |
| 74 new SkChunkAlloc(8*sizeof(GrUniqueKey))
} |
| 75 , fFlushParity(0) |
67 #if GR_CACHE_STATS | 76 #if GR_CACHE_STATS |
68 , fHighWaterCount(0) | 77 , fHighWaterCount(0) |
69 , fHighWaterBytes(0) | 78 , fHighWaterBytes(0) |
70 , fBudgetedHighWaterCount(0) | 79 , fBudgetedHighWaterCount(0) |
71 , fBudgetedHighWaterBytes(0) | 80 , fBudgetedHighWaterBytes(0) |
72 #endif | 81 #endif |
73 , fBytes(0) | 82 , fBytes(0) |
74 , fBudgetedCount(0) | 83 , fBudgetedCount(0) |
75 , fBudgetedBytes(0) | 84 , fBudgetedBytes(0) |
76 , fRequestFlush(false) | |
77 , fExternalFlushCnt(0) | 85 , fExternalFlushCnt(0) |
| 86 , fIsPurging(false) |
78 , fPreferVRAMUseOverFlushes(caps->preferVRAMUseOverFlushes()) { | 87 , fPreferVRAMUseOverFlushes(caps->preferVRAMUseOverFlushes()) { |
79 SkDEBUGCODE(fCount = 0;) | 88 SkDEBUGCODE(fCount = 0;) |
80 SkDEBUGCODE(fNewlyPurgeableResourceForValidation = nullptr;) | 89 SkDEBUGCODE(fNewlyPurgeableResourceForValidation = nullptr;) |
81 } | 90 } |
82 | 91 |
83 GrResourceCache::~GrResourceCache() { | 92 GrResourceCache::~GrResourceCache() { |
84 this->releaseAll(); | 93 this->releaseAll(); |
| 94 delete fUniqueKeysPurgedThisFlushStorage[0]; |
| 95 delete fUniqueKeysPurgedThisFlushStorage[1]; |
85 } | 96 } |
86 | 97 |
87 void GrResourceCache::setLimits(int count, size_t bytes, int maxUnusedFlushes) { | 98 void GrResourceCache::setLimits(int count, size_t bytes, int maxUnusedFlushes) { |
88 fMaxCount = count; | 99 fMaxCount = count; |
89 fMaxBytes = bytes; | 100 fMaxBytes = bytes; |
90 fMaxUnusedFlushes = maxUnusedFlushes; | 101 fMaxUnusedFlushes = maxUnusedFlushes; |
91 this->purgeAsNeeded(); | 102 this->purgeAsNeeded(); |
92 } | 103 } |
93 | 104 |
94 void GrResourceCache::insertResource(GrGpuResource* resource) { | 105 void GrResourceCache::insertResource(GrGpuResource* resource) { |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 return !fRejectPendingIO || !resource->internalHasPendingIO(); | 231 return !fRejectPendingIO || !resource->internalHasPendingIO(); |
221 } | 232 } |
222 | 233 |
223 private: | 234 private: |
224 bool fRejectPendingIO; | 235 bool fRejectPendingIO; |
225 }; | 236 }; |
226 | 237 |
227 GrGpuResource* GrResourceCache::findAndRefScratchResource(const GrScratchKey& sc
ratchKey, | 238 GrGpuResource* GrResourceCache::findAndRefScratchResource(const GrScratchKey& sc
ratchKey, |
228 size_t resourceSize, | 239 size_t resourceSize, |
229 uint32_t flags) { | 240 uint32_t flags) { |
| 241 // We don't currently track misses for scratch resources for selecting the r
eplacement policy. |
| 242 // The reason is that it is common to look for a scratch resource before cre
ating a texture |
| 243 // that will immediately become uniquely keyed. |
230 SkASSERT(scratchKey.isValid()); | 244 SkASSERT(scratchKey.isValid()); |
231 | |
232 GrGpuResource* resource; | 245 GrGpuResource* resource; |
233 if (flags & (kPreferNoPendingIO_ScratchFlag | kRequireNoPendingIO_ScratchFla
g)) { | 246 if (flags & (kPreferNoPendingIO_ScratchFlag | kRequireNoPendingIO_ScratchFla
g)) { |
234 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(true)); | 247 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(true)); |
235 if (resource) { | 248 if (resource) { |
236 this->refAndMakeResourceMRU(resource); | 249 this->refAndMakeResourceMRU(resource); |
237 this->validate(); | 250 this->validate(); |
238 return resource; | 251 return resource; |
239 } else if (flags & kRequireNoPendingIO_ScratchFlag) { | 252 } else if (flags & kRequireNoPendingIO_ScratchFlag) { |
240 return nullptr; | 253 return nullptr; |
241 } | 254 } |
242 // We would prefer to consume more available VRAM rather than flushing | 255 // We would prefer to consume more available VRAM rather than flushing |
243 // immediately, but on ANGLE this can lead to starving of the GPU. | 256 // immediately, but on ANGLE this can lead to starving of the GPU. |
244 if (fPreferVRAMUseOverFlushes && this->wouldFit(resourceSize)) { | 257 if (fPreferVRAMUseOverFlushes && this->wouldFit(resourceSize)) { |
245 // kPrefer is specified, we didn't find a resource without pending i
o, | 258 // kPrefer is specified, we didn't find a resource without pending i
o, |
246 // but there is still space in our budget for the resource so force | 259 // but there is still space in our budget for the resource so force |
247 // the caller to allocate a new resource. | 260 // the caller to allocate a new resource. |
248 return nullptr; | 261 return nullptr; |
249 } | 262 } |
250 } | 263 } |
251 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(false)); | 264 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(false)); |
252 if (resource) { | 265 if (resource) { |
253 this->refAndMakeResourceMRU(resource); | 266 this->refAndMakeResourceMRU(resource); |
254 this->validate(); | 267 this->validate(); |
255 } | 268 } |
256 return resource; | 269 return resource; |
257 } | 270 } |
258 | 271 |
| 272 GrGpuResource* GrResourceCache::findAndRefUniqueResource(const GrUniqueKey& key)
{ |
| 273 GrGpuResource* resource = fUniqueHash.find(key); |
| 274 if (resource) { |
| 275 this->refAndMakeResourceMRU(resource); |
| 276 } else { |
| 277 this->recordKeyMiss(key); |
| 278 } |
| 279 return resource; |
| 280 } |
| 281 |
| 282 void GrResourceCache::recordKeyMiss(const GrUniqueKey& key) { |
| 283 // If a resource with this key was purged either this flush or the previous
flush, consider it |
| 284 // a recent purge. |
| 285 if (fUniqueKeysPurgedThisFlush[0].find(key) || fUniqueKeysPurgedThisFlush[1]
.find(key)) { |
| 286 ++fMissesThisFlushPurgedRecently; |
| 287 } |
| 288 ++fTotalMissesThisFlush; |
| 289 } |
| 290 |
259 void GrResourceCache::willRemoveScratchKey(const GrGpuResource* resource) { | 291 void GrResourceCache::willRemoveScratchKey(const GrGpuResource* resource) { |
260 SkASSERT(resource->resourcePriv().getScratchKey().isValid()); | 292 SkASSERT(resource->resourcePriv().getScratchKey().isValid()); |
261 if (!resource->getUniqueKey().isValid()) { | 293 if (!resource->getUniqueKey().isValid()) { |
262 fScratchMap.remove(resource->resourcePriv().getScratchKey(), resource); | 294 fScratchMap.remove(resource->resourcePriv().getScratchKey(), resource); |
263 } | 295 } |
264 } | 296 } |
265 | 297 |
266 void GrResourceCache::removeUniqueKey(GrGpuResource* resource) { | 298 void GrResourceCache::removeUniqueKey(GrGpuResource* resource) { |
267 // Someone has a ref to this resource in order to have removed the key. When
the ref count | 299 // Someone has a ref to this resource in order to have removed the key. When
the ref count |
268 // reaches zero we will get a ref cnt notification and figure out what to do
with it. | 300 // reaches zero we will get a ref cnt notification and figure out what to do
with it. |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
373 // We won't purge an existing resource to make room for this one. | 405 // We won't purge an existing resource to make room for this one. |
374 if (fBudgetedCount < fMaxCount && | 406 if (fBudgetedCount < fMaxCount && |
375 fBudgetedBytes + resource->gpuMemorySize() <= fMaxBytes) { | 407 fBudgetedBytes + resource->gpuMemorySize() <= fMaxBytes) { |
376 resource->resourcePriv().makeBudgeted(); | 408 resource->resourcePriv().makeBudgeted(); |
377 return; | 409 return; |
378 } | 410 } |
379 } | 411 } |
380 } else { | 412 } else { |
381 // Purge the resource immediately if we're over budget | 413 // Purge the resource immediately if we're over budget |
382 // Also purge if the resource has neither a valid scratch key nor a uniq
ue key. | 414 // Also purge if the resource has neither a valid scratch key nor a uniq
ue key. |
383 bool noKey = !resource->resourcePriv().getScratchKey().isValid() && | 415 bool hasKey = resource->resourcePriv().getScratchKey().isValid() || |
384 !resource->getUniqueKey().isValid(); | 416 resource->getUniqueKey().isValid(); |
385 if (!this->overBudget() && !noKey) { | 417 if (hasKey) { |
| 418 if (this->overBudget()) { |
| 419 this->purgeAsNeeded(); |
| 420 } |
386 return; | 421 return; |
387 } | 422 } |
388 } | 423 } |
389 | 424 |
390 SkDEBUGCODE(int beforeCount = this->getResourceCount();) | 425 SkDEBUGCODE(int beforeCount = this->getResourceCount();) |
391 resource->cacheAccess().release(); | 426 resource->cacheAccess().release(); |
392 // We should at least free this resource, perhaps dependent resources as wel
l. | 427 // We should at least free this resource, perhaps dependent resources as wel
l. |
393 SkASSERT(this->getResourceCount() < beforeCount); | 428 SkASSERT(this->getResourceCount() < beforeCount); |
394 this->validate(); | 429 this->validate(); |
395 } | 430 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
435 } else { | 470 } else { |
436 --fBudgetedCount; | 471 --fBudgetedCount; |
437 fBudgetedBytes -= size; | 472 fBudgetedBytes -= size; |
438 } | 473 } |
439 TRACE_COUNTER2(TRACE_DISABLED_BY_DEFAULT("skia.gpu.cache"), "skia budget", "
used", | 474 TRACE_COUNTER2(TRACE_DISABLED_BY_DEFAULT("skia.gpu.cache"), "skia budget", "
used", |
440 fBudgetedBytes, "free", fMaxBytes - fBudgetedBytes); | 475 fBudgetedBytes, "free", fMaxBytes - fBudgetedBytes); |
441 | 476 |
442 this->validate(); | 477 this->validate(); |
443 } | 478 } |
444 | 479 |
445 void GrResourceCache::purgeAsNeeded() { | 480 void GrResourceCache::recordPurgedKey(GrGpuResource* resource) { |
| 481 // This maximum exists to avoid allocating too much space for key tracking. |
| 482 static constexpr int kMaxTrackedKeys = 256; |
| 483 if (fUniqueKeysPurgedThisFlush[fFlushParity].count() >= kMaxTrackedKeys) { |
| 484 return; |
| 485 } |
| 486 if (resource->getUniqueKey().isValid() && |
| 487 !fUniqueKeysPurgedThisFlush[fFlushParity].find(resource->getUniqueKey())
) { |
| 488 void* p = fUniqueKeysPurgedThisFlushStorage[fFlushParity]->allocThrow(si
zeof(GrUniqueKey)); |
| 489 GrUniqueKey* copy = new (p) GrUniqueKey; |
| 490 *copy = resource->getUniqueKey(); |
| 491 fUniqueKeysPurgedThisFlush[fFlushParity].add(copy); |
| 492 } |
| 493 } |
| 494 |
| 495 GrGpuResource* GrResourceCache::selectResourceUsingStrategy() { |
| 496 switch (fStrategy) { |
| 497 case ReplacementStrategy::kLRU: |
| 498 return fPurgeableQueue.peek(); |
| 499 case ReplacementStrategy::kRandom: |
| 500 return fPurgeableQueue.at(fRandom.nextULessThan(fPurgeableQueue.coun
t())); |
| 501 } |
| 502 return nullptr; |
| 503 } |
| 504 |
| 505 void GrResourceCache::internalPurgeAsNeeded(bool fromFlushNotification) { |
| 506 if (fIsPurging) { |
| 507 return; |
| 508 } |
| 509 fIsPurging = true; |
446 SkTArray<GrUniqueKeyInvalidatedMessage> invalidKeyMsgs; | 510 SkTArray<GrUniqueKeyInvalidatedMessage> invalidKeyMsgs; |
447 fInvalidUniqueKeyInbox.poll(&invalidKeyMsgs); | 511 fInvalidUniqueKeyInbox.poll(&invalidKeyMsgs); |
448 if (invalidKeyMsgs.count()) { | 512 if (invalidKeyMsgs.count()) { |
449 this->processInvalidUniqueKeys(invalidKeyMsgs); | 513 this->processInvalidUniqueKeys(invalidKeyMsgs); |
450 } | 514 } |
451 | 515 |
452 if (fMaxUnusedFlushes > 0) { | 516 if (fMaxUnusedFlushes > 0) { |
453 // We want to know how many complete flushes have occurred without the r
esource being used. | 517 // We want to know how many complete flushes have occurred without the r
esource being used. |
454 // If the resource was tagged when fExternalFlushCnt was N then this mea
ns it became | 518 // If the resource was tagged when fExternalFlushCnt was N then this mea
ns it became |
455 // purgeable during activity that became the N+1th flush. So when the fl
ush count is N+2 | 519 // purgeable during activity that became the N+1th flush. So when the fl
ush count is N+2 |
456 // it has sat in the purgeable queue for one entire flush. | 520 // it has sat in the purgeable queue for one entire flush. |
457 uint32_t oldestAllowedFlushCnt = fExternalFlushCnt - fMaxUnusedFlushes -
1; | 521 uint32_t oldestAllowedFlushCnt = fExternalFlushCnt - fMaxUnusedFlushes -
1; |
458 // check for underflow | 522 // check for underflow |
459 if (oldestAllowedFlushCnt < fExternalFlushCnt) { | 523 if (oldestAllowedFlushCnt < fExternalFlushCnt) { |
460 while (fPurgeableQueue.count()) { | 524 while (fPurgeableQueue.count()) { |
461 uint32_t flushWhenResourceBecamePurgeable = | 525 uint32_t flushWhenResourceBecamePurgeable = |
462 fPurgeableQueue.peek()->cacheAccess().flushCntWhenResour
ceBecamePurgeable(); | 526 fPurgeableQueue.peek()->cacheAccess().flushCntWhenResour
ceBecamePurgeable(); |
463 if (oldestAllowedFlushCnt < flushWhenResourceBecamePurgeable) { | 527 if (oldestAllowedFlushCnt < flushWhenResourceBecamePurgeable) { |
464 // Resources were given both LRU timestamps and tagged with
a flush cnt when | 528 // Resources were given both LRU timestamps and tagged with
a flush cnt when |
465 // they first became purgeable. The LRU timestamp won't chan
ge again until the | 529 // they first became purgeable. The LRU timestamp won't chan
ge again until the |
466 // resource is made non-purgeable again. So, at this point a
ll the remaining | 530 // resource is made non-purgeable again. So, at this point a
ll the remaining |
467 // resources in the timestamp-sorted queue will have a flush
count >= to this | 531 // resources in the timestamp-sorted queue will have a flush
count >= to this |
468 // one. | 532 // one. |
469 break; | 533 break; |
470 } | 534 } |
471 GrGpuResource* resource = fPurgeableQueue.peek(); | 535 GrGpuResource* resource = fPurgeableQueue.peek(); |
472 SkASSERT(resource->isPurgeable()); | 536 SkASSERT(resource->isPurgeable()); |
| 537 this->recordPurgedKey(resource); |
473 resource->cacheAccess().release(); | 538 resource->cacheAccess().release(); |
474 } | 539 } |
475 } | 540 } |
476 } | 541 } |
477 | 542 |
| 543 if (ReplacementStrategy::kRandom == fStrategy && !fromFlushNotification) { |
| 544 // Wait until after the requested flush when all the pending IO resource
s will be eligible |
| 545 // for the draft. |
| 546 SkASSERT(!this->overBudget() || this->requestsFlush()); |
| 547 fIsPurging = false; |
| 548 return; |
| 549 } |
| 550 |
478 bool stillOverbudget = this->overBudget(); | 551 bool stillOverbudget = this->overBudget(); |
479 while (stillOverbudget && fPurgeableQueue.count()) { | 552 while (stillOverbudget && fPurgeableQueue.count()) { |
480 GrGpuResource* resource = fPurgeableQueue.peek(); | 553 GrGpuResource* resource = this->selectResourceUsingStrategy(); |
481 SkASSERT(resource->isPurgeable()); | 554 SkASSERT(resource->isPurgeable()); |
| 555 this->recordPurgedKey(resource); |
482 resource->cacheAccess().release(); | 556 resource->cacheAccess().release(); |
483 stillOverbudget = this->overBudget(); | 557 stillOverbudget = this->overBudget(); |
484 } | 558 } |
485 | 559 |
486 this->validate(); | 560 this->validate(); |
487 | 561 fIsPurging = false; |
488 if (stillOverbudget) { | |
489 // Set this so that GrDrawingManager will issue a flush to free up resou
rces with pending | |
490 // IO that we were unable to purge in this pass. | |
491 fRequestFlush = true; | |
492 } | |
493 } | 562 } |
494 | 563 |
495 void GrResourceCache::purgeAllUnlocked() { | 564 void GrResourceCache::purgeAllUnlocked() { |
496 // We could disable maintaining the heap property here, but it would add a l
ot of complexity. | 565 // We could disable maintaining the heap property here, but it would add a l
ot of complexity. |
497 // Moreover, this is rarely called. | 566 // Moreover, this is rarely called. |
498 while (fPurgeableQueue.count()) { | 567 while (fPurgeableQueue.count()) { |
499 GrGpuResource* resource = fPurgeableQueue.peek(); | 568 GrGpuResource* resource = fPurgeableQueue.peek(); |
500 SkASSERT(resource->isPurgeable()); | 569 SkASSERT(resource->isPurgeable()); |
501 resource->cacheAccess().release(); | 570 resource->cacheAccess().release(); |
502 } | 571 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
542 // Reset all the timestamps. We sort the resources by timestamp and
then assign | 611 // Reset all the timestamps. We sort the resources by timestamp and
then assign |
543 // sequential timestamps beginning with 0. This is O(n*lg(n)) but it
should be extremely | 612 // sequential timestamps beginning with 0. This is O(n*lg(n)) but it
should be extremely |
544 // rare. | 613 // rare. |
545 SkTDArray<GrGpuResource*> sortedPurgeableResources; | 614 SkTDArray<GrGpuResource*> sortedPurgeableResources; |
546 sortedPurgeableResources.setReserve(fPurgeableQueue.count()); | 615 sortedPurgeableResources.setReserve(fPurgeableQueue.count()); |
547 | 616 |
548 while (fPurgeableQueue.count()) { | 617 while (fPurgeableQueue.count()) { |
549 *sortedPurgeableResources.append() = fPurgeableQueue.peek(); | 618 *sortedPurgeableResources.append() = fPurgeableQueue.peek(); |
550 fPurgeableQueue.pop(); | 619 fPurgeableQueue.pop(); |
551 } | 620 } |
552 | |
553 SkTQSort(fNonpurgeableResources.begin(), fNonpurgeableResources.end(
) - 1, | 621 SkTQSort(fNonpurgeableResources.begin(), fNonpurgeableResources.end(
) - 1, |
554 CompareTimestamp); | 622 CompareTimestamp); |
555 | 623 |
556 // Pick resources out of the purgeable and non-purgeable arrays base
d on lowest | 624 // Pick resources out of the purgeable and non-purgeable arrays base
d on lowest |
557 // timestamp and assign new timestamps. | 625 // timestamp and assign new timestamps. |
558 int currP = 0; | 626 int currP = 0; |
559 int currNP = 0; | 627 int currNP = 0; |
560 while (currP < sortedPurgeableResources.count() && | 628 while (currP < sortedPurgeableResources.count() && |
561 currNP < fNonpurgeableResources.count()) { | 629 currNP < fNonpurgeableResources.count()) { |
562 uint32_t tsP = sortedPurgeableResources[currP]->cacheAccess().ti
mestamp(); | 630 uint32_t tsP = sortedPurgeableResources[currP]->cacheAccess().ti
mestamp(); |
(...skipping 30 matching lines...) Expand all Loading... |
593 } | 661 } |
594 } | 662 } |
595 return fTimestamp++; | 663 return fTimestamp++; |
596 } | 664 } |
597 | 665 |
598 void GrResourceCache::notifyFlushOccurred(FlushType type) { | 666 void GrResourceCache::notifyFlushOccurred(FlushType type) { |
599 switch (type) { | 667 switch (type) { |
600 case FlushType::kImmediateMode: | 668 case FlushType::kImmediateMode: |
601 break; | 669 break; |
602 case FlushType::kCacheRequested: | 670 case FlushType::kCacheRequested: |
603 SkASSERT(fRequestFlush); | |
604 fRequestFlush = false; | |
605 break; | 671 break; |
606 case FlushType::kExternal: | 672 case FlushType::kExternal: { |
| 673 int scoreDelta = 1; |
| 674 if (fMissesThisFlushPurgedRecently) { |
| 675 // If > 60% of our cache misses were things we purged in the las
t two flushes |
| 676 // then we move closer towards selecting random replacement. |
| 677 if ((float)fMissesThisFlushPurgedRecently / fTotalMissesThisFlus
h > 0.6f) { |
| 678 scoreDelta = -1; |
| 679 } |
| 680 } |
| 681 fStrategyScore = SkTPin(fStrategyScore + scoreDelta, kStrategyScoreM
in, |
| 682 kStrategyScoreMax); |
| 683 fStrategy = fStrategyScore < 0 ? ReplacementStrategy::kRandom |
| 684 : ReplacementStrategy::kLRU; |
| 685 fMissesThisFlushPurgedRecently = 0; |
| 686 fTotalMissesThisFlush = 0; |
| 687 fFlushParity = -(fFlushParity - 1); |
| 688 fUniqueKeysPurgedThisFlush[fFlushParity].reset(); |
| 689 fUniqueKeysPurgedThisFlushStorage[fFlushParity]->rewind(); |
607 ++fExternalFlushCnt; | 690 ++fExternalFlushCnt; |
608 if (0 == fExternalFlushCnt) { | 691 if (0 == fExternalFlushCnt) { |
609 // When this wraps just reset all the purgeable resources' last
used flush state. | 692 // When this wraps just reset all the purgeable resources' last
used flush state. |
610 for (int i = 0; i < fPurgeableQueue.count(); ++i) { | 693 for (int i = 0; i < fPurgeableQueue.count(); ++i) { |
611 fPurgeableQueue.at(i)->cacheAccess().setFlushCntWhenResource
BecamePurgeable(0); | 694 fPurgeableQueue.at(i)->cacheAccess().setFlushCntWhenResource
BecamePurgeable(0); |
612 } | 695 } |
613 } | 696 } |
614 break; | 697 break; |
| 698 } |
615 } | 699 } |
616 this->purgeAsNeeded(); | 700 this->internalPurgeAsNeeded(true); |
617 } | 701 } |
618 | 702 |
619 void GrResourceCache::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) c
onst { | 703 void GrResourceCache::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) c
onst { |
620 for (int i = 0; i < fNonpurgeableResources.count(); ++i) { | 704 for (int i = 0; i < fNonpurgeableResources.count(); ++i) { |
621 fNonpurgeableResources[i]->dumpMemoryStatistics(traceMemoryDump); | 705 fNonpurgeableResources[i]->dumpMemoryStatistics(traceMemoryDump); |
622 } | 706 } |
623 for (int i = 0; i < fPurgeableQueue.count(); ++i) { | 707 for (int i = 0; i < fPurgeableQueue.count(); ++i) { |
624 fPurgeableQueue.at(i)->dumpMemoryStatistics(traceMemoryDump); | 708 fPurgeableQueue.at(i)->dumpMemoryStatistics(traceMemoryDump); |
625 } | 709 } |
626 } | 710 } |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
754 return true; | 838 return true; |
755 } | 839 } |
756 if (index < fNonpurgeableResources.count() && fNonpurgeableResources[index]
== resource) { | 840 if (index < fNonpurgeableResources.count() && fNonpurgeableResources[index]
== resource) { |
757 return true; | 841 return true; |
758 } | 842 } |
759 SkDEBUGFAIL("Resource index should be -1 or the resource should be in the ca
che."); | 843 SkDEBUGFAIL("Resource index should be -1 or the resource should be in the ca
che."); |
760 return false; | 844 return false; |
761 } | 845 } |
762 | 846 |
763 #endif | 847 #endif |
OLD | NEW |