Correct accounting for wrapped resources
BUG=skia:2889
Review URL: https://codereview.chromium.org/720033004
diff --git a/src/gpu/GrResourceCache2.cpp b/src/gpu/GrResourceCache2.cpp
index 4593b82..d5590d0 100644
--- a/src/gpu/GrResourceCache2.cpp
+++ b/src/gpu/GrResourceCache2.cpp
@@ -66,9 +66,13 @@
#if GR_CACHE_STATS
, fHighWaterCount(0)
, fHighWaterBytes(0)
+ , fBudgetedHighWaterCount(0)
+ , fBudgetedHighWaterBytes(0)
#endif
, fCount(0)
, fBytes(0)
+ , fBudgetedCount(0)
+ , fBudgetedBytes(0)
, fPurging(false)
, fNewlyPurgableResourceWhilePurging(false)
, fOverBudgetCB(NULL)
@@ -94,12 +98,21 @@
SkASSERT(!fPurging);
fResources.addToHead(resource);
+ size_t size = resource->gpuMemorySize();
++fCount;
fBytes += resource->gpuMemorySize();
#if GR_CACHE_STATS
fHighWaterCount = SkTMax(fCount, fHighWaterCount);
fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes);
#endif
+ if (!resource->cacheAccess().isWrapped()) {
+ ++fBudgetedCount;
+ fBudgetedBytes += size;
+#if GR_CACHE_STATS
+ fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount);
+ fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes);
+#endif
+ }
if (!resource->cacheAccess().getScratchKey().isNullScratch()) {
// TODO(bsalomon): Make this assertion possible.
// SkASSERT(!resource->isWrapped());
@@ -112,10 +125,17 @@
void GrResourceCache2::removeResource(GrGpuResource* resource) {
AutoValidate av(this);
- --fCount;
- fBytes -= resource->gpuMemorySize();
SkASSERT(this->isInCache(resource));
- fResources.remove(resource);
+
+ size_t size = resource->gpuMemorySize();
+ --fCount;
+ fBytes -= size;
+ if (!resource->cacheAccess().isWrapped()) {
+ --fBudgetedCount;
+ fBudgetedBytes -= size;
+ }
+
+ fResources.remove(resource);
if (!resource->cacheAccess().getScratchKey().isNullScratch()) {
fScratchMap.remove(resource->cacheAccess().getScratchKey(), resource);
}
@@ -137,6 +157,9 @@
SkASSERT(!fScratchMap.count());
SkASSERT(!fContentHash.count());
SkASSERT(!fCount);
+ SkASSERT(!fBytes);
+ SkASSERT(!fBudgetedCount);
+ SkASSERT(!fBudgetedBytes);
}
void GrResourceCache2::releaseAll() {
@@ -151,6 +174,9 @@
}
SkASSERT(!fScratchMap.count());
SkASSERT(!fCount);
+ SkASSERT(!fBytes);
+ SkASSERT(!fBudgetedCount);
+ SkASSERT(!fBudgetedBytes);
}
class GrResourceCache2::AvailableForScratchUse {
@@ -236,12 +262,16 @@
}
// Purge the resource if we're over budget
- bool overBudget = fCount > fMaxCount || fBytes > fMaxBytes;
+ bool overBudget = fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes;
// Also purge if the resource has neither a valid scratch key nor a content key.
bool noKey = !resource->cacheAccess().isScratch() &&
(NULL == resource->cacheAccess().getContentKey());
+ // Wrapped resources should never have a key.
+ SkASSERT(noKey || !resource->cacheAccess().isWrapped());
+
+ // And purge if the resource is wrapped
if (overBudget || noKey) {
SkDEBUGCODE(int beforeCount = fCount;)
resource->cacheAccess().release();
@@ -257,10 +287,18 @@
SkASSERT(resource);
SkASSERT(this->isInCache(resource));
- fBytes += resource->gpuMemorySize() - oldSize;
+ ptrdiff_t delta = resource->gpuMemorySize() - oldSize;
+
+ fBytes += delta;
#if GR_CACHE_STATS
fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes);
#endif
+ if (!resource->cacheAccess().isWrapped()) {
+ fBudgetedBytes += delta;
+#if GR_CACHE_STATS
+ fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes);
+#endif
+ }
this->purgeAsNeeded();
this->validate();
@@ -269,7 +307,7 @@
void GrResourceCache2::internalPurgeAsNeeded() {
SkASSERT(!fPurging);
SkASSERT(!fNewlyPurgableResourceWhilePurging);
- SkASSERT(fCount > fMaxCount || fBytes > fMaxBytes);
+ SkASSERT(fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes);
fPurging = true;
@@ -288,7 +326,7 @@
resource->cacheAccess().release();
}
resource = prev;
- if (fCount <= fMaxCount && fBytes <= fMaxBytes) {
+ if (fBudgetedCount <= fMaxCount && fBudgetedBytes <= fMaxBytes) {
overBudget = false;
resource = NULL;
}
@@ -337,6 +375,8 @@
void GrResourceCache2::validate() const {
size_t bytes = 0;
int count = 0;
+ int budgetedCount = 0;
+ size_t budgetedBytes = 0;
int locked = 0;
int scratch = 0;
int couldBeScratch = 0;
@@ -356,30 +396,46 @@
SkASSERT(NULL == resource->cacheAccess().getContentKey());
++scratch;
SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey()));
+ SkASSERT(!resource->cacheAccess().isWrapped());
} else if (!resource->cacheAccess().getScratchKey().isNullScratch()) {
SkASSERT(NULL != resource->cacheAccess().getContentKey());
++couldBeScratch;
SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey()));
+ SkASSERT(!resource->cacheAccess().isWrapped());
}
if (const GrResourceKey* contentKey = resource->cacheAccess().getContentKey()) {
++content;
SkASSERT(fContentHash.find(*contentKey) == resource);
+ SkASSERT(!resource->cacheAccess().isWrapped());
+ }
+
+ if (!resource->cacheAccess().isWrapped()) {
+ ++budgetedCount;
+ budgetedBytes += resource->gpuMemorySize();
}
}
+ SkASSERT(fBudgetedCount <= fCount);
+ SkASSERT(fBudgetedBytes <= fBudgetedBytes);
SkASSERT(bytes == fBytes);
SkASSERT(count == fCount);
+ SkASSERT(budgetedBytes == fBudgetedBytes);
+ SkASSERT(budgetedCount == fBudgetedCount);
#if GR_CACHE_STATS
+ SkASSERT(fBudgetedHighWaterCount <= fHighWaterCount);
+ SkASSERT(fBudgetedHighWaterBytes <= fHighWaterBytes);
SkASSERT(bytes <= fHighWaterBytes);
SkASSERT(count <= fHighWaterCount);
+ SkASSERT(budgetedBytes <= fBudgetedHighWaterBytes);
+ SkASSERT(budgetedCount <= fBudgetedHighWaterCount);
#endif
SkASSERT(content == fContentHash.count());
SkASSERT(scratch + couldBeScratch == fScratchMap.count());
// This assertion is not currently valid because we can be in recursive notifyIsPurgable()
// calls. This will be fixed when subresource registration is explicit.
- // bool overBudget = bytes > fMaxBytes || count > fMaxCount;
+ // bool overBudget = budgetedBytes > fMaxBytes || budgetedCount > fMaxCount;
// SkASSERT(!overBudget || locked == count || fPurging);
}
#endif
@@ -403,14 +459,15 @@
}
}
- float countUtilization = (100.f * fCount) / fMaxCount;
- float byteUtilization = (100.f * fBytes) / fMaxBytes;
+ float countUtilization = (100.f * fBudgetedCount) / fMaxCount;
+ float byteUtilization = (100.f * fBudgetedBytes) / fMaxBytes;
SkDebugf("Budget: %d items %d bytes\n", fMaxCount, fMaxBytes);
- SkDebugf("\t\tEntry Count: current %d (%d locked, %d scratch %.2g%% full), high %d\n",
- fCount, locked, scratch, countUtilization, fHighWaterCount);
- SkDebugf("\t\tEntry Bytes: current %d (%.2g%% full) high %d\n",
- fBytes, byteUtilization, fHighWaterBytes);
+ SkDebugf(
+ "\t\tEntry Count: current %d (%d budgeted, %d locked, %d scratch %.2g%% full), high %d\n",
+ fCount, fBudgetedCount, locked, scratch, countUtilization, fHighWaterCount);
+ SkDebugf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full) high %d\n",
+ fBytes, fBudgetedBytes, byteUtilization, fHighWaterBytes);
}
#endif