Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #ifndef GrResourceCache_DEFINED | 8 #ifndef GrResourceCache_DEFINED |
| 9 #define GrResourceCache_DEFINED | 9 #define GrResourceCache_DEFINED |
| 10 | 10 |
| 11 #include "GrGpuResource.h" | 11 #include "GrGpuResource.h" |
| 12 #include "GrGpuResourceCacheAccess.h" | 12 #include "GrGpuResourceCacheAccess.h" |
| 13 #include "GrGpuResourcePriv.h" | 13 #include "GrGpuResourcePriv.h" |
| 14 #include "GrResourceCache.h" | 14 #include "GrResourceCache.h" |
| 15 #include "GrResourceKey.h" | 15 #include "GrResourceKey.h" |
| 16 #include "SkChunkAlloc.h" | |
| 16 #include "SkMessageBus.h" | 17 #include "SkMessageBus.h" |
| 18 #include "SkRandom.h" | |
| 17 #include "SkRefCnt.h" | 19 #include "SkRefCnt.h" |
| 18 #include "SkTArray.h" | 20 #include "SkTArray.h" |
| 19 #include "SkTDPQueue.h" | 21 #include "SkTDPQueue.h" |
| 20 #include "SkTInternalLList.h" | 22 #include "SkTInternalLList.h" |
| 21 #include "SkTMultiMap.h" | 23 #include "SkTMultiMap.h" |
| 22 | 24 |
| 23 class GrCaps; | 25 class GrCaps; |
| 24 class SkString; | 26 class SkString; |
| 25 class SkTraceMemoryDump; | 27 class SkTraceMemoryDump; |
| 26 | 28 |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 135 #ifdef SK_DEBUG | 137 #ifdef SK_DEBUG |
| 136 // This is not particularly fast and only used for validation, so debug only . | 138 // This is not particularly fast and only used for validation, so debug only . |
| 137 int countScratchEntriesForKey(const GrScratchKey& scratchKey) const { | 139 int countScratchEntriesForKey(const GrScratchKey& scratchKey) const { |
| 138 return fScratchMap.countForKey(scratchKey); | 140 return fScratchMap.countForKey(scratchKey); |
| 139 } | 141 } |
| 140 #endif | 142 #endif |
| 141 | 143 |
| 142 /** | 144 /** |
| 143 * Find a resource that matches a unique key. | 145 * Find a resource that matches a unique key. |
| 144 */ | 146 */ |
| 145 GrGpuResource* findAndRefUniqueResource(const GrUniqueKey& key) { | 147 GrGpuResource* findAndRefUniqueResource(const GrUniqueKey& key); |
| 146 GrGpuResource* resource = fUniqueHash.find(key); | |
| 147 if (resource) { | |
| 148 this->refAndMakeResourceMRU(resource); | |
| 149 } | |
| 150 return resource; | |
| 151 } | |
| 152 | 148 |
| 153 /** | 149 /** |
| 154 * Query whether a unique key exists in the cache. | 150 * Query whether a unique key exists in the cache. |
| 155 */ | 151 */ |
| 156 bool hasUniqueKey(const GrUniqueKey& key) const { | 152 bool hasUniqueKey(const GrUniqueKey& key) const { |
| 157 return SkToBool(fUniqueHash.find(key)); | 153 return SkToBool(fUniqueHash.find(key)); |
| 158 } | 154 } |
| 159 | 155 |
| 160 /** Purges resources to become under budget and processes resources with inv alidated unique | 156 /** Purges resources to become under budget and processes resources with inv alidated unique |
| 161 keys. */ | 157 keys. */ |
| 162 void purgeAsNeeded(); | 158 void purgeAsNeeded() { this->internalPurgeAsNeeded(false); } |
| 163 | 159 |
| 164 /** Purges all resources that don't have external owners. */ | 160 /** Purges all resources that don't have external owners. */ |
| 165 void purgeAllUnlocked(); | 161 void purgeAllUnlocked(); |
| 166 | 162 |
| 167 /** Returns true if the cache would like a flush to occur in order to make m ore resources | 163 /** Returns true if the cache would like a flush to occur in order to make m ore resources |
| 168 purgeable. */ | 164 purgeable. */ |
| 169 bool requestsFlush() const { return fRequestFlush; } | 165 bool requestsFlush() const { |
| 166 // When in random replacement mode we request a flush in order to make a s many resources | |
| 167 // as possible subject to replacement. | |
| 168 return this->overBudget() && (ReplacementStrategy::kRandom == fStrategy || | |
| 169 0 == fPurgeableQueue.count()); | |
| 170 } | |
| 170 | 171 |
| 171 enum FlushType { | 172 enum FlushType { |
| 172 kExternal, | 173 kExternal, |
| 173 kImmediateMode, | 174 kImmediateMode, |
| 174 kCacheRequested, | 175 kCacheRequested, |
| 175 }; | 176 }; |
| 176 void notifyFlushOccurred(FlushType); | 177 void notifyFlushOccurred(FlushType); |
| 177 | 178 |
| 178 #if GR_CACHE_STATS | 179 #if GR_CACHE_STATS |
| 179 struct Stats { | 180 struct Stats { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 230 void removeResource(GrGpuResource*); | 231 void removeResource(GrGpuResource*); |
| 231 void notifyCntReachedZero(GrGpuResource*, uint32_t flags); | 232 void notifyCntReachedZero(GrGpuResource*, uint32_t flags); |
| 232 void didChangeGpuMemorySize(const GrGpuResource*, size_t oldSize); | 233 void didChangeGpuMemorySize(const GrGpuResource*, size_t oldSize); |
| 233 void changeUniqueKey(GrGpuResource*, const GrUniqueKey&); | 234 void changeUniqueKey(GrGpuResource*, const GrUniqueKey&); |
| 234 void removeUniqueKey(GrGpuResource*); | 235 void removeUniqueKey(GrGpuResource*); |
| 235 void willRemoveScratchKey(const GrGpuResource*); | 236 void willRemoveScratchKey(const GrGpuResource*); |
| 236 void didChangeBudgetStatus(GrGpuResource*); | 237 void didChangeBudgetStatus(GrGpuResource*); |
| 237 void refAndMakeResourceMRU(GrGpuResource*); | 238 void refAndMakeResourceMRU(GrGpuResource*); |
| 238 /// @} | 239 /// @} |
| 239 | 240 |
| 241 void internalPurgeAsNeeded(bool fromFlushNotification); | |
| 240 void resetFlushTimestamps(); | 242 void resetFlushTimestamps(); |
| 241 void processInvalidUniqueKeys(const SkTArray<GrUniqueKeyInvalidatedMessage>& ); | 243 void processInvalidUniqueKeys(const SkTArray<GrUniqueKeyInvalidatedMessage>& ); |
| 242 void addToNonpurgeableArray(GrGpuResource*); | 244 void addToNonpurgeableArray(GrGpuResource*); |
| 243 void removeFromNonpurgeableArray(GrGpuResource*); | 245 void removeFromNonpurgeableArray(GrGpuResource*); |
| 244 bool overBudget() const { return fBudgetedBytes > fMaxBytes || fBudgetedCoun t > fMaxCount; } | 246 bool overBudget() const { return fBudgetedBytes > fMaxBytes || fBudgetedCoun t > fMaxCount; } |
| 247 GrGpuResource* selectResourceUsingStrategy(); | |
| 248 void recordPurgedKey(GrGpuResource*); | |
| 249 void recordKeyMiss(const GrUniqueKey&); | |
| 245 | 250 |
| 246 bool wouldFit(size_t bytes) { | 251 bool wouldFit(size_t bytes) { |
| 247 return fBudgetedBytes+bytes <= fMaxBytes && fBudgetedCount+1 <= fMaxCoun t; | 252 return fBudgetedBytes+bytes <= fMaxBytes && fBudgetedCount+1 <= fMaxCoun t; |
| 248 } | 253 } |
| 249 | 254 |
| 250 uint32_t getNextTimestamp(); | 255 uint32_t getNextTimestamp(); |
| 251 | 256 |
| 252 #ifdef SK_DEBUG | 257 #ifdef SK_DEBUG |
| 253 bool isInCache(const GrGpuResource* r) const; | 258 bool isInCache(const GrGpuResource* r) const; |
| 254 void validate() const; | 259 void validate() const; |
| 255 #else | 260 #else |
| 256 void validate() const {} | 261 void validate() const {} |
| 257 #endif | 262 #endif |
| 258 | 263 |
| 259 class AutoValidate; | 264 class AutoValidate; |
| 260 | 265 |
| 261 class AvailableForScratchUse; | 266 class AvailableForScratchUse; |
| 262 | 267 |
| 263 struct ScratchMapTraits { | 268 struct HashTraitsBase { |
| 269 static uint32_t Hash(const GrResourceKey& key) { return key.hash(); } | |
| 270 }; | |
| 271 | |
| 272 struct ScratchMapTraits : public HashTraitsBase { | |
| 264 static const GrScratchKey& GetKey(const GrGpuResource& r) { | 273 static const GrScratchKey& GetKey(const GrGpuResource& r) { |
| 265 return r.resourcePriv().getScratchKey(); | 274 return r.resourcePriv().getScratchKey(); |
| 266 } | 275 } |
| 267 | |
| 268 static uint32_t Hash(const GrScratchKey& key) { return key.hash(); } | |
| 269 }; | 276 }; |
| 270 typedef SkTMultiMap<GrGpuResource, GrScratchKey, ScratchMapTraits> ScratchMa p; | 277 typedef SkTMultiMap<GrGpuResource, GrScratchKey, ScratchMapTraits> ScratchMa p; |
| 271 | 278 |
| 272 struct UniqueHashTraits { | 279 struct UniqueHashTraits : public HashTraitsBase { |
| 273 static const GrUniqueKey& GetKey(const GrGpuResource& r) { return r.getU niqueKey(); } | 280 static const GrUniqueKey& GetKey(const GrGpuResource& r) { return r.getU niqueKey(); } |
| 274 | |
| 275 static uint32_t Hash(const GrUniqueKey& key) { return key.hash(); } | |
| 276 }; | 281 }; |
| 277 typedef SkTDynamicHash<GrGpuResource, GrUniqueKey, UniqueHashTraits> UniqueH ash; | 282 typedef SkTDynamicHash<GrGpuResource, GrUniqueKey, UniqueHashTraits> UniqueH ash; |
| 278 | 283 |
|
robertphillips
2016/09/13 13:05:21
missing space before '{' ?
bsalomon
2016/09/13 13:31:33
Done.
| |
| 284 struct UniqueSetTraits : public HashTraitsBase{ | |
| 285 static const GrUniqueKey& GetKey(const GrUniqueKey& key) { return key; } | |
| 286 }; | |
| 287 typedef SkTDynamicHash<GrUniqueKey, GrUniqueKey, UniqueSetTraits> UniqueKeyS et; | |
| 288 | |
| 279 static bool CompareTimestamp(GrGpuResource* const& a, GrGpuResource* const& b) { | 289 static bool CompareTimestamp(GrGpuResource* const& a, GrGpuResource* const& b) { |
| 280 return a->cacheAccess().timestamp() < b->cacheAccess().timestamp(); | 290 return a->cacheAccess().timestamp() < b->cacheAccess().timestamp(); |
| 281 } | 291 } |
| 282 | 292 |
| 283 static int* AccessResourceIndex(GrGpuResource* const& res) { | 293 static int* AccessResourceIndex(GrGpuResource* const& res) { |
| 284 return res->cacheAccess().accessCacheIndex(); | 294 return res->cacheAccess().accessCacheIndex(); |
| 285 } | 295 } |
| 286 | 296 |
| 297 /** | |
| 298 * The resource cache chooses one of these replacement strategies based on a "strategy score" | |
| 299 * updated after each external flush based on unique key cache misses. | |
| 300 */ | |
| 301 enum class ReplacementStrategy { | |
| 302 kLRU, | |
| 303 kRandom | |
| 304 }; | |
| 305 /** | |
| 306 * When the current strategy score is >=0 LRU is chosen, when it is < 0 rand om is chosen. The | |
| 307 * absolute value of the score moves by 1 each flush. | |
| 308 */ | |
| 309 static constexpr int kStrategyScoreMin = -5; | |
| 310 static constexpr int kStrategyScoreMax = 4; | |
| 311 static constexpr int kInitialStrategyScoreMax = 3; | |
| 312 | |
| 287 typedef SkMessageBus<GrUniqueKeyInvalidatedMessage>::Inbox InvalidUniqueKeyI nbox; | 313 typedef SkMessageBus<GrUniqueKeyInvalidatedMessage>::Inbox InvalidUniqueKeyI nbox; |
| 288 typedef SkTDPQueue<GrGpuResource*, CompareTimestamp, AccessResourceIndex> Pu rgeableQueue; | 314 typedef SkTDPQueue<GrGpuResource*, CompareTimestamp, AccessResourceIndex> Pu rgeableQueue; |
| 289 typedef SkTDArray<GrGpuResource*> ResourceArray; | 315 typedef SkTDArray<GrGpuResource*> ResourceArray; |
| 290 | 316 |
| 291 // Whenever a resource is added to the cache or the result of a cache lookup , fTimestamp is | 317 // Whenever a resource is added to the cache or the result of a cache lookup , fTimestamp is |
| 292 // assigned as the resource's timestamp and then incremented. fPurgeableQueu e orders the | 318 // assigned as the resource's timestamp and then incremented. fPurgeableQueu e orders the |
| 293 // purgeable resources by this value, and thus is used to purge resources in LRU order. | 319 // purgeable resources by this value, and thus is used to purge resources in LRU order. |
| 294 uint32_t fTimestamp; | 320 uint32_t fTimestamp; |
| 295 PurgeableQueue fPurgeableQueue; | 321 PurgeableQueue fPurgeableQueue; |
| 296 ResourceArray fNonpurgeableResources; | 322 ResourceArray fNonpurgeableResources; |
| 297 | 323 |
| 298 // This map holds all resources that can be used as scratch resources. | 324 // This map holds all resources that can be used as scratch resources. |
| 299 ScratchMap fScratchMap; | 325 ScratchMap fScratchMap; |
| 300 // This holds all resources that have unique keys. | 326 // This holds all resources that have unique keys. |
| 301 UniqueHash fUniqueHash; | 327 UniqueHash fUniqueHash; |
| 302 | 328 |
| 303 // our budget, used in purgeAsNeeded() | 329 // our budget, used in purgeAsNeeded() |
| 304 int fMaxCount; | 330 int fMaxCount; |
| 305 size_t fMaxBytes; | 331 size_t fMaxBytes; |
| 306 int fMaxUnusedFlushes; | 332 int fMaxUnusedFlushes; |
| 307 | 333 |
| 334 // Data related to replacement strategy. | |
| 335 SkRandom fRandom; | |
| 336 ReplacementStrategy fStrategy; | |
| 337 int fStrategyScore; | |
| 338 int fTotalMissesThisFlush; | |
| 339 int fMissesThisFlushPurgedRecently; | |
| 340 UniqueKeySet fUniqueKeysPurgedThisFlush[2]; | |
| 341 SkChunkAlloc fUniqueKeysPurgedThisFlushStorage[2]; | |
| 342 int fFlushParity; | |
| 343 | |
| 308 #if GR_CACHE_STATS | 344 #if GR_CACHE_STATS |
| 309 int fHighWaterCount; | 345 int fHighWaterCount; |
| 310 size_t fHighWaterBytes; | 346 size_t fHighWaterBytes; |
| 311 int fBudgetedHighWaterCount; | 347 int fBudgetedHighWaterCount; |
| 312 size_t fBudgetedHighWaterBytes; | 348 size_t fBudgetedHighWaterBytes; |
| 313 #endif | 349 #endif |
| 314 | 350 |
| 315 // our current stats for all resources | 351 // our current stats for all resources |
| 316 SkDEBUGCODE(int fCount;) | 352 SkDEBUGCODE(int fCount;) |
| 317 size_t fBytes; | 353 size_t fBytes; |
| 318 | 354 |
| 319 // our current stats for resources that count against the budget | 355 // our current stats for resources that count against the budget |
| 320 int fBudgetedCount; | 356 int fBudgetedCount; |
| 321 size_t fBudgetedBytes; | 357 size_t fBudgetedBytes; |
| 322 | 358 |
| 323 bool fRequestFlush; | |
| 324 | |
| 325 // We keep track of the "timestamps" of the last n flushes. If a resource ha sn't been used in | 359 // We keep track of the "timestamps" of the last n flushes. If a resource ha sn't been used in |
| 326 // that time then we well preemptively purge it to reduce memory usage. | 360 // that time then we well preemptively purge it to reduce memory usage. |
| 327 uint32_t* fFlushTimestamps; | 361 uint32_t* fFlushTimestamps; |
| 328 int fLastFlushTimestampIndex; | 362 int fLastFlushTimestampIndex; |
| 329 | 363 |
| 330 InvalidUniqueKeyInbox fInvalidUniqueKeyInbox; | 364 InvalidUniqueKeyInbox fInvalidUniqueKeyInbox; |
| 331 | 365 |
| 332 // This resource is allowed to be in the nonpurgeable array for the sake of validate() because | 366 // This resource is allowed to be in the nonpurgeable array for the sake of validate() because |
| 333 // we're in the midst of converting it to purgeable status. | 367 // we're in the midst of converting it to purgeable status. |
| 334 SkDEBUGCODE(GrGpuResource* fNewlyPurgeableResourceForValidation;) | 368 SkDEBUGCODE(GrGpuResource* fNewlyPurgeableResourceForValidation;) |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 413 | 447 |
| 414 friend class GrGpuResource; // To access all the proxy inline methods. | 448 friend class GrGpuResource; // To access all the proxy inline methods. |
| 415 friend class GrResourceCache; // To create this type. | 449 friend class GrResourceCache; // To create this type. |
| 416 }; | 450 }; |
| 417 | 451 |
| 418 inline GrResourceCache::ResourceAccess GrResourceCache::resourceAccess() { | 452 inline GrResourceCache::ResourceAccess GrResourceCache::resourceAccess() { |
| 419 return ResourceAccess(this); | 453 return ResourceAccess(this); |
| 420 } | 454 } |
| 421 | 455 |
| 422 #endif | 456 #endif |
| OLD | NEW |