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

Side by Side Diff: src/gpu/GrResourceCache2.cpp

Issue 720033004: Correct accounting for wrapped resources (Closed) Base URL: https://skia.googlesource.com/skia.git@res2
Patch Set: rebase again Created 6 years, 1 month 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
« no previous file with comments | « src/gpu/GrResourceCache2.h ('k') | tests/ResourceCacheTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 9
10 #include "GrResourceCache2.h" 10 #include "GrResourceCache2.h"
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 59
60 static const int kDefaultMaxCount = 2 * (1 << 10); 60 static const int kDefaultMaxCount = 2 * (1 << 10);
61 static const size_t kDefaultMaxSize = 96 * (1 << 20); 61 static const size_t kDefaultMaxSize = 96 * (1 << 20);
62 62
63 GrResourceCache2::GrResourceCache2() 63 GrResourceCache2::GrResourceCache2()
64 : fMaxCount(kDefaultMaxCount) 64 : fMaxCount(kDefaultMaxCount)
65 , fMaxBytes(kDefaultMaxSize) 65 , fMaxBytes(kDefaultMaxSize)
66 #if GR_CACHE_STATS 66 #if GR_CACHE_STATS
67 , fHighWaterCount(0) 67 , fHighWaterCount(0)
68 , fHighWaterBytes(0) 68 , fHighWaterBytes(0)
69 , fBudgetedHighWaterCount(0)
70 , fBudgetedHighWaterBytes(0)
69 #endif 71 #endif
70 , fCount(0) 72 , fCount(0)
71 , fBytes(0) 73 , fBytes(0)
74 , fBudgetedCount(0)
75 , fBudgetedBytes(0)
72 , fPurging(false) 76 , fPurging(false)
73 , fNewlyPurgableResourceWhilePurging(false) 77 , fNewlyPurgableResourceWhilePurging(false)
74 , fOverBudgetCB(NULL) 78 , fOverBudgetCB(NULL)
75 , fOverBudgetData(NULL) { 79 , fOverBudgetData(NULL) {
76 } 80 }
77 81
78 GrResourceCache2::~GrResourceCache2() { 82 GrResourceCache2::~GrResourceCache2() {
79 this->releaseAll(); 83 this->releaseAll();
80 } 84 }
81 85
82 void GrResourceCache2::setLimits(int count, size_t bytes) { 86 void GrResourceCache2::setLimits(int count, size_t bytes) {
83 fMaxCount = count; 87 fMaxCount = count;
84 fMaxBytes = bytes; 88 fMaxBytes = bytes;
85 this->purgeAsNeeded(); 89 this->purgeAsNeeded();
86 } 90 }
87 91
88 void GrResourceCache2::insertResource(GrGpuResource* resource) { 92 void GrResourceCache2::insertResource(GrGpuResource* resource) {
89 AutoValidate av(this); 93 AutoValidate av(this);
90 94
91 SkASSERT(resource); 95 SkASSERT(resource);
92 SkASSERT(!resource->wasDestroyed()); 96 SkASSERT(!resource->wasDestroyed());
93 SkASSERT(!this->isInCache(resource)); 97 SkASSERT(!this->isInCache(resource));
94 SkASSERT(!fPurging); 98 SkASSERT(!fPurging);
95 fResources.addToHead(resource); 99 fResources.addToHead(resource);
96 100
101 size_t size = resource->gpuMemorySize();
97 ++fCount; 102 ++fCount;
98 fBytes += resource->gpuMemorySize(); 103 fBytes += resource->gpuMemorySize();
99 #if GR_CACHE_STATS 104 #if GR_CACHE_STATS
100 fHighWaterCount = SkTMax(fCount, fHighWaterCount); 105 fHighWaterCount = SkTMax(fCount, fHighWaterCount);
101 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes); 106 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes);
102 #endif 107 #endif
108 if (!resource->cacheAccess().isWrapped()) {
109 ++fBudgetedCount;
110 fBudgetedBytes += size;
111 #if GR_CACHE_STATS
112 fBudgetedHighWaterCount = SkTMax(fBudgetedCount, fBudgetedHighWaterCount );
113 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes );
114 #endif
115 }
103 if (!resource->cacheAccess().getScratchKey().isNullScratch()) { 116 if (!resource->cacheAccess().getScratchKey().isNullScratch()) {
104 // TODO(bsalomon): Make this assertion possible. 117 // TODO(bsalomon): Make this assertion possible.
105 // SkASSERT(!resource->isWrapped()); 118 // SkASSERT(!resource->isWrapped());
106 fScratchMap.insert(resource->cacheAccess().getScratchKey(), resource); 119 fScratchMap.insert(resource->cacheAccess().getScratchKey(), resource);
107 } 120 }
108 121
109 this->purgeAsNeeded(); 122 this->purgeAsNeeded();
110 } 123 }
111 124
112 void GrResourceCache2::removeResource(GrGpuResource* resource) { 125 void GrResourceCache2::removeResource(GrGpuResource* resource) {
113 AutoValidate av(this); 126 AutoValidate av(this);
114 127
128 SkASSERT(this->isInCache(resource));
129
130 size_t size = resource->gpuMemorySize();
115 --fCount; 131 --fCount;
116 fBytes -= resource->gpuMemorySize(); 132 fBytes -= size;
117 SkASSERT(this->isInCache(resource)); 133 if (!resource->cacheAccess().isWrapped()) {
118 fResources.remove(resource); 134 --fBudgetedCount;
135 fBudgetedBytes -= size;
136 }
137
138 fResources.remove(resource);
119 if (!resource->cacheAccess().getScratchKey().isNullScratch()) { 139 if (!resource->cacheAccess().getScratchKey().isNullScratch()) {
120 fScratchMap.remove(resource->cacheAccess().getScratchKey(), resource); 140 fScratchMap.remove(resource->cacheAccess().getScratchKey(), resource);
121 } 141 }
122 if (const GrResourceKey* contentKey = resource->cacheAccess().getContentKey( )) { 142 if (const GrResourceKey* contentKey = resource->cacheAccess().getContentKey( )) {
123 fContentHash.remove(*contentKey); 143 fContentHash.remove(*contentKey);
124 } 144 }
125 } 145 }
126 146
127 void GrResourceCache2::abandonAll() { 147 void GrResourceCache2::abandonAll() {
128 AutoValidate av(this); 148 AutoValidate av(this);
129 149
130 SkASSERT(!fPurging); 150 SkASSERT(!fPurging);
131 while (GrGpuResource* head = fResources.head()) { 151 while (GrGpuResource* head = fResources.head()) {
132 SkASSERT(!head->wasDestroyed()); 152 SkASSERT(!head->wasDestroyed());
133 head->cacheAccess().abandon(); 153 head->cacheAccess().abandon();
134 // abandon should have already removed this from the list. 154 // abandon should have already removed this from the list.
135 SkASSERT(head != fResources.head()); 155 SkASSERT(head != fResources.head());
136 } 156 }
137 SkASSERT(!fScratchMap.count()); 157 SkASSERT(!fScratchMap.count());
138 SkASSERT(!fContentHash.count()); 158 SkASSERT(!fContentHash.count());
139 SkASSERT(!fCount); 159 SkASSERT(!fCount);
160 SkASSERT(!fBytes);
161 SkASSERT(!fBudgetedCount);
162 SkASSERT(!fBudgetedBytes);
140 } 163 }
141 164
142 void GrResourceCache2::releaseAll() { 165 void GrResourceCache2::releaseAll() {
143 AutoValidate av(this); 166 AutoValidate av(this);
144 167
145 SkASSERT(!fPurging); 168 SkASSERT(!fPurging);
146 while (GrGpuResource* head = fResources.head()) { 169 while (GrGpuResource* head = fResources.head()) {
147 SkASSERT(!head->wasDestroyed()); 170 SkASSERT(!head->wasDestroyed());
148 head->cacheAccess().release(); 171 head->cacheAccess().release();
149 // release should have already removed this from the list. 172 // release should have already removed this from the list.
150 SkASSERT(head != fResources.head()); 173 SkASSERT(head != fResources.head());
151 } 174 }
152 SkASSERT(!fScratchMap.count()); 175 SkASSERT(!fScratchMap.count());
153 SkASSERT(!fCount); 176 SkASSERT(!fCount);
177 SkASSERT(!fBytes);
178 SkASSERT(!fBudgetedCount);
179 SkASSERT(!fBudgetedBytes);
154 } 180 }
155 181
156 class GrResourceCache2::AvailableForScratchUse { 182 class GrResourceCache2::AvailableForScratchUse {
157 public: 183 public:
158 AvailableForScratchUse(bool rejectPendingIO) : fRejectPendingIO(rejectPendin gIO) { } 184 AvailableForScratchUse(bool rejectPendingIO) : fRejectPendingIO(rejectPendin gIO) { }
159 185
160 bool operator()(const GrGpuResource* resource) const { 186 bool operator()(const GrGpuResource* resource) const {
161 if (resource->internalHasRef() || !resource->cacheAccess().isScratch()) { 187 if (resource->internalHasRef() || !resource->cacheAccess().isScratch()) {
162 return false; 188 return false;
163 } 189 }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 SkASSERT(resource->isPurgable()); 255 SkASSERT(resource->isPurgable());
230 256
231 // We can't purge if in the middle of purging because purge is iterating. In stead record 257 // We can't purge if in the middle of purging because purge is iterating. In stead record
232 // that additional resources became purgable. 258 // that additional resources became purgable.
233 if (fPurging) { 259 if (fPurging) {
234 fNewlyPurgableResourceWhilePurging = true; 260 fNewlyPurgableResourceWhilePurging = true;
235 return; 261 return;
236 } 262 }
237 263
238 // Purge the resource if we're over budget 264 // Purge the resource if we're over budget
239 bool overBudget = fCount > fMaxCount || fBytes > fMaxBytes; 265 bool overBudget = fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes;
240 266
241 // Also purge if the resource has neither a valid scratch key nor a content key. 267 // Also purge if the resource has neither a valid scratch key nor a content key.
242 bool noKey = !resource->cacheAccess().isScratch() && 268 bool noKey = !resource->cacheAccess().isScratch() &&
243 (NULL == resource->cacheAccess().getContentKey()); 269 (NULL == resource->cacheAccess().getContentKey());
244 270
271 // Wrapped resources should never have a key.
272 SkASSERT(noKey || !resource->cacheAccess().isWrapped());
273
274 // And purge if the resource is wrapped
245 if (overBudget || noKey) { 275 if (overBudget || noKey) {
246 SkDEBUGCODE(int beforeCount = fCount;) 276 SkDEBUGCODE(int beforeCount = fCount;)
247 resource->cacheAccess().release(); 277 resource->cacheAccess().release();
248 // We should at least free this resource, perhaps dependent resources as well. 278 // We should at least free this resource, perhaps dependent resources as well.
249 SkASSERT(fCount < beforeCount); 279 SkASSERT(fCount < beforeCount);
250 } 280 }
251 281
252 this->validate(); 282 this->validate();
253 } 283 }
254 284
255 void GrResourceCache2::didChangeGpuMemorySize(const GrGpuResource* resource, siz e_t oldSize) { 285 void GrResourceCache2::didChangeGpuMemorySize(const GrGpuResource* resource, siz e_t oldSize) {
256 // SkASSERT(!fPurging); GrPathRange increases size during flush. :( 286 // SkASSERT(!fPurging); GrPathRange increases size during flush. :(
257 SkASSERT(resource); 287 SkASSERT(resource);
258 SkASSERT(this->isInCache(resource)); 288 SkASSERT(this->isInCache(resource));
259 289
260 fBytes += resource->gpuMemorySize() - oldSize; 290 ptrdiff_t delta = resource->gpuMemorySize() - oldSize;
291
292 fBytes += delta;
261 #if GR_CACHE_STATS 293 #if GR_CACHE_STATS
262 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes); 294 fHighWaterBytes = SkTMax(fBytes, fHighWaterBytes);
263 #endif 295 #endif
296 if (!resource->cacheAccess().isWrapped()) {
297 fBudgetedBytes += delta;
298 #if GR_CACHE_STATS
299 fBudgetedHighWaterBytes = SkTMax(fBudgetedBytes, fBudgetedHighWaterBytes );
300 #endif
301 }
264 302
265 this->purgeAsNeeded(); 303 this->purgeAsNeeded();
266 this->validate(); 304 this->validate();
267 } 305 }
268 306
269 void GrResourceCache2::internalPurgeAsNeeded() { 307 void GrResourceCache2::internalPurgeAsNeeded() {
270 SkASSERT(!fPurging); 308 SkASSERT(!fPurging);
271 SkASSERT(!fNewlyPurgableResourceWhilePurging); 309 SkASSERT(!fNewlyPurgableResourceWhilePurging);
272 SkASSERT(fCount > fMaxCount || fBytes > fMaxBytes); 310 SkASSERT(fBudgetedCount > fMaxCount || fBudgetedBytes > fMaxBytes);
273 311
274 fPurging = true; 312 fPurging = true;
275 313
276 AutoValidate av(this); // Put this after setting fPurging so we're allowed t o be over budget. 314 AutoValidate av(this); // Put this after setting fPurging so we're allowed t o be over budget.
277 315
278 bool overBudget = true; 316 bool overBudget = true;
279 do { 317 do {
280 fNewlyPurgableResourceWhilePurging = false; 318 fNewlyPurgableResourceWhilePurging = false;
281 ResourceList::Iter resourceIter; 319 ResourceList::Iter resourceIter;
282 GrGpuResource* resource = resourceIter.init(fResources, 320 GrGpuResource* resource = resourceIter.init(fResources,
283 ResourceList::Iter::kTail_It erStart); 321 ResourceList::Iter::kTail_It erStart);
284 322
285 while (resource) { 323 while (resource) {
286 GrGpuResource* prev = resourceIter.prev(); 324 GrGpuResource* prev = resourceIter.prev();
287 if (resource->isPurgable()) { 325 if (resource->isPurgable()) {
288 resource->cacheAccess().release(); 326 resource->cacheAccess().release();
289 } 327 }
290 resource = prev; 328 resource = prev;
291 if (fCount <= fMaxCount && fBytes <= fMaxBytes) { 329 if (fBudgetedCount <= fMaxCount && fBudgetedBytes <= fMaxBytes) {
292 overBudget = false; 330 overBudget = false;
293 resource = NULL; 331 resource = NULL;
294 } 332 }
295 } 333 }
296 334
297 if (!fNewlyPurgableResourceWhilePurging && overBudget && fOverBudgetCB) { 335 if (!fNewlyPurgableResourceWhilePurging && overBudget && fOverBudgetCB) {
298 // Despite the purge we're still over budget. Call our over budget c allback. 336 // Despite the purge we're still over budget. Call our over budget c allback.
299 (*fOverBudgetCB)(fOverBudgetData); 337 (*fOverBudgetCB)(fOverBudgetData);
300 } 338 }
301 } while (overBudget && fNewlyPurgableResourceWhilePurging); 339 } while (overBudget && fNewlyPurgableResourceWhilePurging);
(...skipping 28 matching lines...) Expand all
330 (*fOverBudgetCB)(fOverBudgetData); 368 (*fOverBudgetCB)(fOverBudgetData);
331 } 369 }
332 } while (fNewlyPurgableResourceWhilePurging); 370 } while (fNewlyPurgableResourceWhilePurging);
333 fPurging = false; 371 fPurging = false;
334 } 372 }
335 373
336 #ifdef SK_DEBUG 374 #ifdef SK_DEBUG
337 void GrResourceCache2::validate() const { 375 void GrResourceCache2::validate() const {
338 size_t bytes = 0; 376 size_t bytes = 0;
339 int count = 0; 377 int count = 0;
378 int budgetedCount = 0;
379 size_t budgetedBytes = 0;
340 int locked = 0; 380 int locked = 0;
341 int scratch = 0; 381 int scratch = 0;
342 int couldBeScratch = 0; 382 int couldBeScratch = 0;
343 int content = 0; 383 int content = 0;
344 384
345 ResourceList::Iter iter; 385 ResourceList::Iter iter;
346 GrGpuResource* resource = iter.init(fResources, ResourceList::Iter::kHead_It erStart); 386 GrGpuResource* resource = iter.init(fResources, ResourceList::Iter::kHead_It erStart);
347 for ( ; resource; resource = iter.next()) { 387 for ( ; resource; resource = iter.next()) {
348 bytes += resource->gpuMemorySize(); 388 bytes += resource->gpuMemorySize();
349 ++count; 389 ++count;
350 390
351 if (!resource->isPurgable()) { 391 if (!resource->isPurgable()) {
352 ++locked; 392 ++locked;
353 } 393 }
354 394
355 if (resource->cacheAccess().isScratch()) { 395 if (resource->cacheAccess().isScratch()) {
356 SkASSERT(NULL == resource->cacheAccess().getContentKey()); 396 SkASSERT(NULL == resource->cacheAccess().getContentKey());
357 ++scratch; 397 ++scratch;
358 SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchK ey())); 398 SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchK ey()));
399 SkASSERT(!resource->cacheAccess().isWrapped());
359 } else if (!resource->cacheAccess().getScratchKey().isNullScratch()) { 400 } else if (!resource->cacheAccess().getScratchKey().isNullScratch()) {
360 SkASSERT(NULL != resource->cacheAccess().getContentKey()); 401 SkASSERT(NULL != resource->cacheAccess().getContentKey());
361 ++couldBeScratch; 402 ++couldBeScratch;
362 SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchK ey())); 403 SkASSERT(fScratchMap.countForKey(resource->cacheAccess().getScratchK ey()));
404 SkASSERT(!resource->cacheAccess().isWrapped());
363 } 405 }
364 406
365 if (const GrResourceKey* contentKey = resource->cacheAccess().getContent Key()) { 407 if (const GrResourceKey* contentKey = resource->cacheAccess().getContent Key()) {
366 ++content; 408 ++content;
367 SkASSERT(fContentHash.find(*contentKey) == resource); 409 SkASSERT(fContentHash.find(*contentKey) == resource);
410 SkASSERT(!resource->cacheAccess().isWrapped());
411 }
412
413 if (!resource->cacheAccess().isWrapped()) {
414 ++budgetedCount;
415 budgetedBytes += resource->gpuMemorySize();
368 } 416 }
369 } 417 }
370 418
419 SkASSERT(fBudgetedCount <= fCount);
420 SkASSERT(fBudgetedBytes <= fBudgetedBytes);
371 SkASSERT(bytes == fBytes); 421 SkASSERT(bytes == fBytes);
372 SkASSERT(count == fCount); 422 SkASSERT(count == fCount);
423 SkASSERT(budgetedBytes == fBudgetedBytes);
424 SkASSERT(budgetedCount == fBudgetedCount);
373 #if GR_CACHE_STATS 425 #if GR_CACHE_STATS
426 SkASSERT(fBudgetedHighWaterCount <= fHighWaterCount);
427 SkASSERT(fBudgetedHighWaterBytes <= fHighWaterBytes);
374 SkASSERT(bytes <= fHighWaterBytes); 428 SkASSERT(bytes <= fHighWaterBytes);
375 SkASSERT(count <= fHighWaterCount); 429 SkASSERT(count <= fHighWaterCount);
430 SkASSERT(budgetedBytes <= fBudgetedHighWaterBytes);
431 SkASSERT(budgetedCount <= fBudgetedHighWaterCount);
376 #endif 432 #endif
377 SkASSERT(content == fContentHash.count()); 433 SkASSERT(content == fContentHash.count());
378 SkASSERT(scratch + couldBeScratch == fScratchMap.count()); 434 SkASSERT(scratch + couldBeScratch == fScratchMap.count());
379 435
380 // This assertion is not currently valid because we can be in recursive noti fyIsPurgable() 436 // This assertion is not currently valid because we can be in recursive noti fyIsPurgable()
381 // calls. This will be fixed when subresource registration is explicit. 437 // calls. This will be fixed when subresource registration is explicit.
382 // bool overBudget = bytes > fMaxBytes || count > fMaxCount; 438 // bool overBudget = budgetedBytes > fMaxBytes || budgetedCount > fMaxCount;
383 // SkASSERT(!overBudget || locked == count || fPurging); 439 // SkASSERT(!overBudget || locked == count || fPurging);
384 } 440 }
385 #endif 441 #endif
386 442
387 #if GR_CACHE_STATS 443 #if GR_CACHE_STATS
388 void GrResourceCache2::printStats() const { 444 void GrResourceCache2::printStats() const {
389 this->validate(); 445 this->validate();
390 446
391 int locked = 0; 447 int locked = 0;
392 int scratch = 0; 448 int scratch = 0;
393 449
394 ResourceList::Iter iter; 450 ResourceList::Iter iter;
395 GrGpuResource* resource = iter.init(fResources, ResourceList::Iter::kHead_It erStart); 451 GrGpuResource* resource = iter.init(fResources, ResourceList::Iter::kHead_It erStart);
396 452
397 for ( ; resource; resource = iter.next()) { 453 for ( ; resource; resource = iter.next()) {
398 if (!resource->isPurgable()) { 454 if (!resource->isPurgable()) {
399 ++locked; 455 ++locked;
400 } 456 }
401 if (resource->cacheAccess().isScratch()) { 457 if (resource->cacheAccess().isScratch()) {
402 ++scratch; 458 ++scratch;
403 } 459 }
404 } 460 }
405 461
406 float countUtilization = (100.f * fCount) / fMaxCount; 462 float countUtilization = (100.f * fBudgetedCount) / fMaxCount;
407 float byteUtilization = (100.f * fBytes) / fMaxBytes; 463 float byteUtilization = (100.f * fBudgetedBytes) / fMaxBytes;
408 464
409 SkDebugf("Budget: %d items %d bytes\n", fMaxCount, fMaxBytes); 465 SkDebugf("Budget: %d items %d bytes\n", fMaxCount, fMaxBytes);
410 SkDebugf("\t\tEntry Count: current %d (%d locked, %d scratch %.2g%% full), h igh %d\n", 466 SkDebugf(
411 fCount, locked, scratch, countUtilization, fHighWaterCount); 467 "\t\tEntry Count: current %d (%d budgeted, %d locked, %d scratch %.2g%% full), high %d\n",
412 SkDebugf("\t\tEntry Bytes: current %d (%.2g%% full) high %d\n", 468 fCount, fBudgetedCount, locked, scratch, countUtilization, fHighWaterCou nt);
413 fBytes, byteUtilization, fHighWaterBytes); 469 SkDebugf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full) high %d\n",
470 fBytes, fBudgetedBytes, byteUtilization, fHighWaterBytes);
414 } 471 }
415 472
416 #endif 473 #endif
OLDNEW
« no previous file with comments | « src/gpu/GrResourceCache2.h ('k') | tests/ResourceCacheTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698