From ee47914ae5661043c20754f46523665a6d31bc73 Mon Sep 17 00:00:00 2001 From: Derek Sollenberger Date: Wed, 24 May 2017 11:41:33 -0400 Subject: [PATCH] Add GrContext API to report the number of purgeable bytes in the cache. Change-Id: I1457eec9831736f386e3b3b80d9eac8dbb337a9b Reviewed-on: https://skia-review.googlesource.com/17829 Reviewed-by: Brian Salomon Commit-Queue: Derek Sollenberger --- include/gpu/GrContext.h | 5 +++++ src/gpu/GrContext.cpp | 5 +++++ src/gpu/GrResourceCache.cpp | 11 ++++++++++- src/gpu/GrResourceCache.h | 6 ++++++ tests/ResourceCacheTest.cpp | 22 ++++++++++++++++++++++ 5 files changed, 48 insertions(+), 1 deletion(-) diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h index ec07e96..5bd9574 100644 --- a/include/gpu/GrContext.h +++ b/include/gpu/GrContext.h @@ -138,6 +138,11 @@ public: void getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const; /** + * Gets the number of bytes in the cache consumed by purgeable (e.g. unlocked) resources. + */ + size_t getResourceCachePurgeableBytes() const; + + /** * Specify the GPU resource cache limits. If the current cache exceeds either * of these, it will be purged (LRU) to keep the cache within these limits. * diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 1455800..e7aff35 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -215,6 +215,11 @@ void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) } } +size_t GrContext::getResourceCachePurgeableBytes() const { + ASSERT_SINGLE_OWNER + return fResourceCache->getPurgeableBytes(); +} + //////////////////////////////////////////////////////////////////////////////// void GrContext::TextBlobCacheOverBudgetCB(void* data) { diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp index 299f63f..53a62c0 100644 --- a/src/gpu/GrResourceCache.cpp +++ b/src/gpu/GrResourceCache.cpp @@ -75,6 +75,7 @@ GrResourceCache::GrResourceCache(const GrCaps* caps, uint32_t contextUniqueID) , fBytes(0) , fBudgetedCount(0) , fBudgetedBytes(0) + , fPurgeableBytes(0) , fRequestFlush(false) , fExternalFlushCnt(0) , fContextUniqueID(contextUniqueID) @@ -136,13 +137,14 @@ void GrResourceCache::removeResource(GrGpuResource* resource) { this->validate(); SkASSERT(this->isInCache(resource)); + size_t size = resource->gpuMemorySize(); if (resource->isPurgeable()) { fPurgeableQueue.remove(resource); + fPurgeableBytes -= size; } else { this->removeFromNonpurgeableArray(resource); } - size_t size = resource->gpuMemorySize(); SkDEBUGCODE(--fCount;) fBytes -= size; if (SkBudgeted::kYes == resource->resourcePriv().isBudgeted()) { @@ -184,6 +186,7 @@ void GrResourceCache::abandonAll() { SkASSERT(!fBytes); SkASSERT(!fBudgetedCount); SkASSERT(!fBudgetedBytes); + SkASSERT(!fPurgeableBytes); } void GrResourceCache::releaseAll() { @@ -210,6 +213,7 @@ void GrResourceCache::releaseAll() { SkASSERT(!fBytes); SkASSERT(!fBudgetedCount); SkASSERT(!fBudgetedBytes); + SkASSERT(!fPurgeableBytes); } class GrResourceCache::AvailableForScratchUse { @@ -330,6 +334,7 @@ void GrResourceCache::refAndMakeResourceMRU(GrGpuResource* resource) { if (resource->isPurgeable()) { // It's about to become unpurgeable. + fPurgeableBytes -= resource->gpuMemorySize(); fPurgeableQueue.remove(resource); this->addToNonpurgeableArray(resource); } @@ -371,6 +376,7 @@ void GrResourceCache::notifyCntReachedZero(GrGpuResource* resource, uint32_t fla fPurgeableQueue.insert(resource); resource->cacheAccess().setFlushCntWhenResourceBecamePurgeable(fExternalFlushCnt); resource->cacheAccess().setTimeWhenResourceBecomePurgeable(); + fPurgeableBytes += resource->gpuMemorySize(); if (SkBudgeted::kNo == resource->resourcePriv().isBudgeted()) { // Check whether this resource could still be used as a scratch resource. @@ -747,6 +753,7 @@ void GrResourceCache::validate() const { } Stats stats(this); + size_t purgeableBytes = 0; for (int i = 0; i < fNonpurgeableResources.count(); ++i) { SkASSERT(!fNonpurgeableResources[i]->isPurgeable() || @@ -760,6 +767,7 @@ void GrResourceCache::validate() const { SkASSERT(*fPurgeableQueue.at(i)->cacheAccess().accessCacheIndex() == i); SkASSERT(!fPurgeableQueue.at(i)->wasDestroyed()); stats.update(fPurgeableQueue.at(i)); + purgeableBytes += fPurgeableQueue.at(i)->gpuMemorySize(); } SkASSERT(fCount == this->getResourceCount()); @@ -768,6 +776,7 @@ void GrResourceCache::validate() const { SkASSERT(stats.fBytes == fBytes); SkASSERT(stats.fBudgetedBytes == fBudgetedBytes); SkASSERT(stats.fBudgetedCount == fBudgetedCount); + SkASSERT(purgeableBytes == fPurgeableBytes); #if GR_CACHE_STATS SkASSERT(fBudgetedHighWaterCount <= fHighWaterCount); SkASSERT(fBudgetedHighWaterBytes <= fHighWaterBytes); diff --git a/src/gpu/GrResourceCache.h b/src/gpu/GrResourceCache.h index 71070ee..6362c37 100644 --- a/src/gpu/GrResourceCache.h +++ b/src/gpu/GrResourceCache.h @@ -93,6 +93,11 @@ public: size_t getResourceBytes() const { return fBytes; } /** + * Returns the number of bytes held by unlocked reosources which are available for purging. + */ + size_t getPurgeableBytes() const { return fPurgeableBytes; } + + /** * Returns the number of bytes consumed by budgeted resources. */ size_t getBudgetedResourceBytes() const { return fBudgetedBytes; } @@ -331,6 +336,7 @@ private: // our current stats for resources that count against the budget int fBudgetedCount; size_t fBudgetedBytes; + size_t fPurgeableBytes; bool fRequestFlush; uint32_t fExternalFlushCnt; diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp index 45946cf..3a63521 100644 --- a/tests/ResourceCacheTest.cpp +++ b/tests/ResourceCacheTest.cpp @@ -471,6 +471,7 @@ static void test_budgeting(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount()); REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() == cache->getBudgetedResourceBytes()); + REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes()); // Our refs mean that the resources are non purgeable. cache->purgeAllUnlocked(); @@ -481,43 +482,51 @@ static void test_budgeting(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount()); REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() == cache->getBudgetedResourceBytes()); + REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes()); // Unreffing the wrapped resource should free it right away. wrapped->unref(); REPORTER_ASSERT(reporter, 3 == cache->getResourceCount()); REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + unique->gpuMemorySize() + unbudgeted->gpuMemorySize() == cache->getResourceBytes()); + REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes()); // Now try freeing the budgeted resources first wrapped = TestResource::CreateWrapped(context->getGpu()); scratch->setSize(12); unique->unref(); + REPORTER_ASSERT(reporter, 11 == cache->getPurgeableBytes()); cache->purgeAllUnlocked(); REPORTER_ASSERT(reporter, 3 == cache->getResourceCount()); REPORTER_ASSERT(reporter, scratch->gpuMemorySize() + wrapped->gpuMemorySize() + unbudgeted->gpuMemorySize() == cache->getResourceBytes()); REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount()); REPORTER_ASSERT(reporter, scratch->gpuMemorySize() == cache->getBudgetedResourceBytes()); + REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes()); scratch->unref(); + REPORTER_ASSERT(reporter, 12 == cache->getPurgeableBytes()); cache->purgeAllUnlocked(); REPORTER_ASSERT(reporter, 2 == cache->getResourceCount()); REPORTER_ASSERT(reporter, unbudgeted->gpuMemorySize() + wrapped->gpuMemorySize() == cache->getResourceBytes()); REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount()); REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes()); + REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes()); wrapped->unref(); REPORTER_ASSERT(reporter, 1 == cache->getResourceCount()); REPORTER_ASSERT(reporter, unbudgeted->gpuMemorySize() == cache->getResourceBytes()); REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount()); REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes()); + REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes()); unbudgeted->unref(); REPORTER_ASSERT(reporter, 0 == cache->getResourceCount()); REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes()); REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount()); REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes()); + REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes()); } static void test_unbudgeted(skiatest::Reporter* reporter) { @@ -543,6 +552,7 @@ static void test_unbudgeted(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, 10 == cache->getResourceBytes()); REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount()); REPORTER_ASSERT(reporter, 10 == cache->getBudgetedResourceBytes()); + REPORTER_ASSERT(reporter, 10 == cache->getPurgeableBytes()); unique = new TestResource(context->getGpu()); unique->setSize(11); @@ -552,6 +562,7 @@ static void test_unbudgeted(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, 21 == cache->getResourceBytes()); REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount()); REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes()); + REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes()); size_t large = 2 * cache->getResourceBytes(); unbudgeted = new TestResource(context->getGpu(), SkBudgeted::kNo, large); @@ -559,30 +570,35 @@ static void test_unbudgeted(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, 21 + large == cache->getResourceBytes()); REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount()); REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes()); + REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes()); unbudgeted->unref(); REPORTER_ASSERT(reporter, 2 == cache->getResourceCount()); REPORTER_ASSERT(reporter, 21 == cache->getResourceBytes()); REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount()); REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes()); + REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes()); wrapped = TestResource::CreateWrapped(context->getGpu(), large); REPORTER_ASSERT(reporter, 3 == cache->getResourceCount()); REPORTER_ASSERT(reporter, 21 + large == cache->getResourceBytes()); REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount()); REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes()); + REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes()); wrapped->unref(); REPORTER_ASSERT(reporter, 2 == cache->getResourceCount()); REPORTER_ASSERT(reporter, 21 == cache->getResourceBytes()); REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount()); REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes()); + REPORTER_ASSERT(reporter, 21 == cache->getPurgeableBytes()); cache->purgeAllUnlocked(); REPORTER_ASSERT(reporter, 0 == cache->getResourceCount()); REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes()); REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount()); REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes()); + REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes()); } // This method can't be static because it needs to friended in GrGpuResource::CacheAccess. @@ -609,6 +625,7 @@ void test_unbudgeted_to_scratch(skiatest::Reporter* reporter); REPORTER_ASSERT(reporter, size == cache->getResourceBytes()); REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount()); REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes()); + REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes()); // Once it is unrefed, it should become available as scratch. resource->unref(); @@ -616,6 +633,7 @@ void test_unbudgeted_to_scratch(skiatest::Reporter* reporter); REPORTER_ASSERT(reporter, size == cache->getResourceBytes()); REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount()); REPORTER_ASSERT(reporter, size == cache->getBudgetedResourceBytes()); + REPORTER_ASSERT(reporter, size == cache->getPurgeableBytes()); resource = static_cast(cache->findAndRefScratchResource(key, TestResource::kDefaultSize, 0)); REPORTER_ASSERT(reporter, resource); REPORTER_ASSERT(reporter, resource->resourcePriv().getScratchKey() == key); @@ -633,6 +651,7 @@ void test_unbudgeted_to_scratch(skiatest::Reporter* reporter); REPORTER_ASSERT(reporter, size == cache->getResourceBytes()); REPORTER_ASSERT(reporter, 1 == cache->getBudgetedResourceCount()); REPORTER_ASSERT(reporter, size == cache->getBudgetedResourceBytes()); + REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes()); REPORTER_ASSERT(reporter, !resource->resourcePriv().getScratchKey().isValid()); REPORTER_ASSERT(reporter, !resource->cacheAccess().isScratch()); REPORTER_ASSERT(reporter, SkBudgeted::kYes == resource->resourcePriv().isBudgeted()); @@ -643,6 +662,7 @@ void test_unbudgeted_to_scratch(skiatest::Reporter* reporter); REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes()); REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceCount()); REPORTER_ASSERT(reporter, 0 == cache->getBudgetedResourceBytes()); + REPORTER_ASSERT(reporter, 0 == cache->getPurgeableBytes()); } } } @@ -1369,6 +1389,7 @@ static void test_large_resource_count(skiatest::Reporter* reporter) { } REPORTER_ASSERT(reporter, TestResource::NumAlive() == 2 * kResourceCnt); + REPORTER_ASSERT(reporter, cache->getPurgeableBytes() == 2 * kResourceCnt); REPORTER_ASSERT(reporter, cache->getBudgetedResourceBytes() == 2 * kResourceCnt); REPORTER_ASSERT(reporter, cache->getBudgetedResourceCount() == 2 * kResourceCnt); REPORTER_ASSERT(reporter, cache->getResourceBytes() == 2 * kResourceCnt); @@ -1384,6 +1405,7 @@ static void test_large_resource_count(skiatest::Reporter* reporter) { cache->purgeAllUnlocked(); REPORTER_ASSERT(reporter, TestResource::NumAlive() == 0); + REPORTER_ASSERT(reporter, cache->getPurgeableBytes() == 0); REPORTER_ASSERT(reporter, cache->getBudgetedResourceBytes() == 0); REPORTER_ASSERT(reporter, cache->getBudgetedResourceCount() == 0); REPORTER_ASSERT(reporter, cache->getResourceBytes() == 0); -- 2.7.4