1c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon/* 2c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon * Copyright 2014 Google Inc. 3c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon * 4c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon * Use of this source code is governed by a BSD-style license that can be 5c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon * found in the LICENSE file. 6c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon */ 7c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon 8c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon 90ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon#include "GrResourceCache.h" 1028a838e532250fcca9673aca6c4616193a5a139drobertphillips 1128a838e532250fcca9673aca6c4616193a5a139drobertphillips#include "GrCaps.h" 123582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon#include "GrGpuResourceCacheAccess.h" 131afd4cdb0800e2e395b465da24eb71e0e834dafaRobert Phillips#include "GrProxyProvider.h" 14ae7d3f3992708354a3284bb49066737e36a76f40Robert Phillips#include "GrTexture.h" 15ae7d3f3992708354a3284bb49066737e36a76f40Robert Phillips#include "GrTextureProxyCacheAccess.h" 16876c3132d75966829ad58b2f9b2957d50457cc29hendrikw#include "GrTracing.h" 1771cb0c241e439b6ed746b90294d0b6916644a644bsalomon#include "SkGr.h" 1871cb0c241e439b6ed746b90294d0b6916644a644bsalomon#include "SkMessageBus.h" 194e97607d9a1cef66fac16f347c5ca813ec4f9515mtklein#include "SkOpts.h" 20ddf30e64fe474847b204d7062fad3341d245062cbsalomon#include "SkTSort.h" 2171cb0c241e439b6ed746b90294d0b6916644a644bsalomon 228718aafec239c93485e45bbe8fed19d9a8def079bsalomonDECLARE_SKMESSAGEBUS_MESSAGE(GrUniqueKeyInvalidatedMessage); 2371cb0c241e439b6ed746b90294d0b6916644a644bsalomon 2413dddce65fd87a8175a209a49f35615735a2886aBrian OsmanDECLARE_SKMESSAGEBUS_MESSAGE(GrGpuResourceFreedMessage); 2513dddce65fd87a8175a209a49f35615735a2886aBrian Osman 2671cb0c241e439b6ed746b90294d0b6916644a644bsalomon////////////////////////////////////////////////////////////////////////////// 2771cb0c241e439b6ed746b90294d0b6916644a644bsalomon 287775c85611c734a2af709b3a9c127939a4296c48bsalomonGrScratchKey::ResourceType GrScratchKey::GenerateResourceType() { 2924db3b1c35fb935660229da164fc5ad31977387fbsalomon static int32_t gType = INHERITED::kInvalidDomain + 1; 30fe369ee34bc59a7e87b5d21bb0117e92cf75c103bsalomon 317775c85611c734a2af709b3a9c127939a4296c48bsalomon int32_t type = sk_atomic_inc(&gType); 329790a7b36b7704f6f490368778bff16302bb7cb6robertphillips if (type > SK_MaxU16) { 33b4aab9ae6d27c446af8302b79d15b832c816c633Ben Wagner SK_ABORT("Too many Resource Types"); 347775c85611c734a2af709b3a9c127939a4296c48bsalomon } 35fe369ee34bc59a7e87b5d21bb0117e92cf75c103bsalomon 367775c85611c734a2af709b3a9c127939a4296c48bsalomon return static_cast<ResourceType>(type); 37fe369ee34bc59a7e87b5d21bb0117e92cf75c103bsalomon} 38fe369ee34bc59a7e87b5d21bb0117e92cf75c103bsalomon 398718aafec239c93485e45bbe8fed19d9a8def079bsalomonGrUniqueKey::Domain GrUniqueKey::GenerateDomain() { 4024db3b1c35fb935660229da164fc5ad31977387fbsalomon static int32_t gDomain = INHERITED::kInvalidDomain + 1; 4171cb0c241e439b6ed746b90294d0b6916644a644bsalomon 4224db3b1c35fb935660229da164fc5ad31977387fbsalomon int32_t domain = sk_atomic_inc(&gDomain); 43016dffb7b3f5f94b4777ddc6bd8bcd03becf4e38kkinnunen if (domain > SK_MaxU16) { 44b4aab9ae6d27c446af8302b79d15b832c816c633Ben Wagner SK_ABORT("Too many GrUniqueKey Domains"); 4571cb0c241e439b6ed746b90294d0b6916644a644bsalomon } 4624db3b1c35fb935660229da164fc5ad31977387fbsalomon 4724db3b1c35fb935660229da164fc5ad31977387fbsalomon return static_cast<Domain>(domain); 4824db3b1c35fb935660229da164fc5ad31977387fbsalomon} 493f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon 5024db3b1c35fb935660229da164fc5ad31977387fbsalomonuint32_t GrResourceKeyHash(const uint32_t* data, size_t size) { 514e97607d9a1cef66fac16f347c5ca813ec4f9515mtklein return SkOpts::hash(data, size); 5271cb0c241e439b6ed746b90294d0b6916644a644bsalomon} 5371cb0c241e439b6ed746b90294d0b6916644a644bsalomon 54fe369ee34bc59a7e87b5d21bb0117e92cf75c103bsalomon////////////////////////////////////////////////////////////////////////////// 55fe369ee34bc59a7e87b5d21bb0117e92cf75c103bsalomon 560ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomonclass GrResourceCache::AutoValidate : ::SkNoncopyable { 5771cb0c241e439b6ed746b90294d0b6916644a644bsalomonpublic: 580ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon AutoValidate(GrResourceCache* cache) : fCache(cache) { cache->validate(); } 5971cb0c241e439b6ed746b90294d0b6916644a644bsalomon ~AutoValidate() { fCache->validate(); } 6071cb0c241e439b6ed746b90294d0b6916644a644bsalomonprivate: 610ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon GrResourceCache* fCache; 6271cb0c241e439b6ed746b90294d0b6916644a644bsalomon}; 6371cb0c241e439b6ed746b90294d0b6916644a644bsalomon 6471cb0c241e439b6ed746b90294d0b6916644a644bsalomon ////////////////////////////////////////////////////////////////////////////// 65ee843b2ae4d75748d8bc323287f0c310fad548a7robertphillips 6671cb0c241e439b6ed746b90294d0b6916644a644bsalomon 6713dddce65fd87a8175a209a49f35615735a2886aBrian OsmanGrResourceCache::GrResourceCache(const GrCaps* caps, uint32_t contextUniqueID) 681afd4cdb0800e2e395b465da24eb71e0e834dafaRobert Phillips : fProxyProvider(nullptr) 691afd4cdb0800e2e395b465da24eb71e0e834dafaRobert Phillips , fTimestamp(0) 709f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon , fMaxCount(kDefaultMaxCount) 7171cb0c241e439b6ed746b90294d0b6916644a644bsalomon , fMaxBytes(kDefaultMaxSize) 723f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon , fMaxUnusedFlushes(kDefaultMaxUnusedFlushes) 7371cb0c241e439b6ed746b90294d0b6916644a644bsalomon#if GR_CACHE_STATS 7471cb0c241e439b6ed746b90294d0b6916644a644bsalomon , fHighWaterCount(0) 7571cb0c241e439b6ed746b90294d0b6916644a644bsalomon , fHighWaterBytes(0) 76dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon , fBudgetedHighWaterCount(0) 77dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon , fBudgetedHighWaterBytes(0) 7871cb0c241e439b6ed746b90294d0b6916644a644bsalomon#endif 7971cb0c241e439b6ed746b90294d0b6916644a644bsalomon , fBytes(0) 80dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon , fBudgetedCount(0) 81dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon , fBudgetedBytes(0) 82ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger , fPurgeableBytes(0) 83ee843b2ae4d75748d8bc323287f0c310fad548a7robertphillips , fRequestFlush(false) 84e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon , fExternalFlushCnt(0) 8513dddce65fd87a8175a209a49f35615735a2886aBrian Osman , fContextUniqueID(contextUniqueID) 8663926683c583e8497d9d907977e773663cb4bd9erobertphillips , fPreferVRAMUseOverFlushes(caps->preferVRAMUseOverFlushes()) { 87f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkDEBUGCODE(fCount = 0;) 8896fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkDEBUGCODE(fNewlyPurgeableResourceForValidation = nullptr;) 8971cb0c241e439b6ed746b90294d0b6916644a644bsalomon} 9071cb0c241e439b6ed746b90294d0b6916644a644bsalomon 910ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomonGrResourceCache::~GrResourceCache() { 92c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon this->releaseAll(); 93c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon} 94c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon 953f324321cdd8fde7976d958e2888a1ec4e657e35bsalomonvoid GrResourceCache::setLimits(int count, size_t bytes, int maxUnusedFlushes) { 9671cb0c241e439b6ed746b90294d0b6916644a644bsalomon fMaxCount = count; 9771cb0c241e439b6ed746b90294d0b6916644a644bsalomon fMaxBytes = bytes; 983f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon fMaxUnusedFlushes = maxUnusedFlushes; 9971cb0c241e439b6ed746b90294d0b6916644a644bsalomon this->purgeAsNeeded(); 10071cb0c241e439b6ed746b90294d0b6916644a644bsalomon} 10171cb0c241e439b6ed746b90294d0b6916644a644bsalomon 1020ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomonvoid GrResourceCache::insertResource(GrGpuResource* resource) { 10349f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(resource); 104169612621f00b3fe9f71014079991287d311751absalomon SkASSERT(!this->isInCache(resource)); 105f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkASSERT(!resource->wasDestroyed()); 106f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkASSERT(!resource->isPurgeable()); 107ddf30e64fe474847b204d7062fad3341d245062cbsalomon 108ddf30e64fe474847b204d7062fad3341d245062cbsalomon // We must set the timestamp before adding to the array in case the timestamp wraps and we wind 109ddf30e64fe474847b204d7062fad3341d245062cbsalomon // up iterating over all the resources that already have timestamps. 110ddf30e64fe474847b204d7062fad3341d245062cbsalomon resource->cacheAccess().setTimestamp(this->getNextTimestamp()); 111ddf30e64fe474847b204d7062fad3341d245062cbsalomon 112f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon this->addToNonpurgeableArray(resource); 11371cb0c241e439b6ed746b90294d0b6916644a644bsalomon 114dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon size_t size = resource->gpuMemorySize(); 115f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkDEBUGCODE(++fCount;) 11684c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon fBytes += size; 11782b1d620137f35fe48bc635bc74f638c9716710bbsalomon#if GR_CACHE_STATS 118f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon fHighWaterCount = SkTMax(this->getResourceCount(), fHighWaterCount); 11982b1d620137f35fe48bc635bc74f638c9716710bbsalomon fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes); 12082b1d620137f35fe48bc635bc74f638c9716710bbsalomon#endif 1215ec26ae9bfca635ccc98283aad5deda11519d826bsalomon if (SkBudgeted::kYes == resource->resourcePriv().isBudgeted()) { 122dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon ++fBudgetedCount; 123dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon fBudgetedBytes += size; 12439c08ac3be30f9956cea7c5e4fd9a1d86e993a65Brian Osman TRACE_COUNTER2("skia.gpu.cache", "skia budget", "used", 125876c3132d75966829ad58b2f9b2957d50457cc29hendrikw fBudgetedBytes, "free", fMaxBytes - fBudgetedBytes); 126dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon#if GR_CACHE_STATS 127dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount); 128dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes); 129dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon#endif 130dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon } 131c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips if (resource->resourcePriv().getScratchKey().isValid() && 132c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips !resource->getUniqueKey().isValid()) { 1332e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen SkASSERT(!resource->resourcePriv().refsWrappedObjects()); 1343582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon fScratchMap.insert(resource->resourcePriv().getScratchKey(), resource); 135744998e666073166307d2522847b2536000a7619bsalomon } 1369f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon 13771cb0c241e439b6ed746b90294d0b6916644a644bsalomon this->purgeAsNeeded(); 138c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon} 139c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon 1400ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomonvoid GrResourceCache::removeResource(GrGpuResource* resource) { 1419f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon this->validate(); 142169612621f00b3fe9f71014079991287d311751absalomon SkASSERT(this->isInCache(resource)); 143dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon 144ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger size_t size = resource->gpuMemorySize(); 1459f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon if (resource->isPurgeable()) { 1469f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon fPurgeableQueue.remove(resource); 147ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger fPurgeableBytes -= size; 148f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon } else { 149f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon this->removeFromNonpurgeableArray(resource); 1509f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon } 1519f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon 152f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkDEBUGCODE(--fCount;) 153dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon fBytes -= size; 1545ec26ae9bfca635ccc98283aad5deda11519d826bsalomon if (SkBudgeted::kYes == resource->resourcePriv().isBudgeted()) { 155dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon --fBudgetedCount; 156dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon fBudgetedBytes -= size; 15739c08ac3be30f9956cea7c5e4fd9a1d86e993a65Brian Osman TRACE_COUNTER2("skia.gpu.cache", "skia budget", "used", 158876c3132d75966829ad58b2f9b2957d50457cc29hendrikw fBudgetedBytes, "free", fMaxBytes - fBudgetedBytes); 159dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon } 160dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon 161c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips if (resource->resourcePriv().getScratchKey().isValid() && 162c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips !resource->getUniqueKey().isValid()) { 1633582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon fScratchMap.remove(resource->resourcePriv().getScratchKey(), resource); 164744998e666073166307d2522847b2536000a7619bsalomon } 1658718aafec239c93485e45bbe8fed19d9a8def079bsalomon if (resource->getUniqueKey().isValid()) { 1668718aafec239c93485e45bbe8fed19d9a8def079bsalomon fUniqueHash.remove(resource->getUniqueKey()); 1678b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon } 168b436ed6754452d7acb6c70e70307904c8f4a50e7bsalomon this->validate(); 169c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon} 170c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon 1710ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomonvoid GrResourceCache::abandonAll() { 17271cb0c241e439b6ed746b90294d0b6916644a644bsalomon AutoValidate av(this); 17371cb0c241e439b6ed746b90294d0b6916644a644bsalomon 174f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon while (fNonpurgeableResources.count()) { 175f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon GrGpuResource* back = *(fNonpurgeableResources.end() - 1); 176f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkASSERT(!back->wasDestroyed()); 177f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon back->cacheAccess().abandon(); 178f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon } 179f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon 180f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon while (fPurgeableQueue.count()) { 181f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon GrGpuResource* top = fPurgeableQueue.peek(); 182f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkASSERT(!top->wasDestroyed()); 183f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon top->cacheAccess().abandon(); 184c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon } 185f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon 186744998e666073166307d2522847b2536000a7619bsalomon SkASSERT(!fScratchMap.count()); 1878718aafec239c93485e45bbe8fed19d9a8def079bsalomon SkASSERT(!fUniqueHash.count()); 188c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon SkASSERT(!fCount); 189f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkASSERT(!this->getResourceCount()); 190dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon SkASSERT(!fBytes); 191dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon SkASSERT(!fBudgetedCount); 192dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon SkASSERT(!fBudgetedBytes); 193ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger SkASSERT(!fPurgeableBytes); 194c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon} 195c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon 1960ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomonvoid GrResourceCache::releaseAll() { 19771cb0c241e439b6ed746b90294d0b6916644a644bsalomon AutoValidate av(this); 19871cb0c241e439b6ed746b90294d0b6916644a644bsalomon 19913dddce65fd87a8175a209a49f35615735a2886aBrian Osman this->processFreedGpuResources(); 20013dddce65fd87a8175a209a49f35615735a2886aBrian Osman 2011afd4cdb0800e2e395b465da24eb71e0e834dafaRobert Phillips SkASSERT(fProxyProvider); // better have called setProxyProvider 2023ec9573ac3fd8b973fe4feda27c109d47cb5defcRobert Phillips // We must remove the uniqueKeys from the proxies here. While they possess a uniqueKey 2033ec9573ac3fd8b973fe4feda27c109d47cb5defcRobert Phillips // they also have a raw pointer back to this class (which is presumably going away)! 2041afd4cdb0800e2e395b465da24eb71e0e834dafaRobert Phillips fProxyProvider->removeAllUniqueKeys(); 20545a6f147b0dc47630e75dcfc8f9c4ce816392553Robert Phillips 206f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon while(fNonpurgeableResources.count()) { 207f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon GrGpuResource* back = *(fNonpurgeableResources.end() - 1); 208f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkASSERT(!back->wasDestroyed()); 209f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon back->cacheAccess().release(); 210c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon } 211f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon 212f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon while (fPurgeableQueue.count()) { 213f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon GrGpuResource* top = fPurgeableQueue.peek(); 214f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkASSERT(!top->wasDestroyed()); 215f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon top->cacheAccess().release(); 216f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon } 217f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon 218744998e666073166307d2522847b2536000a7619bsalomon SkASSERT(!fScratchMap.count()); 2198718aafec239c93485e45bbe8fed19d9a8def079bsalomon SkASSERT(!fUniqueHash.count()); 220c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon SkASSERT(!fCount); 221f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkASSERT(!this->getResourceCount()); 222dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon SkASSERT(!fBytes); 223dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon SkASSERT(!fBudgetedCount); 224dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon SkASSERT(!fBudgetedBytes); 225ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger SkASSERT(!fPurgeableBytes); 226c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon} 227bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon 2280ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomonclass GrResourceCache::AvailableForScratchUse { 229bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomonpublic: 230000f829f14a9535a005082731af5de1526284c83bsalomon AvailableForScratchUse(bool rejectPendingIO) : fRejectPendingIO(rejectPendingIO) { } 231bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon 232bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon bool operator()(const GrGpuResource* resource) const { 233c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips SkASSERT(!resource->getUniqueKey().isValid() && 234c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips resource->resourcePriv().getScratchKey().isValid()); 23512299ab7a1be5f4b99284ecf289d46107ef0a946bsalomon if (resource->internalHasRef() || !resource->cacheAccess().isScratch()) { 236000f829f14a9535a005082731af5de1526284c83bsalomon return false; 237bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon } 238000f829f14a9535a005082731af5de1526284c83bsalomon return !fRejectPendingIO || !resource->internalHasPendingIO(); 239bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon } 2401e2530babb65a883a01df5ee87147432f6707ce3bsalomon 241bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomonprivate: 242000f829f14a9535a005082731af5de1526284c83bsalomon bool fRejectPendingIO; 243bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon}; 244bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon 2450ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomonGrGpuResource* GrResourceCache::findAndRefScratchResource(const GrScratchKey& scratchKey, 2466e83ac778f8f90939abe3aee3ea865428dff592frobertphillips size_t resourceSize, 2479f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon uint32_t flags) { 2487775c85611c734a2af709b3a9c127939a4296c48bsalomon SkASSERT(scratchKey.isValid()); 249ee843b2ae4d75748d8bc323287f0c310fad548a7robertphillips 25071cb0c241e439b6ed746b90294d0b6916644a644bsalomon GrGpuResource* resource; 251000f829f14a9535a005082731af5de1526284c83bsalomon if (flags & (kPreferNoPendingIO_ScratchFlag | kRequireNoPendingIO_ScratchFlag)) { 25271cb0c241e439b6ed746b90294d0b6916644a644bsalomon resource = fScratchMap.find(scratchKey, AvailableForScratchUse(true)); 253000f829f14a9535a005082731af5de1526284c83bsalomon if (resource) { 2549f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon this->refAndMakeResourceMRU(resource); 255b436ed6754452d7acb6c70e70307904c8f4a50e7bsalomon this->validate(); 256b436ed6754452d7acb6c70e70307904c8f4a50e7bsalomon return resource; 257000f829f14a9535a005082731af5de1526284c83bsalomon } else if (flags & kRequireNoPendingIO_ScratchFlag) { 25896fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 259000f829f14a9535a005082731af5de1526284c83bsalomon } 26063926683c583e8497d9d907977e773663cb4bd9erobertphillips // We would prefer to consume more available VRAM rather than flushing 26163926683c583e8497d9d907977e773663cb4bd9erobertphillips // immediately, but on ANGLE this can lead to starving of the GPU. 26263926683c583e8497d9d907977e773663cb4bd9erobertphillips if (fPreferVRAMUseOverFlushes && this->wouldFit(resourceSize)) { 2636e83ac778f8f90939abe3aee3ea865428dff592frobertphillips // kPrefer is specified, we didn't find a resource without pending io, 26463926683c583e8497d9d907977e773663cb4bd9erobertphillips // but there is still space in our budget for the resource so force 26563926683c583e8497d9d907977e773663cb4bd9erobertphillips // the caller to allocate a new resource. 26696fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 2676e83ac778f8f90939abe3aee3ea865428dff592frobertphillips } 268000f829f14a9535a005082731af5de1526284c83bsalomon } 26971cb0c241e439b6ed746b90294d0b6916644a644bsalomon resource = fScratchMap.find(scratchKey, AvailableForScratchUse(false)); 27071cb0c241e439b6ed746b90294d0b6916644a644bsalomon if (resource) { 2719f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon this->refAndMakeResourceMRU(resource); 272b436ed6754452d7acb6c70e70307904c8f4a50e7bsalomon this->validate(); 27371cb0c241e439b6ed746b90294d0b6916644a644bsalomon } 27471cb0c241e439b6ed746b90294d0b6916644a644bsalomon return resource; 275bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon} 2768b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon 2770ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomonvoid GrResourceCache::willRemoveScratchKey(const GrGpuResource* resource) { 2783582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon SkASSERT(resource->resourcePriv().getScratchKey().isValid()); 279c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips if (!resource->getUniqueKey().isValid()) { 280c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips fScratchMap.remove(resource->resourcePriv().getScratchKey(), resource); 281c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips } 28210e23caea3106be125acea10a637789e5a15c728bsalomon} 28310e23caea3106be125acea10a637789e5a15c728bsalomon 284f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomonvoid GrResourceCache::removeUniqueKey(GrGpuResource* resource) { 2853f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon // Someone has a ref to this resource in order to have removed the key. When the ref count 2863f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon // reaches zero we will get a ref cnt notification and figure out what to do with it. 287f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon if (resource->getUniqueKey().isValid()) { 288f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon SkASSERT(resource == fUniqueHash.find(resource->getUniqueKey())); 289f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon fUniqueHash.remove(resource->getUniqueKey()); 290f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon } 291f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon resource->cacheAccess().removeUniqueKey(); 292c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips 293c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips if (resource->resourcePriv().getScratchKey().isValid()) { 294c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips fScratchMap.insert(resource->resourcePriv().getScratchKey(), resource); 295c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips } 296c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips 297f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon this->validate(); 29823e619cf462b2a8a500f3ca750e099f79601f508bsalomon} 29923e619cf462b2a8a500f3ca750e099f79601f508bsalomon 300f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomonvoid GrResourceCache::changeUniqueKey(GrGpuResource* resource, const GrUniqueKey& newKey) { 3018b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon SkASSERT(resource); 30271cb0c241e439b6ed746b90294d0b6916644a644bsalomon SkASSERT(this->isInCache(resource)); 3038b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon 304f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon // If another resource has the new key, remove its key then install the key on this resource. 305f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon if (newKey.isValid()) { 3060d53780b8cbf75c0282fb8246a0a3de0026f211bGreg Daniel if (GrGpuResource* old = fUniqueHash.find(newKey)) { 3070d53780b8cbf75c0282fb8246a0a3de0026f211bGreg Daniel // If the old resource using the key is purgeable and is unreachable, then remove it. 3080d53780b8cbf75c0282fb8246a0a3de0026f211bGreg Daniel if (!old->resourcePriv().getScratchKey().isValid() && old->isPurgeable()) { 3090d53780b8cbf75c0282fb8246a0a3de0026f211bGreg Daniel old->cacheAccess().release(); 3100d53780b8cbf75c0282fb8246a0a3de0026f211bGreg Daniel } else { 3110d53780b8cbf75c0282fb8246a0a3de0026f211bGreg Daniel this->removeUniqueKey(old); 3120d53780b8cbf75c0282fb8246a0a3de0026f211bGreg Daniel } 3130d53780b8cbf75c0282fb8246a0a3de0026f211bGreg Daniel } 3140d53780b8cbf75c0282fb8246a0a3de0026f211bGreg Daniel SkASSERT(nullptr == fUniqueHash.find(newKey)); 3150d53780b8cbf75c0282fb8246a0a3de0026f211bGreg Daniel 316c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips // Remove the entry for this resource if it already has a unique key. 317c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips if (resource->getUniqueKey().isValid()) { 318c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips SkASSERT(resource == fUniqueHash.find(resource->getUniqueKey())); 319c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips fUniqueHash.remove(resource->getUniqueKey()); 320c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips SkASSERT(nullptr == fUniqueHash.find(resource->getUniqueKey())); 321c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips } else { 322c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips // 'resource' didn't have a valid unique key before so it is switching sides. Remove it 323c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips // from the ScratchMap 324c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips if (resource->resourcePriv().getScratchKey().isValid()) { 325c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips fScratchMap.remove(resource->resourcePriv().getScratchKey(), resource); 326c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips } 327c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips } 328c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips 329f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon resource->cacheAccess().setUniqueKey(newKey); 330f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon fUniqueHash.add(resource); 331f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon } else { 332c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips this->removeUniqueKey(resource); 3338b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon } 3348b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon 33571cb0c241e439b6ed746b90294d0b6916644a644bsalomon this->validate(); 3368b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon} 33771cb0c241e439b6ed746b90294d0b6916644a644bsalomon 3389f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomonvoid GrResourceCache::refAndMakeResourceMRU(GrGpuResource* resource) { 33971cb0c241e439b6ed746b90294d0b6916644a644bsalomon SkASSERT(resource); 34071cb0c241e439b6ed746b90294d0b6916644a644bsalomon SkASSERT(this->isInCache(resource)); 341ddf30e64fe474847b204d7062fad3341d245062cbsalomon 3429f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon if (resource->isPurgeable()) { 3439f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon // It's about to become unpurgeable. 344ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger fPurgeableBytes -= resource->gpuMemorySize(); 3459f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon fPurgeableQueue.remove(resource); 346f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon this->addToNonpurgeableArray(resource); 3479f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon } 3489f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon resource->ref(); 349ddf30e64fe474847b204d7062fad3341d245062cbsalomon 350ddf30e64fe474847b204d7062fad3341d245062cbsalomon resource->cacheAccess().setTimestamp(this->getNextTimestamp()); 351f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon this->validate(); 35271cb0c241e439b6ed746b90294d0b6916644a644bsalomon} 35371cb0c241e439b6ed746b90294d0b6916644a644bsalomon 3543f324321cdd8fde7976d958e2888a1ec4e657e35bsalomonvoid GrResourceCache::notifyCntReachedZero(GrGpuResource* resource, uint32_t flags) { 35571cb0c241e439b6ed746b90294d0b6916644a644bsalomon SkASSERT(resource); 3563f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon SkASSERT(!resource->wasDestroyed()); 3573f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon SkASSERT(flags); 35871cb0c241e439b6ed746b90294d0b6916644a644bsalomon SkASSERT(this->isInCache(resource)); 3593f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon // This resource should always be in the nonpurgeable array when this function is called. It 3603f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon // will be moved to the queue if it is newly purgeable. 3613f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon SkASSERT(fNonpurgeableResources[*resource->cacheAccess().accessCacheIndex()] == resource); 3623f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon 3633f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon if (SkToBool(ResourceAccess::kRefCntReachedZero_RefNotificationFlag & flags)) { 3643f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon#ifdef SK_DEBUG 3653f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon // When the timestamp overflows validate() is called. validate() checks that resources in 3663f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon // the nonpurgeable array are indeed not purgeable. However, the movement from the array to 3673f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon // the purgeable queue happens just below in this function. So we mark it as an exception. 3683f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon if (resource->isPurgeable()) { 3693f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon fNewlyPurgeableResourceForValidation = resource; 3703f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon } 3713f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon#endif 3723f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon resource->cacheAccess().setTimestamp(this->getNextTimestamp()); 37396fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkDEBUGCODE(fNewlyPurgeableResourceForValidation = nullptr); 3743f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon } 37571cb0c241e439b6ed746b90294d0b6916644a644bsalomon 3763f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon if (!SkToBool(ResourceAccess::kAllCntsReachedZero_RefNotificationFlag & flags)) { 3773f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon SkASSERT(!resource->isPurgeable()); 3783f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon return; 3793f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon } 3803f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon 3813f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon SkASSERT(resource->isPurgeable()); 382f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon this->removeFromNonpurgeableArray(resource); 3839f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon fPurgeableQueue.insert(resource); 384e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon resource->cacheAccess().setFlushCntWhenResourceBecamePurgeable(fExternalFlushCnt); 3855e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon resource->cacheAccess().setTimeWhenResourceBecomePurgeable(); 386ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger fPurgeableBytes += resource->gpuMemorySize(); 387c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon 3885ec26ae9bfca635ccc98283aad5deda11519d826bsalomon if (SkBudgeted::kNo == resource->resourcePriv().isBudgeted()) { 389c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon // Check whether this resource could still be used as a scratch resource. 3902e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen if (!resource->resourcePriv().refsWrappedObjects() && 3919f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon resource->resourcePriv().getScratchKey().isValid()) { 392c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon // We won't purge an existing resource to make room for this one. 393f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon if (fBudgetedCount < fMaxCount && 394f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon fBudgetedBytes + resource->gpuMemorySize() <= fMaxBytes) { 3953582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon resource->resourcePriv().makeBudgeted(); 3969f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon return; 397c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon } 398c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon } 399c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon } else { 4009f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon // Purge the resource immediately if we're over budget 4018718aafec239c93485e45bbe8fed19d9a8def079bsalomon // Also purge if the resource has neither a valid scratch key nor a unique key. 402ee843b2ae4d75748d8bc323287f0c310fad548a7robertphillips bool noKey = !resource->resourcePriv().getScratchKey().isValid() && 403ee843b2ae4d75748d8bc323287f0c310fad548a7robertphillips !resource->getUniqueKey().isValid(); 404ee843b2ae4d75748d8bc323287f0c310fad548a7robertphillips if (!this->overBudget() && !noKey) { 4059f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon return; 406c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon } 407c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon } 408dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon 409f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkDEBUGCODE(int beforeCount = this->getResourceCount();) 4109f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon resource->cacheAccess().release(); 4119f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon // We should at least free this resource, perhaps dependent resources as well. 412f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkASSERT(this->getResourceCount() < beforeCount); 41371cb0c241e439b6ed746b90294d0b6916644a644bsalomon this->validate(); 41471cb0c241e439b6ed746b90294d0b6916644a644bsalomon} 41571cb0c241e439b6ed746b90294d0b6916644a644bsalomon 4160ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomonvoid GrResourceCache::didChangeGpuMemorySize(const GrGpuResource* resource, size_t oldSize) { 41771cb0c241e439b6ed746b90294d0b6916644a644bsalomon // SkASSERT(!fPurging); GrPathRange increases size during flush. :( 41871cb0c241e439b6ed746b90294d0b6916644a644bsalomon SkASSERT(resource); 41971cb0c241e439b6ed746b90294d0b6916644a644bsalomon SkASSERT(this->isInCache(resource)); 42071cb0c241e439b6ed746b90294d0b6916644a644bsalomon 421dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon ptrdiff_t delta = resource->gpuMemorySize() - oldSize; 422dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon 423dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon fBytes += delta; 42482b1d620137f35fe48bc635bc74f638c9716710bbsalomon#if GR_CACHE_STATS 42582b1d620137f35fe48bc635bc74f638c9716710bbsalomon fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes); 42682b1d620137f35fe48bc635bc74f638c9716710bbsalomon#endif 4275ec26ae9bfca635ccc98283aad5deda11519d826bsalomon if (SkBudgeted::kYes == resource->resourcePriv().isBudgeted()) { 428dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon fBudgetedBytes += delta; 42939c08ac3be30f9956cea7c5e4fd9a1d86e993a65Brian Osman TRACE_COUNTER2("skia.gpu.cache", "skia budget", "used", 430876c3132d75966829ad58b2f9b2957d50457cc29hendrikw fBudgetedBytes, "free", fMaxBytes - fBudgetedBytes); 431dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon#if GR_CACHE_STATS 432dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes); 433dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon#endif 434dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon } 43571cb0c241e439b6ed746b90294d0b6916644a644bsalomon 43671cb0c241e439b6ed746b90294d0b6916644a644bsalomon this->purgeAsNeeded(); 43771cb0c241e439b6ed746b90294d0b6916644a644bsalomon this->validate(); 43871cb0c241e439b6ed746b90294d0b6916644a644bsalomon} 43971cb0c241e439b6ed746b90294d0b6916644a644bsalomon 4400ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomonvoid GrResourceCache::didChangeBudgetStatus(GrGpuResource* resource) { 44184c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon SkASSERT(resource); 44284c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon SkASSERT(this->isInCache(resource)); 44384c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon 44484c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon size_t size = resource->gpuMemorySize(); 44584c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon 4465ec26ae9bfca635ccc98283aad5deda11519d826bsalomon if (SkBudgeted::kYes == resource->resourcePriv().isBudgeted()) { 44784c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon ++fBudgetedCount; 44884c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon fBudgetedBytes += size; 449afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon#if GR_CACHE_STATS 450afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes); 451afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount); 452afe3005be3392e43bc51eb7eb2017eefaed85ad1bsalomon#endif 45384c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon this->purgeAsNeeded(); 45484c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon } else { 45584c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon --fBudgetedCount; 45684c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon fBudgetedBytes -= size; 45784c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon } 45839c08ac3be30f9956cea7c5e4fd9a1d86e993a65Brian Osman TRACE_COUNTER2("skia.gpu.cache", "skia budget", "used", 459876c3132d75966829ad58b2f9b2957d50457cc29hendrikw fBudgetedBytes, "free", fMaxBytes - fBudgetedBytes); 46084c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon 46184c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon this->validate(); 46284c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon} 46384c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon 464ee843b2ae4d75748d8bc323287f0c310fad548a7robertphillipsvoid GrResourceCache::purgeAsNeeded() { 4653f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon SkTArray<GrUniqueKeyInvalidatedMessage> invalidKeyMsgs; 4663f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon fInvalidUniqueKeyInbox.poll(&invalidKeyMsgs); 4673f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon if (invalidKeyMsgs.count()) { 4683f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon this->processInvalidUniqueKeys(invalidKeyMsgs); 4693f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon } 47071cb0c241e439b6ed746b90294d0b6916644a644bsalomon 47113dddce65fd87a8175a209a49f35615735a2886aBrian Osman this->processFreedGpuResources(); 47213dddce65fd87a8175a209a49f35615735a2886aBrian Osman 473e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon if (fMaxUnusedFlushes > 0) { 474e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon // We want to know how many complete flushes have occurred without the resource being used. 475e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon // If the resource was tagged when fExternalFlushCnt was N then this means it became 476e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon // purgeable during activity that became the N+1th flush. So when the flush count is N+2 477e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon // it has sat in the purgeable queue for one entire flush. 478e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon uint32_t oldestAllowedFlushCnt = fExternalFlushCnt - fMaxUnusedFlushes - 1; 479e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon // check for underflow 480e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon if (oldestAllowedFlushCnt < fExternalFlushCnt) { 481e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon while (fPurgeableQueue.count()) { 482e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon uint32_t flushWhenResourceBecamePurgeable = 483e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon fPurgeableQueue.peek()->cacheAccess().flushCntWhenResourceBecamePurgeable(); 484e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon if (oldestAllowedFlushCnt < flushWhenResourceBecamePurgeable) { 485e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon // Resources were given both LRU timestamps and tagged with a flush cnt when 486e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon // they first became purgeable. The LRU timestamp won't change again until the 487e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon // resource is made non-purgeable again. So, at this point all the remaining 488e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon // resources in the timestamp-sorted queue will have a flush count >= to this 489e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon // one. 490e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon break; 491e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon } 492e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon GrGpuResource* resource = fPurgeableQueue.peek(); 493e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon SkASSERT(resource->isPurgeable()); 494e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon resource->cacheAccess().release(); 4953f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon } 4963f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon } 4973f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon } 4983f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon 4993f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon bool stillOverbudget = this->overBudget(); 5003f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon while (stillOverbudget && fPurgeableQueue.count()) { 501ee843b2ae4d75748d8bc323287f0c310fad548a7robertphillips GrGpuResource* resource = fPurgeableQueue.peek(); 5029f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon SkASSERT(resource->isPurgeable()); 5039f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon resource->cacheAccess().release(); 5043f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon stillOverbudget = this->overBudget(); 5059f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon } 50671cb0c241e439b6ed746b90294d0b6916644a644bsalomon 507b436ed6754452d7acb6c70e70307904c8f4a50e7bsalomon this->validate(); 508ee843b2ae4d75748d8bc323287f0c310fad548a7robertphillips 509ee843b2ae4d75748d8bc323287f0c310fad548a7robertphillips if (stillOverbudget) { 510ee843b2ae4d75748d8bc323287f0c310fad548a7robertphillips // Set this so that GrDrawingManager will issue a flush to free up resources with pending 511ee843b2ae4d75748d8bc323287f0c310fad548a7robertphillips // IO that we were unable to purge in this pass. 512ee843b2ae4d75748d8bc323287f0c310fad548a7robertphillips fRequestFlush = true; 513ee843b2ae4d75748d8bc323287f0c310fad548a7robertphillips } 51471cb0c241e439b6ed746b90294d0b6916644a644bsalomon} 51571cb0c241e439b6ed746b90294d0b6916644a644bsalomon 51647710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillipsvoid GrResourceCache::purgeUnlockedResources(bool scratchResourcesOnly) { 51747710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips if (!scratchResourcesOnly) { 51847710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips // We could disable maintaining the heap property here, but it would add a lot of 51947710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips // complexity. Moreover, this is rarely called. 52047710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips while (fPurgeableQueue.count()) { 52147710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips GrGpuResource* resource = fPurgeableQueue.peek(); 52247710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips SkASSERT(resource->isPurgeable()); 52347710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips resource->cacheAccess().release(); 52447710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips } 52547710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips } else { 52647710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips // Sort the queue 52747710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips fPurgeableQueue.sort(); 52847710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips 52947710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips // Make a list of the scratch resources to delete 53047710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips SkTDArray<GrGpuResource*> scratchResources; 53147710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips for (int i = 0; i < fPurgeableQueue.count(); i++) { 53247710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips GrGpuResource* resource = fPurgeableQueue.at(i); 53347710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips SkASSERT(resource->isPurgeable()); 53447710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips if (!resource->getUniqueKey().isValid()) { 53547710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips *scratchResources.append() = resource; 53647710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips } 53747710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips } 53847710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips 53947710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips // Delete the scratch resources. This must be done as a separate pass 54047710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips // to avoid messing up the sorted order of the queue 54147710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips for (int i = 0; i < scratchResources.count(); i++) { 54247710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips scratchResources.getAt(i)->cacheAccess().release(); 54347710a52505e9b8d2ae6ef8521f6b7a022542b9eRobert Phillips } 5449f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon } 54571cb0c241e439b6ed746b90294d0b6916644a644bsalomon 546b436ed6754452d7acb6c70e70307904c8f4a50e7bsalomon this->validate(); 54771cb0c241e439b6ed746b90294d0b6916644a644bsalomon} 54871cb0c241e439b6ed746b90294d0b6916644a644bsalomon 5495e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomonvoid GrResourceCache::purgeResourcesNotUsedSince(GrStdSteadyClock::time_point purgeTime) { 5505e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon while (fPurgeableQueue.count()) { 5515e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon const GrStdSteadyClock::time_point resourceTime = 5525e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon fPurgeableQueue.peek()->cacheAccess().timeWhenResourceBecamePurgeable(); 5535e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon if (resourceTime >= purgeTime) { 5545e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon // Resources were given both LRU timestamps and tagged with a frame number when 5555e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon // they first became purgeable. The LRU timestamp won't change again until the 5565e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon // resource is made non-purgeable again. So, at this point all the remaining 5575e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon // resources in the timestamp-sorted queue will have a frame number >= to this 5585e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon // one. 5595e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon break; 5605e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon } 5615e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon GrGpuResource* resource = fPurgeableQueue.peek(); 5625e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon SkASSERT(resource->isPurgeable()); 5635e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon resource->cacheAccess().release(); 5645e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon } 5655e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon} 5665e150851d0dd5ddb161449b44edf1bf52d18ac5aBrian Salomon 5675480a18d8799511034d0da219c72932cd8f25274Derek Sollenbergervoid GrResourceCache::purgeUnlockedResources(size_t bytesToPurge, bool preferScratchResources) { 5685480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger 5695480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger const size_t tmpByteBudget = SkTMax((size_t)0, fBytes - bytesToPurge); 5705480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger bool stillOverbudget = tmpByteBudget < fBytes; 5715480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger 5725480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger if (preferScratchResources && bytesToPurge < fPurgeableBytes) { 5735480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger // Sort the queue 5745480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger fPurgeableQueue.sort(); 5755480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger 5765480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger // Make a list of the scratch resources to delete 5775480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger SkTDArray<GrGpuResource*> scratchResources; 5785480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger size_t scratchByteCount = 0; 5795480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger for (int i = 0; i < fPurgeableQueue.count() && stillOverbudget; i++) { 5805480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger GrGpuResource* resource = fPurgeableQueue.at(i); 5815480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger SkASSERT(resource->isPurgeable()); 5825480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger if (!resource->getUniqueKey().isValid()) { 5835480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger *scratchResources.append() = resource; 5845480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger scratchByteCount += resource->gpuMemorySize(); 5855480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger stillOverbudget = tmpByteBudget < fBytes - scratchByteCount; 5865480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger } 5875480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger } 5885480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger 5895480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger // Delete the scratch resources. This must be done as a separate pass 5905480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger // to avoid messing up the sorted order of the queue 5915480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger for (int i = 0; i < scratchResources.count(); i++) { 5925480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger scratchResources.getAt(i)->cacheAccess().release(); 5935480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger } 5945480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger stillOverbudget = tmpByteBudget < fBytes; 5955480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger 5965480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger this->validate(); 5975480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger } 5985480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger 5995480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger // Purge any remaining resources in LRU order 6005480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger if (stillOverbudget) { 6015480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger const size_t cachedByteCount = fMaxBytes; 6025480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger fMaxBytes = tmpByteBudget; 6035480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger this->purgeAsNeeded(); 6045480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger fMaxBytes = cachedByteCount; 6055480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger } 6065480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger} 6075480a18d8799511034d0da219c72932cd8f25274Derek Sollenberger 6088718aafec239c93485e45bbe8fed19d9a8def079bsalomonvoid GrResourceCache::processInvalidUniqueKeys( 6091afd4cdb0800e2e395b465da24eb71e0e834dafaRobert Phillips const SkTArray<GrUniqueKeyInvalidatedMessage>& msgs) { 6101afd4cdb0800e2e395b465da24eb71e0e834dafaRobert Phillips SkASSERT(fProxyProvider); // better have called setProxyProvider 6111afd4cdb0800e2e395b465da24eb71e0e834dafaRobert Phillips 61223e619cf462b2a8a500f3ca750e099f79601f508bsalomon for (int i = 0; i < msgs.count(); ++i) { 6131afd4cdb0800e2e395b465da24eb71e0e834dafaRobert Phillips fProxyProvider->processInvalidProxyUniqueKey(msgs[i].key()); 614ae7d3f3992708354a3284bb49066737e36a76f40Robert Phillips 6158718aafec239c93485e45bbe8fed19d9a8def079bsalomon GrGpuResource* resource = this->findAndRefUniqueResource(msgs[i].key()); 61623e619cf462b2a8a500f3ca750e099f79601f508bsalomon if (resource) { 6178718aafec239c93485e45bbe8fed19d9a8def079bsalomon resource->resourcePriv().removeUniqueKey(); 6183f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon resource->unref(); // If this resource is now purgeable, the cache will be notified. 61923e619cf462b2a8a500f3ca750e099f79601f508bsalomon } 62023e619cf462b2a8a500f3ca750e099f79601f508bsalomon } 62123e619cf462b2a8a500f3ca750e099f79601f508bsalomon} 62223e619cf462b2a8a500f3ca750e099f79601f508bsalomon 62313dddce65fd87a8175a209a49f35615735a2886aBrian Osmanvoid GrResourceCache::insertCrossContextGpuResource(GrGpuResource* resource) { 62413dddce65fd87a8175a209a49f35615735a2886aBrian Osman resource->ref(); 62513dddce65fd87a8175a209a49f35615735a2886aBrian Osman} 62613dddce65fd87a8175a209a49f35615735a2886aBrian Osman 62713dddce65fd87a8175a209a49f35615735a2886aBrian Osmanvoid GrResourceCache::processFreedGpuResources() { 62813dddce65fd87a8175a209a49f35615735a2886aBrian Osman SkTArray<GrGpuResourceFreedMessage> msgs; 62913dddce65fd87a8175a209a49f35615735a2886aBrian Osman fFreedGpuResourceInbox.poll(&msgs); 63013dddce65fd87a8175a209a49f35615735a2886aBrian Osman for (int i = 0; i < msgs.count(); ++i) { 63113dddce65fd87a8175a209a49f35615735a2886aBrian Osman if (msgs[i].fOwningUniqueID == fContextUniqueID) { 63213dddce65fd87a8175a209a49f35615735a2886aBrian Osman msgs[i].fResource->unref(); 63313dddce65fd87a8175a209a49f35615735a2886aBrian Osman } 63413dddce65fd87a8175a209a49f35615735a2886aBrian Osman } 63513dddce65fd87a8175a209a49f35615735a2886aBrian Osman} 63613dddce65fd87a8175a209a49f35615735a2886aBrian Osman 637f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomonvoid GrResourceCache::addToNonpurgeableArray(GrGpuResource* resource) { 638f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon int index = fNonpurgeableResources.count(); 639f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon *fNonpurgeableResources.append() = resource; 640f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon *resource->cacheAccess().accessCacheIndex() = index; 641f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon} 642f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon 643f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomonvoid GrResourceCache::removeFromNonpurgeableArray(GrGpuResource* resource) { 644f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon int* index = resource->cacheAccess().accessCacheIndex(); 645f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon // Fill the whole we will create in the array with the tail object, adjust its index, and 646f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon // then pop the array 647f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon GrGpuResource* tail = *(fNonpurgeableResources.end() - 1); 648f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkASSERT(fNonpurgeableResources[*index] == resource); 649f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon fNonpurgeableResources[*index] = tail; 650f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon *tail->cacheAccess().accessCacheIndex() = *index; 651f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon fNonpurgeableResources.pop(); 652f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkDEBUGCODE(*index = -1); 653f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon} 654f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon 655ddf30e64fe474847b204d7062fad3341d245062cbsalomonuint32_t GrResourceCache::getNextTimestamp() { 656ddf30e64fe474847b204d7062fad3341d245062cbsalomon // If we wrap then all the existing resources will appear older than any resources that get 657ddf30e64fe474847b204d7062fad3341d245062cbsalomon // a timestamp after the wrap. 658ddf30e64fe474847b204d7062fad3341d245062cbsalomon if (0 == fTimestamp) { 659ddf30e64fe474847b204d7062fad3341d245062cbsalomon int count = this->getResourceCount(); 660ddf30e64fe474847b204d7062fad3341d245062cbsalomon if (count) { 661ddf30e64fe474847b204d7062fad3341d245062cbsalomon // Reset all the timestamps. We sort the resources by timestamp and then assign 662ddf30e64fe474847b204d7062fad3341d245062cbsalomon // sequential timestamps beginning with 0. This is O(n*lg(n)) but it should be extremely 663ddf30e64fe474847b204d7062fad3341d245062cbsalomon // rare. 664ddf30e64fe474847b204d7062fad3341d245062cbsalomon SkTDArray<GrGpuResource*> sortedPurgeableResources; 665ddf30e64fe474847b204d7062fad3341d245062cbsalomon sortedPurgeableResources.setReserve(fPurgeableQueue.count()); 666ddf30e64fe474847b204d7062fad3341d245062cbsalomon 667ddf30e64fe474847b204d7062fad3341d245062cbsalomon while (fPurgeableQueue.count()) { 668ddf30e64fe474847b204d7062fad3341d245062cbsalomon *sortedPurgeableResources.append() = fPurgeableQueue.peek(); 669ddf30e64fe474847b204d7062fad3341d245062cbsalomon fPurgeableQueue.pop(); 670ddf30e64fe474847b204d7062fad3341d245062cbsalomon } 671ee843b2ae4d75748d8bc323287f0c310fad548a7robertphillips 672e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon SkTQSort(fNonpurgeableResources.begin(), fNonpurgeableResources.end() - 1, 673e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon CompareTimestamp); 674ddf30e64fe474847b204d7062fad3341d245062cbsalomon 675ddf30e64fe474847b204d7062fad3341d245062cbsalomon // Pick resources out of the purgeable and non-purgeable arrays based on lowest 676ddf30e64fe474847b204d7062fad3341d245062cbsalomon // timestamp and assign new timestamps. 677ddf30e64fe474847b204d7062fad3341d245062cbsalomon int currP = 0; 678ddf30e64fe474847b204d7062fad3341d245062cbsalomon int currNP = 0; 679ddf30e64fe474847b204d7062fad3341d245062cbsalomon while (currP < sortedPurgeableResources.count() && 68056da02502019cfbb817898e37e320539b9838e2bmtklein currNP < fNonpurgeableResources.count()) { 681ddf30e64fe474847b204d7062fad3341d245062cbsalomon uint32_t tsP = sortedPurgeableResources[currP]->cacheAccess().timestamp(); 682ddf30e64fe474847b204d7062fad3341d245062cbsalomon uint32_t tsNP = fNonpurgeableResources[currNP]->cacheAccess().timestamp(); 683ddf30e64fe474847b204d7062fad3341d245062cbsalomon SkASSERT(tsP != tsNP); 684ddf30e64fe474847b204d7062fad3341d245062cbsalomon if (tsP < tsNP) { 685ddf30e64fe474847b204d7062fad3341d245062cbsalomon sortedPurgeableResources[currP++]->cacheAccess().setTimestamp(fTimestamp++); 686ddf30e64fe474847b204d7062fad3341d245062cbsalomon } else { 687ddf30e64fe474847b204d7062fad3341d245062cbsalomon // Correct the index in the nonpurgeable array stored on the resource post-sort. 688ddf30e64fe474847b204d7062fad3341d245062cbsalomon *fNonpurgeableResources[currNP]->cacheAccess().accessCacheIndex() = currNP; 689ddf30e64fe474847b204d7062fad3341d245062cbsalomon fNonpurgeableResources[currNP++]->cacheAccess().setTimestamp(fTimestamp++); 690ddf30e64fe474847b204d7062fad3341d245062cbsalomon } 691ddf30e64fe474847b204d7062fad3341d245062cbsalomon } 692ddf30e64fe474847b204d7062fad3341d245062cbsalomon 693ddf30e64fe474847b204d7062fad3341d245062cbsalomon // The above loop ended when we hit the end of one array. Finish the other one. 694ddf30e64fe474847b204d7062fad3341d245062cbsalomon while (currP < sortedPurgeableResources.count()) { 695ddf30e64fe474847b204d7062fad3341d245062cbsalomon sortedPurgeableResources[currP++]->cacheAccess().setTimestamp(fTimestamp++); 696ddf30e64fe474847b204d7062fad3341d245062cbsalomon } 697ddf30e64fe474847b204d7062fad3341d245062cbsalomon while (currNP < fNonpurgeableResources.count()) { 698ddf30e64fe474847b204d7062fad3341d245062cbsalomon *fNonpurgeableResources[currNP]->cacheAccess().accessCacheIndex() = currNP; 699ddf30e64fe474847b204d7062fad3341d245062cbsalomon fNonpurgeableResources[currNP++]->cacheAccess().setTimestamp(fTimestamp++); 700ddf30e64fe474847b204d7062fad3341d245062cbsalomon } 701ddf30e64fe474847b204d7062fad3341d245062cbsalomon 702ddf30e64fe474847b204d7062fad3341d245062cbsalomon // Rebuild the queue. 703ddf30e64fe474847b204d7062fad3341d245062cbsalomon for (int i = 0; i < sortedPurgeableResources.count(); ++i) { 704ddf30e64fe474847b204d7062fad3341d245062cbsalomon fPurgeableQueue.insert(sortedPurgeableResources[i]); 705ddf30e64fe474847b204d7062fad3341d245062cbsalomon } 706ddf30e64fe474847b204d7062fad3341d245062cbsalomon 707ddf30e64fe474847b204d7062fad3341d245062cbsalomon this->validate(); 708ddf30e64fe474847b204d7062fad3341d245062cbsalomon SkASSERT(count == this->getResourceCount()); 709ddf30e64fe474847b204d7062fad3341d245062cbsalomon 710ddf30e64fe474847b204d7062fad3341d245062cbsalomon // count should be the next timestamp we return. 711ddf30e64fe474847b204d7062fad3341d245062cbsalomon SkASSERT(fTimestamp == SkToU32(count)); 71256da02502019cfbb817898e37e320539b9838e2bmtklein } 713ddf30e64fe474847b204d7062fad3341d245062cbsalomon } 714ddf30e64fe474847b204d7062fad3341d245062cbsalomon return fTimestamp++; 715ddf30e64fe474847b204d7062fad3341d245062cbsalomon} 716ddf30e64fe474847b204d7062fad3341d245062cbsalomon 717b77a907c2fb4402b7e70e9fff70eb71482354e67bsalomonvoid GrResourceCache::notifyFlushOccurred(FlushType type) { 718b77a907c2fb4402b7e70e9fff70eb71482354e67bsalomon switch (type) { 719b77a907c2fb4402b7e70e9fff70eb71482354e67bsalomon case FlushType::kCacheRequested: 720ee843b2ae4d75748d8bc323287f0c310fad548a7robertphillips SkASSERT(fRequestFlush); 721ee843b2ae4d75748d8bc323287f0c310fad548a7robertphillips fRequestFlush = false; 722b77a907c2fb4402b7e70e9fff70eb71482354e67bsalomon break; 723ee843b2ae4d75748d8bc323287f0c310fad548a7robertphillips case FlushType::kExternal: 724e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon ++fExternalFlushCnt; 725e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon if (0 == fExternalFlushCnt) { 726e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon // When this wraps just reset all the purgeable resources' last used flush state. 727e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon for (int i = 0; i < fPurgeableQueue.count(); ++i) { 728e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon fPurgeableQueue.at(i)->cacheAccess().setFlushCntWhenResourceBecamePurgeable(0); 729e2e87f3484e5524dbfd6c01f402136738d1d434bbsalomon } 730b77a907c2fb4402b7e70e9fff70eb71482354e67bsalomon } 731b77a907c2fb4402b7e70e9fff70eb71482354e67bsalomon break; 7323f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon } 733ee843b2ae4d75748d8bc323287f0c310fad548a7robertphillips this->purgeAsNeeded(); 7343f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon} 7353f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon 7360a5fa484fd58d27088f8696bdc11c8cc8f2b4866ericrkvoid GrResourceCache::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const { 7370a5fa484fd58d27088f8696bdc11c8cc8f2b4866ericrk for (int i = 0; i < fNonpurgeableResources.count(); ++i) { 7380a5fa484fd58d27088f8696bdc11c8cc8f2b4866ericrk fNonpurgeableResources[i]->dumpMemoryStatistics(traceMemoryDump); 7390a5fa484fd58d27088f8696bdc11c8cc8f2b4866ericrk } 7400a5fa484fd58d27088f8696bdc11c8cc8f2b4866ericrk for (int i = 0; i < fPurgeableQueue.count(); ++i) { 7410a5fa484fd58d27088f8696bdc11c8cc8f2b4866ericrk fPurgeableQueue.at(i)->dumpMemoryStatistics(traceMemoryDump); 7420a5fa484fd58d27088f8696bdc11c8cc8f2b4866ericrk } 7430a5fa484fd58d27088f8696bdc11c8cc8f2b4866ericrk} 7440a5fa484fd58d27088f8696bdc11c8cc8f2b4866ericrk 74571cb0c241e439b6ed746b90294d0b6916644a644bsalomon#ifdef SK_DEBUG 7460ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomonvoid GrResourceCache::validate() const { 747c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon // Reduce the frequency of validations for large resource counts. 748c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon static SkRandom gRandom; 749c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon int mask = (SkNextPow2(fCount + 1) >> 5) - 1; 750c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon if (~mask && (gRandom.nextU() & mask)) { 751c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon return; 752c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon } 753c2f35b750a57d7dc0b8053a98279631d1ccb9b56bsalomon 754f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon struct Stats { 755f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon size_t fBytes; 756f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon int fBudgetedCount; 757f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon size_t fBudgetedBytes; 758f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon int fLocked; 759f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon int fScratch; 760f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon int fCouldBeScratch; 761f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon int fContent; 762f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon const ScratchMap* fScratchMap; 7638718aafec239c93485e45bbe8fed19d9a8def079bsalomon const UniqueHash* fUniqueHash; 764f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon 765f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon Stats(const GrResourceCache* cache) { 766f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon memset(this, 0, sizeof(*this)); 767f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon fScratchMap = &cache->fScratchMap; 7688718aafec239c93485e45bbe8fed19d9a8def079bsalomon fUniqueHash = &cache->fUniqueHash; 76971cb0c241e439b6ed746b90294d0b6916644a644bsalomon } 77071cb0c241e439b6ed746b90294d0b6916644a644bsalomon 771f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon void update(GrGpuResource* resource) { 772f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon fBytes += resource->gpuMemorySize(); 773dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon 774f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon if (!resource->isPurgeable()) { 775f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon ++fLocked; 776f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon } 7779f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon 778c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips const GrScratchKey& scratchKey = resource->resourcePriv().getScratchKey(); 779c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips const GrUniqueKey& uniqueKey = resource->getUniqueKey(); 780c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips 781f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon if (resource->cacheAccess().isScratch()) { 782c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips SkASSERT(!uniqueKey.isValid()); 783f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon ++fScratch; 784c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips SkASSERT(fScratchMap->countForKey(scratchKey)); 7852e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen SkASSERT(!resource->resourcePriv().refsWrappedObjects()); 786c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips } else if (scratchKey.isValid()) { 7875ec26ae9bfca635ccc98283aad5deda11519d826bsalomon SkASSERT(SkBudgeted::kNo == resource->resourcePriv().isBudgeted() || 788c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips uniqueKey.isValid()); 789c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips if (!uniqueKey.isValid()) { 7904e97607d9a1cef66fac16f347c5ca813ec4f9515mtklein ++fCouldBeScratch; 791c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips SkASSERT(fScratchMap->countForKey(scratchKey)); 792c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips } 7932e6055b3ea14a04fcde1ac1974a70bf00b1e295bkkinnunen SkASSERT(!resource->resourcePriv().refsWrappedObjects()); 794f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon } 7958718aafec239c93485e45bbe8fed19d9a8def079bsalomon if (uniqueKey.isValid()) { 796f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon ++fContent; 7978718aafec239c93485e45bbe8fed19d9a8def079bsalomon SkASSERT(fUniqueHash->find(uniqueKey) == resource); 7980562eb9c6c98f07732ca96a1dd4e986f1ca089b8Brian Osman SkASSERT(SkBudgeted::kYes == resource->resourcePriv().isBudgeted() || 7990562eb9c6c98f07732ca96a1dd4e986f1ca089b8Brian Osman resource->resourcePriv().refsWrappedObjects()); 800c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips 801c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips if (scratchKey.isValid()) { 802c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips SkASSERT(!fScratchMap->has(resource, scratchKey)); 803c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips } 804f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon } 805f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon 8065ec26ae9bfca635ccc98283aad5deda11519d826bsalomon if (SkBudgeted::kYes == resource->resourcePriv().isBudgeted()) { 807f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon ++fBudgetedCount; 808f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon fBudgetedBytes += resource->gpuMemorySize(); 809f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon } 8109f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon } 811f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon }; 8129f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon 813c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips { 814c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips ScratchMap::ConstIter iter(&fScratchMap); 815c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips 816c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips int count = 0; 817c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips for ( ; !iter.done(); ++iter) { 818c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips const GrGpuResource* resource = *iter; 819c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips SkASSERT(resource->resourcePriv().getScratchKey().isValid()); 820c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips SkASSERT(!resource->getUniqueKey().isValid()); 821c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips count++; 822c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips } 823c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips SkASSERT(count == fScratchMap.count()); // ensure the iterator is working correctly 824c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips } 825c4ed68426649dd4ca2c3119cdafdd562d3c3ba28robertphillips 826f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon Stats stats(this); 827ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger size_t purgeableBytes = 0; 828f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon 829f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon for (int i = 0; i < fNonpurgeableResources.count(); ++i) { 8303f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon SkASSERT(!fNonpurgeableResources[i]->isPurgeable() || 8313f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon fNewlyPurgeableResourceForValidation == fNonpurgeableResources[i]); 832f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkASSERT(*fNonpurgeableResources[i]->cacheAccess().accessCacheIndex() == i); 833f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkASSERT(!fNonpurgeableResources[i]->wasDestroyed()); 834f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon stats.update(fNonpurgeableResources[i]); 835f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon } 8369f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon for (int i = 0; i < fPurgeableQueue.count(); ++i) { 8379f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon SkASSERT(fPurgeableQueue.at(i)->isPurgeable()); 838f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkASSERT(*fPurgeableQueue.at(i)->cacheAccess().accessCacheIndex() == i); 839f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkASSERT(!fPurgeableQueue.at(i)->wasDestroyed()); 840f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon stats.update(fPurgeableQueue.at(i)); 841ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger purgeableBytes += fPurgeableQueue.at(i)->gpuMemorySize(); 84271cb0c241e439b6ed746b90294d0b6916644a644bsalomon } 84371cb0c241e439b6ed746b90294d0b6916644a644bsalomon 844f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkASSERT(fCount == this->getResourceCount()); 845dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon SkASSERT(fBudgetedCount <= fCount); 846f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkASSERT(fBudgetedBytes <= fBytes); 847f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkASSERT(stats.fBytes == fBytes); 848f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkASSERT(stats.fBudgetedBytes == fBudgetedBytes); 849f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkASSERT(stats.fBudgetedCount == fBudgetedCount); 850ee47914ae5661043c20754f46523665a6d31bc73Derek Sollenberger SkASSERT(purgeableBytes == fPurgeableBytes); 85171cb0c241e439b6ed746b90294d0b6916644a644bsalomon#if GR_CACHE_STATS 852dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon SkASSERT(fBudgetedHighWaterCount <= fHighWaterCount); 853dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon SkASSERT(fBudgetedHighWaterBytes <= fHighWaterBytes); 854f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkASSERT(fBytes <= fHighWaterBytes); 855f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkASSERT(fCount <= fHighWaterCount); 856f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkASSERT(fBudgetedBytes <= fBudgetedHighWaterBytes); 857f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkASSERT(fBudgetedCount <= fBudgetedHighWaterCount); 85871cb0c241e439b6ed746b90294d0b6916644a644bsalomon#endif 8598718aafec239c93485e45bbe8fed19d9a8def079bsalomon SkASSERT(stats.fContent == fUniqueHash.count()); 860f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkASSERT(stats.fScratch + stats.fCouldBeScratch == fScratchMap.count()); 86171cb0c241e439b6ed746b90294d0b6916644a644bsalomon 8623f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon // This assertion is not currently valid because we can be in recursive notifyCntReachedZero() 86312299ab7a1be5f4b99284ecf289d46107ef0a946bsalomon // calls. This will be fixed when subresource registration is explicit. 864dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon // bool overBudget = budgetedBytes > fMaxBytes || budgetedCount > fMaxCount; 86512299ab7a1be5f4b99284ecf289d46107ef0a946bsalomon // SkASSERT(!overBudget || locked == count || fPurging); 86671cb0c241e439b6ed746b90294d0b6916644a644bsalomon} 867f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon 868f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomonbool GrResourceCache::isInCache(const GrGpuResource* resource) const { 869f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon int index = *resource->cacheAccess().accessCacheIndex(); 870f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon if (index < 0) { 871f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon return false; 872f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon } 873f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon if (index < fPurgeableQueue.count() && fPurgeableQueue.at(index) == resource) { 874f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon return true; 875f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon } 876f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon if (index < fNonpurgeableResources.count() && fNonpurgeableResources[index] == resource) { 877f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon return true; 878f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon } 879f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkDEBUGFAIL("Resource index should be -1 or the resource should be in the cache."); 880f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon return false; 881f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon} 882f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon 88371cb0c241e439b6ed746b90294d0b6916644a644bsalomon#endif 884