Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: src/gpu/GrResourceCache.h

Issue 2321563006: Make GrResourceCache dynamically change between LRU and random replacement strategies. (Closed)
Patch Set: rebase Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698