blob: 2171c9e4fe4575aa7f5d9957834cdb825df175b9 [file] [log] [blame]
Robert Phillips5af44de2017-07-18 14:49:38 -04001/*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/gpu/GrResourceAllocator.h"
Robert Phillips5af44de2017-07-18 14:49:38 -04009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "src/gpu/GrGpuResourcePriv.h"
Greg Danielf41b2bd2019-08-22 16:19:24 -040011#include "src/gpu/GrOpsTask.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040012#include "src/gpu/GrRenderTargetProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "src/gpu/GrResourceProvider.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040014#include "src/gpu/GrSurfaceProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/gpu/GrSurfaceProxyPriv.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040016#include "src/gpu/GrTextureProxy.h"
Robert Phillips5af44de2017-07-18 14:49:38 -040017
Robert Phillipsda1be462018-07-27 07:18:06 -040018#if GR_TRACK_INTERVAL_CREATION
Mike Klein0ec1c572018-12-04 11:52:51 -050019 #include <atomic>
20
21 uint32_t GrResourceAllocator::Interval::CreateUniqueID() {
22 static std::atomic<uint32_t> nextID{1};
23 uint32_t id;
24 do {
Adlai Holler4888cda2020-11-06 16:37:37 -050025 id = nextID.fetch_add(1, std::memory_order_relaxed);
Mike Klein0ec1c572018-12-04 11:52:51 -050026 } while (id == SK_InvalidUniqueID);
27 return id;
28 }
Robert Phillipsda1be462018-07-27 07:18:06 -040029#endif
30
Robert Phillips5b65a842017-11-13 15:48:12 -050031void GrResourceAllocator::Interval::assign(sk_sp<GrSurface> s) {
32 SkASSERT(!fAssignedSurface);
33 fAssignedSurface = s;
34 fProxy->priv().assign(std::move(s));
35}
36
Robert Phillipsc73666f2019-04-24 08:49:48 -040037void GrResourceAllocator::determineRecyclability() {
38 for (Interval* cur = fIntvlList.peekHead(); cur; cur = cur->next()) {
39 if (cur->proxy()->canSkipResourceAllocator()) {
40 // These types of proxies can slip in here if they require a stencil buffer
41 continue;
42 }
43
Brian Salomon557e8122019-10-24 10:37:08 -040044 if (!cur->proxy()->refCntGreaterThan(cur->uses())) {
Robert Phillipsc73666f2019-04-24 08:49:48 -040045 // All the refs on the proxy are known to the resource allocator thus no one
46 // should be holding onto it outside of Ganesh.
Robert Phillipsc73666f2019-04-24 08:49:48 -040047 cur->markAsRecyclable();
48 }
49 }
50}
51
Robert Phillips5b65a842017-11-13 15:48:12 -050052GrResourceAllocator::~GrResourceAllocator() {
Robert Phillips5b65a842017-11-13 15:48:12 -050053 SkASSERT(fIntvlList.empty());
54 SkASSERT(fActiveIntvls.empty());
55 SkASSERT(!fIntvlHash.count());
Robert Phillips5b65a842017-11-13 15:48:12 -050056}
57
Adlai Holler7f7a5df2021-02-09 17:41:10 +000058void GrResourceAllocator::addInterval(GrSurfaceProxy* proxy, unsigned int start, unsigned int end,
59 ActualUse actualUse
Chris Dalton8816b932017-11-29 16:48:25 -070060 SkDEBUGCODE(, bool isDirectDstRead)) {
Brian Salomonbeb7f522019-08-30 16:19:42 -040061 SkASSERT(start <= end);
62 SkASSERT(!fAssigned); // We shouldn't be adding any intervals after (or during) assignment
Robert Phillips5f78adf2019-04-22 12:41:39 -040063
Chris Dalton97155592019-06-13 13:40:20 -060064 if (proxy->canSkipResourceAllocator()) {
Robert Phillips5f78adf2019-04-22 12:41:39 -040065 return;
66 }
67
Brian Salomon9cadc312018-12-05 15:09:19 -050068 // If a proxy is read only it must refer to a texture with specific content that cannot be
69 // recycled. We don't need to assign a texture to it and no other proxy can be instantiated
70 // with the same texture.
71 if (proxy->readOnly()) {
Brian Salomonbeb7f522019-08-30 16:19:42 -040072 if (proxy->isLazy() && !proxy->priv().doLazyInstantiation(fResourceProvider)) {
Adlai Holler19fd5142021-03-08 10:19:30 -070073 fFailedInstantiation = true;
Brian Salomon9cadc312018-12-05 15:09:19 -050074 } else {
Brian Salomonbeb7f522019-08-30 16:19:42 -040075 // Since we aren't going to add an interval we won't revisit this proxy in assign(). So
76 // must already be instantiated or it must be a lazy proxy that we instantiated above.
77 SkASSERT(proxy->isInstantiated());
Brian Salomon9cadc312018-12-05 15:09:19 -050078 }
Brian Salomonbeb7f522019-08-30 16:19:42 -040079 return;
80 }
81 if (Interval* intvl = fIntvlHash.find(proxy->uniqueID().asUInt())) {
82 // Revise the interval for an existing use
83#ifdef SK_DEBUG
Adlai Holler9e2c50e2021-02-09 14:41:52 -050084 if (0 == start && 0 == end) {
85 // This interval is for the initial upload to a deferred proxy. Due to the vagaries
86 // of how deferred proxies are collected they can appear as uploads multiple times
87 // in a single opsTasks' list and as uploads in several opsTasks.
88 SkASSERT(0 == intvl->start());
89 } else if (isDirectDstRead) {
Brian Salomonbeb7f522019-08-30 16:19:42 -040090 // Direct reads from the render target itself should occur w/in the existing
91 // interval
92 SkASSERT(intvl->start() <= start && intvl->end() >= end);
93 } else {
94 SkASSERT(intvl->end() <= start && intvl->end() <= end);
95 }
96#endif
Adlai Holler7f7a5df2021-02-09 17:41:10 +000097 if (ActualUse::kYes == actualUse) {
98 intvl->addUse();
99 }
Brian Salomonbeb7f522019-08-30 16:19:42 -0400100 intvl->extendEnd(end);
101 return;
102 }
103 Interval* newIntvl;
104 if (fFreeIntervalList) {
105 newIntvl = fFreeIntervalList;
106 fFreeIntervalList = newIntvl->next();
107 newIntvl->setNext(nullptr);
108 newIntvl->resetTo(proxy, start, end);
109 } else {
110 newIntvl = fIntervalAllocator.make<Interval>(proxy, start, end);
Brian Salomonc6093532018-12-05 21:34:36 +0000111 }
112
Adlai Holler7f7a5df2021-02-09 17:41:10 +0000113 if (ActualUse::kYes == actualUse) {
114 newIntvl->addUse();
115 }
Brian Salomonbeb7f522019-08-30 16:19:42 -0400116 fIntvlList.insertByIncreasingStart(newIntvl);
117 fIntvlHash.add(newIntvl);
Robert Phillips5af44de2017-07-18 14:49:38 -0400118}
119
120GrResourceAllocator::Interval* GrResourceAllocator::IntervalList::popHead() {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400121 SkDEBUGCODE(this->validate());
122
Robert Phillips5af44de2017-07-18 14:49:38 -0400123 Interval* temp = fHead;
124 if (temp) {
Robert Phillipsf8e25022017-11-08 15:24:31 -0500125 fHead = temp->next();
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400126 if (!fHead) {
127 fTail = nullptr;
128 }
129 temp->setNext(nullptr);
Robert Phillips5af44de2017-07-18 14:49:38 -0400130 }
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400131
132 SkDEBUGCODE(this->validate());
Robert Phillips5af44de2017-07-18 14:49:38 -0400133 return temp;
134}
135
136// TODO: fuse this with insertByIncreasingEnd
137void GrResourceAllocator::IntervalList::insertByIncreasingStart(Interval* intvl) {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400138 SkDEBUGCODE(this->validate());
139 SkASSERT(!intvl->next());
140
Robert Phillips5af44de2017-07-18 14:49:38 -0400141 if (!fHead) {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400142 // 14%
143 fHead = fTail = intvl;
Robert Phillipsf8e25022017-11-08 15:24:31 -0500144 } else if (intvl->start() <= fHead->start()) {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400145 // 3%
Robert Phillipsf8e25022017-11-08 15:24:31 -0500146 intvl->setNext(fHead);
Robert Phillips5af44de2017-07-18 14:49:38 -0400147 fHead = intvl;
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400148 } else if (fTail->start() <= intvl->start()) {
149 // 83%
150 fTail->setNext(intvl);
151 fTail = intvl;
Robert Phillips5af44de2017-07-18 14:49:38 -0400152 } else {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400153 // almost never
Robert Phillips5af44de2017-07-18 14:49:38 -0400154 Interval* prev = fHead;
Robert Phillipsf8e25022017-11-08 15:24:31 -0500155 Interval* next = prev->next();
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400156 for (; intvl->start() > next->start(); prev = next, next = next->next()) {
Robert Phillips5af44de2017-07-18 14:49:38 -0400157 }
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400158
159 SkASSERT(next);
Robert Phillipsf8e25022017-11-08 15:24:31 -0500160 intvl->setNext(next);
161 prev->setNext(intvl);
Robert Phillips5af44de2017-07-18 14:49:38 -0400162 }
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400163
164 SkDEBUGCODE(this->validate());
Robert Phillips5af44de2017-07-18 14:49:38 -0400165}
166
167// TODO: fuse this with insertByIncreasingStart
168void GrResourceAllocator::IntervalList::insertByIncreasingEnd(Interval* intvl) {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400169 SkDEBUGCODE(this->validate());
170 SkASSERT(!intvl->next());
171
Robert Phillips5af44de2017-07-18 14:49:38 -0400172 if (!fHead) {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400173 // 14%
174 fHead = fTail = intvl;
Robert Phillipsf8e25022017-11-08 15:24:31 -0500175 } else if (intvl->end() <= fHead->end()) {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400176 // 64%
Robert Phillipsf8e25022017-11-08 15:24:31 -0500177 intvl->setNext(fHead);
Robert Phillips5af44de2017-07-18 14:49:38 -0400178 fHead = intvl;
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400179 } else if (fTail->end() <= intvl->end()) {
180 // 3%
181 fTail->setNext(intvl);
182 fTail = intvl;
Robert Phillips5af44de2017-07-18 14:49:38 -0400183 } else {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400184 // 19% but 81% of those land right after the list's head
Robert Phillips5af44de2017-07-18 14:49:38 -0400185 Interval* prev = fHead;
Robert Phillipsf8e25022017-11-08 15:24:31 -0500186 Interval* next = prev->next();
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400187 for (; intvl->end() > next->end(); prev = next, next = next->next()) {
Robert Phillips5af44de2017-07-18 14:49:38 -0400188 }
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400189
190 SkASSERT(next);
Robert Phillipsf8e25022017-11-08 15:24:31 -0500191 intvl->setNext(next);
192 prev->setNext(intvl);
Robert Phillips5af44de2017-07-18 14:49:38 -0400193 }
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400194
195 SkDEBUGCODE(this->validate());
Robert Phillips5af44de2017-07-18 14:49:38 -0400196}
197
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400198#ifdef SK_DEBUG
199void GrResourceAllocator::IntervalList::validate() const {
200 SkASSERT(SkToBool(fHead) == SkToBool(fTail));
201
202 Interval* prev = nullptr;
203 for (Interval* cur = fHead; cur; prev = cur, cur = cur->next()) {
204 }
205
206 SkASSERT(fTail == prev);
207}
208#endif
Robert Phillips4150eea2018-02-07 17:08:21 -0500209
210 GrResourceAllocator::Interval* GrResourceAllocator::IntervalList::detachAll() {
211 Interval* tmp = fHead;
212 fHead = nullptr;
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400213 fTail = nullptr;
Robert Phillips4150eea2018-02-07 17:08:21 -0500214 return tmp;
215}
216
Robert Phillips5af44de2017-07-18 14:49:38 -0400217// 'surface' can be reused. Add it back to the free pool.
Robert Phillips715d08c2018-07-18 13:56:48 -0400218void GrResourceAllocator::recycleSurface(sk_sp<GrSurface> surface) {
Robert Phillips57aa3672017-07-21 11:38:13 -0400219 const GrScratchKey &key = surface->resourcePriv().getScratchKey();
220
221 if (!key.isValid()) {
222 return; // can't do it w/o a valid scratch key
223 }
224
Robert Phillipsf8e25022017-11-08 15:24:31 -0500225 if (surface->getUniqueKey().isValid()) {
226 // If the surface has a unique key we throw it back into the resource cache.
227 // If things get really tight 'findSurfaceFor' may pull it back out but there is
228 // no need to have it in tight rotation.
229 return;
230 }
231
Robert Phillips715d08c2018-07-18 13:56:48 -0400232#if GR_ALLOCATION_SPEW
233 SkDebugf("putting surface %d back into pool\n", surface->uniqueID().asUInt());
234#endif
Robert Phillips57aa3672017-07-21 11:38:13 -0400235 // TODO: fix this insertion so we get a more LRU-ish behavior
Robert Phillips5b65a842017-11-13 15:48:12 -0500236 fFreePool.insert(key, surface.release());
Robert Phillips5af44de2017-07-18 14:49:38 -0400237}
238
239// First try to reuse one of the recently allocated/used GrSurfaces in the free pool.
240// If we can't find a useable one, create a new one.
Chris Dalton0b68dda2019-11-07 21:08:03 -0700241sk_sp<GrSurface> GrResourceAllocator::findSurfaceFor(const GrSurfaceProxy* proxy) {
Robert Phillips0790f8a2018-09-18 13:11:03 -0400242 if (proxy->asTextureProxy() && proxy->asTextureProxy()->getUniqueKey().isValid()) {
243 // First try to reattach to a cached version if the proxy is uniquely keyed
Chris Dalton0b68dda2019-11-07 21:08:03 -0700244 if (sk_sp<GrSurface> surface = fResourceProvider->findByUniqueKey<GrSurface>(
245 proxy->asTextureProxy()->getUniqueKey())) {
Robert Phillips0790f8a2018-09-18 13:11:03 -0400246 return surface;
247 }
248 }
249
Robert Phillips57aa3672017-07-21 11:38:13 -0400250 // First look in the free pool
251 GrScratchKey key;
Robert Phillips5af44de2017-07-18 14:49:38 -0400252
Greg Danield51fa2f2020-01-22 16:53:38 -0500253 proxy->priv().computeScratchKey(*fResourceProvider->caps(), &key);
Robert Phillips57aa3672017-07-21 11:38:13 -0400254
Robert Phillips10d17212019-04-24 14:09:10 -0400255 auto filter = [] (const GrSurface* s) {
256 return true;
Robert Phillipsf8e25022017-11-08 15:24:31 -0500257 };
258 sk_sp<GrSurface> surface(fFreePool.findAndRemove(key, filter));
Robert Phillips57aa3672017-07-21 11:38:13 -0400259 if (surface) {
Robert Phillipsf8e25022017-11-08 15:24:31 -0500260 if (SkBudgeted::kYes == proxy->isBudgeted() &&
Brian Salomonfa2ebea2019-01-24 15:58:58 -0500261 GrBudgetedType::kBudgeted != surface->resourcePriv().budgetedType()) {
Robert Phillipsf8e25022017-11-08 15:24:31 -0500262 // This gets the job done but isn't quite correct. It would be better to try to
Brian Salomonfa2ebea2019-01-24 15:58:58 -0500263 // match budgeted proxies w/ budgeted surfaces and unbudgeted w/ unbudgeted.
Robert Phillipsf8e25022017-11-08 15:24:31 -0500264 surface->resourcePriv().makeBudgeted();
265 }
Robert Phillips0790f8a2018-09-18 13:11:03 -0400266 SkASSERT(!surface->getUniqueKey().isValid());
Robert Phillipsf8e25022017-11-08 15:24:31 -0500267 return surface;
Robert Phillips57aa3672017-07-21 11:38:13 -0400268 }
269
270 // Failing that, try to grab a new one from the resource cache
Robert Phillips5af44de2017-07-18 14:49:38 -0400271 return proxy->priv().createSurface(fResourceProvider);
272}
273
274// Remove any intervals that end before the current index. Return their GrSurfaces
Robert Phillips39667382019-04-17 16:03:30 -0400275// to the free pool if possible.
Robert Phillips5af44de2017-07-18 14:49:38 -0400276void GrResourceAllocator::expire(unsigned int curIndex) {
Robert Phillipsf8e25022017-11-08 15:24:31 -0500277 while (!fActiveIntvls.empty() && fActiveIntvls.peekHead()->end() < curIndex) {
Robert Phillips5af44de2017-07-18 14:49:38 -0400278 Interval* temp = fActiveIntvls.popHead();
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400279 SkASSERT(!temp->next());
Robert Phillips5b65a842017-11-13 15:48:12 -0500280
281 if (temp->wasAssignedSurface()) {
Robert Phillips715d08c2018-07-18 13:56:48 -0400282 sk_sp<GrSurface> surface = temp->detachSurface();
283
Robert Phillipsc73666f2019-04-24 08:49:48 -0400284 if (temp->isRecyclable()) {
Robert Phillips715d08c2018-07-18 13:56:48 -0400285 this->recycleSurface(std::move(surface));
286 }
Robert Phillips5b65a842017-11-13 15:48:12 -0500287 }
Robert Phillips8186cbe2017-11-01 17:32:39 -0400288
289 // Add temp to the free interval list so it can be reused
Robert Phillips715d08c2018-07-18 13:56:48 -0400290 SkASSERT(!temp->wasAssignedSurface()); // it had better not have a ref on a surface
Robert Phillipsf8e25022017-11-08 15:24:31 -0500291 temp->setNext(fFreeIntervalList);
Robert Phillips8186cbe2017-11-01 17:32:39 -0400292 fFreeIntervalList = temp;
Robert Phillips5af44de2017-07-18 14:49:38 -0400293 }
294}
295
Adlai Holler19fd5142021-03-08 10:19:30 -0700296bool GrResourceAllocator::assign() {
Robert Phillips5f78adf2019-04-22 12:41:39 -0400297 fIntvlHash.reset(); // we don't need the interval hash anymore
298
Robert Phillips5af44de2017-07-18 14:49:38 -0400299 SkDEBUGCODE(fAssigned = true;)
300
Adlai Hollerc616e1c2021-02-11 15:18:17 -0500301 if (fIntvlList.empty()) {
Adlai Holler19fd5142021-03-08 10:19:30 -0700302 return !fFailedInstantiation; // no resources to assign
Adlai Hollerc616e1c2021-02-11 15:18:17 -0500303 }
304
Robert Phillips715d08c2018-07-18 13:56:48 -0400305#if GR_ALLOCATION_SPEW
Adlai Hollerc616e1c2021-02-11 15:18:17 -0500306 SkDebugf("assigning %d ops\n", fNumOps);
Robert Phillips715d08c2018-07-18 13:56:48 -0400307 this->dumpIntervals();
308#endif
Robert Phillipseafd48a2017-11-16 07:52:08 -0500309
Adlai Hollerc616e1c2021-02-11 15:18:17 -0500310 // TODO: Can this be done inline during the main iteration?
311 this->determineRecyclability();
312
Adlai Holler19fd5142021-03-08 10:19:30 -0700313 Interval* cur = nullptr;
Adlai Holler043a7372021-03-08 17:35:27 -0700314 while ((cur = fIntvlList.popHead())) {
Robert Phillipsf8e25022017-11-08 15:24:31 -0500315 this->expire(cur->start());
Robert Phillips57aa3672017-07-21 11:38:13 -0400316
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400317 if (cur->proxy()->isInstantiated()) {
Robert Phillips57aa3672017-07-21 11:38:13 -0400318 fActiveIntvls.insertByIncreasingEnd(cur);
Robert Phillipseafd48a2017-11-16 07:52:08 -0500319
Robert Phillips57aa3672017-07-21 11:38:13 -0400320 continue;
321 }
322
Brian Salomonbeb7f522019-08-30 16:19:42 -0400323 if (cur->proxy()->isLazy()) {
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500324 if (!cur->proxy()->priv().doLazyInstantiation(fResourceProvider)) {
Adlai Holler19fd5142021-03-08 10:19:30 -0700325 fFailedInstantiation = true;
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500326 }
Chris Dalton0b68dda2019-11-07 21:08:03 -0700327 } else if (sk_sp<GrSurface> surface = this->findSurfaceFor(cur->proxy())) {
Robert Phillipsf8e25022017-11-08 15:24:31 -0500328 // TODO: make getUniqueKey virtual on GrSurfaceProxy
Robert Phillips0790f8a2018-09-18 13:11:03 -0400329 GrTextureProxy* texProxy = cur->proxy()->asTextureProxy();
330
331 if (texProxy && texProxy->getUniqueKey().isValid()) {
332 if (!surface->getUniqueKey().isValid()) {
333 fResourceProvider->assignUniqueKeyToResource(texProxy->getUniqueKey(),
334 surface.get());
335 }
336 SkASSERT(surface->getUniqueKey() == texProxy->getUniqueKey());
Robert Phillipsf8e25022017-11-08 15:24:31 -0500337 }
338
Robert Phillips715d08c2018-07-18 13:56:48 -0400339#if GR_ALLOCATION_SPEW
340 SkDebugf("Assigning %d to %d\n",
341 surface->uniqueID().asUInt(),
342 cur->proxy()->uniqueID().asUInt());
343#endif
344
Robert Phillips5b65a842017-11-13 15:48:12 -0500345 cur->assign(std::move(surface));
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500346 } else {
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400347 SkASSERT(!cur->proxy()->isInstantiated());
Adlai Holler19fd5142021-03-08 10:19:30 -0700348 fFailedInstantiation = true;
Robert Phillips5af44de2017-07-18 14:49:38 -0400349 }
Robert Phillipseafd48a2017-11-16 07:52:08 -0500350
Robert Phillips5af44de2017-07-18 14:49:38 -0400351 fActiveIntvls.insertByIncreasingEnd(cur);
352 }
Robert Phillips5b65a842017-11-13 15:48:12 -0500353
354 // expire all the remaining intervals to drain the active interval list
355 this->expire(std::numeric_limits<unsigned int>::max());
Adlai Holler19fd5142021-03-08 10:19:30 -0700356 return !fFailedInstantiation;
Robert Phillips5af44de2017-07-18 14:49:38 -0400357}
Robert Phillips715d08c2018-07-18 13:56:48 -0400358
359#if GR_ALLOCATION_SPEW
360void GrResourceAllocator::dumpIntervals() {
Robert Phillips715d08c2018-07-18 13:56:48 -0400361 // Print all the intervals while computing their range
Robert Phillips3bf3d4a2019-03-27 07:09:09 -0400362 SkDebugf("------------------------------------------------------------\n");
363 unsigned int min = std::numeric_limits<unsigned int>::max();
Robert Phillips715d08c2018-07-18 13:56:48 -0400364 unsigned int max = 0;
365 for(const Interval* cur = fIntvlList.peekHead(); cur; cur = cur->next()) {
Greg Danielc61d7e32020-02-04 14:27:45 -0500366 SkDebugf("{ %3d,%3d }: [%2d, %2d] - refProxys:%d surfaceRefs:%d\n",
Robert Phillips715d08c2018-07-18 13:56:48 -0400367 cur->proxy()->uniqueID().asUInt(),
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400368 cur->proxy()->isInstantiated() ? cur->proxy()->underlyingUniqueID().asUInt() : -1,
Robert Phillips715d08c2018-07-18 13:56:48 -0400369 cur->start(),
370 cur->end(),
371 cur->proxy()->priv().getProxyRefCnt(),
Robert Phillipsb5204762019-06-19 14:12:13 -0400372 cur->proxy()->testingOnly_getBackingRefCnt());
Brian Osman788b9162020-02-07 10:36:46 -0500373 min = std::min(min, cur->start());
374 max = std::max(max, cur->end());
Robert Phillips715d08c2018-07-18 13:56:48 -0400375 }
376
377 // Draw a graph of the useage intervals
378 for(const Interval* cur = fIntvlList.peekHead(); cur; cur = cur->next()) {
379 SkDebugf("{ %3d,%3d }: ",
380 cur->proxy()->uniqueID().asUInt(),
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400381 cur->proxy()->isInstantiated() ? cur->proxy()->underlyingUniqueID().asUInt() : -1);
Robert Phillips715d08c2018-07-18 13:56:48 -0400382 for (unsigned int i = min; i <= max; ++i) {
383 if (i >= cur->start() && i <= cur->end()) {
384 SkDebugf("x");
385 } else {
386 SkDebugf(" ");
387 }
388 }
389 SkDebugf("\n");
390 }
391}
392#endif