Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1184)

Side by Side Diff: src/gpu/GrResourceCache.cpp

Issue 916103006: Handle the case when the GrResourceCache timestamp wraps. (Closed) Base URL: https://skia.googlesource.com/skia.git@sharesb
Patch Set: fix warning Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/GrResourceCache.h ('k') | src/gpu/GrTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2014 Google Inc. 3 * Copyright 2014 Google Inc.
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 9
10 #include "GrResourceCache.h" 10 #include "GrResourceCache.h"
11 #include "GrGpuResourceCacheAccess.h" 11 #include "GrGpuResourceCacheAccess.h"
12 #include "SkChecksum.h" 12 #include "SkChecksum.h"
13 #include "SkGr.h" 13 #include "SkGr.h"
14 #include "SkMessageBus.h" 14 #include "SkMessageBus.h"
15 #include "SkTSort.h"
15 16
16 DECLARE_SKMESSAGEBUS_MESSAGE(GrUniqueKeyInvalidatedMessage); 17 DECLARE_SKMESSAGEBUS_MESSAGE(GrUniqueKeyInvalidatedMessage);
17 18
18 ////////////////////////////////////////////////////////////////////////////// 19 //////////////////////////////////////////////////////////////////////////////
19 20
20 GrScratchKey::ResourceType GrScratchKey::GenerateResourceType() { 21 GrScratchKey::ResourceType GrScratchKey::GenerateResourceType() {
21 static int32_t gType = INHERITED::kInvalidDomain + 1; 22 static int32_t gType = INHERITED::kInvalidDomain + 1;
22 23
23 int32_t type = sk_atomic_inc(&gType); 24 int32_t type = sk_atomic_inc(&gType);
24 if (type > SK_MaxU16) { 25 if (type > SK_MaxU16) {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 fMaxCount = count; 84 fMaxCount = count;
84 fMaxBytes = bytes; 85 fMaxBytes = bytes;
85 this->purgeAsNeeded(); 86 this->purgeAsNeeded();
86 } 87 }
87 88
88 void GrResourceCache::insertResource(GrGpuResource* resource) { 89 void GrResourceCache::insertResource(GrGpuResource* resource) {
89 SkASSERT(resource); 90 SkASSERT(resource);
90 SkASSERT(!this->isInCache(resource)); 91 SkASSERT(!this->isInCache(resource));
91 SkASSERT(!resource->wasDestroyed()); 92 SkASSERT(!resource->wasDestroyed());
92 SkASSERT(!resource->isPurgeable()); 93 SkASSERT(!resource->isPurgeable());
94
95 // We must set the timestamp before adding to the array in case the timestam p wraps and we wind
96 // up iterating over all the resources that already have timestamps.
97 resource->cacheAccess().setTimestamp(this->getNextTimestamp());
98
93 this->addToNonpurgeableArray(resource); 99 this->addToNonpurgeableArray(resource);
94 100
95 size_t size = resource->gpuMemorySize(); 101 size_t size = resource->gpuMemorySize();
96 SkDEBUGCODE(++fCount;) 102 SkDEBUGCODE(++fCount;)
97 fBytes += size; 103 fBytes += size;
98 #if GR_CACHE_STATS 104 #if GR_CACHE_STATS
99 fHighWaterCount = SkTMax(this->getResourceCount(), fHighWaterCount); 105 fHighWaterCount = SkTMax(this->getResourceCount(), fHighWaterCount);
100 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes); 106 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes);
101 #endif 107 #endif
102 if (resource->resourcePriv().isBudgeted()) { 108 if (resource->resourcePriv().isBudgeted()) {
103 ++fBudgetedCount; 109 ++fBudgetedCount;
104 fBudgetedBytes += size; 110 fBudgetedBytes += size;
105 #if GR_CACHE_STATS 111 #if GR_CACHE_STATS
106 fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount ); 112 fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount );
107 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes ); 113 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes );
108 #endif 114 #endif
109 } 115 }
110 if (resource->resourcePriv().getScratchKey().isValid()) { 116 if (resource->resourcePriv().getScratchKey().isValid()) {
111 SkASSERT(!resource->cacheAccess().isWrapped()); 117 SkASSERT(!resource->cacheAccess().isWrapped());
112 fScratchMap.insert(resource->resourcePriv().getScratchKey(), resource); 118 fScratchMap.insert(resource->resourcePriv().getScratchKey(), resource);
113 } 119 }
114 120
115 resource->cacheAccess().setTimestamp(fTimestamp++);
116
117 this->purgeAsNeeded(); 121 this->purgeAsNeeded();
118 } 122 }
119 123
120 void GrResourceCache::removeResource(GrGpuResource* resource) { 124 void GrResourceCache::removeResource(GrGpuResource* resource) {
121 this->validate(); 125 this->validate();
122 SkASSERT(this->isInCache(resource)); 126 SkASSERT(this->isInCache(resource));
123 127
124 if (resource->isPurgeable()) { 128 if (resource->isPurgeable()) {
125 fPurgeableQueue.remove(resource); 129 fPurgeableQueue.remove(resource);
126 } else { 130 } else {
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 } else { 283 } else {
280 resource->cacheAccess().removeUniqueKey(); 284 resource->cacheAccess().removeUniqueKey();
281 } 285 }
282 286
283 this->validate(); 287 this->validate();
284 } 288 }
285 289
286 void GrResourceCache::refAndMakeResourceMRU(GrGpuResource* resource) { 290 void GrResourceCache::refAndMakeResourceMRU(GrGpuResource* resource) {
287 SkASSERT(resource); 291 SkASSERT(resource);
288 SkASSERT(this->isInCache(resource)); 292 SkASSERT(this->isInCache(resource));
293
289 if (resource->isPurgeable()) { 294 if (resource->isPurgeable()) {
290 // It's about to become unpurgeable. 295 // It's about to become unpurgeable.
291 fPurgeableQueue.remove(resource); 296 fPurgeableQueue.remove(resource);
292 this->addToNonpurgeableArray(resource); 297 this->addToNonpurgeableArray(resource);
293 } 298 }
294 resource->ref(); 299 resource->ref();
295 resource->cacheAccess().setTimestamp(fTimestamp++); 300
301 resource->cacheAccess().setTimestamp(this->getNextTimestamp());
296 this->validate(); 302 this->validate();
297 } 303 }
298 304
299 void GrResourceCache::notifyPurgeable(GrGpuResource* resource) { 305 void GrResourceCache::notifyPurgeable(GrGpuResource* resource) {
300 SkASSERT(resource); 306 SkASSERT(resource);
301 SkASSERT(this->isInCache(resource)); 307 SkASSERT(this->isInCache(resource));
302 SkASSERT(resource->isPurgeable()); 308 SkASSERT(resource->isPurgeable());
303 309
304 this->removeFromNonpurgeableArray(resource); 310 this->removeFromNonpurgeableArray(resource);
305 fPurgeableQueue.insert(resource); 311 fPurgeableQueue.insert(resource);
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
434 // Fill the whole we will create in the array with the tail object, adjust i ts index, and 440 // Fill the whole we will create in the array with the tail object, adjust i ts index, and
435 // then pop the array 441 // then pop the array
436 GrGpuResource* tail = *(fNonpurgeableResources.end() - 1); 442 GrGpuResource* tail = *(fNonpurgeableResources.end() - 1);
437 SkASSERT(fNonpurgeableResources[*index] == resource); 443 SkASSERT(fNonpurgeableResources[*index] == resource);
438 fNonpurgeableResources[*index] = tail; 444 fNonpurgeableResources[*index] = tail;
439 *tail->cacheAccess().accessCacheIndex() = *index; 445 *tail->cacheAccess().accessCacheIndex() = *index;
440 fNonpurgeableResources.pop(); 446 fNonpurgeableResources.pop();
441 SkDEBUGCODE(*index = -1); 447 SkDEBUGCODE(*index = -1);
442 } 448 }
443 449
450 uint32_t GrResourceCache::getNextTimestamp() {
451 // If we wrap then all the existing resources will appear older than any res ources that get
452 // a timestamp after the wrap.
453 if (0 == fTimestamp) {
454 int count = this->getResourceCount();
455 if (count) {
456 // Reset all the timestamps. We sort the resources by timestamp and then assign
457 // sequential timestamps beginning with 0. This is O(n*lg(n)) but it should be extremely
458 // rare.
459 SkTDArray<GrGpuResource*> sortedPurgeableResources;
460 sortedPurgeableResources.setReserve(fPurgeableQueue.count());
461
462 while (fPurgeableQueue.count()) {
463 *sortedPurgeableResources.append() = fPurgeableQueue.peek();
464 fPurgeableQueue.pop();
465 }
466
467 struct Less {
468 bool operator()(GrGpuResource* a, GrGpuResource* b) {
469 return CompareTimestamp(a,b);
470 }
471 };
472 Less less;
473 SkTQSort(fNonpurgeableResources.begin(), fNonpurgeableResources.end( ) - 1, less);
474
475 // Pick resources out of the purgeable and non-purgeable arrays base d on lowest
476 // timestamp and assign new timestamps.
477 int currP = 0;
478 int currNP = 0;
479 while (currP < sortedPurgeableResources.count() &&
480 currNP < fNonpurgeableResources.count()) {
481 uint32_t tsP = sortedPurgeableResources[currP]->cacheAccess().ti mestamp();
482 uint32_t tsNP = fNonpurgeableResources[currNP]->cacheAccess().ti mestamp();
483 SkASSERT(tsP != tsNP);
484 if (tsP < tsNP) {
485 sortedPurgeableResources[currP++]->cacheAccess().setTimestam p(fTimestamp++);
486 } else {
487 // Correct the index in the nonpurgeable array stored on the resource post-sort.
488 *fNonpurgeableResources[currNP]->cacheAccess().accessCacheIn dex() = currNP;
489 fNonpurgeableResources[currNP++]->cacheAccess().setTimestamp (fTimestamp++);
490 }
491 }
492
493 // The above loop ended when we hit the end of one array. Finish the other one.
494 while (currP < sortedPurgeableResources.count()) {
495 sortedPurgeableResources[currP++]->cacheAccess().setTimestamp(fT imestamp++);
496 }
497 while (currNP < fNonpurgeableResources.count()) {
498 *fNonpurgeableResources[currNP]->cacheAccess().accessCacheIndex( ) = currNP;
499 fNonpurgeableResources[currNP++]->cacheAccess().setTimestamp(fTi mestamp++);
500 }
501
502 // Rebuild the queue.
503 for (int i = 0; i < sortedPurgeableResources.count(); ++i) {
504 fPurgeableQueue.insert(sortedPurgeableResources[i]);
505 }
506
507 this->validate();
508 SkASSERT(count == this->getResourceCount());
509
510 // count should be the next timestamp we return.
511 SkASSERT(fTimestamp == SkToU32(count));
512 }
513 }
514 return fTimestamp++;
515 }
516
444 #ifdef SK_DEBUG 517 #ifdef SK_DEBUG
445 void GrResourceCache::validate() const { 518 void GrResourceCache::validate() const {
446 // Reduce the frequency of validations for large resource counts. 519 // Reduce the frequency of validations for large resource counts.
447 static SkRandom gRandom; 520 static SkRandom gRandom;
448 int mask = (SkNextPow2(fCount + 1) >> 5) - 1; 521 int mask = (SkNextPow2(fCount + 1) >> 5) - 1;
449 if (~mask && (gRandom.nextU() & mask)) { 522 if (~mask && (gRandom.nextU() & mask)) {
450 return; 523 return;
451 } 524 }
452 525
453 struct Stats { 526 struct Stats {
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 return true; 621 return true;
549 } 622 }
550 if (index < fNonpurgeableResources.count() && fNonpurgeableResources[index] == resource) { 623 if (index < fNonpurgeableResources.count() && fNonpurgeableResources[index] == resource) {
551 return true; 624 return true;
552 } 625 }
553 SkDEBUGFAIL("Resource index should be -1 or the resource should be in the ca che."); 626 SkDEBUGFAIL("Resource index should be -1 or the resource should be in the ca che.");
554 return false; 627 return false;
555 } 628 }
556 629
557 #endif 630 #endif
OLDNEW
« no previous file with comments | « src/gpu/GrResourceCache.h ('k') | src/gpu/GrTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698