1c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon 2c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon/* 3c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon * Copyright 2014 Google Inc. 4c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon * 5c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon * Use of this source code is governed by a BSD-style license that can be 6c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon * found in the LICENSE file. 7c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon */ 8c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon 90ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon#ifndef GrResourceCache_DEFINED 100ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon#define GrResourceCache_DEFINED 11c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon 12744998e666073166307d2522847b2536000a7619bsalomon#include "GrGpuResource.h" 139f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon#include "GrGpuResourceCacheAccess.h" 143582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon#include "GrGpuResourcePriv.h" 15744998e666073166307d2522847b2536000a7619bsalomon#include "GrResourceKey.h" 1623e619cf462b2a8a500f3ca750e099f79601f508bsalomon#include "SkMessageBus.h" 178b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon#include "SkRefCnt.h" 1823e619cf462b2a8a500f3ca750e099f79601f508bsalomon#include "SkTArray.h" 199f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon#include "SkTDPQueue.h" 20c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon#include "SkTInternalLList.h" 21744998e666073166307d2522847b2536000a7619bsalomon#include "SkTMultiMap.h" 22c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon 2363926683c583e8497d9d907977e773663cb4bd9erobertphillipsclass GrCaps; 24b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtkleinclass SkString; 250a5fa484fd58d27088f8696bdc11c8cc8f2b4866ericrkclass SkTraceMemoryDump; 26b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtklein 27c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon/** 2871cb0c241e439b6ed746b90294d0b6916644a644bsalomon * Manages the lifetime of all GrGpuResource instances. 2971cb0c241e439b6ed746b90294d0b6916644a644bsalomon * 3071cb0c241e439b6ed746b90294d0b6916644a644bsalomon * Resources may have optionally have two types of keys: 3171cb0c241e439b6ed746b90294d0b6916644a644bsalomon * 1) A scratch key. This is for resources whose allocations are cached but not their contents. 3271cb0c241e439b6ed746b90294d0b6916644a644bsalomon * Multiple resources can share the same scratch key. This is so a caller can have two 3384c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon * resource instances with the same properties (e.g. multipass rendering that ping-pongs 348718aafec239c93485e45bbe8fed19d9a8def079bsalomon * between two temporary surfaces). The scratch key is set at resource creation time and 3571cb0c241e439b6ed746b90294d0b6916644a644bsalomon * should never change. Resources need not have a scratch key. 368718aafec239c93485e45bbe8fed19d9a8def079bsalomon * 2) A unique key. This key's meaning is specific to the domain that created the key. Only one 37f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon * resource may have a given unique key. The unique key can be set, cleared, or changed 38f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon * anytime after resource creation. 39f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon * 408718aafec239c93485e45bbe8fed19d9a8def079bsalomon * A unique key always takes precedence over a scratch key when a resource has both types of keys. 4171cb0c241e439b6ed746b90294d0b6916644a644bsalomon * If a resource has neither key type then it will be deleted as soon as the last reference to it 428718aafec239c93485e45bbe8fed19d9a8def079bsalomon * is dropped. 433f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * 443f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * When proactive purging is enabled, on every flush, the timestamp of that flush is stored in a 453f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * n-sized ring buffer. When purging occurs each purgeable resource's timestamp is compared to the 463f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * timestamp of the n-th prior flush. If the resource's last use timestamp is older than the old 473f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * flush then the resource is proactively purged even when the cache is under budget. By default 483f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * this feature is disabled, though it can be enabled by calling GrResourceCache::setLimits. 49c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon */ 500ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomonclass GrResourceCache { 51c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomonpublic: 5263926683c583e8497d9d907977e773663cb4bd9erobertphillips GrResourceCache(const GrCaps* caps); 530ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon ~GrResourceCache(); 54c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon 553f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon // Default maximum number of budgeted resources in the cache. 563f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon static const int kDefaultMaxCount = 2 * (1 << 12); 573f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon // Default maximum number of bytes of gpu memory of budgeted resources in the cache. 583f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon static const size_t kDefaultMaxSize = 96 * (1 << 20); 593f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon // Default number of flushes a budgeted resources can go unused in the cache before it is 603f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon // purged. Large values disable the feature (as the ring buffer of flush timestamps would be 61c03bdfa8e653fbdcb6b9f59ce862e00212e7c419bsalomon // large). This is currently the default until we decide to enable this feature 62c03bdfa8e653fbdcb6b9f59ce862e00212e7c419bsalomon // of the cache by default. 639f0337ed4b5b5f7b3a049175365658470061b3cbbsalomon static const int kDefaultMaxUnusedFlushes = 64; 643f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon 6571cb0c241e439b6ed746b90294d0b6916644a644bsalomon /** Used to access functionality needed by GrGpuResource for lifetime management. */ 6671cb0c241e439b6ed746b90294d0b6916644a644bsalomon class ResourceAccess; 6771cb0c241e439b6ed746b90294d0b6916644a644bsalomon ResourceAccess resourceAccess(); 68407aa584d183c1bf314f5defd1cf0202e8a96c89bsalomon 6971cb0c241e439b6ed746b90294d0b6916644a644bsalomon /** 703f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * Sets the cache limits in terms of number of resources, max gpu memory byte size, and number 713f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * of GrContext flushes that a resource can be unused before it is evicted. The latter value is 723f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * a suggestion and there is no promise that a resource will be purged immediately after it 733f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * hasn't been used in maxUnusedFlushes flushes. 7471cb0c241e439b6ed746b90294d0b6916644a644bsalomon */ 753f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon void setLimits(int count, size_t bytes, int maxUnusedFlushes = kDefaultMaxUnusedFlushes); 7666a450f21a3da174b7eed89a1d5fc8591e8b6ee6bsalomon 7771cb0c241e439b6ed746b90294d0b6916644a644bsalomon /** 78dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon * Returns the number of resources. 7971cb0c241e439b6ed746b90294d0b6916644a644bsalomon */ 80f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon int getResourceCount() const { 81f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon return fPurgeableQueue.count() + fNonpurgeableResources.count(); 82f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon } 8371cb0c241e439b6ed746b90294d0b6916644a644bsalomon 8471cb0c241e439b6ed746b90294d0b6916644a644bsalomon /** 85dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon * Returns the number of resources that count against the budget. 86dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon */ 87dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon int getBudgetedResourceCount() const { return fBudgetedCount; } 88dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon 89dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon /** 90dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon * Returns the number of bytes consumed by resources. 9171cb0c241e439b6ed746b90294d0b6916644a644bsalomon */ 9271cb0c241e439b6ed746b90294d0b6916644a644bsalomon size_t getResourceBytes() const { return fBytes; } 9371cb0c241e439b6ed746b90294d0b6916644a644bsalomon 9471cb0c241e439b6ed746b90294d0b6916644a644bsalomon /** 95dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon * Returns the number of bytes consumed by budgeted resources. 96dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon */ 97dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon size_t getBudgetedResourceBytes() const { return fBudgetedBytes; } 98dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon 99dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon /** 10071cb0c241e439b6ed746b90294d0b6916644a644bsalomon * Returns the cached resources count budget. 10171cb0c241e439b6ed746b90294d0b6916644a644bsalomon */ 10271cb0c241e439b6ed746b90294d0b6916644a644bsalomon int getMaxResourceCount() const { return fMaxCount; } 103407aa584d183c1bf314f5defd1cf0202e8a96c89bsalomon 10471cb0c241e439b6ed746b90294d0b6916644a644bsalomon /** 10571cb0c241e439b6ed746b90294d0b6916644a644bsalomon * Returns the number of bytes consumed by cached resources. 10671cb0c241e439b6ed746b90294d0b6916644a644bsalomon */ 10771cb0c241e439b6ed746b90294d0b6916644a644bsalomon size_t getMaxResourceBytes() const { return fMaxBytes; } 10871cb0c241e439b6ed746b90294d0b6916644a644bsalomon 10971cb0c241e439b6ed746b90294d0b6916644a644bsalomon /** 11071cb0c241e439b6ed746b90294d0b6916644a644bsalomon * Abandons the backend API resources owned by all GrGpuResource objects and removes them from 11171cb0c241e439b6ed746b90294d0b6916644a644bsalomon * the cache. 11271cb0c241e439b6ed746b90294d0b6916644a644bsalomon */ 113c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon void abandonAll(); 114c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon 11571cb0c241e439b6ed746b90294d0b6916644a644bsalomon /** 11671cb0c241e439b6ed746b90294d0b6916644a644bsalomon * Releases the backend API resources owned by all GrGpuResource objects and removes them from 11771cb0c241e439b6ed746b90294d0b6916644a644bsalomon * the cache. 11871cb0c241e439b6ed746b90294d0b6916644a644bsalomon */ 119c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon void releaseAll(); 120c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon 121000f829f14a9535a005082731af5de1526284c83bsalomon enum { 122000f829f14a9535a005082731af5de1526284c83bsalomon /** Preferentially returns scratch resources with no pending IO. */ 123000f829f14a9535a005082731af5de1526284c83bsalomon kPreferNoPendingIO_ScratchFlag = 0x1, 124000f829f14a9535a005082731af5de1526284c83bsalomon /** Will not return any resources that match but have pending IO. */ 125000f829f14a9535a005082731af5de1526284c83bsalomon kRequireNoPendingIO_ScratchFlag = 0x2, 126000f829f14a9535a005082731af5de1526284c83bsalomon }; 12771cb0c241e439b6ed746b90294d0b6916644a644bsalomon 12871cb0c241e439b6ed746b90294d0b6916644a644bsalomon /** 12971cb0c241e439b6ed746b90294d0b6916644a644bsalomon * Find a resource that matches a scratch key. 13071cb0c241e439b6ed746b90294d0b6916644a644bsalomon */ 1316e83ac778f8f90939abe3aee3ea865428dff592frobertphillips GrGpuResource* findAndRefScratchResource(const GrScratchKey& scratchKey, 1326e83ac778f8f90939abe3aee3ea865428dff592frobertphillips size_t resourceSize, 1336e83ac778f8f90939abe3aee3ea865428dff592frobertphillips uint32_t flags); 1348b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon 1358b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon#ifdef SK_DEBUG 1368b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon // This is not particularly fast and only used for validation, so debug only. 1377775c85611c734a2af709b3a9c127939a4296c48bsalomon int countScratchEntriesForKey(const GrScratchKey& scratchKey) const { 1388b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon return fScratchMap.countForKey(scratchKey); 1398b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon } 1408b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon#endif 1418b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon 14271cb0c241e439b6ed746b90294d0b6916644a644bsalomon /** 1438718aafec239c93485e45bbe8fed19d9a8def079bsalomon * Find a resource that matches a unique key. 14471cb0c241e439b6ed746b90294d0b6916644a644bsalomon */ 1458718aafec239c93485e45bbe8fed19d9a8def079bsalomon GrGpuResource* findAndRefUniqueResource(const GrUniqueKey& key) { 1468718aafec239c93485e45bbe8fed19d9a8def079bsalomon GrGpuResource* resource = fUniqueHash.find(key); 14771cb0c241e439b6ed746b90294d0b6916644a644bsalomon if (resource) { 1489f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon this->refAndMakeResourceMRU(resource); 14971cb0c241e439b6ed746b90294d0b6916644a644bsalomon } 15071cb0c241e439b6ed746b90294d0b6916644a644bsalomon return resource; 1518b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon } 1528b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon 15371cb0c241e439b6ed746b90294d0b6916644a644bsalomon /** 1548718aafec239c93485e45bbe8fed19d9a8def079bsalomon * Query whether a unique key exists in the cache. 15571cb0c241e439b6ed746b90294d0b6916644a644bsalomon */ 1568718aafec239c93485e45bbe8fed19d9a8def079bsalomon bool hasUniqueKey(const GrUniqueKey& key) const { 1578718aafec239c93485e45bbe8fed19d9a8def079bsalomon return SkToBool(fUniqueHash.find(key)); 1588b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon } 159bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon 1608718aafec239c93485e45bbe8fed19d9a8def079bsalomon /** Purges resources to become under budget and processes resources with invalidated unique 16123e619cf462b2a8a500f3ca750e099f79601f508bsalomon keys. */ 1623f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon void purgeAsNeeded(); 16323e619cf462b2a8a500f3ca750e099f79601f508bsalomon 16471cb0c241e439b6ed746b90294d0b6916644a644bsalomon /** Purges all resources that don't have external owners. */ 16571cb0c241e439b6ed746b90294d0b6916644a644bsalomon void purgeAllUnlocked(); 16671cb0c241e439b6ed746b90294d0b6916644a644bsalomon 16771cb0c241e439b6ed746b90294d0b6916644a644bsalomon /** 16871cb0c241e439b6ed746b90294d0b6916644a644bsalomon * The callback function used by the cache when it is still over budget after a purge. The 16971cb0c241e439b6ed746b90294d0b6916644a644bsalomon * passed in 'data' is the same 'data' handed to setOverbudgetCallback. 17071cb0c241e439b6ed746b90294d0b6916644a644bsalomon */ 17171cb0c241e439b6ed746b90294d0b6916644a644bsalomon typedef void (*PFOverBudgetCB)(void* data); 17271cb0c241e439b6ed746b90294d0b6916644a644bsalomon 17371cb0c241e439b6ed746b90294d0b6916644a644bsalomon /** 17471cb0c241e439b6ed746b90294d0b6916644a644bsalomon * Set the callback the cache should use when it is still over budget after a purge. The 'data' 17571cb0c241e439b6ed746b90294d0b6916644a644bsalomon * provided here will be passed back to the callback. Note that the cache will attempt to purge 17671cb0c241e439b6ed746b90294d0b6916644a644bsalomon * any resources newly freed by the callback. 17771cb0c241e439b6ed746b90294d0b6916644a644bsalomon */ 17871cb0c241e439b6ed746b90294d0b6916644a644bsalomon void setOverBudgetCallback(PFOverBudgetCB overBudgetCB, void* data) { 17971cb0c241e439b6ed746b90294d0b6916644a644bsalomon fOverBudgetCB = overBudgetCB; 18071cb0c241e439b6ed746b90294d0b6916644a644bsalomon fOverBudgetData = data; 18171cb0c241e439b6ed746b90294d0b6916644a644bsalomon } 1820a5fa484fd58d27088f8696bdc11c8cc8f2b4866ericrk 1833f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon void notifyFlushOccurred(); 18471cb0c241e439b6ed746b90294d0b6916644a644bsalomon 18560029a5397f75aae4bdb994f26bd297edc3e433crobertphillips#if GR_CACHE_STATS 18660029a5397f75aae4bdb994f26bd297edc3e433crobertphillips struct Stats { 18760029a5397f75aae4bdb994f26bd297edc3e433crobertphillips int fTotal; 18860029a5397f75aae4bdb994f26bd297edc3e433crobertphillips int fNumPurgeable; 18960029a5397f75aae4bdb994f26bd297edc3e433crobertphillips int fNumNonPurgeable; 19060029a5397f75aae4bdb994f26bd297edc3e433crobertphillips 19160029a5397f75aae4bdb994f26bd297edc3e433crobertphillips int fScratch; 19260029a5397f75aae4bdb994f26bd297edc3e433crobertphillips int fExternal; 19360029a5397f75aae4bdb994f26bd297edc3e433crobertphillips int fBorrowed; 19460029a5397f75aae4bdb994f26bd297edc3e433crobertphillips int fAdopted; 19560029a5397f75aae4bdb994f26bd297edc3e433crobertphillips size_t fUnbudgetedSize; 19660029a5397f75aae4bdb994f26bd297edc3e433crobertphillips 19760029a5397f75aae4bdb994f26bd297edc3e433crobertphillips Stats() { this->reset(); } 19860029a5397f75aae4bdb994f26bd297edc3e433crobertphillips 19960029a5397f75aae4bdb994f26bd297edc3e433crobertphillips void reset() { 20060029a5397f75aae4bdb994f26bd297edc3e433crobertphillips fTotal = 0; 20160029a5397f75aae4bdb994f26bd297edc3e433crobertphillips fNumPurgeable = 0; 20260029a5397f75aae4bdb994f26bd297edc3e433crobertphillips fNumNonPurgeable = 0; 20360029a5397f75aae4bdb994f26bd297edc3e433crobertphillips fScratch = 0; 20460029a5397f75aae4bdb994f26bd297edc3e433crobertphillips fExternal = 0; 20560029a5397f75aae4bdb994f26bd297edc3e433crobertphillips fBorrowed = 0; 20660029a5397f75aae4bdb994f26bd297edc3e433crobertphillips fAdopted = 0; 20760029a5397f75aae4bdb994f26bd297edc3e433crobertphillips fUnbudgetedSize = 0; 20860029a5397f75aae4bdb994f26bd297edc3e433crobertphillips } 20960029a5397f75aae4bdb994f26bd297edc3e433crobertphillips 21060029a5397f75aae4bdb994f26bd297edc3e433crobertphillips void update(GrGpuResource* resource) { 21160029a5397f75aae4bdb994f26bd297edc3e433crobertphillips if (resource->cacheAccess().isScratch()) { 21260029a5397f75aae4bdb994f26bd297edc3e433crobertphillips ++fScratch; 21360029a5397f75aae4bdb994f26bd297edc3e433crobertphillips } 21460029a5397f75aae4bdb994f26bd297edc3e433crobertphillips if (resource->cacheAccess().isExternal()) { 21560029a5397f75aae4bdb994f26bd297edc3e433crobertphillips ++fExternal; 21660029a5397f75aae4bdb994f26bd297edc3e433crobertphillips } 21760029a5397f75aae4bdb994f26bd297edc3e433crobertphillips if (resource->cacheAccess().isBorrowed()) { 21860029a5397f75aae4bdb994f26bd297edc3e433crobertphillips ++fBorrowed; 21960029a5397f75aae4bdb994f26bd297edc3e433crobertphillips } 22060029a5397f75aae4bdb994f26bd297edc3e433crobertphillips if (resource->cacheAccess().isAdopted()) { 22160029a5397f75aae4bdb994f26bd297edc3e433crobertphillips ++fAdopted; 22260029a5397f75aae4bdb994f26bd297edc3e433crobertphillips } 2235ec26ae9bfca635ccc98283aad5deda11519d826bsalomon if (SkBudgeted::kNo == resource->resourcePriv().isBudgeted()) { 22460029a5397f75aae4bdb994f26bd297edc3e433crobertphillips fUnbudgetedSize += resource->gpuMemorySize(); 22560029a5397f75aae4bdb994f26bd297edc3e433crobertphillips } 22660029a5397f75aae4bdb994f26bd297edc3e433crobertphillips } 22760029a5397f75aae4bdb994f26bd297edc3e433crobertphillips }; 22860029a5397f75aae4bdb994f26bd297edc3e433crobertphillips 22960029a5397f75aae4bdb994f26bd297edc3e433crobertphillips void getStats(Stats*) const; 23060029a5397f75aae4bdb994f26bd297edc3e433crobertphillips 231b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtklein void dumpStats(SkString*) const; 232dc5685ac3752e90dd68179e9f1675ff6f15ed600joshualitt 233dc5685ac3752e90dd68179e9f1675ff6f15ed600joshualitt void dumpStatsKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* value) const; 23471cb0c241e439b6ed746b90294d0b6916644a644bsalomon#endif 23571cb0c241e439b6ed746b90294d0b6916644a644bsalomon 236ddf30e64fe474847b204d7062fad3341d245062cbsalomon // This function is for unit testing and is only defined in test tools. 237ddf30e64fe474847b204d7062fad3341d245062cbsalomon void changeTimestamp(uint32_t newTimestamp); 238ddf30e64fe474847b204d7062fad3341d245062cbsalomon 2390a5fa484fd58d27088f8696bdc11c8cc8f2b4866ericrk // Enumerates all cached resources and dumps their details to traceMemoryDump. 2400a5fa484fd58d27088f8696bdc11c8cc8f2b4866ericrk void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const; 2410a5fa484fd58d27088f8696bdc11c8cc8f2b4866ericrk 242c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomonprivate: 24371cb0c241e439b6ed746b90294d0b6916644a644bsalomon /////////////////////////////////////////////////////////////////////////// 24471cb0c241e439b6ed746b90294d0b6916644a644bsalomon /// @name Methods accessible via ResourceAccess 24571cb0c241e439b6ed746b90294d0b6916644a644bsalomon //// 24671cb0c241e439b6ed746b90294d0b6916644a644bsalomon void insertResource(GrGpuResource*); 24771cb0c241e439b6ed746b90294d0b6916644a644bsalomon void removeResource(GrGpuResource*); 2483f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon void notifyCntReachedZero(GrGpuResource*, uint32_t flags); 24971cb0c241e439b6ed746b90294d0b6916644a644bsalomon void didChangeGpuMemorySize(const GrGpuResource*, size_t oldSize); 250f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon void changeUniqueKey(GrGpuResource*, const GrUniqueKey&); 251f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon void removeUniqueKey(GrGpuResource*); 25210e23caea3106be125acea10a637789e5a15c728bsalomon void willRemoveScratchKey(const GrGpuResource*); 25384c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon void didChangeBudgetStatus(GrGpuResource*); 2549f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon void refAndMakeResourceMRU(GrGpuResource*); 25571cb0c241e439b6ed746b90294d0b6916644a644bsalomon /// @} 25671cb0c241e439b6ed746b90294d0b6916644a644bsalomon 2573f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon void resetFlushTimestamps(); 2588718aafec239c93485e45bbe8fed19d9a8def079bsalomon void processInvalidUniqueKeys(const SkTArray<GrUniqueKeyInvalidatedMessage>&); 259f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon void addToNonpurgeableArray(GrGpuResource*); 260f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon void removeFromNonpurgeableArray(GrGpuResource*); 261f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon bool overBudget() const { return fBudgetedBytes > fMaxBytes || fBudgetedCount > fMaxCount; } 26271cb0c241e439b6ed746b90294d0b6916644a644bsalomon 2636e83ac778f8f90939abe3aee3ea865428dff592frobertphillips bool wouldFit(size_t bytes) { 2646e83ac778f8f90939abe3aee3ea865428dff592frobertphillips return fBudgetedBytes+bytes <= fMaxBytes && fBudgetedCount+1 <= fMaxCount; 2656e83ac778f8f90939abe3aee3ea865428dff592frobertphillips } 2666e83ac778f8f90939abe3aee3ea865428dff592frobertphillips 267ddf30e64fe474847b204d7062fad3341d245062cbsalomon uint32_t getNextTimestamp(); 268ddf30e64fe474847b204d7062fad3341d245062cbsalomon 269169612621f00b3fe9f71014079991287d311751absalomon#ifdef SK_DEBUG 270f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon bool isInCache(const GrGpuResource* r) const; 27171cb0c241e439b6ed746b90294d0b6916644a644bsalomon void validate() const; 27271cb0c241e439b6ed746b90294d0b6916644a644bsalomon#else 27371cb0c241e439b6ed746b90294d0b6916644a644bsalomon void validate() const {} 274169612621f00b3fe9f71014079991287d311751absalomon#endif 275169612621f00b3fe9f71014079991287d311751absalomon 27671cb0c241e439b6ed746b90294d0b6916644a644bsalomon class AutoValidate; 27771cb0c241e439b6ed746b90294d0b6916644a644bsalomon 278bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon class AvailableForScratchUse; 279744998e666073166307d2522847b2536000a7619bsalomon 280744998e666073166307d2522847b2536000a7619bsalomon struct ScratchMapTraits { 2817775c85611c734a2af709b3a9c127939a4296c48bsalomon static const GrScratchKey& GetKey(const GrGpuResource& r) { 2823582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon return r.resourcePriv().getScratchKey(); 283744998e666073166307d2522847b2536000a7619bsalomon } 284744998e666073166307d2522847b2536000a7619bsalomon 2857775c85611c734a2af709b3a9c127939a4296c48bsalomon static uint32_t Hash(const GrScratchKey& key) { return key.hash(); } 286744998e666073166307d2522847b2536000a7619bsalomon }; 2877775c85611c734a2af709b3a9c127939a4296c48bsalomon typedef SkTMultiMap<GrGpuResource, GrScratchKey, ScratchMapTraits> ScratchMap; 288744998e666073166307d2522847b2536000a7619bsalomon 2898718aafec239c93485e45bbe8fed19d9a8def079bsalomon struct UniqueHashTraits { 2908718aafec239c93485e45bbe8fed19d9a8def079bsalomon static const GrUniqueKey& GetKey(const GrGpuResource& r) { return r.getUniqueKey(); } 2918b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon 2928718aafec239c93485e45bbe8fed19d9a8def079bsalomon static uint32_t Hash(const GrUniqueKey& key) { return key.hash(); } 2938b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon }; 2948718aafec239c93485e45bbe8fed19d9a8def079bsalomon typedef SkTDynamicHash<GrGpuResource, GrUniqueKey, UniqueHashTraits> UniqueHash; 2958b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon 2969f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon static bool CompareTimestamp(GrGpuResource* const& a, GrGpuResource* const& b) { 2979f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon return a->cacheAccess().timestamp() < b->cacheAccess().timestamp(); 2989f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon } 2999f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon 3009f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon static int* AccessResourceIndex(GrGpuResource* const& res) { 3019f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon return res->cacheAccess().accessCacheIndex(); 3029f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon } 3039f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon 3048718aafec239c93485e45bbe8fed19d9a8def079bsalomon typedef SkMessageBus<GrUniqueKeyInvalidatedMessage>::Inbox InvalidUniqueKeyInbox; 3059f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon typedef SkTDPQueue<GrGpuResource*, CompareTimestamp, AccessResourceIndex> PurgeableQueue; 306f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon typedef SkTDArray<GrGpuResource*> ResourceArray; 30723e619cf462b2a8a500f3ca750e099f79601f508bsalomon 3089f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon // Whenever a resource is added to the cache or the result of a cache lookup, fTimestamp is 3099f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon // assigned as the resource's timestamp and then incremented. fPurgeableQueue orders the 3109f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon // purgeable resources by this value, and thus is used to purge resources in LRU order. 3119f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon uint32_t fTimestamp; 3129f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon PurgeableQueue fPurgeableQueue; 313f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon ResourceArray fNonpurgeableResources; 3149f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon 315744998e666073166307d2522847b2536000a7619bsalomon // This map holds all resources that can be used as scratch resources. 3168b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon ScratchMap fScratchMap; 3178718aafec239c93485e45bbe8fed19d9a8def079bsalomon // This holds all resources that have unique keys. 3188718aafec239c93485e45bbe8fed19d9a8def079bsalomon UniqueHash fUniqueHash; 31971cb0c241e439b6ed746b90294d0b6916644a644bsalomon 32071cb0c241e439b6ed746b90294d0b6916644a644bsalomon // our budget, used in purgeAsNeeded() 32171cb0c241e439b6ed746b90294d0b6916644a644bsalomon int fMaxCount; 32271cb0c241e439b6ed746b90294d0b6916644a644bsalomon size_t fMaxBytes; 3233f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon int fMaxUnusedFlushes; 32471cb0c241e439b6ed746b90294d0b6916644a644bsalomon 32571cb0c241e439b6ed746b90294d0b6916644a644bsalomon#if GR_CACHE_STATS 32671cb0c241e439b6ed746b90294d0b6916644a644bsalomon int fHighWaterCount; 32771cb0c241e439b6ed746b90294d0b6916644a644bsalomon size_t fHighWaterBytes; 328dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon int fBudgetedHighWaterCount; 329dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon size_t fBudgetedHighWaterBytes; 33071cb0c241e439b6ed746b90294d0b6916644a644bsalomon#endif 33171cb0c241e439b6ed746b90294d0b6916644a644bsalomon 332dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon // our current stats for all resources 333f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkDEBUGCODE(int fCount;) 33471cb0c241e439b6ed746b90294d0b6916644a644bsalomon size_t fBytes; 33571cb0c241e439b6ed746b90294d0b6916644a644bsalomon 336dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon // our current stats for resources that count against the budget 337dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon int fBudgetedCount; 338dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon size_t fBudgetedBytes; 339dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon 34071cb0c241e439b6ed746b90294d0b6916644a644bsalomon PFOverBudgetCB fOverBudgetCB; 34171cb0c241e439b6ed746b90294d0b6916644a644bsalomon void* fOverBudgetData; 34271cb0c241e439b6ed746b90294d0b6916644a644bsalomon 3433f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon // We keep track of the "timestamps" of the last n flushes. If a resource hasn't been used in 3443f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon // that time then we well preemptively purge it to reduce memory usage. 3453f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon uint32_t* fFlushTimestamps; 3463f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon int fLastFlushTimestampIndex; 3473f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon 3488718aafec239c93485e45bbe8fed19d9a8def079bsalomon InvalidUniqueKeyInbox fInvalidUniqueKeyInbox; 3493f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon 3503f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon // This resource is allowed to be in the nonpurgeable array for the sake of validate() because 3513f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon // we're in the midst of converting it to purgeable status. 3523f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon SkDEBUGCODE(GrGpuResource* fNewlyPurgeableResourceForValidation;) 35363926683c583e8497d9d907977e773663cb4bd9erobertphillips 35463926683c583e8497d9d907977e773663cb4bd9erobertphillips bool fPreferVRAMUseOverFlushes; 355c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon}; 356c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon 3570ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomonclass GrResourceCache::ResourceAccess { 35871cb0c241e439b6ed746b90294d0b6916644a644bsalomonprivate: 3590ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon ResourceAccess(GrResourceCache* cache) : fCache(cache) { } 36071cb0c241e439b6ed746b90294d0b6916644a644bsalomon ResourceAccess(const ResourceAccess& that) : fCache(that.fCache) { } 36171cb0c241e439b6ed746b90294d0b6916644a644bsalomon ResourceAccess& operator=(const ResourceAccess&); // unimpl 36271cb0c241e439b6ed746b90294d0b6916644a644bsalomon 36371cb0c241e439b6ed746b90294d0b6916644a644bsalomon /** 36471cb0c241e439b6ed746b90294d0b6916644a644bsalomon * Insert a resource into the cache. 36571cb0c241e439b6ed746b90294d0b6916644a644bsalomon */ 36671cb0c241e439b6ed746b90294d0b6916644a644bsalomon void insertResource(GrGpuResource* resource) { fCache->insertResource(resource); } 36771cb0c241e439b6ed746b90294d0b6916644a644bsalomon 36871cb0c241e439b6ed746b90294d0b6916644a644bsalomon /** 36971cb0c241e439b6ed746b90294d0b6916644a644bsalomon * Removes a resource from the cache. 37071cb0c241e439b6ed746b90294d0b6916644a644bsalomon */ 37171cb0c241e439b6ed746b90294d0b6916644a644bsalomon void removeResource(GrGpuResource* resource) { fCache->removeResource(resource); } 37271cb0c241e439b6ed746b90294d0b6916644a644bsalomon 37371cb0c241e439b6ed746b90294d0b6916644a644bsalomon /** 3743f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * Notifications that should be sent to the cache when the ref/io cnt status of resources 3753f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * changes. 3763f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon */ 3773f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon enum RefNotificationFlags { 3783f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon /** All types of refs on the resource have reached zero. */ 3793f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon kAllCntsReachedZero_RefNotificationFlag = 0x1, 3803f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon /** The normal (not pending IO type) ref cnt has reached zero. */ 3813f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon kRefCntReachedZero_RefNotificationFlag = 0x2, 3823f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon }; 3833f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon /** 3843f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * Called by GrGpuResources when they detect that their ref/io cnts have reached zero. When the 3853f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * normal ref cnt reaches zero the flags that are set should be: 3863f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * a) kRefCntReachedZero if a pending IO cnt is still non-zero. 3873f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * b) (kRefCntReachedZero | kAllCntsReachedZero) when all pending IO cnts are also zero. 3883f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * kAllCntsReachedZero is set by itself if a pending IO cnt is decremented to zero and all the 3893f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * the other cnts are already zero. 39071cb0c241e439b6ed746b90294d0b6916644a644bsalomon */ 3913f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon void notifyCntReachedZero(GrGpuResource* resource, uint32_t flags) { 3923f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon fCache->notifyCntReachedZero(resource, flags); 3933f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon } 39471cb0c241e439b6ed746b90294d0b6916644a644bsalomon 39571cb0c241e439b6ed746b90294d0b6916644a644bsalomon /** 39671cb0c241e439b6ed746b90294d0b6916644a644bsalomon * Called by GrGpuResources when their sizes change. 39771cb0c241e439b6ed746b90294d0b6916644a644bsalomon */ 39871cb0c241e439b6ed746b90294d0b6916644a644bsalomon void didChangeGpuMemorySize(const GrGpuResource* resource, size_t oldSize) { 39971cb0c241e439b6ed746b90294d0b6916644a644bsalomon fCache->didChangeGpuMemorySize(resource, oldSize); 40071cb0c241e439b6ed746b90294d0b6916644a644bsalomon } 40171cb0c241e439b6ed746b90294d0b6916644a644bsalomon 40271cb0c241e439b6ed746b90294d0b6916644a644bsalomon /** 403f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon * Called by GrGpuResources to change their unique keys. 40471cb0c241e439b6ed746b90294d0b6916644a644bsalomon */ 405f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon void changeUniqueKey(GrGpuResource* resource, const GrUniqueKey& newKey) { 406f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon fCache->changeUniqueKey(resource, newKey); 407f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon } 40871cb0c241e439b6ed746b90294d0b6916644a644bsalomon 40910e23caea3106be125acea10a637789e5a15c728bsalomon /** 410f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon * Called by a GrGpuResource to remove its unique key. 41123e619cf462b2a8a500f3ca750e099f79601f508bsalomon */ 412f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon void removeUniqueKey(GrGpuResource* resource) { fCache->removeUniqueKey(resource); } 41323e619cf462b2a8a500f3ca750e099f79601f508bsalomon 41423e619cf462b2a8a500f3ca750e099f79601f508bsalomon /** 41523e619cf462b2a8a500f3ca750e099f79601f508bsalomon * Called by a GrGpuResource when it removes its scratch key. 41610e23caea3106be125acea10a637789e5a15c728bsalomon */ 41710e23caea3106be125acea10a637789e5a15c728bsalomon void willRemoveScratchKey(const GrGpuResource* resource) { 41810e23caea3106be125acea10a637789e5a15c728bsalomon fCache->willRemoveScratchKey(resource); 41910e23caea3106be125acea10a637789e5a15c728bsalomon } 42084c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon 42184c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon /** 42284c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon * Called by GrGpuResources when they change from budgeted to unbudgeted or vice versa. 42384c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon */ 42484c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon void didChangeBudgetStatus(GrGpuResource* resource) { fCache->didChangeBudgetStatus(resource); } 42584c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon 42671cb0c241e439b6ed746b90294d0b6916644a644bsalomon // No taking addresses of this type. 42771cb0c241e439b6ed746b90294d0b6916644a644bsalomon const ResourceAccess* operator&() const; 42871cb0c241e439b6ed746b90294d0b6916644a644bsalomon ResourceAccess* operator&(); 42971cb0c241e439b6ed746b90294d0b6916644a644bsalomon 4300ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon GrResourceCache* fCache; 43171cb0c241e439b6ed746b90294d0b6916644a644bsalomon 43271cb0c241e439b6ed746b90294d0b6916644a644bsalomon friend class GrGpuResource; // To access all the proxy inline methods. 4330ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon friend class GrResourceCache; // To create this type. 43471cb0c241e439b6ed746b90294d0b6916644a644bsalomon}; 43571cb0c241e439b6ed746b90294d0b6916644a644bsalomon 4360ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomoninline GrResourceCache::ResourceAccess GrResourceCache::resourceAccess() { 43771cb0c241e439b6ed746b90294d0b6916644a644bsalomon return ResourceAccess(this); 43871cb0c241e439b6ed746b90294d0b6916644a644bsalomon} 43971cb0c241e439b6ed746b90294d0b6916644a644bsalomon 440c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon#endif 441