GrResourceCache.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. /*
  2. * Copyright 2014 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #ifndef GrResourceCache_DEFINED
  8. #define GrResourceCache_DEFINED
  9. #include "include/core/SkRefCnt.h"
  10. #include "include/gpu/GrGpuResource.h"
  11. #include "include/private/GrResourceKey.h"
  12. #include "include/private/SkTArray.h"
  13. #include "include/private/SkTHash.h"
  14. #include "src/core/SkMessageBus.h"
  15. #include "src/core/SkTDPQueue.h"
  16. #include "src/core/SkTInternalLList.h"
  17. #include "src/core/SkTMultiMap.h"
  18. #include "src/gpu/GrGpuResourceCacheAccess.h"
  19. #include "src/gpu/GrGpuResourcePriv.h"
  20. class GrCaps;
  21. class GrProxyProvider;
  22. class SkString;
  23. class SkTraceMemoryDump;
  24. class GrSingleOwner;
  25. struct GrGpuResourceFreedMessage {
  26. GrGpuResource* fResource;
  27. uint32_t fOwningUniqueID;
  28. };
  29. static inline bool SkShouldPostMessageToBus(
  30. const GrGpuResourceFreedMessage& msg, uint32_t msgBusUniqueID) {
  31. // The inbox's ID is the unique ID of the owning GrContext.
  32. return msgBusUniqueID == msg.fOwningUniqueID;
  33. }
  34. /**
  35. * Manages the lifetime of all GrGpuResource instances.
  36. *
  37. * Resources may have optionally have two types of keys:
  38. * 1) A scratch key. This is for resources whose allocations are cached but not their contents.
  39. * Multiple resources can share the same scratch key. This is so a caller can have two
  40. * resource instances with the same properties (e.g. multipass rendering that ping-pongs
  41. * between two temporary surfaces). The scratch key is set at resource creation time and
  42. * should never change. Resources need not have a scratch key.
  43. * 2) A unique key. This key's meaning is specific to the domain that created the key. Only one
  44. * resource may have a given unique key. The unique key can be set, cleared, or changed
  45. * anytime after resource creation.
  46. *
  47. * A unique key always takes precedence over a scratch key when a resource has both types of keys.
  48. * If a resource has neither key type then it will be deleted as soon as the last reference to it
  49. * is dropped.
  50. */
  51. class GrResourceCache {
  52. public:
  53. GrResourceCache(const GrCaps*, GrSingleOwner* owner, uint32_t contextUniqueID);
  54. ~GrResourceCache();
  55. // Default maximum number of budgeted resources in the cache.
  56. static const int kDefaultMaxCount = 2 * (1 << 12);
  57. // Default maximum number of bytes of gpu memory of budgeted resources in the cache.
  58. static const size_t kDefaultMaxSize = 96 * (1 << 20);
  59. /** Used to access functionality needed by GrGpuResource for lifetime management. */
  60. class ResourceAccess;
  61. ResourceAccess resourceAccess();
  62. /** Unique ID of the owning GrContext. */
  63. uint32_t contextUniqueID() const { return fContextUniqueID; }
  64. /** Sets the cache limits in terms of number of resources and max gpu memory byte size. */
  65. void setLimits(int count, size_t bytes);
  66. /**
  67. * Returns the number of resources.
  68. */
  69. int getResourceCount() const {
  70. return fPurgeableQueue.count() + fNonpurgeableResources.count();
  71. }
  72. /**
  73. * Returns the number of resources that count against the budget.
  74. */
  75. int getBudgetedResourceCount() const { return fBudgetedCount; }
  76. /**
  77. * Returns the number of bytes consumed by resources.
  78. */
  79. size_t getResourceBytes() const { return fBytes; }
  80. /**
  81. * Returns the number of bytes held by unlocked reosources which are available for purging.
  82. */
  83. size_t getPurgeableBytes() const { return fPurgeableBytes; }
  84. /**
  85. * Returns the number of bytes consumed by budgeted resources.
  86. */
  87. size_t getBudgetedResourceBytes() const { return fBudgetedBytes; }
  88. /**
  89. * Returns the cached resources count budget.
  90. */
  91. int getMaxResourceCount() const { return fMaxCount; }
  92. /**
  93. * Returns the number of bytes consumed by cached resources.
  94. */
  95. size_t getMaxResourceBytes() const { return fMaxBytes; }
  96. /**
  97. * Abandons the backend API resources owned by all GrGpuResource objects and removes them from
  98. * the cache.
  99. */
  100. void abandonAll();
  101. /**
  102. * Releases the backend API resources owned by all GrGpuResource objects and removes them from
  103. * the cache.
  104. */
  105. void releaseAll();
  106. enum class ScratchFlags {
  107. kNone = 0,
  108. /** Preferentially returns scratch resources with no pending IO. */
  109. kPreferNoPendingIO = 0x1,
  110. /** Will not return any resources that match but have pending IO. */
  111. kRequireNoPendingIO = 0x2,
  112. };
  113. /**
  114. * Find a resource that matches a scratch key.
  115. */
  116. GrGpuResource* findAndRefScratchResource(const GrScratchKey& scratchKey, size_t resourceSize,
  117. ScratchFlags);
  118. #ifdef SK_DEBUG
  119. // This is not particularly fast and only used for validation, so debug only.
  120. int countScratchEntriesForKey(const GrScratchKey& scratchKey) const {
  121. return fScratchMap.countForKey(scratchKey);
  122. }
  123. #endif
  124. /**
  125. * Find a resource that matches a unique key.
  126. */
  127. GrGpuResource* findAndRefUniqueResource(const GrUniqueKey& key) {
  128. GrGpuResource* resource = fUniqueHash.find(key);
  129. if (resource) {
  130. this->refAndMakeResourceMRU(resource);
  131. }
  132. return resource;
  133. }
  134. /**
  135. * Query whether a unique key exists in the cache.
  136. */
  137. bool hasUniqueKey(const GrUniqueKey& key) const {
  138. return SkToBool(fUniqueHash.find(key));
  139. }
  140. /** Purges resources to become under budget and processes resources with invalidated unique
  141. keys. */
  142. void purgeAsNeeded();
  143. /** Purges all resources that don't have external owners. */
  144. void purgeAllUnlocked() { this->purgeUnlockedResources(false); }
  145. // Purge unlocked resources. If 'scratchResourcesOnly' is true the purgeable resources
  146. // containing persistent data are spared. If it is false then all purgeable resources will
  147. // be deleted.
  148. void purgeUnlockedResources(bool scratchResourcesOnly);
  149. /** Purge all resources not used since the passed in time. */
  150. void purgeResourcesNotUsedSince(GrStdSteadyClock::time_point);
  151. bool overBudget() const { return fBudgetedBytes > fMaxBytes || fBudgetedCount > fMaxCount; }
  152. /**
  153. * Purge unlocked resources from the cache until the the provided byte count has been reached
  154. * or we have purged all unlocked resources. The default policy is to purge in LRU order, but
  155. * can be overridden to prefer purging scratch resources (in LRU order) prior to purging other
  156. * resource types.
  157. *
  158. * @param maxBytesToPurge the desired number of bytes to be purged.
  159. * @param preferScratchResources If true scratch resources will be purged prior to other
  160. * resource types.
  161. */
  162. void purgeUnlockedResources(size_t bytesToPurge, bool preferScratchResources);
  163. /** Returns true if the cache would like a flush to occur in order to make more resources
  164. purgeable. */
  165. bool requestsFlush() const;
  166. /** Maintain a ref to this resource until we receive a GrGpuResourceFreedMessage. */
  167. void insertDelayedResourceUnref(GrGpuResource* resource);
  168. #if GR_CACHE_STATS
  169. struct Stats {
  170. int fTotal;
  171. int fNumPurgeable;
  172. int fNumNonPurgeable;
  173. int fScratch;
  174. int fWrapped;
  175. size_t fUnbudgetedSize;
  176. Stats() { this->reset(); }
  177. void reset() {
  178. fTotal = 0;
  179. fNumPurgeable = 0;
  180. fNumNonPurgeable = 0;
  181. fScratch = 0;
  182. fWrapped = 0;
  183. fUnbudgetedSize = 0;
  184. }
  185. void update(GrGpuResource* resource) {
  186. if (resource->cacheAccess().isScratch()) {
  187. ++fScratch;
  188. }
  189. if (resource->resourcePriv().refsWrappedObjects()) {
  190. ++fWrapped;
  191. }
  192. if (GrBudgetedType::kBudgeted != resource->resourcePriv().budgetedType()) {
  193. fUnbudgetedSize += resource->gpuMemorySize();
  194. }
  195. }
  196. };
  197. void getStats(Stats*) const;
  198. #if GR_TEST_UTILS
  199. void dumpStats(SkString*) const;
  200. void dumpStatsKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* value) const;
  201. #endif
  202. #endif
  203. #ifdef SK_DEBUG
  204. int countUniqueKeysWithTag(const char* tag) const;
  205. #endif
  206. // This function is for unit testing and is only defined in test tools.
  207. void changeTimestamp(uint32_t newTimestamp);
  208. // Enumerates all cached resources and dumps their details to traceMemoryDump.
  209. void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const;
  210. void setProxyProvider(GrProxyProvider* proxyProvider) { fProxyProvider = proxyProvider; }
  211. private:
  212. ///////////////////////////////////////////////////////////////////////////
  213. /// @name Methods accessible via ResourceAccess
  214. ////
  215. void insertResource(GrGpuResource*);
  216. void removeResource(GrGpuResource*);
  217. void notifyCntReachedZero(GrGpuResource*, uint32_t flags);
  218. void changeUniqueKey(GrGpuResource*, const GrUniqueKey&);
  219. void removeUniqueKey(GrGpuResource*);
  220. void willRemoveScratchKey(const GrGpuResource*);
  221. void didChangeBudgetStatus(GrGpuResource*);
  222. void refResource(GrGpuResource* resource);
  223. /// @}
  224. void refAndMakeResourceMRU(GrGpuResource*);
  225. void processFreedGpuResources();
  226. void addToNonpurgeableArray(GrGpuResource*);
  227. void removeFromNonpurgeableArray(GrGpuResource*);
  228. bool wouldFit(size_t bytes) {
  229. return fBudgetedBytes+bytes <= fMaxBytes && fBudgetedCount+1 <= fMaxCount;
  230. }
  231. uint32_t getNextTimestamp();
  232. #ifdef SK_DEBUG
  233. bool isInCache(const GrGpuResource* r) const;
  234. void validate() const;
  235. #else
  236. void validate() const {}
  237. #endif
  238. class AutoValidate;
  239. class AvailableForScratchUse;
  240. struct ScratchMapTraits {
  241. static const GrScratchKey& GetKey(const GrGpuResource& r) {
  242. return r.resourcePriv().getScratchKey();
  243. }
  244. static uint32_t Hash(const GrScratchKey& key) { return key.hash(); }
  245. static void OnFree(GrGpuResource*) { }
  246. };
  247. typedef SkTMultiMap<GrGpuResource, GrScratchKey, ScratchMapTraits> ScratchMap;
  248. struct UniqueHashTraits {
  249. static const GrUniqueKey& GetKey(const GrGpuResource& r) { return r.getUniqueKey(); }
  250. static uint32_t Hash(const GrUniqueKey& key) { return key.hash(); }
  251. };
  252. typedef SkTDynamicHash<GrGpuResource, GrUniqueKey, UniqueHashTraits> UniqueHash;
  253. class ResourceAwaitingUnref {
  254. public:
  255. ResourceAwaitingUnref();
  256. ResourceAwaitingUnref(GrGpuResource* resource);
  257. ResourceAwaitingUnref(const ResourceAwaitingUnref&) = delete;
  258. ResourceAwaitingUnref& operator=(const ResourceAwaitingUnref&) = delete;
  259. ResourceAwaitingUnref(ResourceAwaitingUnref&&);
  260. ResourceAwaitingUnref& operator=(ResourceAwaitingUnref&&);
  261. ~ResourceAwaitingUnref();
  262. void addRef();
  263. void unref();
  264. bool finished();
  265. private:
  266. GrGpuResource* fResource = nullptr;
  267. int fNumUnrefs = 0;
  268. };
  269. using ReourcesAwaitingUnref = SkTHashMap<uint32_t, ResourceAwaitingUnref>;
  270. static bool CompareTimestamp(GrGpuResource* const& a, GrGpuResource* const& b) {
  271. return a->cacheAccess().timestamp() < b->cacheAccess().timestamp();
  272. }
  273. static int* AccessResourceIndex(GrGpuResource* const& res) {
  274. return res->cacheAccess().accessCacheIndex();
  275. }
  276. typedef SkMessageBus<GrUniqueKeyInvalidatedMessage>::Inbox InvalidUniqueKeyInbox;
  277. typedef SkMessageBus<GrGpuResourceFreedMessage>::Inbox FreedGpuResourceInbox;
  278. typedef SkTDPQueue<GrGpuResource*, CompareTimestamp, AccessResourceIndex> PurgeableQueue;
  279. typedef SkTDArray<GrGpuResource*> ResourceArray;
  280. GrProxyProvider* fProxyProvider = nullptr;
  281. // Whenever a resource is added to the cache or the result of a cache lookup, fTimestamp is
  282. // assigned as the resource's timestamp and then incremented. fPurgeableQueue orders the
  283. // purgeable resources by this value, and thus is used to purge resources in LRU order.
  284. uint32_t fTimestamp = 0;
  285. PurgeableQueue fPurgeableQueue;
  286. ResourceArray fNonpurgeableResources;
  287. // This map holds all resources that can be used as scratch resources.
  288. ScratchMap fScratchMap;
  289. // This holds all resources that have unique keys.
  290. UniqueHash fUniqueHash;
  291. // our budget, used in purgeAsNeeded()
  292. int fMaxCount = kDefaultMaxCount;
  293. size_t fMaxBytes = kDefaultMaxSize;
  294. #if GR_CACHE_STATS
  295. int fHighWaterCount = 0;
  296. size_t fHighWaterBytes = 0;
  297. int fBudgetedHighWaterCount = 0;
  298. size_t fBudgetedHighWaterBytes = 0;
  299. #endif
  300. // our current stats for all resources
  301. SkDEBUGCODE(int fCount = 0;)
  302. size_t fBytes = 0;
  303. // our current stats for resources that count against the budget
  304. int fBudgetedCount = 0;
  305. size_t fBudgetedBytes = 0;
  306. size_t fPurgeableBytes = 0;
  307. int fNumBudgetedResourcesFlushWillMakePurgeable = 0;
  308. InvalidUniqueKeyInbox fInvalidUniqueKeyInbox;
  309. FreedGpuResourceInbox fFreedGpuResourceInbox;
  310. ReourcesAwaitingUnref fResourcesAwaitingUnref;
  311. uint32_t fContextUniqueID = SK_InvalidUniqueID;
  312. GrSingleOwner* fSingleOwner = nullptr;
  313. // This resource is allowed to be in the nonpurgeable array for the sake of validate() because
  314. // we're in the midst of converting it to purgeable status.
  315. SkDEBUGCODE(GrGpuResource* fNewlyPurgeableResourceForValidation = nullptr;)
  316. bool fPreferVRAMUseOverFlushes = false;
  317. };
  318. GR_MAKE_BITFIELD_CLASS_OPS(GrResourceCache::ScratchFlags);
  319. class GrResourceCache::ResourceAccess {
  320. private:
  321. ResourceAccess(GrResourceCache* cache) : fCache(cache) { }
  322. ResourceAccess(const ResourceAccess& that) : fCache(that.fCache) { }
  323. ResourceAccess& operator=(const ResourceAccess&); // unimpl
  324. /**
  325. * Insert a resource into the cache.
  326. */
  327. void insertResource(GrGpuResource* resource) { fCache->insertResource(resource); }
  328. /**
  329. * Removes a resource from the cache.
  330. */
  331. void removeResource(GrGpuResource* resource) { fCache->removeResource(resource); }
  332. /**
  333. * Adds a ref to a resource with proper tracking if the resource has 0 refs prior to
  334. * adding the ref.
  335. */
  336. void refResource(GrGpuResource* resource) { fCache->refResource(resource); }
  337. /**
  338. * Notifications that should be sent to the cache when the ref/io cnt status of resources
  339. * changes.
  340. */
  341. enum RefNotificationFlags {
  342. /** All types of refs on the resource have reached zero. */
  343. kAllCntsReachedZero_RefNotificationFlag = 0x1,
  344. /** The normal (not pending IO type) ref cnt has reached zero. */
  345. kRefCntReachedZero_RefNotificationFlag = 0x2,
  346. };
  347. /**
  348. * Called by GrGpuResources when they detect that their ref/io cnts have reached zero. When the
  349. * normal ref cnt reaches zero the flags that are set should be:
  350. * a) kRefCntReachedZero if a pending IO cnt is still non-zero.
  351. * b) (kRefCntReachedZero | kAllCntsReachedZero) when all pending IO cnts are also zero.
  352. * kAllCntsReachedZero is set by itself if a pending IO cnt is decremented to zero and all the
  353. * the other cnts are already zero.
  354. */
  355. void notifyCntReachedZero(GrGpuResource* resource, uint32_t flags) {
  356. fCache->notifyCntReachedZero(resource, flags);
  357. }
  358. /**
  359. * Called by GrGpuResources to change their unique keys.
  360. */
  361. void changeUniqueKey(GrGpuResource* resource, const GrUniqueKey& newKey) {
  362. fCache->changeUniqueKey(resource, newKey);
  363. }
  364. /**
  365. * Called by a GrGpuResource to remove its unique key.
  366. */
  367. void removeUniqueKey(GrGpuResource* resource) { fCache->removeUniqueKey(resource); }
  368. /**
  369. * Called by a GrGpuResource when it removes its scratch key.
  370. */
  371. void willRemoveScratchKey(const GrGpuResource* resource) {
  372. fCache->willRemoveScratchKey(resource);
  373. }
  374. /**
  375. * Called by GrGpuResources when they change from budgeted to unbudgeted or vice versa.
  376. */
  377. void didChangeBudgetStatus(GrGpuResource* resource) { fCache->didChangeBudgetStatus(resource); }
  378. // No taking addresses of this type.
  379. const ResourceAccess* operator&() const;
  380. ResourceAccess* operator&();
  381. GrResourceCache* fCache;
  382. friend class GrGpuResource; // To access all the proxy inline methods.
  383. friend class GrResourceCache; // To create this type.
  384. };
  385. inline GrResourceCache::ResourceAccess GrResourceCache::resourceAccess() {
  386. return ResourceAccess(this);
  387. }
  388. #endif