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 |