diff options
author | Skia_Android Canary Bot <31977622648@project.gserviceaccount.com> | 2018-03-29 14:08:53 +0000 |
---|---|---|
committer | Derek Sollenberger <djsollen@google.com> | 2018-03-29 14:12:58 +0000 |
commit | 6f377116f520ca5dd7ef9ed04c6f87a6ab193252 (patch) | |
tree | 2edb7142010c6370b719f5a5f8717aef7fc5b2c7 | |
parent | 3b2d2df6fc10754e56a0aec2ba4b1644fbe6515b (diff) | |
parent | 47710a52505e9b8d2ae6ef8521f6b7a022542b9e (diff) | |
download | skia-6f377116f520ca5dd7ef9ed04c6f87a6ab193252.tar.gz |
Roll external/skia 5734c4b3d..47710a525 (1 commits)
https://skia.googlesource.com/skia.git/+log/5734c4b3d..47710a525
2018-03-29 robertphillips@google.com Add new GrResourceCache::purgeUnlockedResources variant
The AutoRoll server is located here: https://android-next-roll.skia.org
Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+/master/autoroll/README.md
If the roll is causing failures, please contact the current sheriff, who should
be CC'd on the roll, and stop the roller if necessary.
Bug: 74436619
Bug: 73808481
Test: Presubmit checks will test this change.
Change-Id: I23bd02cd2974f448816b2f24cede82df436010fb
Exempt-From-Owner-Approval: The autoroll bot does not require owner approval.
-rw-r--r-- | include/gpu/GrContext.h | 15 | ||||
-rw-r--r-- | src/gpu/GrContext.cpp | 7 | ||||
-rw-r--r-- | src/gpu/GrResourceCache.cpp | 35 | ||||
-rw-r--r-- | src/gpu/GrResourceCache.h | 7 | ||||
-rw-r--r-- | tests/ResourceCacheTest.cpp | 69 |
5 files changed, 125 insertions, 8 deletions
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h index 6578638183..8621ea5f46 100644 --- a/include/gpu/GrContext.h +++ b/include/gpu/GrContext.h @@ -216,6 +216,21 @@ public: */ void purgeUnlockedResources(size_t bytesToPurge, bool preferScratchResources); + /** + * This entry point is intended for instances where an app has been backgrounded or + * suspended. + * If 'scratchResourcesOnly' is true all unlocked scratch resources will be purged but the + * unlocked resources with persistent data will remain. If 'scratchResourcesOnly' is false + * then all unlocked resources will be purged. + * In either case, after the unlocked resources are purged a separate pass will be made to + * ensure that resource usage is under budget (i.e., even if 'scratchResourcesOnly' is true + * some resources with persistent data may be purged to be under budget). + * + * @param scratchResourcesOnly If true only unlocked scratch resources will be purged prior + * enforcing the budget requirements. + */ + void purgeUnlockedResources(bool scratchResourcesOnly); + /** Access the context capabilities */ const GrCaps* caps() const { return fCaps.get(); } diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 45c4f87e83..26da7a80ee 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -523,6 +523,13 @@ void GrContext::freeGpuResources() { fResourceCache->purgeAllUnlocked(); } +void GrContext::purgeUnlockedResources(bool scratchResourcesOnly) { + ASSERT_SINGLE_OWNER + fResourceCache->purgeUnlockedResources(scratchResourcesOnly); + fResourceCache->purgeAsNeeded(); + fTextBlobCache->purgeStaleBlobs(); +} + void GrContext::performDeferredCleanup(std::chrono::milliseconds msNotUsed) { ASSERT_SINGLE_OWNER fResourceCache->purgeAsNeeded(); diff --git a/src/gpu/GrResourceCache.cpp b/src/gpu/GrResourceCache.cpp index 50b2e9a229..d2eb91c0e8 100644 --- a/src/gpu/GrResourceCache.cpp +++ b/src/gpu/GrResourceCache.cpp @@ -513,13 +513,34 @@ void GrResourceCache::purgeAsNeeded() { } } -void GrResourceCache::purgeAllUnlocked() { - // We could disable maintaining the heap property here, but it would add a lot of complexity. - // Moreover, this is rarely called. - while (fPurgeableQueue.count()) { - GrGpuResource* resource = fPurgeableQueue.peek(); - SkASSERT(resource->isPurgeable()); - resource->cacheAccess().release(); +void GrResourceCache::purgeUnlockedResources(bool scratchResourcesOnly) { + if (!scratchResourcesOnly) { + // We could disable maintaining the heap property here, but it would add a lot of + // complexity. Moreover, this is rarely called. + while (fPurgeableQueue.count()) { + GrGpuResource* resource = fPurgeableQueue.peek(); + SkASSERT(resource->isPurgeable()); + resource->cacheAccess().release(); + } + } else { + // Sort the queue + fPurgeableQueue.sort(); + + // Make a list of the scratch resources to delete + SkTDArray<GrGpuResource*> scratchResources; + for (int i = 0; i < fPurgeableQueue.count(); i++) { + GrGpuResource* resource = fPurgeableQueue.at(i); + SkASSERT(resource->isPurgeable()); + if (!resource->getUniqueKey().isValid()) { + *scratchResources.append() = resource; + } + } + + // Delete the scratch resources. This must be done as a separate pass + // to avoid messing up the sorted order of the queue + for (int i = 0; i < scratchResources.count(); i++) { + scratchResources.getAt(i)->cacheAccess().release(); + } } this->validate(); diff --git a/src/gpu/GrResourceCache.h b/src/gpu/GrResourceCache.h index 6869e4e8c2..32c3836122 100644 --- a/src/gpu/GrResourceCache.h +++ b/src/gpu/GrResourceCache.h @@ -169,7 +169,12 @@ public: void purgeAsNeeded(); /** Purges all resources that don't have external owners. */ - void purgeAllUnlocked(); + void purgeAllUnlocked() { this->purgeUnlockedResources(false); } + + // Purge unlocked resources. If 'scratchResourcesOnly' is true the purgeable resources + // containing persistent data are spared. If it is false then all purgeable resources will + // be deleted. + void purgeUnlockedResources(bool scratchResourcesOnly); /** Purge all resources not used since the passed in time. */ void purgeResourcesNotUsedSince(GrStdSteadyClock::time_point); diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp index f6ff21853b..4fa13b32d6 100644 --- a/tests/ResourceCacheTest.cpp +++ b/tests/ResourceCacheTest.cpp @@ -424,6 +424,74 @@ static void make_unique_key(GrUniqueKey* key, int data, const char* tag = nullpt builder[0] = data; } +static void test_purge_unlocked(skiatest::Reporter* reporter) { + Mock mock(10, 30000); + GrContext* context = mock.context(); + GrResourceCache* cache = mock.cache(); + GrGpu* gpu = context->contextPriv().getGpu(); + + // Create two resource w/ a unique key and two w/o but all of which have scratch keys. + TestResource* a = TestResource::CreateScratch(gpu, SkBudgeted::kYes, + TestResource::kA_SimulatedProperty); + a->setSize(11); + + GrUniqueKey uniqueKey; + make_unique_key<0>(&uniqueKey, 0); + + TestResource* b = TestResource::CreateScratch(gpu, SkBudgeted::kYes, + TestResource::kA_SimulatedProperty); + b->setSize(12); + b->resourcePriv().setUniqueKey(uniqueKey); + + TestResource* c = TestResource::CreateScratch(gpu, SkBudgeted::kYes, + TestResource::kA_SimulatedProperty); + c->setSize(13); + + GrUniqueKey uniqueKey2; + make_unique_key<0>(&uniqueKey2, 1); + + TestResource* d = TestResource::CreateScratch(gpu, SkBudgeted::kYes, + TestResource::kA_SimulatedProperty); + d->setSize(14); + d->resourcePriv().setUniqueKey(uniqueKey2); + + + REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive()); + REPORTER_ASSERT(reporter, 4 == cache->getResourceCount()); + REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() + c->gpuMemorySize() + + d->gpuMemorySize() == cache->getResourceBytes()); + + // Should be safe to purge without deleting the resources since we still have refs. + cache->purgeUnlockedResources(false); + REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive()); + + // Unref them all. Since they all have keys they should remain in the cache. + + a->unref(); + b->unref(); + c->unref(); + d->unref(); + REPORTER_ASSERT(reporter, 4 == TestResource::NumAlive()); + REPORTER_ASSERT(reporter, 4 == cache->getResourceCount()); + REPORTER_ASSERT(reporter, a->gpuMemorySize() + b->gpuMemorySize() + c->gpuMemorySize() + + d->gpuMemorySize() == cache->getResourceBytes()); + + // Purge only the two scratch resources + cache->purgeUnlockedResources(true); + + REPORTER_ASSERT(reporter, 2 == TestResource::NumAlive()); + REPORTER_ASSERT(reporter, 2 == cache->getResourceCount()); + REPORTER_ASSERT(reporter, b->gpuMemorySize() + d->gpuMemorySize() == + cache->getResourceBytes()); + + // Purge the uniquely keyed resources + cache->purgeUnlockedResources(false); + + REPORTER_ASSERT(reporter, 0 == TestResource::NumAlive()); + REPORTER_ASSERT(reporter, 0 == cache->getResourceCount()); + REPORTER_ASSERT(reporter, 0 == cache->getResourceBytes()); +} + static void test_budgeting(skiatest::Reporter* reporter) { Mock mock(10, 300); GrContext* context = mock.context(); @@ -1619,6 +1687,7 @@ static void test_tags(skiatest::Reporter* reporter) { DEF_GPUTEST(ResourceCacheMisc, reporter, /* options */) { // The below tests create their own mock contexts. test_no_key(reporter); + test_purge_unlocked(reporter); test_budgeting(reporter); test_unbudgeted(reporter); test_unbudgeted_to_scratch(reporter); |