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 |