blob: a63bda8cc7af14477a7b2c8d7ec0e21bd2c90708 [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() {
bsalomon24db3b12015-01-23 04:24:04 -080022 static int32_t gType = INHERITED::kInvalidDomain + 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
bsalomon24db3b12015-01-23 04:24:04 -080032GrContentKey::Domain GrContentKey::GenerateDomain() {
33 static int32_t gDomain = INHERITED::kInvalidDomain + 1;
bsalomon7775c852014-12-30 12:50:52 -080034
bsalomon24db3b12015-01-23 04:24:04 -080035 int32_t domain = sk_atomic_inc(&gDomain);
36 if (kInvalidDomain == gDomain) {
37 SkFAIL("Too many Content Key Domains");
bsalomon7775c852014-12-30 12:50:52 -080038 }
bsalomon24db3b12015-01-23 04:24:04 -080039
40 return static_cast<Domain>(domain);
41}
42uint32_t GrResourceKeyHash(const uint32_t* data, size_t size) {
43 return SkChecksum::Compute(data, size);
bsalomon7775c852014-12-30 12:50:52 -080044}
45
bsalomonfe369ee2014-11-10 11:59:06 -080046//////////////////////////////////////////////////////////////////////////////
47
bsalomon71cb0c22014-11-14 12:10:14 -080048class GrResourceCache2::AutoValidate : ::SkNoncopyable {
49public:
50 AutoValidate(GrResourceCache2* cache) : fCache(cache) { cache->validate(); }
51 ~AutoValidate() { fCache->validate(); }
52private:
53 GrResourceCache2* fCache;
54};
55
56 //////////////////////////////////////////////////////////////////////////////
57
58static const int kDefaultMaxCount = 2 * (1 << 10);
59static const size_t kDefaultMaxSize = 96 * (1 << 20);
60
61GrResourceCache2::GrResourceCache2()
62 : fMaxCount(kDefaultMaxCount)
63 , fMaxBytes(kDefaultMaxSize)
64#if GR_CACHE_STATS
65 , fHighWaterCount(0)
66 , fHighWaterBytes(0)
bsalomondace19e2014-11-17 07:34:06 -080067 , fBudgetedHighWaterCount(0)
68 , fBudgetedHighWaterBytes(0)
bsalomon71cb0c22014-11-14 12:10:14 -080069#endif
70 , fCount(0)
71 , fBytes(0)
bsalomondace19e2014-11-17 07:34:06 -080072 , fBudgetedCount(0)
73 , fBudgetedBytes(0)
bsalomon71cb0c22014-11-14 12:10:14 -080074 , fPurging(false)
75 , fNewlyPurgableResourceWhilePurging(false)
76 , fOverBudgetCB(NULL)
77 , fOverBudgetData(NULL) {
78}
79
bsalomonc8dc1f72014-08-21 13:02:13 -070080GrResourceCache2::~GrResourceCache2() {
81 this->releaseAll();
82}
83
bsalomon71cb0c22014-11-14 12:10:14 -080084void GrResourceCache2::setLimits(int count, size_t bytes) {
85 fMaxCount = count;
86 fMaxBytes = bytes;
87 this->purgeAsNeeded();
88}
89
bsalomonc8dc1f72014-08-21 13:02:13 -070090void GrResourceCache2::insertResource(GrGpuResource* resource) {
bsalomon49f085d2014-09-05 13:34:00 -070091 SkASSERT(resource);
bsalomonc8dc1f72014-08-21 13:02:13 -070092 SkASSERT(!resource->wasDestroyed());
bsalomon16961262014-08-26 14:01:07 -070093 SkASSERT(!this->isInCache(resource));
bsalomon71cb0c22014-11-14 12:10:14 -080094 SkASSERT(!fPurging);
bsalomonc8dc1f72014-08-21 13:02:13 -070095 fResources.addToHead(resource);
bsalomon71cb0c22014-11-14 12:10:14 -080096
bsalomondace19e2014-11-17 07:34:06 -080097 size_t size = resource->gpuMemorySize();
bsalomonc8dc1f72014-08-21 13:02:13 -070098 ++fCount;
bsalomon84c8e622014-11-17 09:33:27 -080099 fBytes += size;
bsalomon82b1d622014-11-14 13:59:57 -0800100#if GR_CACHE_STATS
101 fHighWaterCount = SkTMax(fCount, fHighWaterCount);
102 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes);
103#endif
bsalomon84c8e622014-11-17 09:33:27 -0800104 if (resource->cacheAccess().isBudgeted()) {
bsalomondace19e2014-11-17 07:34:06 -0800105 ++fBudgetedCount;
106 fBudgetedBytes += size;
107#if GR_CACHE_STATS
108 fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount);
109 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes);
110#endif
111 }
bsalomon7775c852014-12-30 12:50:52 -0800112 if (resource->cacheAccess().getScratchKey().isValid()) {
bsalomon84c8e622014-11-17 09:33:27 -0800113 SkASSERT(!resource->cacheAccess().isWrapped());
bsalomon453cf402014-11-11 14:15:57 -0800114 fScratchMap.insert(resource->cacheAccess().getScratchKey(), resource);
bsalomon744998e2014-08-28 09:54:34 -0700115 }
bsalomon71cb0c22014-11-14 12:10:14 -0800116
117 this->purgeAsNeeded();
bsalomonc8dc1f72014-08-21 13:02:13 -0700118}
119
120void GrResourceCache2::removeResource(GrGpuResource* resource) {
bsalomon16961262014-08-26 14:01:07 -0700121 SkASSERT(this->isInCache(resource));
bsalomondace19e2014-11-17 07:34:06 -0800122
123 size_t size = resource->gpuMemorySize();
124 --fCount;
125 fBytes -= size;
bsalomon84c8e622014-11-17 09:33:27 -0800126 if (resource->cacheAccess().isBudgeted()) {
bsalomondace19e2014-11-17 07:34:06 -0800127 --fBudgetedCount;
128 fBudgetedBytes -= size;
129 }
130
131 fResources.remove(resource);
bsalomon7775c852014-12-30 12:50:52 -0800132 if (resource->cacheAccess().getScratchKey().isValid()) {
bsalomon453cf402014-11-11 14:15:57 -0800133 fScratchMap.remove(resource->cacheAccess().getScratchKey(), resource);
bsalomon744998e2014-08-28 09:54:34 -0700134 }
bsalomon24db3b12015-01-23 04:24:04 -0800135 if (resource->cacheAccess().getContentKey().isValid()) {
136 fContentHash.remove(resource->cacheAccess().getContentKey());
bsalomon8b79d232014-11-10 10:19:06 -0800137 }
bsalomonb436ed62014-11-17 12:15:56 -0800138 this->validate();
bsalomonc8dc1f72014-08-21 13:02:13 -0700139}
140
141void GrResourceCache2::abandonAll() {
bsalomon71cb0c22014-11-14 12:10:14 -0800142 AutoValidate av(this);
143
144 SkASSERT(!fPurging);
bsalomonc8dc1f72014-08-21 13:02:13 -0700145 while (GrGpuResource* head = fResources.head()) {
146 SkASSERT(!head->wasDestroyed());
bsalomon12299ab2014-11-14 13:33:09 -0800147 head->cacheAccess().abandon();
bsalomonc8dc1f72014-08-21 13:02:13 -0700148 // abandon should have already removed this from the list.
149 SkASSERT(head != fResources.head());
150 }
bsalomon744998e2014-08-28 09:54:34 -0700151 SkASSERT(!fScratchMap.count());
bsalomon8b79d232014-11-10 10:19:06 -0800152 SkASSERT(!fContentHash.count());
bsalomonc8dc1f72014-08-21 13:02:13 -0700153 SkASSERT(!fCount);
bsalomondace19e2014-11-17 07:34:06 -0800154 SkASSERT(!fBytes);
155 SkASSERT(!fBudgetedCount);
156 SkASSERT(!fBudgetedBytes);
bsalomonc8dc1f72014-08-21 13:02:13 -0700157}
158
159void GrResourceCache2::releaseAll() {
bsalomon71cb0c22014-11-14 12:10:14 -0800160 AutoValidate av(this);
161
162 SkASSERT(!fPurging);
bsalomonc8dc1f72014-08-21 13:02:13 -0700163 while (GrGpuResource* head = fResources.head()) {
164 SkASSERT(!head->wasDestroyed());
bsalomon12299ab2014-11-14 13:33:09 -0800165 head->cacheAccess().release();
bsalomonc8dc1f72014-08-21 13:02:13 -0700166 // release should have already removed this from the list.
167 SkASSERT(head != fResources.head());
168 }
bsalomon744998e2014-08-28 09:54:34 -0700169 SkASSERT(!fScratchMap.count());
bsalomonc8dc1f72014-08-21 13:02:13 -0700170 SkASSERT(!fCount);
bsalomondace19e2014-11-17 07:34:06 -0800171 SkASSERT(!fBytes);
172 SkASSERT(!fBudgetedCount);
173 SkASSERT(!fBudgetedBytes);
bsalomonc8dc1f72014-08-21 13:02:13 -0700174}
bsalomonbcf0a522014-10-08 08:40:09 -0700175
176class GrResourceCache2::AvailableForScratchUse {
177public:
bsalomon000f8292014-10-15 19:04:14 -0700178 AvailableForScratchUse(bool rejectPendingIO) : fRejectPendingIO(rejectPendingIO) { }
bsalomonbcf0a522014-10-08 08:40:09 -0700179
180 bool operator()(const GrGpuResource* resource) const {
bsalomon12299ab2014-11-14 13:33:09 -0800181 if (resource->internalHasRef() || !resource->cacheAccess().isScratch()) {
bsalomon000f8292014-10-15 19:04:14 -0700182 return false;
bsalomonbcf0a522014-10-08 08:40:09 -0700183 }
bsalomon000f8292014-10-15 19:04:14 -0700184 return !fRejectPendingIO || !resource->internalHasPendingIO();
bsalomonbcf0a522014-10-08 08:40:09 -0700185 }
bsalomon1e2530b2014-10-09 09:57:18 -0700186
bsalomonbcf0a522014-10-08 08:40:09 -0700187private:
bsalomon000f8292014-10-15 19:04:14 -0700188 bool fRejectPendingIO;
bsalomonbcf0a522014-10-08 08:40:09 -0700189};
190
bsalomon7775c852014-12-30 12:50:52 -0800191GrGpuResource* GrResourceCache2::findAndRefScratchResource(const GrScratchKey& scratchKey,
bsalomon000f8292014-10-15 19:04:14 -0700192 uint32_t flags) {
bsalomon71cb0c22014-11-14 12:10:14 -0800193 SkASSERT(!fPurging);
bsalomon7775c852014-12-30 12:50:52 -0800194 SkASSERT(scratchKey.isValid());
bsalomon000f8292014-10-15 19:04:14 -0700195
bsalomon71cb0c22014-11-14 12:10:14 -0800196 GrGpuResource* resource;
bsalomon000f8292014-10-15 19:04:14 -0700197 if (flags & (kPreferNoPendingIO_ScratchFlag | kRequireNoPendingIO_ScratchFlag)) {
bsalomon71cb0c22014-11-14 12:10:14 -0800198 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(true));
bsalomon000f8292014-10-15 19:04:14 -0700199 if (resource) {
bsalomonb436ed62014-11-17 12:15:56 -0800200 resource->ref();
bsalomon71cb0c22014-11-14 12:10:14 -0800201 this->makeResourceMRU(resource);
bsalomonb436ed62014-11-17 12:15:56 -0800202 this->validate();
203 return resource;
bsalomon000f8292014-10-15 19:04:14 -0700204 } else if (flags & kRequireNoPendingIO_ScratchFlag) {
205 return NULL;
206 }
207 // TODO: fail here when kPrefer is specified, we didn't find a resource without pending io,
208 // but there is still space in our budget for the resource.
209 }
bsalomon71cb0c22014-11-14 12:10:14 -0800210 resource = fScratchMap.find(scratchKey, AvailableForScratchUse(false));
211 if (resource) {
212 resource->ref();
213 this->makeResourceMRU(resource);
bsalomonb436ed62014-11-17 12:15:56 -0800214 this->validate();
bsalomon71cb0c22014-11-14 12:10:14 -0800215 }
216 return resource;
bsalomonbcf0a522014-10-08 08:40:09 -0700217}
bsalomon8b79d232014-11-10 10:19:06 -0800218
bsalomon10e23ca2014-11-25 05:52:06 -0800219void GrResourceCache2::willRemoveScratchKey(const GrGpuResource* resource) {
220 SkASSERT(resource->cacheAccess().isScratch());
221 fScratchMap.remove(resource->cacheAccess().getScratchKey(), resource);
222}
223
bsalomon6d4488c2014-11-11 07:27:16 -0800224bool GrResourceCache2::didSetContentKey(GrGpuResource* resource) {
bsalomon71cb0c22014-11-14 12:10:14 -0800225 SkASSERT(!fPurging);
bsalomon8b79d232014-11-10 10:19:06 -0800226 SkASSERT(resource);
bsalomon71cb0c22014-11-14 12:10:14 -0800227 SkASSERT(this->isInCache(resource));
bsalomon24db3b12015-01-23 04:24:04 -0800228 SkASSERT(resource->cacheAccess().getContentKey().isValid());
bsalomon8b79d232014-11-10 10:19:06 -0800229
bsalomon24db3b12015-01-23 04:24:04 -0800230 GrGpuResource* res = fContentHash.find(resource->cacheAccess().getContentKey());
bsalomon8b79d232014-11-10 10:19:06 -0800231 if (NULL != res) {
232 return false;
233 }
234
235 fContentHash.add(resource);
bsalomon71cb0c22014-11-14 12:10:14 -0800236 this->validate();
bsalomon8b79d232014-11-10 10:19:06 -0800237 return true;
238}
bsalomon71cb0c22014-11-14 12:10:14 -0800239
240void GrResourceCache2::makeResourceMRU(GrGpuResource* resource) {
bsalomon71cb0c22014-11-14 12:10:14 -0800241 SkASSERT(!fPurging);
242 SkASSERT(resource);
243 SkASSERT(this->isInCache(resource));
244 fResources.remove(resource);
bsalomonb436ed62014-11-17 12:15:56 -0800245 fResources.addToHead(resource);
bsalomon71cb0c22014-11-14 12:10:14 -0800246}
247
bsalomon12299ab2014-11-14 13:33:09 -0800248void GrResourceCache2::notifyPurgable(GrGpuResource* resource) {
bsalomon71cb0c22014-11-14 12:10:14 -0800249 SkASSERT(resource);
250 SkASSERT(this->isInCache(resource));
251 SkASSERT(resource->isPurgable());
252
253 // We can't purge if in the middle of purging because purge is iterating. Instead record
254 // that additional resources became purgable.
255 if (fPurging) {
256 fNewlyPurgableResourceWhilePurging = true;
257 return;
258 }
259
260 // Purge the resource if we're over budget
bsalomondace19e2014-11-17 07:34:06 -0800261 bool overBudget = fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes;
bsalomon71cb0c22014-11-14 12:10:14 -0800262
bsalomon71cb0c22014-11-14 12:10:14 -0800263 // Also purge if the resource has neither a valid scratch key nor a content key.
bsalomon24db3b12015-01-23 04:24:04 -0800264 bool noKey = !resource->cacheAccess().getScratchKey().isValid() &&
265 !resource->cacheAccess().getContentKey().isValid();
bsalomon71cb0c22014-11-14 12:10:14 -0800266
bsalomon5236cf42015-01-14 10:42:08 -0800267 // Only cached resources should ever have a key.
268 SkASSERT(noKey || resource->cacheAccess().isBudgeted());
bsalomondace19e2014-11-17 07:34:06 -0800269
bsalomon71cb0c22014-11-14 12:10:14 -0800270 if (overBudget || noKey) {
271 SkDEBUGCODE(int beforeCount = fCount;)
bsalomon12299ab2014-11-14 13:33:09 -0800272 resource->cacheAccess().release();
273 // We should at least free this resource, perhaps dependent resources as well.
bsalomon71cb0c22014-11-14 12:10:14 -0800274 SkASSERT(fCount < beforeCount);
275 }
276
277 this->validate();
278}
279
280void GrResourceCache2::didChangeGpuMemorySize(const GrGpuResource* resource, size_t oldSize) {
281 // SkASSERT(!fPurging); GrPathRange increases size during flush. :(
282 SkASSERT(resource);
283 SkASSERT(this->isInCache(resource));
284
bsalomondace19e2014-11-17 07:34:06 -0800285 ptrdiff_t delta = resource->gpuMemorySize() - oldSize;
286
287 fBytes += delta;
bsalomon82b1d622014-11-14 13:59:57 -0800288#if GR_CACHE_STATS
289 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes);
290#endif
bsalomon84c8e622014-11-17 09:33:27 -0800291 if (resource->cacheAccess().isBudgeted()) {
bsalomondace19e2014-11-17 07:34:06 -0800292 fBudgetedBytes += delta;
293#if GR_CACHE_STATS
294 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes);
295#endif
296 }
bsalomon71cb0c22014-11-14 12:10:14 -0800297
298 this->purgeAsNeeded();
299 this->validate();
300}
301
bsalomon84c8e622014-11-17 09:33:27 -0800302void GrResourceCache2::didChangeBudgetStatus(GrGpuResource* resource) {
303 SkASSERT(!fPurging);
304 SkASSERT(resource);
305 SkASSERT(this->isInCache(resource));
306
307 size_t size = resource->gpuMemorySize();
308
309 if (resource->cacheAccess().isBudgeted()) {
310 ++fBudgetedCount;
311 fBudgetedBytes += size;
bsalomonafe30052015-01-16 07:32:33 -0800312#if GR_CACHE_STATS
313 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes);
314 fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount);
315#endif
bsalomon84c8e622014-11-17 09:33:27 -0800316 this->purgeAsNeeded();
317 } else {
318 --fBudgetedCount;
319 fBudgetedBytes -= size;
320 }
321
322 this->validate();
323}
324
bsalomon71cb0c22014-11-14 12:10:14 -0800325void GrResourceCache2::internalPurgeAsNeeded() {
326 SkASSERT(!fPurging);
327 SkASSERT(!fNewlyPurgableResourceWhilePurging);
bsalomondace19e2014-11-17 07:34:06 -0800328 SkASSERT(fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800329
330 fPurging = true;
331
bsalomon71cb0c22014-11-14 12:10:14 -0800332 bool overBudget = true;
333 do {
334 fNewlyPurgableResourceWhilePurging = false;
335 ResourceList::Iter resourceIter;
336 GrGpuResource* resource = resourceIter.init(fResources,
337 ResourceList::Iter::kTail_IterStart);
338
339 while (resource) {
340 GrGpuResource* prev = resourceIter.prev();
341 if (resource->isPurgable()) {
bsalomon12299ab2014-11-14 13:33:09 -0800342 resource->cacheAccess().release();
bsalomon71cb0c22014-11-14 12:10:14 -0800343 }
344 resource = prev;
bsalomondace19e2014-11-17 07:34:06 -0800345 if (fBudgetedCount <= fMaxCount && fBudgetedBytes <= fMaxBytes) {
bsalomon71cb0c22014-11-14 12:10:14 -0800346 overBudget = false;
347 resource = NULL;
348 }
349 }
350
351 if (!fNewlyPurgableResourceWhilePurging && overBudget && fOverBudgetCB) {
352 // Despite the purge we're still over budget. Call our over budget callback.
353 (*fOverBudgetCB)(fOverBudgetData);
354 }
355 } while (overBudget && fNewlyPurgableResourceWhilePurging);
356
357 fNewlyPurgableResourceWhilePurging = false;
358 fPurging = false;
bsalomonb436ed62014-11-17 12:15:56 -0800359 this->validate();
bsalomon71cb0c22014-11-14 12:10:14 -0800360}
361
362void GrResourceCache2::purgeAllUnlocked() {
363 SkASSERT(!fPurging);
364 SkASSERT(!fNewlyPurgableResourceWhilePurging);
365
366 fPurging = true;
367
bsalomon71cb0c22014-11-14 12:10:14 -0800368 do {
369 fNewlyPurgableResourceWhilePurging = false;
370 ResourceList::Iter resourceIter;
371 GrGpuResource* resource =
372 resourceIter.init(fResources, ResourceList::Iter::kTail_IterStart);
373
374 while (resource) {
375 GrGpuResource* prev = resourceIter.prev();
376 if (resource->isPurgable()) {
bsalomon12299ab2014-11-14 13:33:09 -0800377 resource->cacheAccess().release();
378 }
bsalomon71cb0c22014-11-14 12:10:14 -0800379 resource = prev;
380 }
381
382 if (!fNewlyPurgableResourceWhilePurging && fCount && fOverBudgetCB) {
383 (*fOverBudgetCB)(fOverBudgetData);
384 }
385 } while (fNewlyPurgableResourceWhilePurging);
386 fPurging = false;
bsalomonb436ed62014-11-17 12:15:56 -0800387 this->validate();
bsalomon71cb0c22014-11-14 12:10:14 -0800388}
389
390#ifdef SK_DEBUG
391void GrResourceCache2::validate() const {
392 size_t bytes = 0;
393 int count = 0;
bsalomondace19e2014-11-17 07:34:06 -0800394 int budgetedCount = 0;
395 size_t budgetedBytes = 0;
bsalomon71cb0c22014-11-14 12:10:14 -0800396 int locked = 0;
397 int scratch = 0;
398 int couldBeScratch = 0;
399 int content = 0;
400
401 ResourceList::Iter iter;
402 GrGpuResource* resource = iter.init(fResources, ResourceList::Iter::kHead_IterStart);
403 for ( ; resource; resource = iter.next()) {
404 bytes += resource->gpuMemorySize();
405 ++count;
406
407 if (!resource->isPurgable()) {
408 ++locked;
409 }
410
411 if (resource->cacheAccess().isScratch()) {
bsalomon24db3b12015-01-23 04:24:04 -0800412 SkASSERT(!resource->cacheAccess().getContentKey().isValid());
bsalomon71cb0c22014-11-14 12:10:14 -0800413 ++scratch;
414 SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey()));
bsalomondace19e2014-11-17 07:34:06 -0800415 SkASSERT(!resource->cacheAccess().isWrapped());
bsalomon7775c852014-12-30 12:50:52 -0800416 } else if (resource->cacheAccess().getScratchKey().isValid()) {
bsalomon24db3b12015-01-23 04:24:04 -0800417 SkASSERT(resource->cacheAccess().getContentKey().isValid());
bsalomon71cb0c22014-11-14 12:10:14 -0800418 ++couldBeScratch;
419 SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchKey()));
bsalomondace19e2014-11-17 07:34:06 -0800420 SkASSERT(!resource->cacheAccess().isWrapped());
bsalomon71cb0c22014-11-14 12:10:14 -0800421 }
bsalomon24db3b12015-01-23 04:24:04 -0800422 const GrContentKey& contentKey = resource->cacheAccess().getContentKey();
423 if (contentKey.isValid()) {
bsalomon71cb0c22014-11-14 12:10:14 -0800424 ++content;
bsalomon24db3b12015-01-23 04:24:04 -0800425 SkASSERT(fContentHash.find(contentKey) == resource);
bsalomondace19e2014-11-17 07:34:06 -0800426 SkASSERT(!resource->cacheAccess().isWrapped());
427 }
428
bsalomon84c8e622014-11-17 09:33:27 -0800429 if (resource->cacheAccess().isBudgeted()) {
bsalomondace19e2014-11-17 07:34:06 -0800430 ++budgetedCount;
431 budgetedBytes += resource->gpuMemorySize();
bsalomon71cb0c22014-11-14 12:10:14 -0800432 }
433 }
434
bsalomondace19e2014-11-17 07:34:06 -0800435 SkASSERT(fBudgetedCount <= fCount);
436 SkASSERT(fBudgetedBytes <= fBudgetedBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800437 SkASSERT(bytes == fBytes);
438 SkASSERT(count == fCount);
bsalomondace19e2014-11-17 07:34:06 -0800439 SkASSERT(budgetedBytes == fBudgetedBytes);
440 SkASSERT(budgetedCount == fBudgetedCount);
bsalomon71cb0c22014-11-14 12:10:14 -0800441#if GR_CACHE_STATS
bsalomondace19e2014-11-17 07:34:06 -0800442 SkASSERT(fBudgetedHighWaterCount <= fHighWaterCount);
443 SkASSERT(fBudgetedHighWaterBytes <= fHighWaterBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800444 SkASSERT(bytes <= fHighWaterBytes);
445 SkASSERT(count <= fHighWaterCount);
bsalomondace19e2014-11-17 07:34:06 -0800446 SkASSERT(budgetedBytes <= fBudgetedHighWaterBytes);
447 SkASSERT(budgetedCount <= fBudgetedHighWaterCount);
bsalomon71cb0c22014-11-14 12:10:14 -0800448#endif
449 SkASSERT(content == fContentHash.count());
450 SkASSERT(scratch + couldBeScratch == fScratchMap.count());
451
bsalomon12299ab2014-11-14 13:33:09 -0800452 // This assertion is not currently valid because we can be in recursive notifyIsPurgable()
453 // calls. This will be fixed when subresource registration is explicit.
bsalomondace19e2014-11-17 07:34:06 -0800454 // bool overBudget = budgetedBytes > fMaxBytes || budgetedCount > fMaxCount;
bsalomon12299ab2014-11-14 13:33:09 -0800455 // SkASSERT(!overBudget || locked == count || fPurging);
bsalomon71cb0c22014-11-14 12:10:14 -0800456}
457#endif
458
459#if GR_CACHE_STATS
460void GrResourceCache2::printStats() const {
461 this->validate();
462
463 int locked = 0;
464 int scratch = 0;
bsalomon84c8e622014-11-17 09:33:27 -0800465 int wrapped = 0;
466 size_t unbudgetedSize = 0;
bsalomon71cb0c22014-11-14 12:10:14 -0800467
468 ResourceList::Iter iter;
469 GrGpuResource* resource = iter.init(fResources, ResourceList::Iter::kHead_IterStart);
470
471 for ( ; resource; resource = iter.next()) {
472 if (!resource->isPurgable()) {
473 ++locked;
474 }
475 if (resource->cacheAccess().isScratch()) {
476 ++scratch;
477 }
bsalomon84c8e622014-11-17 09:33:27 -0800478 if (resource->cacheAccess().isWrapped()) {
479 ++wrapped;
480 }
481 if (!resource->cacheAccess().isBudgeted()) {
482 unbudgetedSize += resource->gpuMemorySize();
483 }
bsalomon71cb0c22014-11-14 12:10:14 -0800484 }
485
bsalomondace19e2014-11-17 07:34:06 -0800486 float countUtilization = (100.f * fBudgetedCount) / fMaxCount;
487 float byteUtilization = (100.f * fBudgetedBytes) / fMaxBytes;
bsalomon71cb0c22014-11-14 12:10:14 -0800488
489 SkDebugf("Budget: %d items %d bytes\n", fMaxCount, fMaxBytes);
bsalomon84c8e622014-11-17 09:33:27 -0800490 SkDebugf("\t\tEntry Count: current %d"
491 " (%d budgeted, %d wrapped, %d locked, %d scratch %.2g%% full), high %d\n",
492 fCount, fBudgetedCount, wrapped, locked, scratch, countUtilization, fHighWaterCount);
493 SkDebugf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full, %d unbudgeted) high %d\n",
494 fBytes, fBudgetedBytes, byteUtilization, unbudgetedSize, fHighWaterBytes);
bsalomon71cb0c22014-11-14 12:10:14 -0800495}
496
497#endif