Chromium Code Reviews| 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::kInitialStrategyScoreMax; | |
| 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) | |
|
robertphillips
2016/09/13 13:05:21
Should kInitialStrategyScoreMax just be kInitialSt
bsalomon
2016/09/13 13:31:32
Ha, yes.
| |
| 70 , fStrategyScore(kInitialStrategyScoreMax) | |
| 71 , fTotalMissesThisFlush(0) | |
| 72 , fMissesThisFlushPurgedRecently(0) | |
| 73 , fUniqueKeysPurgedThisFlushStorage {{8*sizeof(GrUniqueKey)}, {8*sizeof(GrUn iqueKey)}} | |
| 74 , fFlushParity(0) | |
| 67 #if GR_CACHE_STATS | 75 #if GR_CACHE_STATS |
| 68 , fHighWaterCount(0) | 76 , fHighWaterCount(0) |
| 69 , fHighWaterBytes(0) | 77 , fHighWaterBytes(0) |
| 70 , fBudgetedHighWaterCount(0) | 78 , fBudgetedHighWaterCount(0) |
| 71 , fBudgetedHighWaterBytes(0) | 79 , fBudgetedHighWaterBytes(0) |
| 72 #endif | 80 #endif |
| 73 , fBytes(0) | 81 , fBytes(0) |
| 74 , fBudgetedCount(0) | 82 , fBudgetedCount(0) |
| 75 , fBudgetedBytes(0) | 83 , fBudgetedBytes(0) |
| 76 , fRequestFlush(false) | |
| 77 , fFlushTimestamps(nullptr) | 84 , fFlushTimestamps(nullptr) |
| 78 , fLastFlushTimestampIndex(0) | 85 , fLastFlushTimestampIndex(0) |
| 79 , fPreferVRAMUseOverFlushes(caps->preferVRAMUseOverFlushes()) { | 86 , fPreferVRAMUseOverFlushes(caps->preferVRAMUseOverFlushes()) { |
| 80 SkDEBUGCODE(fCount = 0;) | 87 SkDEBUGCODE(fCount = 0;) |
| 81 SkDEBUGCODE(fNewlyPurgeableResourceForValidation = nullptr;) | 88 SkDEBUGCODE(fNewlyPurgeableResourceForValidation = nullptr;) |
| 82 this->resetFlushTimestamps(); | 89 this->resetFlushTimestamps(); |
| 83 } | 90 } |
| 84 | 91 |
| 85 GrResourceCache::~GrResourceCache() { | 92 GrResourceCache::~GrResourceCache() { |
| 86 this->releaseAll(); | 93 this->releaseAll(); |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 246 return !fRejectPendingIO || !resource->internalHasPendingIO(); | 253 return !fRejectPendingIO || !resource->internalHasPendingIO(); |
| 247 } | 254 } |
| 248 | 255 |
| 249 private: | 256 private: |
| 250 bool fRejectPendingIO; | 257 bool fRejectPendingIO; |
| 251 }; | 258 }; |
| 252 | 259 |
| 253 GrGpuResource* GrResourceCache::findAndRefScratchResource(const GrScratchKey& sc ratchKey, | 260 GrGpuResource* GrResourceCache::findAndRefScratchResource(const GrScratchKey& sc ratchKey, |
| 254 size_t resourceSize, | 261 size_t resourceSize, |
| 255 uint32_t flags) { | 262 uint32_t flags) { |
| 263 // We don't currently track misses for scratch resources for selecting the r eplacement policy. | |
| 264 // The reason is that it is common to look for a scratch resource before cre ating a texture | |
| 265 // that will immediately become uniquely keyed. | |
| 256 SkASSERT(scratchKey.isValid()); | 266 SkASSERT(scratchKey.isValid()); |
| 257 | |
| 258 GrGpuResource* resource; | 267 GrGpuResource* resource; |
| 259 if (flags & (kPreferNoPendingIO_ScratchFlag | kRequireNoPendingIO_ScratchFla g)) { | 268 if (flags & (kPreferNoPendingIO_ScratchFlag | kRequireNoPendingIO_ScratchFla g)) { |
| 260 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(true)); | 269 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(true)); |
| 261 if (resource) { | 270 if (resource) { |
| 262 this->refAndMakeResourceMRU(resource); | 271 this->refAndMakeResourceMRU(resource); |
| 263 this->validate(); | 272 this->validate(); |
| 264 return resource; | 273 return resource; |
| 265 } else if (flags & kRequireNoPendingIO_ScratchFlag) { | 274 } else if (flags & kRequireNoPendingIO_ScratchFlag) { |
| 266 return nullptr; | 275 return nullptr; |
| 267 } | 276 } |
| 268 // We would prefer to consume more available VRAM rather than flushing | 277 // We would prefer to consume more available VRAM rather than flushing |
| 269 // immediately, but on ANGLE this can lead to starving of the GPU. | 278 // immediately, but on ANGLE this can lead to starving of the GPU. |
| 270 if (fPreferVRAMUseOverFlushes && this->wouldFit(resourceSize)) { | 279 if (fPreferVRAMUseOverFlushes && this->wouldFit(resourceSize)) { |
| 271 // kPrefer is specified, we didn't find a resource without pending i o, | 280 // kPrefer is specified, we didn't find a resource without pending i o, |
| 272 // but there is still space in our budget for the resource so force | 281 // but there is still space in our budget for the resource so force |
| 273 // the caller to allocate a new resource. | 282 // the caller to allocate a new resource. |
| 274 return nullptr; | 283 return nullptr; |
| 275 } | 284 } |
| 276 } | 285 } |
| 277 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(false)); | 286 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(false)); |
| 278 if (resource) { | 287 if (resource) { |
| 279 this->refAndMakeResourceMRU(resource); | 288 this->refAndMakeResourceMRU(resource); |
| 280 this->validate(); | 289 this->validate(); |
| 281 } | 290 } |
| 282 return resource; | 291 return resource; |
| 283 } | 292 } |
| 284 | 293 |
| 294 GrGpuResource* GrResourceCache::findAndRefUniqueResource(const GrUniqueKey& key) { | |
| 295 GrGpuResource* resource = fUniqueHash.find(key); | |
| 296 if (resource) { | |
| 297 this->refAndMakeResourceMRU(resource); | |
| 298 } else { | |
| 299 this->recordKeyMiss(key); | |
| 300 } | |
| 301 return resource; | |
| 302 } | |
| 303 | |
| 304 void GrResourceCache::recordKeyMiss(const GrUniqueKey& key) { | |
| 305 // If a resource with this key was purged either this flush or the previous flush, consider it | |
| 306 // a recent purge. | |
| 307 if (fUniqueKeysPurgedThisFlush[0].find(key) || fUniqueKeysPurgedThisFlush[1] .find(key)) { | |
| 308 ++fMissesThisFlushPurgedRecently; | |
| 309 } | |
| 310 ++fTotalMissesThisFlush; | |
| 311 } | |
| 312 | |
| 285 void GrResourceCache::willRemoveScratchKey(const GrGpuResource* resource) { | 313 void GrResourceCache::willRemoveScratchKey(const GrGpuResource* resource) { |
| 286 SkASSERT(resource->resourcePriv().getScratchKey().isValid()); | 314 SkASSERT(resource->resourcePriv().getScratchKey().isValid()); |
| 287 if (!resource->getUniqueKey().isValid()) { | 315 if (!resource->getUniqueKey().isValid()) { |
| 288 fScratchMap.remove(resource->resourcePriv().getScratchKey(), resource); | 316 fScratchMap.remove(resource->resourcePriv().getScratchKey(), resource); |
| 289 } | 317 } |
| 290 } | 318 } |
| 291 | 319 |
| 292 void GrResourceCache::removeUniqueKey(GrGpuResource* resource) { | 320 void GrResourceCache::removeUniqueKey(GrGpuResource* resource) { |
| 293 // Someone has a ref to this resource in order to have removed the key. When the ref count | 321 // Someone has a ref to this resource in order to have removed the key. When the ref count |
| 294 // reaches zero we will get a ref cnt notification and figure out what to do with it. | 322 // reaches zero we will get a ref cnt notification and figure out what to do with it. |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 398 // We won't purge an existing resource to make room for this one. | 426 // We won't purge an existing resource to make room for this one. |
| 399 if (fBudgetedCount < fMaxCount && | 427 if (fBudgetedCount < fMaxCount && |
| 400 fBudgetedBytes + resource->gpuMemorySize() <= fMaxBytes) { | 428 fBudgetedBytes + resource->gpuMemorySize() <= fMaxBytes) { |
| 401 resource->resourcePriv().makeBudgeted(); | 429 resource->resourcePriv().makeBudgeted(); |
| 402 return; | 430 return; |
| 403 } | 431 } |
| 404 } | 432 } |
| 405 } else { | 433 } else { |
| 406 // Purge the resource immediately if we're over budget | 434 // Purge the resource immediately if we're over budget |
| 407 // Also purge if the resource has neither a valid scratch key nor a uniq ue key. | 435 // Also purge if the resource has neither a valid scratch key nor a uniq ue key. |
| 408 bool noKey = !resource->resourcePriv().getScratchKey().isValid() && | 436 bool hasKey = resource->resourcePriv().getScratchKey().isValid() || |
| 409 !resource->getUniqueKey().isValid(); | 437 resource->getUniqueKey().isValid(); |
| 410 if (!this->overBudget() && !noKey) { | 438 if (hasKey) { |
| 439 if (this->overBudget()) { | |
| 440 this->purgeAsNeeded(); | |
| 441 } | |
| 411 return; | 442 return; |
| 412 } | 443 } |
| 413 } | 444 } |
| 414 | 445 |
| 415 SkDEBUGCODE(int beforeCount = this->getResourceCount();) | 446 SkDEBUGCODE(int beforeCount = this->getResourceCount();) |
| 416 resource->cacheAccess().release(); | 447 resource->cacheAccess().release(); |
| 417 // We should at least free this resource, perhaps dependent resources as wel l. | 448 // We should at least free this resource, perhaps dependent resources as wel l. |
| 418 SkASSERT(this->getResourceCount() < beforeCount); | 449 SkASSERT(this->getResourceCount() < beforeCount); |
| 419 this->validate(); | 450 this->validate(); |
| 420 } | 451 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 460 } else { | 491 } else { |
| 461 --fBudgetedCount; | 492 --fBudgetedCount; |
| 462 fBudgetedBytes -= size; | 493 fBudgetedBytes -= size; |
| 463 } | 494 } |
| 464 TRACE_COUNTER2(TRACE_DISABLED_BY_DEFAULT("skia.gpu.cache"), "skia budget", " used", | 495 TRACE_COUNTER2(TRACE_DISABLED_BY_DEFAULT("skia.gpu.cache"), "skia budget", " used", |
| 465 fBudgetedBytes, "free", fMaxBytes - fBudgetedBytes); | 496 fBudgetedBytes, "free", fMaxBytes - fBudgetedBytes); |
| 466 | 497 |
| 467 this->validate(); | 498 this->validate(); |
| 468 } | 499 } |
| 469 | 500 |
| 470 void GrResourceCache::purgeAsNeeded() { | 501 void GrResourceCache::recordPurgedKey(GrGpuResource* resource) { |
| 502 // This maximum exists to avoid allocating too much space for key tracking. | |
| 503 static constexpr int kMaxTrackedKeys = 256; | |
| 504 if (fUniqueKeysPurgedThisFlush[fFlushParity].count() >= kMaxTrackedKeys) { | |
| 505 return; | |
| 506 } | |
| 507 if (resource->getUniqueKey().isValid() && | |
| 508 !fUniqueKeysPurgedThisFlush[fFlushParity].find(resource->getUniqueKey()) ) { | |
| 509 void* p = fUniqueKeysPurgedThisFlushStorage[fFlushParity].allocThrow(siz eof(GrUniqueKey)); | |
| 510 GrUniqueKey* copy = new (p) GrUniqueKey; | |
| 511 *copy = resource->getUniqueKey(); | |
| 512 fUniqueKeysPurgedThisFlush[fFlushParity].add(copy); | |
| 513 } | |
| 514 } | |
| 515 | |
|
robertphillips
2016/09/13 13:05:21
I wonder if it would be better to use function poi
bsalomon
2016/09/13 13:31:33
We're about to perform a fairly heavy operation, s
robertphillips
2016/09/13 13:56:48
A bit of both but it is certainly fine as is.
| |
| 516 GrGpuResource* GrResourceCache::selectResourceUsingStrategy() { | |
| 517 switch (fStrategy) { | |
| 518 case ReplacementStrategy::kLRU: | |
| 519 return fPurgeableQueue.peek(); | |
| 520 case ReplacementStrategy::kRandom: | |
| 521 return fPurgeableQueue.at(fRandom.nextULessThan(fPurgeableQueue.coun t())); | |
| 522 } | |
| 523 return nullptr; | |
| 524 } | |
| 525 | |
| 526 void GrResourceCache::internalPurgeAsNeeded(bool fromFlushNotification) { | |
| 471 SkTArray<GrUniqueKeyInvalidatedMessage> invalidKeyMsgs; | 527 SkTArray<GrUniqueKeyInvalidatedMessage> invalidKeyMsgs; |
| 472 fInvalidUniqueKeyInbox.poll(&invalidKeyMsgs); | 528 fInvalidUniqueKeyInbox.poll(&invalidKeyMsgs); |
| 473 if (invalidKeyMsgs.count()) { | 529 if (invalidKeyMsgs.count()) { |
| 474 this->processInvalidUniqueKeys(invalidKeyMsgs); | 530 this->processInvalidUniqueKeys(invalidKeyMsgs); |
| 475 } | 531 } |
| 476 | 532 |
| 477 if (fFlushTimestamps) { | 533 if (fFlushTimestamps) { |
| 478 // Assuming kNumFlushesToDeleteUnusedResource is a power of 2. | 534 // Assuming kNumFlushesToDeleteUnusedResource is a power of 2. |
| 479 SkASSERT(SkIsPow2(fMaxUnusedFlushes)); | 535 SkASSERT(SkIsPow2(fMaxUnusedFlushes)); |
| 480 int oldestFlushIndex = (fLastFlushTimestampIndex + 1) & (fMaxUnusedFlush es - 1); | 536 int oldestFlushIndex = (fLastFlushTimestampIndex + 1) & (fMaxUnusedFlush es - 1); |
| 481 | 537 |
| 482 uint32_t oldestAllowedTimestamp = fFlushTimestamps[oldestFlushIndex]; | 538 uint32_t oldestAllowedTimestamp = fFlushTimestamps[oldestFlushIndex]; |
| 483 while (fPurgeableQueue.count()) { | 539 while (fPurgeableQueue.count()) { |
| 484 uint32_t oldestResourceTimestamp = fPurgeableQueue.peek()->cacheAcce ss().timestamp(); | 540 uint32_t oldestResourceTimestamp = fPurgeableQueue.peek()->cacheAcce ss().timestamp(); |
| 485 if (oldestAllowedTimestamp < oldestResourceTimestamp) { | 541 if (oldestAllowedTimestamp < oldestResourceTimestamp) { |
| 486 break; | 542 break; |
| 487 } | 543 } |
| 488 GrGpuResource* resource = fPurgeableQueue.peek(); | 544 GrGpuResource* resource = fPurgeableQueue.peek(); |
| 489 SkASSERT(resource->isPurgeable()); | 545 SkASSERT(resource->isPurgeable()); |
| 546 this->recordPurgedKey(resource); | |
| 490 resource->cacheAccess().release(); | 547 resource->cacheAccess().release(); |
| 491 } | 548 } |
| 492 } | 549 } |
| 550 if (ReplacementStrategy::kRandom == fStrategy && !fromFlushNotification) { | |
| 551 // Wait until after the requested flush when all the pending IO resource s will be eligible | |
| 552 // for the draft. | |
| 553 SkASSERT(!this->overBudget() || this->requestsFlush()); | |
| 554 return; | |
| 555 } | |
| 493 | 556 |
| 494 bool stillOverbudget = this->overBudget(); | 557 bool stillOverbudget = this->overBudget(); |
| 495 while (stillOverbudget && fPurgeableQueue.count()) { | 558 while (stillOverbudget && fPurgeableQueue.count()) { |
| 496 GrGpuResource* resource = fPurgeableQueue.peek(); | 559 GrGpuResource* resource = this->selectResourceUsingStrategy(); |
| 497 SkASSERT(resource->isPurgeable()); | 560 SkASSERT(resource->isPurgeable()); |
| 561 this->recordPurgedKey(resource); | |
| 498 resource->cacheAccess().release(); | 562 resource->cacheAccess().release(); |
| 499 stillOverbudget = this->overBudget(); | 563 stillOverbudget = this->overBudget(); |
| 500 } | 564 } |
| 501 | 565 |
| 502 this->validate(); | 566 this->validate(); |
| 503 | |
| 504 if (stillOverbudget) { | |
| 505 // Set this so that GrDrawingManager will issue a flush to free up resou rces with pending | |
| 506 // IO that we were unable to purge in this pass. | |
| 507 fRequestFlush = true; | |
| 508 } | |
| 509 } | 567 } |
| 510 | 568 |
| 511 void GrResourceCache::purgeAllUnlocked() { | 569 void GrResourceCache::purgeAllUnlocked() { |
| 512 // We could disable maintaining the heap property here, but it would add a l ot of complexity. | 570 // We could disable maintaining the heap property here, but it would add a l ot of complexity. |
| 513 // Moreover, this is rarely called. | 571 // Moreover, this is rarely called. |
| 514 while (fPurgeableQueue.count()) { | 572 while (fPurgeableQueue.count()) { |
| 515 GrGpuResource* resource = fPurgeableQueue.peek(); | 573 GrGpuResource* resource = fPurgeableQueue.peek(); |
| 516 SkASSERT(resource->isPurgeable()); | 574 SkASSERT(resource->isPurgeable()); |
| 517 resource->cacheAccess().release(); | 575 resource->cacheAccess().release(); |
| 518 } | 576 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 558 // Reset all the timestamps. We sort the resources by timestamp and then assign | 616 // Reset all the timestamps. We sort the resources by timestamp and then assign |
| 559 // sequential timestamps beginning with 0. This is O(n*lg(n)) but it should be extremely | 617 // sequential timestamps beginning with 0. This is O(n*lg(n)) but it should be extremely |
| 560 // rare. | 618 // rare. |
| 561 SkTDArray<GrGpuResource*> sortedPurgeableResources; | 619 SkTDArray<GrGpuResource*> sortedPurgeableResources; |
| 562 sortedPurgeableResources.setReserve(fPurgeableQueue.count()); | 620 sortedPurgeableResources.setReserve(fPurgeableQueue.count()); |
| 563 | 621 |
| 564 while (fPurgeableQueue.count()) { | 622 while (fPurgeableQueue.count()) { |
| 565 *sortedPurgeableResources.append() = fPurgeableQueue.peek(); | 623 *sortedPurgeableResources.append() = fPurgeableQueue.peek(); |
| 566 fPurgeableQueue.pop(); | 624 fPurgeableQueue.pop(); |
| 567 } | 625 } |
| 568 | 626 SkTQSort(fNonpurgeableResources.begin(), fNonpurgeableResources.end( ) - 1, |
| 569 struct Less { | 627 CompareTimestamp); |
| 570 bool operator()(GrGpuResource* a, GrGpuResource* b) { | |
| 571 return CompareTimestamp(a,b); | |
| 572 } | |
| 573 }; | |
| 574 Less less; | |
| 575 SkTQSort(fNonpurgeableResources.begin(), fNonpurgeableResources.end( ) - 1, less); | |
| 576 | 628 |
| 577 // Pick resources out of the purgeable and non-purgeable arrays base d on lowest | 629 // Pick resources out of the purgeable and non-purgeable arrays base d on lowest |
| 578 // timestamp and assign new timestamps. | 630 // timestamp and assign new timestamps. |
| 579 int currP = 0; | 631 int currP = 0; |
| 580 int currNP = 0; | 632 int currNP = 0; |
| 581 while (currP < sortedPurgeableResources.count() && | 633 while (currP < sortedPurgeableResources.count() && |
| 582 currNP < fNonpurgeableResources.count()) { | 634 currNP < fNonpurgeableResources.count()) { |
| 583 uint32_t tsP = sortedPurgeableResources[currP]->cacheAccess().ti mestamp(); | 635 uint32_t tsP = sortedPurgeableResources[currP]->cacheAccess().ti mestamp(); |
| 584 uint32_t tsNP = fNonpurgeableResources[currNP]->cacheAccess().ti mestamp(); | 636 uint32_t tsNP = fNonpurgeableResources[currNP]->cacheAccess().ti mestamp(); |
| 585 SkASSERT(tsP != tsNP); | 637 SkASSERT(tsP != tsNP); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 617 } | 669 } |
| 618 } | 670 } |
| 619 return fTimestamp++; | 671 return fTimestamp++; |
| 620 } | 672 } |
| 621 | 673 |
| 622 void GrResourceCache::notifyFlushOccurred(FlushType type) { | 674 void GrResourceCache::notifyFlushOccurred(FlushType type) { |
| 623 switch (type) { | 675 switch (type) { |
| 624 case FlushType::kImmediateMode: | 676 case FlushType::kImmediateMode: |
| 625 break; | 677 break; |
| 626 case FlushType::kCacheRequested: | 678 case FlushType::kCacheRequested: |
| 627 SkASSERT(fRequestFlush); | |
| 628 fRequestFlush = false; | |
| 629 break; | 679 break; |
| 630 case FlushType::kExternal: | 680 case FlushType::kExternal: { |
| 681 int scoreDelta = 1; | |
| 682 if (fMissesThisFlushPurgedRecently) { | |
| 683 // If > 60% of our cache misses were things we purged in the las t two flushes | |
| 684 // then we move closer towards selecting random replacement. | |
| 685 if ((float)fMissesThisFlushPurgedRecently / fTotalMissesThisFlus h > 0.6f) { | |
| 686 scoreDelta = -1; | |
| 687 } | |
| 688 } | |
| 689 fStrategyScore = SkTPin(fStrategyScore + scoreDelta, kStrategyScoreM in, | |
| 690 kStrategyScoreMax); | |
| 691 fStrategy = fStrategyScore < 0 ? ReplacementStrategy::kRandom | |
| 692 : ReplacementStrategy::kLRU; | |
| 693 fMissesThisFlushPurgedRecently = 0; | |
| 694 fTotalMissesThisFlush = 0; | |
| 695 fFlushParity = -(fFlushParity - 1); | |
| 696 fUniqueKeysPurgedThisFlush[fFlushParity].reset(); | |
| 697 fUniqueKeysPurgedThisFlushStorage[fFlushParity].rewind(); | |
| 631 if (fFlushTimestamps) { | 698 if (fFlushTimestamps) { |
| 632 SkASSERT(SkIsPow2(fMaxUnusedFlushes)); | 699 SkASSERT(SkIsPow2(fMaxUnusedFlushes)); |
| 633 fLastFlushTimestampIndex = (fLastFlushTimestampIndex + 1) & (fMa xUnusedFlushes - 1); | 700 fLastFlushTimestampIndex = (fLastFlushTimestampIndex + 1) & (fMa xUnusedFlushes - 1); |
| 634 // get the timestamp before accessing fFlushTimestamps because g etNextTimestamp will | 701 // get the timestamp before accessing fFlushTimestamps because g etNextTimestamp will |
| 635 // reallocate fFlushTimestamps on timestamp overflow. | 702 // reallocate fFlushTimestamps on timestamp overflow. |
| 636 uint32_t timestamp = this->getNextTimestamp(); | 703 uint32_t timestamp = this->getNextTimestamp(); |
| 637 fFlushTimestamps[fLastFlushTimestampIndex] = timestamp; | 704 fFlushTimestamps[fLastFlushTimestampIndex] = timestamp; |
| 638 } | 705 } |
| 639 break; | 706 break; |
| 707 } | |
| 640 } | 708 } |
| 641 this->purgeAsNeeded(); | 709 this->internalPurgeAsNeeded(true); |
| 642 } | 710 } |
| 643 | 711 |
| 644 void GrResourceCache::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) c onst { | 712 void GrResourceCache::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) c onst { |
| 645 for (int i = 0; i < fNonpurgeableResources.count(); ++i) { | 713 for (int i = 0; i < fNonpurgeableResources.count(); ++i) { |
| 646 fNonpurgeableResources[i]->dumpMemoryStatistics(traceMemoryDump); | 714 fNonpurgeableResources[i]->dumpMemoryStatistics(traceMemoryDump); |
| 647 } | 715 } |
| 648 for (int i = 0; i < fPurgeableQueue.count(); ++i) { | 716 for (int i = 0; i < fPurgeableQueue.count(); ++i) { |
| 649 fPurgeableQueue.at(i)->dumpMemoryStatistics(traceMemoryDump); | 717 fPurgeableQueue.at(i)->dumpMemoryStatistics(traceMemoryDump); |
| 650 } | 718 } |
| 651 } | 719 } |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 779 return true; | 847 return true; |
| 780 } | 848 } |
| 781 if (index < fNonpurgeableResources.count() && fNonpurgeableResources[index] == resource) { | 849 if (index < fNonpurgeableResources.count() && fNonpurgeableResources[index] == resource) { |
| 782 return true; | 850 return true; |
| 783 } | 851 } |
| 784 SkDEBUGFAIL("Resource index should be -1 or the resource should be in the ca che."); | 852 SkDEBUGFAIL("Resource index should be -1 or the resource should be in the ca che."); |
| 785 return false; | 853 return false; |
| 786 } | 854 } |
| 787 | 855 |
| 788 #endif | 856 #endif |
| OLD | NEW |