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 |