Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2014 Google Inc. | 3 * Copyright 2014 Google Inc. |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 #ifndef GrResourceCache_DEFINED | 9 #ifndef GrResourceCache_DEFINED |
| 10 #define GrResourceCache_DEFINED | 10 #define GrResourceCache_DEFINED |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 37 * | 37 * |
| 38 * A unique key always takes precedence over a scratch key when a resource has b oth types of keys. | 38 * A unique key always takes precedence over a scratch key when a resource has b oth types of keys. |
| 39 * If a resource has neither key type then it will be deleted as soon as the las t reference to it | 39 * If a resource has neither key type then it will be deleted as soon as the las t reference to it |
| 40 * is dropped. | 40 * is dropped. |
| 41 */ | 41 */ |
| 42 class GrResourceCache { | 42 class GrResourceCache { |
| 43 public: | 43 public: |
| 44 GrResourceCache(); | 44 GrResourceCache(); |
| 45 ~GrResourceCache(); | 45 ~GrResourceCache(); |
| 46 | 46 |
| 47 // Default maximum number of budgeted resources in the cache. | |
| 48 static const int kDefaultMaxCount = 2 * (1 << 12); | |
| 49 // Default maximum number of bytes of gpu memory of budgeted resources in th e cache. | |
| 50 static const size_t kDefaultMaxSize = 96 * (1 << 20); | |
| 51 // Default number of flushes a budgeted resources can go unused in the cache before it is | |
| 52 // purged. This is currently set to a large default value until we decide to enable this feature | |
| 53 // of the cache. | |
| 54 static const int kDefaultMaxUnusedFlushes = 1024; | |
| 55 | |
| 47 /** Used to access functionality needed by GrGpuResource for lifetime manage ment. */ | 56 /** Used to access functionality needed by GrGpuResource for lifetime manage ment. */ |
| 48 class ResourceAccess; | 57 class ResourceAccess; |
| 49 ResourceAccess resourceAccess(); | 58 ResourceAccess resourceAccess(); |
| 50 | 59 |
| 51 /** | 60 /** |
| 52 * Sets the cache limits in terms of number of resources and max gpu memory byte size. | 61 * Sets the cache limits in terms of number of resources, max gpu memory byt e size, and number |
| 62 * of GrContext flushes that a resource can be unused before it is evicted. The latter value is | |
| 63 * a suggestion and there is no promise that a resource will be purged immed iately after it | |
| 64 * hasn't been used in maxUnusedFlushes flushes. | |
| 53 */ | 65 */ |
| 54 void setLimits(int count, size_t bytes); | 66 void setLimits(int count, size_t bytes, int maxUnusedFlushes = kDefaultMaxUn usedFlushes); |
| 55 | 67 |
| 56 /** | 68 /** |
| 57 * Returns the number of resources. | 69 * Returns the number of resources. |
| 58 */ | 70 */ |
| 59 int getResourceCount() const { | 71 int getResourceCount() const { |
| 60 return fPurgeableQueue.count() + fNonpurgeableResources.count(); | 72 return fPurgeableQueue.count() + fNonpurgeableResources.count(); |
| 61 } | 73 } |
| 62 | 74 |
| 63 /** | 75 /** |
| 64 * Returns the number of resources that count against the budget. | 76 * Returns the number of resources that count against the budget. |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 129 | 141 |
| 130 /** | 142 /** |
| 131 * Query whether a unique key exists in the cache. | 143 * Query whether a unique key exists in the cache. |
| 132 */ | 144 */ |
| 133 bool hasUniqueKey(const GrUniqueKey& key) const { | 145 bool hasUniqueKey(const GrUniqueKey& key) const { |
| 134 return SkToBool(fUniqueHash.find(key)); | 146 return SkToBool(fUniqueHash.find(key)); |
| 135 } | 147 } |
| 136 | 148 |
| 137 /** Purges resources to become under budget and processes resources with inv alidated unique | 149 /** Purges resources to become under budget and processes resources with inv alidated unique |
| 138 keys. */ | 150 keys. */ |
| 139 void purgeAsNeeded() { | 151 void purgeAsNeeded(); |
| 140 SkTArray<GrUniqueKeyInvalidatedMessage> invalidKeyMsgs; | |
| 141 fInvalidUniqueKeyInbox.poll(&invalidKeyMsgs); | |
| 142 if (invalidKeyMsgs.count()) { | |
| 143 this->processInvalidUniqueKeys(invalidKeyMsgs); | |
| 144 } | |
| 145 if (fBudgetedCount <= fMaxCount && fBudgetedBytes <= fMaxBytes) { | |
| 146 return; | |
| 147 } | |
| 148 this->internalPurgeAsNeeded(); | |
| 149 } | |
| 150 | 152 |
| 151 /** Purges all resources that don't have external owners. */ | 153 /** Purges all resources that don't have external owners. */ |
| 152 void purgeAllUnlocked(); | 154 void purgeAllUnlocked(); |
| 153 | 155 |
| 154 /** | 156 /** |
| 155 * The callback function used by the cache when it is still over budget afte r a purge. The | 157 * The callback function used by the cache when it is still over budget afte r a purge. The |
| 156 * passed in 'data' is the same 'data' handed to setOverbudgetCallback. | 158 * passed in 'data' is the same 'data' handed to setOverbudgetCallback. |
| 157 */ | 159 */ |
| 158 typedef void (*PFOverBudgetCB)(void* data); | 160 typedef void (*PFOverBudgetCB)(void* data); |
| 159 | 161 |
| 160 /** | 162 /** |
| 161 * Set the callback the cache should use when it is still over budget after a purge. The 'data' | 163 * Set the callback the cache should use when it is still over budget after a purge. The 'data' |
| 162 * provided here will be passed back to the callback. Note that the cache wi ll attempt to purge | 164 * provided here will be passed back to the callback. Note that the cache wi ll attempt to purge |
| 163 * any resources newly freed by the callback. | 165 * any resources newly freed by the callback. |
| 164 */ | 166 */ |
| 165 void setOverBudgetCallback(PFOverBudgetCB overBudgetCB, void* data) { | 167 void setOverBudgetCallback(PFOverBudgetCB overBudgetCB, void* data) { |
| 166 fOverBudgetCB = overBudgetCB; | 168 fOverBudgetCB = overBudgetCB; |
| 167 fOverBudgetData = data; | 169 fOverBudgetData = data; |
| 168 } | 170 } |
| 171 | |
| 172 void notifyFlushOccurred(); | |
| 169 | 173 |
| 170 #if GR_GPU_STATS | 174 #if GR_GPU_STATS |
| 171 void dumpStats(SkString*) const; | 175 void dumpStats(SkString*) const; |
| 172 #endif | 176 #endif |
| 173 | 177 |
| 174 // This function is for unit testing and is only defined in test tools. | 178 // This function is for unit testing and is only defined in test tools. |
| 175 void changeTimestamp(uint32_t newTimestamp); | 179 void changeTimestamp(uint32_t newTimestamp); |
| 176 | 180 |
| 177 private: | 181 private: |
| 178 /////////////////////////////////////////////////////////////////////////// | 182 /////////////////////////////////////////////////////////////////////////// |
| 179 /// @name Methods accessible via ResourceAccess | 183 /// @name Methods accessible via ResourceAccess |
| 180 //// | 184 //// |
| 181 void insertResource(GrGpuResource*); | 185 void insertResource(GrGpuResource*); |
| 182 void removeResource(GrGpuResource*); | 186 void removeResource(GrGpuResource*); |
| 183 void notifyPurgeable(GrGpuResource*); | 187 void notifyCntReachedZero(GrGpuResource*, uint32_t flags); |
| 184 void didChangeGpuMemorySize(const GrGpuResource*, size_t oldSize); | 188 void didChangeGpuMemorySize(const GrGpuResource*, size_t oldSize); |
| 185 void changeUniqueKey(GrGpuResource*, const GrUniqueKey&); | 189 void changeUniqueKey(GrGpuResource*, const GrUniqueKey&); |
| 186 void removeUniqueKey(GrGpuResource*); | 190 void removeUniqueKey(GrGpuResource*); |
| 187 void willRemoveScratchKey(const GrGpuResource*); | 191 void willRemoveScratchKey(const GrGpuResource*); |
| 188 void didChangeBudgetStatus(GrGpuResource*); | 192 void didChangeBudgetStatus(GrGpuResource*); |
| 189 void refAndMakeResourceMRU(GrGpuResource*); | 193 void refAndMakeResourceMRU(GrGpuResource*); |
| 190 /// @} | 194 /// @} |
| 191 | 195 |
| 192 void internalPurgeAsNeeded(); | 196 void resetFlushTimestamps(); |
| 193 void processInvalidUniqueKeys(const SkTArray<GrUniqueKeyInvalidatedMessage>& ); | 197 void processInvalidUniqueKeys(const SkTArray<GrUniqueKeyInvalidatedMessage>& ); |
| 194 void addToNonpurgeableArray(GrGpuResource*); | 198 void addToNonpurgeableArray(GrGpuResource*); |
| 195 void removeFromNonpurgeableArray(GrGpuResource*); | 199 void removeFromNonpurgeableArray(GrGpuResource*); |
| 196 bool overBudget() const { return fBudgetedBytes > fMaxBytes || fBudgetedCoun t > fMaxCount; } | 200 bool overBudget() const { return fBudgetedBytes > fMaxBytes || fBudgetedCoun t > fMaxCount; } |
| 197 | 201 |
| 198 uint32_t getNextTimestamp(); | 202 uint32_t getNextTimestamp(); |
| 199 | 203 |
| 200 #ifdef SK_DEBUG | 204 #ifdef SK_DEBUG |
| 201 bool isInCache(const GrGpuResource* r) const; | 205 bool isInCache(const GrGpuResource* r) const; |
| 202 void validate() const; | 206 void validate() const; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 244 ResourceArray fNonpurgeableResources; | 248 ResourceArray fNonpurgeableResources; |
| 245 | 249 |
| 246 // This map holds all resources that can be used as scratch resources. | 250 // This map holds all resources that can be used as scratch resources. |
| 247 ScratchMap fScratchMap; | 251 ScratchMap fScratchMap; |
| 248 // This holds all resources that have unique keys. | 252 // This holds all resources that have unique keys. |
| 249 UniqueHash fUniqueHash; | 253 UniqueHash fUniqueHash; |
| 250 | 254 |
| 251 // our budget, used in purgeAsNeeded() | 255 // our budget, used in purgeAsNeeded() |
| 252 int fMaxCount; | 256 int fMaxCount; |
| 253 size_t fMaxBytes; | 257 size_t fMaxBytes; |
| 258 int fMaxUnusedFlushes; | |
| 254 | 259 |
| 255 #if GR_CACHE_STATS | 260 #if GR_CACHE_STATS |
| 256 int fHighWaterCount; | 261 int fHighWaterCount; |
| 257 size_t fHighWaterBytes; | 262 size_t fHighWaterBytes; |
| 258 int fBudgetedHighWaterCount; | 263 int fBudgetedHighWaterCount; |
| 259 size_t fBudgetedHighWaterBytes; | 264 size_t fBudgetedHighWaterBytes; |
| 260 #endif | 265 #endif |
| 261 | 266 |
| 262 // our current stats for all resources | 267 // our current stats for all resources |
| 263 SkDEBUGCODE(int fCount;) | 268 SkDEBUGCODE(int fCount;) |
| 264 size_t fBytes; | 269 size_t fBytes; |
| 265 | 270 |
| 266 // our current stats for resources that count against the budget | 271 // our current stats for resources that count against the budget |
| 267 int fBudgetedCount; | 272 int fBudgetedCount; |
| 268 size_t fBudgetedBytes; | 273 size_t fBudgetedBytes; |
| 269 | 274 |
| 270 PFOverBudgetCB fOverBudgetCB; | 275 PFOverBudgetCB fOverBudgetCB; |
| 271 void* fOverBudgetData; | 276 void* fOverBudgetData; |
| 272 | 277 |
| 278 // We keep track of the "timestamps" of the last n flushes. If a resource ha sn't been used in | |
|
robertphillips
2015/04/06 19:34:51
Delete the parenthetical question? Isn't fMaxUnuse
bsalomon
2015/04/07 20:33:46
Done.
| |
| 279 // that time then we well preemptively purge it to reduce memory usage. (Mak e this | |
| 280 // configurable with other budget parameters?) | |
| 281 uint32_t* fFlushTimestamps; | |
| 282 int fLastFlushTimestampIndex; | |
| 283 | |
| 273 InvalidUniqueKeyInbox fInvalidUniqueKeyInbox; | 284 InvalidUniqueKeyInbox fInvalidUniqueKeyInbox; |
| 285 | |
| 286 // This resource is allowed to be in the nonpurgeable array for the sake of validate() because | |
| 287 // we're in the midst of converting it to purgeable status. | |
| 288 SkDEBUGCODE(GrGpuResource* fNewlyPurgeableResourceForValidation;) | |
| 274 }; | 289 }; |
| 275 | 290 |
| 276 class GrResourceCache::ResourceAccess { | 291 class GrResourceCache::ResourceAccess { |
| 277 private: | 292 private: |
| 278 ResourceAccess(GrResourceCache* cache) : fCache(cache) { } | 293 ResourceAccess(GrResourceCache* cache) : fCache(cache) { } |
| 279 ResourceAccess(const ResourceAccess& that) : fCache(that.fCache) { } | 294 ResourceAccess(const ResourceAccess& that) : fCache(that.fCache) { } |
| 280 ResourceAccess& operator=(const ResourceAccess&); // unimpl | 295 ResourceAccess& operator=(const ResourceAccess&); // unimpl |
| 281 | 296 |
| 282 /** | 297 /** |
| 283 * Insert a resource into the cache. | 298 * Insert a resource into the cache. |
| 284 */ | 299 */ |
| 285 void insertResource(GrGpuResource* resource) { fCache->insertResource(resour ce); } | 300 void insertResource(GrGpuResource* resource) { fCache->insertResource(resour ce); } |
| 286 | 301 |
| 287 /** | 302 /** |
| 288 * Removes a resource from the cache. | 303 * Removes a resource from the cache. |
| 289 */ | 304 */ |
| 290 void removeResource(GrGpuResource* resource) { fCache->removeResource(resour ce); } | 305 void removeResource(GrGpuResource* resource) { fCache->removeResource(resour ce); } |
| 291 | 306 |
| 292 /** | 307 /** |
| 293 * Called by GrGpuResources when they detects that they are newly purgeable. | 308 * Notifications that should be sent to the cache when the ref/io cnt status of resources |
| 309 * changes. | |
| 294 */ | 310 */ |
| 295 void notifyPurgeable(GrGpuResource* resource) { fCache->notifyPurgeable(reso urce); } | 311 enum RefNotificationFlags { |
| 312 /** All types of refs on the resource have reached zero. */ | |
| 313 kAllCntsReachedZero_RefNotificationFlag = 0x1, | |
| 314 /** The normal (not pending IO type) ref cnt has reached zero. */ | |
| 315 kRefCntReachedZero_RefNotificationFlag = 0x2, | |
| 316 }; | |
| 317 /** | |
|
robertphillips
2015/04/06 19:34:51
detects -> detect ?
bsalomon
2015/04/07 20:33:46
Done.
| |
| 318 * Called by GrGpuResources when they detects that their ref/io cnts have re ached zero. When the | |
| 319 * normal ref cnt reaches zero the flags that are set should be: | |
| 320 * a) kRefCntReachedZero if a pending IO cnt is still non-zero. | |
| 321 * b) (kRefCntReachedZero | kAllCntsReachedZero) when all pending IO cnt s are also zero. | |
| 322 * kAllCntsReachedZero is set by itself if a pending IO cnt is decremented t o zero and all the | |
| 323 * the other cnts are already zero. | |
| 324 */ | |
| 325 void notifyCntReachedZero(GrGpuResource* resource, uint32_t flags) { | |
| 326 fCache->notifyCntReachedZero(resource, flags); | |
| 327 } | |
| 296 | 328 |
| 297 /** | 329 /** |
| 298 * Called by GrGpuResources when their sizes change. | 330 * Called by GrGpuResources when their sizes change. |
| 299 */ | 331 */ |
| 300 void didChangeGpuMemorySize(const GrGpuResource* resource, size_t oldSize) { | 332 void didChangeGpuMemorySize(const GrGpuResource* resource, size_t oldSize) { |
| 301 fCache->didChangeGpuMemorySize(resource, oldSize); | 333 fCache->didChangeGpuMemorySize(resource, oldSize); |
| 302 } | 334 } |
| 303 | 335 |
| 304 /** | 336 /** |
| 305 * Called by GrGpuResources to change their unique keys. | 337 * Called by GrGpuResources to change their unique keys. |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 333 | 365 |
| 334 friend class GrGpuResource; // To access all the proxy inline methods. | 366 friend class GrGpuResource; // To access all the proxy inline methods. |
| 335 friend class GrResourceCache; // To create this type. | 367 friend class GrResourceCache; // To create this type. |
| 336 }; | 368 }; |
| 337 | 369 |
| 338 inline GrResourceCache::ResourceAccess GrResourceCache::resourceAccess() { | 370 inline GrResourceCache::ResourceAccess GrResourceCache::resourceAccess() { |
| 339 return ResourceAccess(this); | 371 return ResourceAccess(this); |
| 340 } | 372 } |
| 341 | 373 |
| 342 #endif | 374 #endif |
| OLD | NEW |