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