blob: ba9d4d10162abf7d72c00c3b036eddf1452bcece [file] [log] [blame]
bsalomonc8dc1f72014-08-21 13:02:13 -07001
2/*
3 * Copyright 2014 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#include "GrResourceCache2.h"
bsalomonbcf0a522014-10-08 08:40:09 -070011#include "GrGpuResource.h"
bsalomonc8dc1f72014-08-21 13:02:13 -070012
bsalomon7775c852014-12-30 12:50:52 -080013#include "SkChecksum.h"
bsalomon71cb0c22014-11-14 12:10:14 -080014#include "SkGr.h"
15#include "SkMessageBus.h"
16
17DECLARE_SKMESSAGEBUS_MESSAGE(GrResourceInvalidatedMessage);
18
19//////////////////////////////////////////////////////////////////////////////
20
bsalomon7775c852014-12-30 12:50:52 -080021GrScratchKey::ResourceType GrScratchKey::GenerateResourceType() {
22 static int32_t gType = kInvalidResourceType + 1;
bsalomonfe369ee2014-11-10 11:59:06 -080023
bsalomon7775c852014-12-30 12:50:52 -080024 int32_t type = sk_atomic_inc(&gType);
robertphillips9790a7b2015-01-05 12:29:15 -080025 if (type > SK_MaxU16) {
bsalomon71cb0c22014-11-14 12:10:14 -080026 SkFAIL("Too many Resource Types");
27 }
28
29 return static_cast<ResourceType>(type);
30}
31
bsalomon7775c852014-12-30 12:50:52 -080032
33void GrScratchKey::Builder::finish() {
34 if (NULL == fKey) {
35 return;
36 }
37 GR_STATIC_ASSERT(0 == kHash_MetaDataIdx);
38 fKey->fKey[kHash_MetaDataIdx] =
39 SkChecksum::Compute(&fKey->fKey[kHash_MetaDataIdx + 1], fKey->size() - sizeof(uint32_t));
40 fKey = NULL;
41}
42
bsalomonfe369ee2014-11-10 11:59:06 -080043//////////////////////////////////////////////////////////////////////////////
44
bsalomon71cb0c22014-11-14 12:10:14 -080045class GrResourceCache2::AutoValidate : ::SkNoncopyable {
46public:
47 AutoValidate(GrResourceCache2* cache) : fCache(cache) { cache->validate(); }
48 ~AutoValidate() { fCache->validate(); }
49private:
50 GrResourceCache2* fCache;
51};
52
53 //////////////////////////////////////////////////////////////////////////////
54
55static const int kDefaultMaxCount = 2 * (1 << 10);
56static const size_t kDefaultMaxSize = 96 * (1 << 20);
57
58GrResourceCache2::GrResourceCache2()
59 : fMaxCount(kDefaultMaxCount)
60 , fMaxBytes(kDefaultMaxSize)
61#if GR_CACHE_STATS
62 , fHighWaterCount(0)
63 , fHighWaterBytes(0)
bsalomondace19e2014-11-17 07:34:06 -080064 , fBudgetedHighWaterCount(0)
65 , fBudgetedHighWaterBytes(0)
bsalomon71cb0c22014-11-14 12:10:14 -080066#endif
67 , fCount(0)
68 , fBytes(0)
bsalomondace19e2014-11-17 07:34:06 -080069 , fBudgetedCount(0)
70 , fBudgetedBytes(0)
bsalomon71cb0c22014-11-14 12:10:14 -080071 , fPurging(false)
72 , fNewlyPurgableResourceWhilePurging(false)
73 , fOverBudgetCB(NULL)
74 , fOverBudgetData(NULL) {
75}
76
bsalomonc8dc1f72014-08-21 13:02:13 -070077GrResourceCache2::~GrResourceCache2() {
78 this->releaseAll();
79}
80
bsalomon71cb0c22014-11-14 12:10:14 -080081void GrResourceCache2::setLimits(int count, size_t bytes) {
82 fMaxCount = count;
83 fMaxBytes = bytes;
84 this->purgeAsNeeded();
85}
86
bsalomonc8dc1f72014-08-21 13:02:13 -070087void GrResourceCache2::insertResource(GrGpuResource* resource) {
bsalomon49f085d2014-09-05 13:34:00 -070088 SkASSERT(resource);
bsalomonc8dc1f72014-08-21 13:02:13 -070089 SkASSERT(!resource->wasDestroyed());
bsalomon16961262014-08-26 14:01:07 -070090 SkASSERT(!this->isInCache(resource));
bsalomon71cb0c22014-11-14 12:10:14 -080091 SkASSERT(!fPurging);
bsalomonc8dc1f72014-08-21 13:02:13 -070092 fResources.addToHead(resource);
bsalomon71cb0c22014-11-14 12:10:14 -080093
bsalomondace19e2014-11-17 07:34:06 -080094 size_t size = resource->gpuMemorySize();
bsalomonc8dc1f72014-08-21 13:02:13 -070095 ++fCount;
bsalomon84c8e622014-11-17 09:33:27 -080096 fBytes += size;
bsalomon82b1d622014-11-14 13:59:57 -080097#if GR_CACHE_STATS
98 fHighWaterCount = SkTMax(fCount, fHighWaterCount);
99 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes);
100#endif
bsalomon84c8e622014-11-17 09:33:27 -0800101 if (resource->cacheAccess().isBudgeted()) {
bsalomondace19e2014-11-17 07:34:06 -0800102 ++fBudgetedCount;
103 fBudgetedBytes += size;
104#if GR_CACHE_STATS
105 fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount);
106 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes);
107#endif
108 }
bsalomon7775c852014-12-30 12:50:52 -0800109 if (resource->cacheAccess().getScratchKey().isValid()) {
bsalomon84c8e622014-11-17 09:33:27 -0800110 SkASSERT(!resource->cacheAccess().isWrapped());
bsalomon453cf402014-11-11 14:15:57 -0800111 fScratchMap.insert(resource->cacheAccess().getScratchKey(), resource);
bsalomon744998e2014-08-28 09:54:34 -0700112 }
bsalomon71cb0c22014-11-14 12:10:14 -0800113
114 this->purgeAsNeeded();
bsalomonc8dc1f72014-08-21 13:02:13 -0700115}
116
117void GrResourceCache2::removeResource(GrGpuResource* resource) {
bsalomon16961262014-08-26 14:01:07 -0700118 SkASSERT(this->isInCache(resource));
bsalomondace19e2014-11-17 07:34:06 -0800119
120 size_t size = resource->gpuMemorySize();
121 --fCount;
122 fBytes -= size;
bsalomon84c8e622014-11-17 09:33:27 -0800123 if (resource->cacheAccess().isBudgeted()) {
bsalomondace19e2014-11-17 07:34:06 -0800124 --fBudgetedCount;
125 fBudgetedBytes -= size;
126 }
127
128 fResources.remove(resource);
bsalomon7775c852014-12-30 12:50:52 -0800129 if (resource->cacheAccess().getScratchKey().isValid()) {
bsalomon453cf402014-11-11 14:15:57 -0800130 fScratchMap.remove(resource->cacheAccess().getScratchKey(), resource);
bsalomon744998e2014-08-28 09:54:34 -0700131 }
bsalomon453cf402014-11-11 14:15:57 -0800132 if (const GrResourceKey* contentKey = resource->cacheAccess().getContentKey()) {
bsalomon8b79d232014-11-10 10:19:06 -0800133 fContentHash.remove(*contentKey);
134 }
bsalomonb436ed62014-11-17 12:15:56 -0800135 this->validate();
bsalomonc8dc1f72014-08-21 13:02:13 -0700136}
137
138void GrResourceCache2::abandonAll() {
bsalomon71cb0c22014-11-14 12:10:14 -0800139 AutoValidate av(this);
140
141 SkASSERT(!fPurging);
bsalomonc8dc1f72014-08-21 13:02:13 -0700142 while (GrGpuResource* head = fResources.head()) {
143 SkASSERT(!head->wasDestroyed());
bsalomon12299ab2014-11-14 13:33:09 -0800144 head->cacheAccess().abandon();
bsalomonc8dc1f72014-08-21 13:02:13 -0700145 // abandon should have already removed this from the list.
146 SkASSERT(head != fResources.head());
147 }
bsalomon744998e2014-08-28 09:54:34 -0700148 SkASSERT(!fScratchMap.count());
bsalomon8b79d232014-11-10 10:19:06 -0800149 SkASSERT(!fContentHash.count());
bsalomonc8dc1f72014-08-21 13:02:13 -0700150 SkASSERT(!fCount);
bsalomondace19e2014-11-17 07:34:06 -0800151 SkASSERT(!fBytes);
152 SkASSERT(!fBudgetedCount);
153 SkASSERT(!fBudgetedBytes);
bsalomonc8dc1f72014-08-21 13:02:13 -0700154}
155
156void GrResourceCache2::releaseAll() {
bsalomon71cb0c22014-11-14 12:10:14 -0800157 AutoValidate av(this);
158
159 SkASSERT(!fPurging);
bsalomonc8dc1f72014-08-21 13:02:13 -0700160 while (GrGpuResource* head = fResources.head()) {
161 SkASSERT(!head->wasDestroyed());
bsalomon12299ab2014-11-14 13:33:09 -0800162 head->cacheAccess().release();
bsalomonc8dc1f72014-08-21 13:02:13 -0700163 // release should have already removed this from the list.
164 SkASSERT(head != fResources.head());
165 }
bsalomon744998e2014-08-28 09:54:34 -0700166 SkASSERT(!fScratchMap.count());
bsalomonc8dc1f72014-08-21 13:02:13 -0700167 SkASSERT(!fCount);
bsalomondace19e2014-11-17 07:34:06 -0800168 SkASSERT(!fBytes);
169 SkASSERT(!fBudgetedCount);
170 SkASSERT(!fBudgetedBytes);
bsalomonc8dc1f72014-08-21 13:02:13 -0700171}
bsalomonbcf0a522014-10-08 08:40:09 -0700172
173class GrResourceCache2::AvailableForScratchUse {
174public:
bsalomon000f8292014-10-15 19:04:14 -0700175 AvailableForScratchUse(bool rejectPendingIO) : fRejectPendingIO(rejectPendingIO) { }
bsalomonbcf0a522014-10-08 08:40:09 -0700176
177 bool operator()(const GrGpuResource* resource) const {
bsalomon12299ab2014-11-14 13:33:09 -0800178 if (resource->internalHasRef() || !resource->cacheAccess().isScratch()) {
bsalomon000f8292014-10-15 19:04:14 -0700179 return false;
bsalomonbcf0a522014-10-08 08:40:09 -0700180 }
bsalomon000f8292014-10-15 19:04:14 -0700181 return !fRejectPendingIO || !resource->internalHasPendingIO();
bsalomonbcf0a522014-10-08 08:40:09 -0700182 }
bsalomon1e2530b2014-10-09 09:57:18 -0700183
bsalomonbcf0a522014-10-08 08:40:09 -0700184private:
bsalomon000f8292014-10-15 19:04:14 -0700185 bool fRejectPendingIO;
bsalomonbcf0a522014-10-08 08:40:09 -0700186};
187
bsalomon7775c852014-12-30 12:50:52 -0800188GrGpuResource* GrResourceCache2::findAndRefScratchResource(const GrScratchKey& scratchKey,
bsalomon000f8292014-10-15 19:04:14 -0700189 uint32_t flags) {
bsalomon71cb0c22014-11-14 12:10:14 -0800190 SkASSERT(!fPurging);
bsalomon7775c852014-12-30 12:50:52 -0800191 SkASSERT(scratchKey.isValid());
bsalomon000f8292014-10-15 19:04:14 -0700192
bsalomon71cb0c22014-11-14 12:10:14 -0800193 GrGpuResource* resource;
bsalomon000f8292014-10-15 19:04:14 -0700194 if (flags & (kPreferNoPendingIO_ScratchFlag | kRequireNoPendingIO_ScratchFlag)) {
bsalomon71cb0c22014-11-14 12:10:14 -0800195 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(true));
bsalomon000f8292014-10-15 19:04:14 -0700196 if (resource) {
bsalomonb436ed62014-11-17 12:15:56 -0800197 resource->ref();
bsalomon71cb0c22014-11-14 12:10:14 -0800198 this->makeResourceMRU(resource);
bsalomonb436ed62014-11-17 12:15:56 -0800199 this->validate();
200 return resource;
bsalomon000f8292014-10-15 19:04:14 -0700201 } else if (flags & kRequireNoPendingIO_ScratchFlag) {
202 return NULL;
203 }
204 // TODO: fail here when kPrefer is specified, we didn't find a resource without pending io,
205 // but there is still space in our budget for the resource.
206 }
bsalomon71cb0c22014-11-14 12:10:14 -0800207 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(false));
208 if (resource) {
209 resource->ref();
210 this->makeResourceMRU(resource);
bsalomonb436ed62014-11-17 12:15:56 -0800211 this->validate();
bsalomon71cb0c22014-11-14 12:10:14 -0800212 }
213 return resource;
bsalomonbcf0a522014-10-08 08:40:09 -0700214}
bsalomon8b79d232014-11-10 10:19:06 -0800215
bsalomon10e23ca2014-11-25 05:52:06 -0800216void GrResourceCache2::willRemoveScratchKey(const GrGpuResource* resource) {
217 SkASSERT(resource->cacheAccess().isScratch());
218 fScratchMap.remove(resource->cacheAccess().getScratchKey(), resource);
219}
220
bsalomon6d4488c2014-11-11 07:27:16 -0800221bool GrResourceCache2::didSetContentKey(GrGpuResource* resource) {
bsalomon71cb0c22014-11-14 12:10:14 -0800222 SkASSERT(!fPurging);
bsalomon8b79d232014-11-10 10:19:06 -0800223 SkASSERT(resource);
bsalomon71cb0c22014-11-14 12:10:14 -0800224 SkASSERT(this->isInCache(resource));
bsalomon453cf402014-11-11 14:15:57 -0800225 SkASSERT(resource->cacheAccess().getContentKey());
bsalomon8b79d232014-11-10 10:19:06 -0800226
bsalomon453cf402014-11-11 14:15:57 -0800227 GrGpuResource* res = fContentHash.find(*resource->cacheAccess().getContentKey());
bsalomon8b79d232014-11-10 10:19:06 -0800228 if (NULL != res) {
229 return false;
230 }
231
232 fContentHash.add(resource);
bsalomon71cb0c22014-11-14 12:10:14 -0800233 this->validate();
bsalomon8b79d232014-11-10 10:19:06 -0800234 return true;
235}
bsalomon71cb0c22014-11-14 12:10:14 -0800236
237void GrResourceCache2::makeResourceMRU(GrGpuResource* resource) {
bsalomon71cb0c22014-11-14 12:10:14 -0800238 SkASSERT(!fPurging);
239 SkASSERT(resource);
240 SkASSERT(this->isInCache(resource));
241 fResources.remove(resource);
bsalomonb436ed62014-11-17 12:15:56 -0800242 fResources.addToHead(resource);
bsalomon71cb0c22014-11-14 12:10:14 -0800243}
244
bsalomon12299ab2014-11-14 13:33:09 -0800245void GrResourceCache2::notifyPurgable(GrGpuResource* resource) {
bsalomon71cb0c22014-11-14 12:10:14 -0800246 SkASSERT(resource);
247 SkASSERT(this->isInCache(resource));
248 SkASSERT(resource->isPurgable());
249
250 // We can't purge if in the middle of purging because purge is iterating. Instead record
251 // that additional resources became purgable.
252 if (fPurging) {
253 fNewlyPurgableResourceWhilePurging = true;
254 return;
255 }
256
257 // Purge the resource if we're over budget
bsalomondace19e2014-11-17 07:34:06 -0800258 bool overBudget = fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes;
bsalomon71cb0c22014-11-14 12:10:14 -0800259
bsalomon71cb0c22014-11-14 12:10:14 -0800260 // Also purge if the resource has neither a valid scratch key nor a content key.
261 bool noKey = !resource->cacheAccess().isScratch() &&
262 (NULL == resource->cacheAccess().getContentKey());
263
bsalomon5236cf42015-01-14 10:42:08 -0800264 // Only cached resources should ever have a key.
265 SkASSERT(noKey || resource->cacheAccess().isBudgeted());
bsalomondace19e2014-11-17 07:34:06 -0800266
bsalomon71cb0c22014-11-14 12:10:14 -0800267 if (overBudget || noKey) {
268 SkDEBUGCODE(int beforeCount = fCount;)
bsalomon12299ab2014-11-14 13:33:09 -0800269 resource->cacheAccess().release();
270 // We should at least free this resource, perhaps dependent resources as well.
bsalomon71cb0c22014-11-14 12:10:14 -0800271 SkASSERT(fCount < beforeCount);
272 }
273
274 this->validate();
275}
276
277void GrResourceCache2::didChangeGpuMemorySize(const GrGpuResource* resource, size_t oldSize) {
278 // SkASSERT(!fPurging); GrPathRange increases size during flush. :(
279 SkASSERT(resource);
280 SkASSERT(this->isInCache(resource));
281
bsalomondace19e2014-11-17 07:34:06 -0800282 ptrdiff_t delta = resource->gpuMemorySize() - oldSize;
283
284 fBytes += delta;
bsalomon82b1d622014-11-14 13:59:57 -0800285#if GR_CACHE_STATS
286 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes);
287#endif
bsalomon84c8e622014-11-17 09:33:27 -0800288 if (resource->cacheAccess().isBudgeted()) {
bsalomondace19e2014-11-17 07:34:06 -0800289 fBudgetedBytes += delta;
290#if GR_CACHE_STATS
291 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes);
292#endif
293 }
bsalomon71cb0c22014-11-14 12:10:14 -0800294
295 this->purgeAsNeeded();
296 this->validate();
297}
298
bsalomon84c8e622014-11-17 09:33:27 -0800299void GrResourceCache2::didChangeBudgetStatus(GrGpuResource* resource) {
300 SkASSERT(!fPurging);
301 SkASSERT(resource);
302 SkASSERT(this->isInCache(resource));
303
304 size_t size = resource->gpuMemorySize();
305
306 if (resource->cacheAccess().isBudgeted()) {
307 ++fBudgetedCount;
308 fBudgetedBytes += size;
bsalomonafe30052015-01-16 07:32:33 -0800309#if GR_CACHE_STATS
310 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes);
311 fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount);
312#endif
bsalomon84c8e622014-11-17 09:33:27 -0800313 this->purgeAsNeeded();
314 } else {
315 --fBudgetedCount;
316 fBudgetedBytes -= size;
317 }
318
319 this->validate();
320}
321
bsalomon71cb0c22014-11-14 12:10:14 -0800322void GrResourceCache2::internalPurgeAsNeeded() {
323 SkASSERT(!fPurging);
324 SkASSERT(!fNewlyPurgableResourceWhilePurging);
bsalomondace19e2014-11-17 07:34:06 -0800325 SkASSERT(fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800326
327 fPurging = true;
328
bsalomon71cb0c22014-11-14 12:10:14 -0800329 bool overBudget = true;
330 do {
331 fNewlyPurgableResourceWhilePurging = false;
332 ResourceList::Iter resourceIter;
333 GrGpuResource* resource = resourceIter.init(fResources,
334 ResourceList::Iter::kTail_IterStart);
335
336 while (resource) {
337 GrGpuResource* prev = resourceIter.prev();
338 if (resource->isPurgable()) {
bsalomon12299ab2014-11-14 13:33:09 -0800339 resource->cacheAccess().release();
bsalomon71cb0c22014-11-14 12:10:14 -0800340 }
341 resource = prev;
bsalomondace19e2014-11-17 07:34:06 -0800342 if (fBudgetedCount <= fMaxCount && fBudgetedBytes <= fMaxBytes) {
bsalomon71cb0c22014-11-14 12:10:14 -0800343 overBudget = false;
344 resource = NULL;
345 }
346 }
347
348 if (!fNewlyPurgableResourceWhilePurging && overBudget && fOverBudgetCB) {
349 // Despite the purge we're still over budget. Call our over budget callback.
350 (*fOverBudgetCB)(fOverBudgetData);
351 }
352 } while (overBudget && fNewlyPurgableResourceWhilePurging);
353
354 fNewlyPurgableResourceWhilePurging = false;
355 fPurging = false;
bsalomonb436ed62014-11-17 12:15:56 -0800356 this->validate();
bsalomon71cb0c22014-11-14 12:10:14 -0800357}
358
359void GrResourceCache2::purgeAllUnlocked() {
360 SkASSERT(!fPurging);
361 SkASSERT(!fNewlyPurgableResourceWhilePurging);
362
363 fPurging = true;
364
bsalomon71cb0c22014-11-14 12:10:14 -0800365 do {
366 fNewlyPurgableResourceWhilePurging = false;
367 ResourceList::Iter resourceIter;
368 GrGpuResource* resource =
369 resourceIter.init(fResources, ResourceList::Iter::kTail_IterStart);
370
371 while (resource) {
372 GrGpuResource* prev = resourceIter.prev();
373 if (resource->isPurgable()) {
bsalomon12299ab2014-11-14 13:33:09 -0800374 resource->cacheAccess().release();
375 }
bsalomon71cb0c22014-11-14 12:10:14 -0800376 resource = prev;
377 }
378
379 if (!fNewlyPurgableResourceWhilePurging && fCount && fOverBudgetCB) {
380 (*fOverBudgetCB)(fOverBudgetData);
381 }
382 } while (fNewlyPurgableResourceWhilePurging);
383 fPurging = false;
bsalomonb436ed62014-11-17 12:15:56 -0800384 this->validate();
bsalomon71cb0c22014-11-14 12:10:14 -0800385}
386
387#ifdef SK_DEBUG
388void GrResourceCache2::validate() const {
389 size_t bytes = 0;
390 int count = 0;
bsalomondace19e2014-11-17 07:34:06 -0800391 int budgetedCount = 0;
392 size_t budgetedBytes = 0;
bsalomon71cb0c22014-11-14 12:10:14 -0800393 int locked = 0;
394 int scratch = 0;
395 int couldBeScratch = 0;
396 int content = 0;
397
398 ResourceList::Iter iter;
399 GrGpuResource* resource = iter.init(fResources, ResourceList::Iter::kHead_IterStart);
400 for ( ; resource; resource = iter.next()) {
401 bytes += resource->gpuMemorySize();
402 ++count;
403
404 if (!resource->isPurgable()) {
405 ++locked;
406 }
407
408 if (resource->cacheAccess().isScratch()) {
409 SkASSERT(NULL == resource->cacheAccess().getContentKey());
410 ++scratch;
411 SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey()));
bsalomondace19e2014-11-17 07:34:06 -0800412 SkASSERT(!resource->cacheAccess().isWrapped());
bsalomon7775c852014-12-30 12:50:52 -0800413 } else if (resource->cacheAccess().getScratchKey().isValid()) {
bsalomon71cb0c22014-11-14 12:10:14 -0800414 SkASSERT(NULL != resource->cacheAccess().getContentKey());
415 ++couldBeScratch;
416 SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey()));
bsalomondace19e2014-11-17 07:34:06 -0800417 SkASSERT(!resource->cacheAccess().isWrapped());
bsalomon71cb0c22014-11-14 12:10:14 -0800418 }
419
420 if (const GrResourceKey* contentKey = resource->cacheAccess().getContentKey()) {
421 ++content;
422 SkASSERT(fContentHash.find(*contentKey) == resource);
bsalomondace19e2014-11-17 07:34:06 -0800423 SkASSERT(!resource->cacheAccess().isWrapped());
424 }
425
bsalomon84c8e622014-11-17 09:33:27 -0800426 if (resource->cacheAccess().isBudgeted()) {
bsalomondace19e2014-11-17 07:34:06 -0800427 ++budgetedCount;
428 budgetedBytes += resource->gpuMemorySize();
bsalomon71cb0c22014-11-14 12:10:14 -0800429 }
430 }
431
bsalomondace19e2014-11-17 07:34:06 -0800432 SkASSERT(fBudgetedCount <= fCount);
433 SkASSERT(fBudgetedBytes <= fBudgetedBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800434 SkASSERT(bytes == fBytes);
435 SkASSERT(count == fCount);
bsalomondace19e2014-11-17 07:34:06 -0800436 SkASSERT(budgetedBytes == fBudgetedBytes);
437 SkASSERT(budgetedCount == fBudgetedCount);
bsalomon71cb0c22014-11-14 12:10:14 -0800438#if GR_CACHE_STATS
bsalomondace19e2014-11-17 07:34:06 -0800439 SkASSERT(fBudgetedHighWaterCount <= fHighWaterCount);
440 SkASSERT(fBudgetedHighWaterBytes <= fHighWaterBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800441 SkASSERT(bytes <= fHighWaterBytes);
442 SkASSERT(count <= fHighWaterCount);
bsalomondace19e2014-11-17 07:34:06 -0800443 SkASSERT(budgetedBytes <= fBudgetedHighWaterBytes);
444 SkASSERT(budgetedCount <= fBudgetedHighWaterCount);
bsalomon71cb0c22014-11-14 12:10:14 -0800445#endif
446 SkASSERT(content == fContentHash.count());
447 SkASSERT(scratch + couldBeScratch == fScratchMap.count());
448
bsalomon12299ab2014-11-14 13:33:09 -0800449 // This assertion is not currently valid because we can be in recursive notifyIsPurgable()
450 // calls. This will be fixed when subresource registration is explicit.
bsalomondace19e2014-11-17 07:34:06 -0800451 // bool overBudget = budgetedBytes > fMaxBytes || budgetedCount > fMaxCount;
bsalomon12299ab2014-11-14 13:33:09 -0800452 // SkASSERT(!overBudget || locked == count || fPurging);
bsalomon71cb0c22014-11-14 12:10:14 -0800453}
454#endif
455
456#if GR_CACHE_STATS
457void GrResourceCache2::printStats() const {
458 this->validate();
459
460 int locked = 0;
461 int scratch = 0;
bsalomon84c8e622014-11-17 09:33:27 -0800462 int wrapped = 0;
463 size_t unbudgetedSize = 0;
bsalomon71cb0c22014-11-14 12:10:14 -0800464
465 ResourceList::Iter iter;
466 GrGpuResource* resource = iter.init(fResources, ResourceList::Iter::kHead_IterStart);
467
468 for ( ; resource; resource = iter.next()) {
469 if (!resource->isPurgable()) {
470 ++locked;
471 }
472 if (resource->cacheAccess().isScratch()) {
473 ++scratch;
474 }
bsalomon84c8e622014-11-17 09:33:27 -0800475 if (resource->cacheAccess().isWrapped()) {
476 ++wrapped;
477 }
478 if (!resource->cacheAccess().isBudgeted()) {
479 unbudgetedSize += resource->gpuMemorySize();
480 }
bsalomon71cb0c22014-11-14 12:10:14 -0800481 }
482
bsalomondace19e2014-11-17 07:34:06 -0800483 float countUtilization = (100.f * fBudgetedCount) / fMaxCount;
484 float byteUtilization = (100.f * fBudgetedBytes) / fMaxBytes;
bsalomon71cb0c22014-11-14 12:10:14 -0800485
486 SkDebugf("Budget: %d items %d bytes\n", fMaxCount, fMaxBytes);
bsalomon84c8e622014-11-17 09:33:27 -0800487 SkDebugf("\t\tEntry Count: current %d"
488 " (%d budgeted, %d wrapped, %d locked, %d scratch %.2g%% full), high %d\n",
489 fCount, fBudgetedCount, wrapped, locked, scratch, countUtilization, fHighWaterCount);
490 SkDebugf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full, %d unbudgeted) high %d\n",
491 fBytes, fBudgetedBytes, byteUtilization, unbudgetedSize, fHighWaterBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800492}
493
494#endif