GrResourceCache.h revision c03bdfa8e653fbdcb6b9f59ce862e00212e7c419
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. 63c03bdfa8e653fbdcb6b9f59ce862e00212e7c419bsalomon static const int kDefaultMaxUnusedFlushes = 1024; 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 18571cb0c241e439b6ed746b90294d0b6916644a644bsalomon#if GR_GPU_STATS 186b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtklein void dumpStats(SkString*) const; 18771cb0c241e439b6ed746b90294d0b6916644a644bsalomon#endif 18871cb0c241e439b6ed746b90294d0b6916644a644bsalomon 189ddf30e64fe474847b204d7062fad3341d245062cbsalomon // This function is for unit testing and is only defined in test tools. 190ddf30e64fe474847b204d7062fad3341d245062cbsalomon void changeTimestamp(uint32_t newTimestamp); 191ddf30e64fe474847b204d7062fad3341d245062cbsalomon 1920a5fa484fd58d27088f8696bdc11c8cc8f2b4866ericrk // Enumerates all cached resources and dumps their details to traceMemoryDump. 1930a5fa484fd58d27088f8696bdc11c8cc8f2b4866ericrk void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const; 1940a5fa484fd58d27088f8696bdc11c8cc8f2b4866ericrk 195c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomonprivate: 19671cb0c241e439b6ed746b90294d0b6916644a644bsalomon /////////////////////////////////////////////////////////////////////////// 19771cb0c241e439b6ed746b90294d0b6916644a644bsalomon /// @name Methods accessible via ResourceAccess 19871cb0c241e439b6ed746b90294d0b6916644a644bsalomon //// 19971cb0c241e439b6ed746b90294d0b6916644a644bsalomon void insertResource(GrGpuResource*); 20071cb0c241e439b6ed746b90294d0b6916644a644bsalomon void removeResource(GrGpuResource*); 2013f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon void notifyCntReachedZero(GrGpuResource*, uint32_t flags); 20271cb0c241e439b6ed746b90294d0b6916644a644bsalomon void didChangeGpuMemorySize(const GrGpuResource*, size_t oldSize); 203f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon void changeUniqueKey(GrGpuResource*, const GrUniqueKey&); 204f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon void removeUniqueKey(GrGpuResource*); 20510e23caea3106be125acea10a637789e5a15c728bsalomon void willRemoveScratchKey(const GrGpuResource*); 20684c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon void didChangeBudgetStatus(GrGpuResource*); 2079f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon void refAndMakeResourceMRU(GrGpuResource*); 20871cb0c241e439b6ed746b90294d0b6916644a644bsalomon /// @} 20971cb0c241e439b6ed746b90294d0b6916644a644bsalomon 2103f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon void resetFlushTimestamps(); 2118718aafec239c93485e45bbe8fed19d9a8def079bsalomon void processInvalidUniqueKeys(const SkTArray<GrUniqueKeyInvalidatedMessage>&); 212f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon void addToNonpurgeableArray(GrGpuResource*); 213f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon void removeFromNonpurgeableArray(GrGpuResource*); 214f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon bool overBudget() const { return fBudgetedBytes > fMaxBytes || fBudgetedCount > fMaxCount; } 21571cb0c241e439b6ed746b90294d0b6916644a644bsalomon 2166e83ac778f8f90939abe3aee3ea865428dff592frobertphillips bool wouldFit(size_t bytes) { 2176e83ac778f8f90939abe3aee3ea865428dff592frobertphillips return fBudgetedBytes+bytes <= fMaxBytes && fBudgetedCount+1 <= fMaxCount; 2186e83ac778f8f90939abe3aee3ea865428dff592frobertphillips } 2196e83ac778f8f90939abe3aee3ea865428dff592frobertphillips 220ddf30e64fe474847b204d7062fad3341d245062cbsalomon uint32_t getNextTimestamp(); 221ddf30e64fe474847b204d7062fad3341d245062cbsalomon 222169612621f00b3fe9f71014079991287d311751absalomon#ifdef SK_DEBUG 223f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon bool isInCache(const GrGpuResource* r) const; 22471cb0c241e439b6ed746b90294d0b6916644a644bsalomon void validate() const; 22571cb0c241e439b6ed746b90294d0b6916644a644bsalomon#else 22671cb0c241e439b6ed746b90294d0b6916644a644bsalomon void validate() const {} 227169612621f00b3fe9f71014079991287d311751absalomon#endif 228169612621f00b3fe9f71014079991287d311751absalomon 22971cb0c241e439b6ed746b90294d0b6916644a644bsalomon class AutoValidate; 23071cb0c241e439b6ed746b90294d0b6916644a644bsalomon 231bcf0a52d4f4221b158e68a06ba0c4cc4db011060bsalomon class AvailableForScratchUse; 232744998e666073166307d2522847b2536000a7619bsalomon 233744998e666073166307d2522847b2536000a7619bsalomon struct ScratchMapTraits { 2347775c85611c734a2af709b3a9c127939a4296c48bsalomon static const GrScratchKey& GetKey(const GrGpuResource& r) { 2353582d3ee9fffdec715f5e4949a241ab08e6271ecbsalomon return r.resourcePriv().getScratchKey(); 236744998e666073166307d2522847b2536000a7619bsalomon } 237744998e666073166307d2522847b2536000a7619bsalomon 2387775c85611c734a2af709b3a9c127939a4296c48bsalomon static uint32_t Hash(const GrScratchKey& key) { return key.hash(); } 239744998e666073166307d2522847b2536000a7619bsalomon }; 2407775c85611c734a2af709b3a9c127939a4296c48bsalomon typedef SkTMultiMap<GrGpuResource, GrScratchKey, ScratchMapTraits> ScratchMap; 241744998e666073166307d2522847b2536000a7619bsalomon 2428718aafec239c93485e45bbe8fed19d9a8def079bsalomon struct UniqueHashTraits { 2438718aafec239c93485e45bbe8fed19d9a8def079bsalomon static const GrUniqueKey& GetKey(const GrGpuResource& r) { return r.getUniqueKey(); } 2448b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon 2458718aafec239c93485e45bbe8fed19d9a8def079bsalomon static uint32_t Hash(const GrUniqueKey& key) { return key.hash(); } 2468b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon }; 2478718aafec239c93485e45bbe8fed19d9a8def079bsalomon typedef SkTDynamicHash<GrGpuResource, GrUniqueKey, UniqueHashTraits> UniqueHash; 2488b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon 2499f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon static bool CompareTimestamp(GrGpuResource* const& a, GrGpuResource* const& b) { 2509f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon return a->cacheAccess().timestamp() < b->cacheAccess().timestamp(); 2519f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon } 2529f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon 2539f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon static int* AccessResourceIndex(GrGpuResource* const& res) { 2549f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon return res->cacheAccess().accessCacheIndex(); 2559f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon } 2569f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon 2578718aafec239c93485e45bbe8fed19d9a8def079bsalomon typedef SkMessageBus<GrUniqueKeyInvalidatedMessage>::Inbox InvalidUniqueKeyInbox; 2589f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon typedef SkTDPQueue<GrGpuResource*, CompareTimestamp, AccessResourceIndex> PurgeableQueue; 259f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon typedef SkTDArray<GrGpuResource*> ResourceArray; 26023e619cf462b2a8a500f3ca750e099f79601f508bsalomon 2619f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon // Whenever a resource is added to the cache or the result of a cache lookup, fTimestamp is 2629f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon // assigned as the resource's timestamp and then incremented. fPurgeableQueue orders the 2639f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon // purgeable resources by this value, and thus is used to purge resources in LRU order. 2649f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon uint32_t fTimestamp; 2659f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon PurgeableQueue fPurgeableQueue; 266f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon ResourceArray fNonpurgeableResources; 2679f2d1571ed1f0ed579e5d7779c46a90e20f30f22bsalomon 268744998e666073166307d2522847b2536000a7619bsalomon // This map holds all resources that can be used as scratch resources. 2698b79d23f825cd9e0f9e3bf8aaa9e209940b17ef6bsalomon ScratchMap fScratchMap; 2708718aafec239c93485e45bbe8fed19d9a8def079bsalomon // This holds all resources that have unique keys. 2718718aafec239c93485e45bbe8fed19d9a8def079bsalomon UniqueHash fUniqueHash; 27271cb0c241e439b6ed746b90294d0b6916644a644bsalomon 27371cb0c241e439b6ed746b90294d0b6916644a644bsalomon // our budget, used in purgeAsNeeded() 27471cb0c241e439b6ed746b90294d0b6916644a644bsalomon int fMaxCount; 27571cb0c241e439b6ed746b90294d0b6916644a644bsalomon size_t fMaxBytes; 2763f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon int fMaxUnusedFlushes; 27771cb0c241e439b6ed746b90294d0b6916644a644bsalomon 27871cb0c241e439b6ed746b90294d0b6916644a644bsalomon#if GR_CACHE_STATS 27971cb0c241e439b6ed746b90294d0b6916644a644bsalomon int fHighWaterCount; 28071cb0c241e439b6ed746b90294d0b6916644a644bsalomon size_t fHighWaterBytes; 281dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon int fBudgetedHighWaterCount; 282dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon size_t fBudgetedHighWaterBytes; 28371cb0c241e439b6ed746b90294d0b6916644a644bsalomon#endif 28471cb0c241e439b6ed746b90294d0b6916644a644bsalomon 285dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon // our current stats for all resources 286f320e04c50a1c8a861bc1d8f50bf732044ff9843bsalomon SkDEBUGCODE(int fCount;) 28771cb0c241e439b6ed746b90294d0b6916644a644bsalomon size_t fBytes; 28871cb0c241e439b6ed746b90294d0b6916644a644bsalomon 289dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon // our current stats for resources that count against the budget 290dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon int fBudgetedCount; 291dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon size_t fBudgetedBytes; 292dace19ec17e85872df3fb35212e1b8bce72018b6bsalomon 29371cb0c241e439b6ed746b90294d0b6916644a644bsalomon PFOverBudgetCB fOverBudgetCB; 29471cb0c241e439b6ed746b90294d0b6916644a644bsalomon void* fOverBudgetData; 29571cb0c241e439b6ed746b90294d0b6916644a644bsalomon 2963f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon // We keep track of the "timestamps" of the last n flushes. If a resource hasn't been used in 2973f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon // that time then we well preemptively purge it to reduce memory usage. 2983f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon uint32_t* fFlushTimestamps; 2993f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon int fLastFlushTimestampIndex; 3003f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon 3018718aafec239c93485e45bbe8fed19d9a8def079bsalomon InvalidUniqueKeyInbox fInvalidUniqueKeyInbox; 3023f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon 3033f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon // This resource is allowed to be in the nonpurgeable array for the sake of validate() because 3043f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon // we're in the midst of converting it to purgeable status. 3053f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon SkDEBUGCODE(GrGpuResource* fNewlyPurgeableResourceForValidation;) 30663926683c583e8497d9d907977e773663cb4bd9erobertphillips 30763926683c583e8497d9d907977e773663cb4bd9erobertphillips bool fPreferVRAMUseOverFlushes; 308c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon}; 309c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon 3100ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomonclass GrResourceCache::ResourceAccess { 31171cb0c241e439b6ed746b90294d0b6916644a644bsalomonprivate: 3120ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon ResourceAccess(GrResourceCache* cache) : fCache(cache) { } 31371cb0c241e439b6ed746b90294d0b6916644a644bsalomon ResourceAccess(const ResourceAccess& that) : fCache(that.fCache) { } 31471cb0c241e439b6ed746b90294d0b6916644a644bsalomon ResourceAccess& operator=(const ResourceAccess&); // unimpl 31571cb0c241e439b6ed746b90294d0b6916644a644bsalomon 31671cb0c241e439b6ed746b90294d0b6916644a644bsalomon /** 31771cb0c241e439b6ed746b90294d0b6916644a644bsalomon * Insert a resource into the cache. 31871cb0c241e439b6ed746b90294d0b6916644a644bsalomon */ 31971cb0c241e439b6ed746b90294d0b6916644a644bsalomon void insertResource(GrGpuResource* resource) { fCache->insertResource(resource); } 32071cb0c241e439b6ed746b90294d0b6916644a644bsalomon 32171cb0c241e439b6ed746b90294d0b6916644a644bsalomon /** 32271cb0c241e439b6ed746b90294d0b6916644a644bsalomon * Removes a resource from the cache. 32371cb0c241e439b6ed746b90294d0b6916644a644bsalomon */ 32471cb0c241e439b6ed746b90294d0b6916644a644bsalomon void removeResource(GrGpuResource* resource) { fCache->removeResource(resource); } 32571cb0c241e439b6ed746b90294d0b6916644a644bsalomon 32671cb0c241e439b6ed746b90294d0b6916644a644bsalomon /** 3273f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * Notifications that should be sent to the cache when the ref/io cnt status of resources 3283f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * changes. 3293f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon */ 3303f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon enum RefNotificationFlags { 3313f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon /** All types of refs on the resource have reached zero. */ 3323f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon kAllCntsReachedZero_RefNotificationFlag = 0x1, 3333f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon /** The normal (not pending IO type) ref cnt has reached zero. */ 3343f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon kRefCntReachedZero_RefNotificationFlag = 0x2, 3353f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon }; 3363f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon /** 3373f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * Called by GrGpuResources when they detect that their ref/io cnts have reached zero. When the 3383f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * normal ref cnt reaches zero the flags that are set should be: 3393f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * a) kRefCntReachedZero if a pending IO cnt is still non-zero. 3403f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * b) (kRefCntReachedZero | kAllCntsReachedZero) when all pending IO cnts are also zero. 3413f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * kAllCntsReachedZero is set by itself if a pending IO cnt is decremented to zero and all the 3423f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon * the other cnts are already zero. 34371cb0c241e439b6ed746b90294d0b6916644a644bsalomon */ 3443f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon void notifyCntReachedZero(GrGpuResource* resource, uint32_t flags) { 3453f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon fCache->notifyCntReachedZero(resource, flags); 3463f324321cdd8fde7976d958e2888a1ec4e657e35bsalomon } 34771cb0c241e439b6ed746b90294d0b6916644a644bsalomon 34871cb0c241e439b6ed746b90294d0b6916644a644bsalomon /** 34971cb0c241e439b6ed746b90294d0b6916644a644bsalomon * Called by GrGpuResources when their sizes change. 35071cb0c241e439b6ed746b90294d0b6916644a644bsalomon */ 35171cb0c241e439b6ed746b90294d0b6916644a644bsalomon void didChangeGpuMemorySize(const GrGpuResource* resource, size_t oldSize) { 35271cb0c241e439b6ed746b90294d0b6916644a644bsalomon fCache->didChangeGpuMemorySize(resource, oldSize); 35371cb0c241e439b6ed746b90294d0b6916644a644bsalomon } 35471cb0c241e439b6ed746b90294d0b6916644a644bsalomon 35571cb0c241e439b6ed746b90294d0b6916644a644bsalomon /** 356f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon * Called by GrGpuResources to change their unique keys. 35771cb0c241e439b6ed746b90294d0b6916644a644bsalomon */ 358f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon void changeUniqueKey(GrGpuResource* resource, const GrUniqueKey& newKey) { 359f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon fCache->changeUniqueKey(resource, newKey); 360f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon } 36171cb0c241e439b6ed746b90294d0b6916644a644bsalomon 36210e23caea3106be125acea10a637789e5a15c728bsalomon /** 363f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon * Called by a GrGpuResource to remove its unique key. 36423e619cf462b2a8a500f3ca750e099f79601f508bsalomon */ 365f99e961f55bb603d099c8cb57d05a2ae52a4e9cabsalomon void removeUniqueKey(GrGpuResource* resource) { fCache->removeUniqueKey(resource); } 36623e619cf462b2a8a500f3ca750e099f79601f508bsalomon 36723e619cf462b2a8a500f3ca750e099f79601f508bsalomon /** 36823e619cf462b2a8a500f3ca750e099f79601f508bsalomon * Called by a GrGpuResource when it removes its scratch key. 36910e23caea3106be125acea10a637789e5a15c728bsalomon */ 37010e23caea3106be125acea10a637789e5a15c728bsalomon void willRemoveScratchKey(const GrGpuResource* resource) { 37110e23caea3106be125acea10a637789e5a15c728bsalomon fCache->willRemoveScratchKey(resource); 37210e23caea3106be125acea10a637789e5a15c728bsalomon } 37384c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon 37484c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon /** 37584c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon * Called by GrGpuResources when they change from budgeted to unbudgeted or vice versa. 37684c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon */ 37784c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon void didChangeBudgetStatus(GrGpuResource* resource) { fCache->didChangeBudgetStatus(resource); } 37884c8e62fad59f0e19b40ac718467f5b7884b431dbsalomon 37971cb0c241e439b6ed746b90294d0b6916644a644bsalomon // No taking addresses of this type. 38071cb0c241e439b6ed746b90294d0b6916644a644bsalomon const ResourceAccess* operator&() const; 38171cb0c241e439b6ed746b90294d0b6916644a644bsalomon ResourceAccess* operator&(); 38271cb0c241e439b6ed746b90294d0b6916644a644bsalomon 3830ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon GrResourceCache* fCache; 38471cb0c241e439b6ed746b90294d0b6916644a644bsalomon 38571cb0c241e439b6ed746b90294d0b6916644a644bsalomon friend class GrGpuResource; // To access all the proxy inline methods. 3860ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomon friend class GrResourceCache; // To create this type. 38771cb0c241e439b6ed746b90294d0b6916644a644bsalomon}; 38871cb0c241e439b6ed746b90294d0b6916644a644bsalomon 3890ea80f43a1af05b8157a4ef387223bb5b0da35edbsalomoninline GrResourceCache::ResourceAccess GrResourceCache::resourceAccess() { 39071cb0c241e439b6ed746b90294d0b6916644a644bsalomon return ResourceAccess(this); 39171cb0c241e439b6ed746b90294d0b6916644a644bsalomon} 39271cb0c241e439b6ed746b90294d0b6916644a644bsalomon 393c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon#endif 394