blob: ccfe382733fa94383c09bd48da8cef75bfe5a86b [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);
25 if (kInvalidResourceType == type) {
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
bsalomondace19e2014-11-17 07:34:06 -0800264 // Wrapped resources should never have a key.
265 SkASSERT(noKey || !resource->cacheAccess().isWrapped());
266
267 // And purge if the resource is wrapped
bsalomon71cb0c22014-11-14 12:10:14 -0800268 if (overBudget || noKey) {
269 SkDEBUGCODE(int beforeCount = fCount;)
bsalomon12299ab2014-11-14 13:33:09 -0800270 resource->cacheAccess().release();
271 // We should at least free this resource, perhaps dependent resources as well.
bsalomon71cb0c22014-11-14 12:10:14 -0800272 SkASSERT(fCount < beforeCount);
273 }
274
275 this->validate();
276}
277
278void GrResourceCache2::didChangeGpuMemorySize(const GrGpuResource* resource, size_t oldSize) {
279 // SkASSERT(!fPurging); GrPathRange increases size during flush. :(
280 SkASSERT(resource);
281 SkASSERT(this->isInCache(resource));
282
bsalomondace19e2014-11-17 07:34:06 -0800283 ptrdiff_t delta = resource->gpuMemorySize() - oldSize;
284
285 fBytes += delta;
bsalomon82b1d622014-11-14 13:59:57 -0800286#if GR_CACHE_STATS
287 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes);
288#endif
bsalomon84c8e622014-11-17 09:33:27 -0800289 if (resource->cacheAccess().isBudgeted()) {
bsalomondace19e2014-11-17 07:34:06 -0800290 fBudgetedBytes += delta;
291#if GR_CACHE_STATS
292 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes);
293#endif
294 }
bsalomon71cb0c22014-11-14 12:10:14 -0800295
296 this->purgeAsNeeded();
297 this->validate();
298}
299
bsalomon84c8e622014-11-17 09:33:27 -0800300void GrResourceCache2::didChangeBudgetStatus(GrGpuResource* resource) {
301 SkASSERT(!fPurging);
302 SkASSERT(resource);
303 SkASSERT(this->isInCache(resource));
304
305 size_t size = resource->gpuMemorySize();
306
307 if (resource->cacheAccess().isBudgeted()) {
308 ++fBudgetedCount;
309 fBudgetedBytes += size;
310 this->purgeAsNeeded();
311 } else {
312 --fBudgetedCount;
313 fBudgetedBytes -= size;
314 }
315
316 this->validate();
317}
318
319
bsalomon71cb0c22014-11-14 12:10:14 -0800320void GrResourceCache2::internalPurgeAsNeeded() {
321 SkASSERT(!fPurging);
322 SkASSERT(!fNewlyPurgableResourceWhilePurging);
bsalomondace19e2014-11-17 07:34:06 -0800323 SkASSERT(fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800324
325 fPurging = true;
326
bsalomon71cb0c22014-11-14 12:10:14 -0800327 bool overBudget = true;
328 do {
329 fNewlyPurgableResourceWhilePurging = false;
330 ResourceList::Iter resourceIter;
331 GrGpuResource* resource = resourceIter.init(fResources,
332 ResourceList::Iter::kTail_IterStart);
333
334 while (resource) {
335 GrGpuResource* prev = resourceIter.prev();
336 if (resource->isPurgable()) {
bsalomon12299ab2014-11-14 13:33:09 -0800337 resource->cacheAccess().release();
bsalomon71cb0c22014-11-14 12:10:14 -0800338 }
339 resource = prev;
bsalomondace19e2014-11-17 07:34:06 -0800340 if (fBudgetedCount <= fMaxCount && fBudgetedBytes <= fMaxBytes) {
bsalomon71cb0c22014-11-14 12:10:14 -0800341 overBudget = false;
342 resource = NULL;
343 }
344 }
345
346 if (!fNewlyPurgableResourceWhilePurging && overBudget && fOverBudgetCB) {
347 // Despite the purge we're still over budget. Call our over budget callback.
348 (*fOverBudgetCB)(fOverBudgetData);
349 }
350 } while (overBudget && fNewlyPurgableResourceWhilePurging);
351
352 fNewlyPurgableResourceWhilePurging = false;
353 fPurging = false;
bsalomonb436ed62014-11-17 12:15:56 -0800354 this->validate();
bsalomon71cb0c22014-11-14 12:10:14 -0800355}
356
357void GrResourceCache2::purgeAllUnlocked() {
358 SkASSERT(!fPurging);
359 SkASSERT(!fNewlyPurgableResourceWhilePurging);
360
361 fPurging = true;
362
bsalomon71cb0c22014-11-14 12:10:14 -0800363 do {
364 fNewlyPurgableResourceWhilePurging = false;
365 ResourceList::Iter resourceIter;
366 GrGpuResource* resource =
367 resourceIter.init(fResources, ResourceList::Iter::kTail_IterStart);
368
369 while (resource) {
370 GrGpuResource* prev = resourceIter.prev();
371 if (resource->isPurgable()) {
bsalomon12299ab2014-11-14 13:33:09 -0800372 resource->cacheAccess().release();
373 }
bsalomon71cb0c22014-11-14 12:10:14 -0800374 resource = prev;
375 }
376
377 if (!fNewlyPurgableResourceWhilePurging && fCount && fOverBudgetCB) {
378 (*fOverBudgetCB)(fOverBudgetData);
379 }
380 } while (fNewlyPurgableResourceWhilePurging);
381 fPurging = false;
bsalomonb436ed62014-11-17 12:15:56 -0800382 this->validate();
bsalomon71cb0c22014-11-14 12:10:14 -0800383}
384
385#ifdef SK_DEBUG
386void GrResourceCache2::validate() const {
387 size_t bytes = 0;
388 int count = 0;
bsalomondace19e2014-11-17 07:34:06 -0800389 int budgetedCount = 0;
390 size_t budgetedBytes = 0;
bsalomon71cb0c22014-11-14 12:10:14 -0800391 int locked = 0;
392 int scratch = 0;
393 int couldBeScratch = 0;
394 int content = 0;
395
396 ResourceList::Iter iter;
397 GrGpuResource* resource = iter.init(fResources, ResourceList::Iter::kHead_IterStart);
398 for ( ; resource; resource = iter.next()) {
399 bytes += resource->gpuMemorySize();
400 ++count;
401
402 if (!resource->isPurgable()) {
403 ++locked;
404 }
405
406 if (resource->cacheAccess().isScratch()) {
407 SkASSERT(NULL == resource->cacheAccess().getContentKey());
408 ++scratch;
409 SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey()));
bsalomondace19e2014-11-17 07:34:06 -0800410 SkASSERT(!resource->cacheAccess().isWrapped());
bsalomon7775c852014-12-30 12:50:52 -0800411 } else if (resource->cacheAccess().getScratchKey().isValid()) {
bsalomon71cb0c22014-11-14 12:10:14 -0800412 SkASSERT(NULL != resource->cacheAccess().getContentKey());
413 ++couldBeScratch;
414 SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey()));
bsalomondace19e2014-11-17 07:34:06 -0800415 SkASSERT(!resource->cacheAccess().isWrapped());
bsalomon71cb0c22014-11-14 12:10:14 -0800416 }
417
418 if (const GrResourceKey* contentKey = resource->cacheAccess().getContentKey()) {
419 ++content;
420 SkASSERT(fContentHash.find(*contentKey) == resource);
bsalomondace19e2014-11-17 07:34:06 -0800421 SkASSERT(!resource->cacheAccess().isWrapped());
422 }
423
bsalomon84c8e622014-11-17 09:33:27 -0800424 if (resource->cacheAccess().isBudgeted()) {
bsalomondace19e2014-11-17 07:34:06 -0800425 ++budgetedCount;
426 budgetedBytes += resource->gpuMemorySize();
bsalomon71cb0c22014-11-14 12:10:14 -0800427 }
428 }
429
bsalomondace19e2014-11-17 07:34:06 -0800430 SkASSERT(fBudgetedCount <= fCount);
431 SkASSERT(fBudgetedBytes <= fBudgetedBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800432 SkASSERT(bytes == fBytes);
433 SkASSERT(count == fCount);
bsalomondace19e2014-11-17 07:34:06 -0800434 SkASSERT(budgetedBytes == fBudgetedBytes);
435 SkASSERT(budgetedCount == fBudgetedCount);
bsalomon71cb0c22014-11-14 12:10:14 -0800436#if GR_CACHE_STATS
bsalomondace19e2014-11-17 07:34:06 -0800437 SkASSERT(fBudgetedHighWaterCount <= fHighWaterCount);
438 SkASSERT(fBudgetedHighWaterBytes <= fHighWaterBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800439 SkASSERT(bytes <= fHighWaterBytes);
440 SkASSERT(count <= fHighWaterCount);
bsalomondace19e2014-11-17 07:34:06 -0800441 SkASSERT(budgetedBytes <= fBudgetedHighWaterBytes);
442 SkASSERT(budgetedCount <= fBudgetedHighWaterCount);
bsalomon71cb0c22014-11-14 12:10:14 -0800443#endif
444 SkASSERT(content == fContentHash.count());
445 SkASSERT(scratch + couldBeScratch == fScratchMap.count());
446
bsalomon12299ab2014-11-14 13:33:09 -0800447 // This assertion is not currently valid because we can be in recursive notifyIsPurgable()
448 // calls. This will be fixed when subresource registration is explicit.
bsalomondace19e2014-11-17 07:34:06 -0800449 // bool overBudget = budgetedBytes > fMaxBytes || budgetedCount > fMaxCount;
bsalomon12299ab2014-11-14 13:33:09 -0800450 // SkASSERT(!overBudget || locked == count || fPurging);
bsalomon71cb0c22014-11-14 12:10:14 -0800451}
452#endif
453
454#if GR_CACHE_STATS
455void GrResourceCache2::printStats() const {
456 this->validate();
457
458 int locked = 0;
459 int scratch = 0;
bsalomon84c8e622014-11-17 09:33:27 -0800460 int wrapped = 0;
461 size_t unbudgetedSize = 0;
bsalomon71cb0c22014-11-14 12:10:14 -0800462
463 ResourceList::Iter iter;
464 GrGpuResource* resource = iter.init(fResources, ResourceList::Iter::kHead_IterStart);
465
466 for ( ; resource; resource = iter.next()) {
467 if (!resource->isPurgable()) {
468 ++locked;
469 }
470 if (resource->cacheAccess().isScratch()) {
471 ++scratch;
472 }
bsalomon84c8e622014-11-17 09:33:27 -0800473 if (resource->cacheAccess().isWrapped()) {
474 ++wrapped;
475 }
476 if (!resource->cacheAccess().isBudgeted()) {
477 unbudgetedSize += resource->gpuMemorySize();
478 }
bsalomon71cb0c22014-11-14 12:10:14 -0800479 }
480
bsalomondace19e2014-11-17 07:34:06 -0800481 float countUtilization = (100.f * fBudgetedCount) / fMaxCount;
482 float byteUtilization = (100.f * fBudgetedBytes) / fMaxBytes;
bsalomon71cb0c22014-11-14 12:10:14 -0800483
484 SkDebugf("Budget: %d items %d bytes\n", fMaxCount, fMaxBytes);
bsalomon84c8e622014-11-17 09:33:27 -0800485 SkDebugf("\t\tEntry Count: current %d"
486 " (%d budgeted, %d wrapped, %d locked, %d scratch %.2g%% full), high %d\n",
487 fCount, fBudgetedCount, wrapped, locked, scratch, countUtilization, fHighWaterCount);
488 SkDebugf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full, %d unbudgeted) high %d\n",
489 fBytes, fBudgetedBytes, byteUtilization, unbudgetedSize, fHighWaterBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800490}
491
492#endif