blob: f266d780b050ba5e1a05872d7a0a3158619bd05b [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
Adlai Hollerca1137b2021-04-08 11:39:55 -040010#include "src/gpu/GrDirectContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "src/gpu/GrGpuResourcePriv.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"
Robert Phillips5af44de2017-07-18 14:49:38 -040016
Adlai Holler4cfbe532021-03-17 10:36:39 -040017#ifdef SK_DEBUG
18#include <atomic>
Mike Klein0ec1c572018-12-04 11:52:51 -050019
Adlai Holler4cfbe532021-03-17 10:36:39 -040020uint32_t GrResourceAllocator::Interval::CreateUniqueID() {
21 static std::atomic<uint32_t> nextID{1};
22 uint32_t id;
23 do {
24 id = nextID.fetch_add(1, std::memory_order_relaxed);
25 } while (id == SK_InvalidUniqueID);
26 return id;
27}
28
29uint32_t GrResourceAllocator::Register::CreateUniqueID() {
30 static std::atomic<uint32_t> nextID{1};
31 uint32_t id;
32 do {
33 id = nextID.fetch_add(1, std::memory_order_relaxed);
34 } while (id == SK_InvalidUniqueID);
35 return id;
36}
Robert Phillipsda1be462018-07-27 07:18:06 -040037#endif
38
Robert Phillips5b65a842017-11-13 15:48:12 -050039GrResourceAllocator::~GrResourceAllocator() {
Adlai Holleree2837b2021-04-09 16:52:48 -040040 SkASSERT(fFailedInstantiation || fIntvlList.empty());
Robert Phillips5b65a842017-11-13 15:48:12 -050041 SkASSERT(fActiveIntvls.empty());
42 SkASSERT(!fIntvlHash.count());
Robert Phillips5b65a842017-11-13 15:48:12 -050043}
44
Adlai Holler7f7a5df2021-02-09 17:41:10 +000045void GrResourceAllocator::addInterval(GrSurfaceProxy* proxy, unsigned int start, unsigned int end,
46 ActualUse actualUse
Chris Dalton8816b932017-11-29 16:48:25 -070047 SkDEBUGCODE(, bool isDirectDstRead)) {
Brian Salomonbeb7f522019-08-30 16:19:42 -040048 SkASSERT(start <= end);
49 SkASSERT(!fAssigned); // We shouldn't be adding any intervals after (or during) assignment
Robert Phillips5f78adf2019-04-22 12:41:39 -040050
Chris Dalton97155592019-06-13 13:40:20 -060051 if (proxy->canSkipResourceAllocator()) {
Robert Phillips5f78adf2019-04-22 12:41:39 -040052 return;
53 }
54
Brian Salomon9cadc312018-12-05 15:09:19 -050055 // If a proxy is read only it must refer to a texture with specific content that cannot be
56 // recycled. We don't need to assign a texture to it and no other proxy can be instantiated
57 // with the same texture.
58 if (proxy->readOnly()) {
Adlai Hollerca1137b2021-04-08 11:39:55 -040059 auto resourceProvider = fDContext->priv().resourceProvider();
60 if (proxy->isLazy() && !proxy->priv().doLazyInstantiation(resourceProvider)) {
Adlai Holler19fd5142021-03-08 10:19:30 -070061 fFailedInstantiation = true;
Brian Salomon9cadc312018-12-05 15:09:19 -050062 } else {
Brian Salomonbeb7f522019-08-30 16:19:42 -040063 // Since we aren't going to add an interval we won't revisit this proxy in assign(). So
64 // must already be instantiated or it must be a lazy proxy that we instantiated above.
65 SkASSERT(proxy->isInstantiated());
Brian Salomon9cadc312018-12-05 15:09:19 -050066 }
Brian Salomonbeb7f522019-08-30 16:19:42 -040067 return;
68 }
Adlai Holler539db2f2021-03-16 09:45:05 -040069 uint32_t proxyID = proxy->uniqueID().asUInt();
70 if (Interval** intvlPtr = fIntvlHash.find(proxyID)) {
Brian Salomonbeb7f522019-08-30 16:19:42 -040071 // Revise the interval for an existing use
Adlai Holler1143b1b2021-03-16 13:07:40 -040072 Interval* intvl = *intvlPtr;
Brian Salomonbeb7f522019-08-30 16:19:42 -040073#ifdef SK_DEBUG
Adlai Holler9e2c50e2021-02-09 14:41:52 -050074 if (0 == start && 0 == end) {
75 // This interval is for the initial upload to a deferred proxy. Due to the vagaries
76 // of how deferred proxies are collected they can appear as uploads multiple times
77 // in a single opsTasks' list and as uploads in several opsTasks.
78 SkASSERT(0 == intvl->start());
79 } else if (isDirectDstRead) {
Brian Salomonbeb7f522019-08-30 16:19:42 -040080 // Direct reads from the render target itself should occur w/in the existing
81 // interval
82 SkASSERT(intvl->start() <= start && intvl->end() >= end);
83 } else {
84 SkASSERT(intvl->end() <= start && intvl->end() <= end);
85 }
86#endif
Adlai Holler7f7a5df2021-02-09 17:41:10 +000087 if (ActualUse::kYes == actualUse) {
88 intvl->addUse();
89 }
Brian Salomonbeb7f522019-08-30 16:19:42 -040090 intvl->extendEnd(end);
91 return;
92 }
Adlai Holler4cfbe532021-03-17 10:36:39 -040093 Interval* newIntvl = fInternalAllocator.make<Interval>(proxy, start, end);
Brian Salomonc6093532018-12-05 21:34:36 +000094
Adlai Holler7f7a5df2021-02-09 17:41:10 +000095 if (ActualUse::kYes == actualUse) {
96 newIntvl->addUse();
97 }
Brian Salomonbeb7f522019-08-30 16:19:42 -040098 fIntvlList.insertByIncreasingStart(newIntvl);
Adlai Holler539db2f2021-03-16 09:45:05 -040099 fIntvlHash.set(proxyID, newIntvl);
Robert Phillips5af44de2017-07-18 14:49:38 -0400100}
101
Adlai Holleree2837b2021-04-09 16:52:48 -0400102// Tragically we have cases where we always have to make new textures.
103static bool can_proxy_use_scratch(const GrCaps& caps, GrSurfaceProxy* proxy) {
104 return caps.reuseScratchTextures() || proxy->asRenderTargetProxy();
105}
106
Adlai Holler3cffe812021-04-09 13:43:32 -0400107GrResourceAllocator::Register::Register(GrSurfaceProxy* originatingProxy,
Adlai Holleree2837b2021-04-09 16:52:48 -0400108 GrScratchKey scratchKey,
109 GrResourceProvider* provider)
Adlai Holler3cffe812021-04-09 13:43:32 -0400110 : fOriginatingProxy(originatingProxy)
111 , fScratchKey(std::move(scratchKey)) {
112 SkASSERT(originatingProxy);
113 SkASSERT(!originatingProxy->isInstantiated());
114 SkASSERT(!originatingProxy->isLazy());
115 SkDEBUGCODE(fUniqueID = CreateUniqueID();)
Adlai Holleree2837b2021-04-09 16:52:48 -0400116 if (scratchKey.isValid()) {
117 if (can_proxy_use_scratch(*provider->caps(), originatingProxy)) {
118 fExistingSurface = provider->findAndRefScratchTexture(fScratchKey);
119 }
120 } else {
121 SkASSERT(this->uniqueKey().isValid());
122 fExistingSurface = provider->findByUniqueKey<GrSurface>(this->uniqueKey());
123 }
Adlai Holler3cffe812021-04-09 13:43:32 -0400124}
125
Adlai Holler7df8d222021-03-19 12:27:49 -0400126bool GrResourceAllocator::Register::isRecyclable(const GrCaps& caps,
127 GrSurfaceProxy* proxy,
128 int knownUseCount) const {
Adlai Holleree2837b2021-04-09 16:52:48 -0400129 if (!can_proxy_use_scratch(caps, proxy)) {
Adlai Holler7df8d222021-03-19 12:27:49 -0400130 return false;
131 }
132
133 if (!this->scratchKey().isValid()) {
134 return false; // no scratch key, no free pool
135 }
136 if (this->uniqueKey().isValid()) {
137 return false; // rely on the resource cache to hold onto uniquely-keyed surfaces.
138 }
139 // If all the refs on the proxy are known to the resource allocator then no one
Adlai Holler1143b1b2021-03-16 13:07:40 -0400140 // should be holding onto it outside of Ganesh.
Adlai Holler7df8d222021-03-19 12:27:49 -0400141 return !proxy->refCntGreaterThan(knownUseCount);
142}
143
144bool GrResourceAllocator::Register::instantiateSurface(GrSurfaceProxy* proxy,
145 GrResourceProvider* resourceProvider) {
146 SkASSERT(!proxy->peekSurface());
147
Adlai Holleree2837b2021-04-09 16:52:48 -0400148 sk_sp<GrSurface> newSurface;
149 if (!fExistingSurface) {
Adlai Holler7df8d222021-03-19 12:27:49 -0400150 if (proxy == fOriginatingProxy) {
Adlai Holleree2837b2021-04-09 16:52:48 -0400151 newSurface = proxy->priv().createSurface(resourceProvider);
Adlai Holler7df8d222021-03-19 12:27:49 -0400152 } else {
Adlai Holleree2837b2021-04-09 16:52:48 -0400153 newSurface = sk_ref_sp(fOriginatingProxy->peekSurface());
Adlai Holler7df8d222021-03-19 12:27:49 -0400154 }
155 }
Adlai Holleree2837b2021-04-09 16:52:48 -0400156 if (!fExistingSurface && !newSurface) {
Adlai Holler7df8d222021-03-19 12:27:49 -0400157 return false;
158 }
159
Adlai Holleree2837b2021-04-09 16:52:48 -0400160 GrSurface* surface = newSurface ? newSurface.get() : fExistingSurface.get();
Adlai Holler7df8d222021-03-19 12:27:49 -0400161 // Make surface budgeted if this proxy is budgeted.
162 if (SkBudgeted::kYes == proxy->isBudgeted() &&
163 GrBudgetedType::kBudgeted != surface->resourcePriv().budgetedType()) {
164 // This gets the job done but isn't quite correct. It would be better to try to
165 // match budgeted proxies w/ budgeted surfaces and unbudgeted w/ unbudgeted.
166 surface->resourcePriv().makeBudgeted();
167 }
168
169 // Propagate the proxy unique key to the surface if we have one.
170 if (const auto& uniqueKey = proxy->getUniqueKey(); uniqueKey.isValid()) {
171 if (!surface->getUniqueKey().isValid()) {
Adlai Holleree2837b2021-04-09 16:52:48 -0400172 resourceProvider->assignUniqueKeyToResource(uniqueKey, surface);
Adlai Holler7df8d222021-03-19 12:27:49 -0400173 }
174 SkASSERT(surface->getUniqueKey() == uniqueKey);
175 }
Adlai Holleree2837b2021-04-09 16:52:48 -0400176 proxy->priv().assign(fExistingSurface ? fExistingSurface : std::move(newSurface));
Adlai Holler7df8d222021-03-19 12:27:49 -0400177 return true;
Adlai Holler1143b1b2021-03-16 13:07:40 -0400178}
179
Robert Phillips5af44de2017-07-18 14:49:38 -0400180GrResourceAllocator::Interval* GrResourceAllocator::IntervalList::popHead() {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400181 SkDEBUGCODE(this->validate());
182
Robert Phillips5af44de2017-07-18 14:49:38 -0400183 Interval* temp = fHead;
184 if (temp) {
Robert Phillipsf8e25022017-11-08 15:24:31 -0500185 fHead = temp->next();
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400186 if (!fHead) {
187 fTail = nullptr;
188 }
189 temp->setNext(nullptr);
Robert Phillips5af44de2017-07-18 14:49:38 -0400190 }
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400191
192 SkDEBUGCODE(this->validate());
Robert Phillips5af44de2017-07-18 14:49:38 -0400193 return temp;
194}
195
196// TODO: fuse this with insertByIncreasingEnd
197void GrResourceAllocator::IntervalList::insertByIncreasingStart(Interval* intvl) {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400198 SkDEBUGCODE(this->validate());
199 SkASSERT(!intvl->next());
200
Robert Phillips5af44de2017-07-18 14:49:38 -0400201 if (!fHead) {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400202 // 14%
203 fHead = fTail = intvl;
Robert Phillipsf8e25022017-11-08 15:24:31 -0500204 } else if (intvl->start() <= fHead->start()) {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400205 // 3%
Robert Phillipsf8e25022017-11-08 15:24:31 -0500206 intvl->setNext(fHead);
Robert Phillips5af44de2017-07-18 14:49:38 -0400207 fHead = intvl;
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400208 } else if (fTail->start() <= intvl->start()) {
209 // 83%
210 fTail->setNext(intvl);
211 fTail = intvl;
Robert Phillips5af44de2017-07-18 14:49:38 -0400212 } else {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400213 // almost never
Robert Phillips5af44de2017-07-18 14:49:38 -0400214 Interval* prev = fHead;
Robert Phillipsf8e25022017-11-08 15:24:31 -0500215 Interval* next = prev->next();
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400216 for (; intvl->start() > next->start(); prev = next, next = next->next()) {
Robert Phillips5af44de2017-07-18 14:49:38 -0400217 }
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400218
219 SkASSERT(next);
Robert Phillipsf8e25022017-11-08 15:24:31 -0500220 intvl->setNext(next);
221 prev->setNext(intvl);
Robert Phillips5af44de2017-07-18 14:49:38 -0400222 }
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400223
224 SkDEBUGCODE(this->validate());
Robert Phillips5af44de2017-07-18 14:49:38 -0400225}
226
227// TODO: fuse this with insertByIncreasingStart
228void GrResourceAllocator::IntervalList::insertByIncreasingEnd(Interval* intvl) {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400229 SkDEBUGCODE(this->validate());
230 SkASSERT(!intvl->next());
231
Robert Phillips5af44de2017-07-18 14:49:38 -0400232 if (!fHead) {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400233 // 14%
234 fHead = fTail = intvl;
Robert Phillipsf8e25022017-11-08 15:24:31 -0500235 } else if (intvl->end() <= fHead->end()) {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400236 // 64%
Robert Phillipsf8e25022017-11-08 15:24:31 -0500237 intvl->setNext(fHead);
Robert Phillips5af44de2017-07-18 14:49:38 -0400238 fHead = intvl;
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400239 } else if (fTail->end() <= intvl->end()) {
240 // 3%
241 fTail->setNext(intvl);
242 fTail = intvl;
Robert Phillips5af44de2017-07-18 14:49:38 -0400243 } else {
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400244 // 19% but 81% of those land right after the list's head
Robert Phillips5af44de2017-07-18 14:49:38 -0400245 Interval* prev = fHead;
Robert Phillipsf8e25022017-11-08 15:24:31 -0500246 Interval* next = prev->next();
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400247 for (; intvl->end() > next->end(); prev = next, next = next->next()) {
Robert Phillips5af44de2017-07-18 14:49:38 -0400248 }
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400249
250 SkASSERT(next);
Robert Phillipsf8e25022017-11-08 15:24:31 -0500251 intvl->setNext(next);
252 prev->setNext(intvl);
Robert Phillips5af44de2017-07-18 14:49:38 -0400253 }
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400254
255 SkDEBUGCODE(this->validate());
Robert Phillips5af44de2017-07-18 14:49:38 -0400256}
257
Robert Phillipsdf25e3a2018-08-08 12:48:40 -0400258#ifdef SK_DEBUG
259void GrResourceAllocator::IntervalList::validate() const {
260 SkASSERT(SkToBool(fHead) == SkToBool(fTail));
261
262 Interval* prev = nullptr;
263 for (Interval* cur = fHead; cur; prev = cur, cur = cur->next()) {
264 }
265
266 SkASSERT(fTail == prev);
267}
268#endif
Robert Phillips4150eea2018-02-07 17:08:21 -0500269
Adlai Holler4cfbe532021-03-17 10:36:39 -0400270// First try to reuse one of the recently allocated/used registers in the free pool.
Adlai Holler7df8d222021-03-19 12:27:49 -0400271GrResourceAllocator::Register* GrResourceAllocator::findOrCreateRegisterFor(GrSurfaceProxy* proxy) {
Adlai Holleree2837b2021-04-09 16:52:48 -0400272 auto resourceProvider = fDContext->priv().resourceProvider();
Adlai Holler7df8d222021-03-19 12:27:49 -0400273 // Handle uniquely keyed proxies
Adlai Hollercc119d92021-03-16 15:17:25 -0400274 if (const auto& uniqueKey = proxy->getUniqueKey(); uniqueKey.isValid()) {
Adlai Holler7df8d222021-03-19 12:27:49 -0400275 if (auto p = fUniqueKeyRegisters.find(uniqueKey)) {
276 return *p;
Robert Phillips0790f8a2018-09-18 13:11:03 -0400277 }
Adlai Holler7df8d222021-03-19 12:27:49 -0400278 // No need for a scratch key. These don't go in the free pool.
Adlai Holleree2837b2021-04-09 16:52:48 -0400279 Register* r = fInternalAllocator.make<Register>(proxy, GrScratchKey(), resourceProvider);
Adlai Holler7df8d222021-03-19 12:27:49 -0400280 fUniqueKeyRegisters.set(uniqueKey, r);
281 return r;
Robert Phillips0790f8a2018-09-18 13:11:03 -0400282 }
283
Adlai Hollercc119d92021-03-16 15:17:25 -0400284 // Then look in the free pool
Adlai Holler7df8d222021-03-19 12:27:49 -0400285 GrScratchKey scratchKey;
Adlai Hollerca1137b2021-04-08 11:39:55 -0400286 proxy->priv().computeScratchKey(*fDContext->priv().caps(), &scratchKey);
Robert Phillips57aa3672017-07-21 11:38:13 -0400287
Adlai Holler4cfbe532021-03-17 10:36:39 -0400288 auto filter = [] (const Register* r) {
Robert Phillips10d17212019-04-24 14:09:10 -0400289 return true;
Robert Phillipsf8e25022017-11-08 15:24:31 -0500290 };
Adlai Holler7df8d222021-03-19 12:27:49 -0400291 if (Register* r = fFreePool.findAndRemove(scratchKey, filter)) {
Adlai Holler4cfbe532021-03-17 10:36:39 -0400292 return r;
Robert Phillips57aa3672017-07-21 11:38:13 -0400293 }
294
Adlai Holleree2837b2021-04-09 16:52:48 -0400295 return fInternalAllocator.make<Register>(proxy, std::move(scratchKey), resourceProvider);
Robert Phillips5af44de2017-07-18 14:49:38 -0400296}
297
Adlai Holler7df8d222021-03-19 12:27:49 -0400298// Remove any intervals that end before the current index. Add their registers
Robert Phillips39667382019-04-17 16:03:30 -0400299// to the free pool if possible.
Robert Phillips5af44de2017-07-18 14:49:38 -0400300void GrResourceAllocator::expire(unsigned int curIndex) {
Robert Phillipsf8e25022017-11-08 15:24:31 -0500301 while (!fActiveIntvls.empty() && fActiveIntvls.peekHead()->end() < curIndex) {
Adlai Holler729ba5e2021-03-15 12:34:31 -0400302 Interval* intvl = fActiveIntvls.popHead();
303 SkASSERT(!intvl->next());
Robert Phillips5b65a842017-11-13 15:48:12 -0500304
Adlai Holler7df8d222021-03-19 12:27:49 -0400305 Register* r = intvl->getRegister();
Adlai Hollerca1137b2021-04-08 11:39:55 -0400306 if (r && r->isRecyclable(*fDContext->priv().caps(), intvl->proxy(), intvl->uses())) {
Adlai Holler7df8d222021-03-19 12:27:49 -0400307#if GR_ALLOCATION_SPEW
308 SkDebugf("putting register %d back into pool\n", r->uniqueID());
309#endif
310 // TODO: fix this insertion so we get a more LRU-ish behavior
311 fFreePool.insert(r->scratchKey(), r);
Robert Phillips5b65a842017-11-13 15:48:12 -0500312 }
Adlai Holler7df8d222021-03-19 12:27:49 -0400313 fFinishedIntvls.insertByIncreasingStart(intvl);
Robert Phillips5af44de2017-07-18 14:49:38 -0400314 }
315}
316
Adlai Holleree2837b2021-04-09 16:52:48 -0400317bool GrResourceAllocator::planAssignment() {
Robert Phillips5f78adf2019-04-22 12:41:39 -0400318 fIntvlHash.reset(); // we don't need the interval hash anymore
319
Adlai Holleree2837b2021-04-09 16:52:48 -0400320 SkASSERT(!fPlanned && !fAssigned);
321 SkDEBUGCODE(fPlanned = true;)
Adlai Hollerc616e1c2021-02-11 15:18:17 -0500322
Robert Phillips715d08c2018-07-18 13:56:48 -0400323#if GR_ALLOCATION_SPEW
Adlai Hollerc616e1c2021-02-11 15:18:17 -0500324 SkDebugf("assigning %d ops\n", fNumOps);
Robert Phillips715d08c2018-07-18 13:56:48 -0400325 this->dumpIntervals();
326#endif
Robert Phillipseafd48a2017-11-16 07:52:08 -0500327
Adlai Holleree2837b2021-04-09 16:52:48 -0400328 auto resourceProvider = fDContext->priv().resourceProvider();
Adlai Holler1143b1b2021-03-16 13:07:40 -0400329 while (Interval* cur = fIntvlList.popHead()) {
Robert Phillipsf8e25022017-11-08 15:24:31 -0500330 this->expire(cur->start());
Adlai Holleree2837b2021-04-09 16:52:48 -0400331 fActiveIntvls.insertByIncreasingEnd(cur);
Robert Phillips57aa3672017-07-21 11:38:13 -0400332
Adlai Holler7df8d222021-03-19 12:27:49 -0400333 // Already-instantiated proxies and lazy proxies don't use registers.
Adlai Holleree2837b2021-04-09 16:52:48 -0400334 if (cur->proxy()->isInstantiated()) {
335 continue;
336 }
Robert Phillipseafd48a2017-11-16 07:52:08 -0500337
Adlai Holleree2837b2021-04-09 16:52:48 -0400338 // Instantiate fully-lazy proxies immediately. Ignore other lazy proxies at this stage.
339 if (cur->proxy()->isLazy()) {
340 if (cur->proxy()->isFullyLazy()) {
341 fFailedInstantiation = !cur->proxy()->priv().doLazyInstantiation(resourceProvider);
342 if (fFailedInstantiation) {
343 break;
344 }
345 }
Robert Phillips57aa3672017-07-21 11:38:13 -0400346 continue;
347 }
348
Adlai Holler7df8d222021-03-19 12:27:49 -0400349 Register* r = this->findOrCreateRegisterFor(cur->proxy());
Robert Phillips715d08c2018-07-18 13:56:48 -0400350#if GR_ALLOCATION_SPEW
Adlai Holler7df8d222021-03-19 12:27:49 -0400351 SkDebugf("Assigning register %d to %d\n",
352 r->uniqueID(),
353 cur->proxy()->uniqueID().asUInt());
Robert Phillips715d08c2018-07-18 13:56:48 -0400354#endif
Adlai Holler7df8d222021-03-19 12:27:49 -0400355 SkASSERT(!cur->proxy()->peekSurface());
356 cur->setRegister(r);
Robert Phillips5af44de2017-07-18 14:49:38 -0400357 }
Robert Phillips5b65a842017-11-13 15:48:12 -0500358
359 // expire all the remaining intervals to drain the active interval list
360 this->expire(std::numeric_limits<unsigned int>::max());
Adlai Holleree2837b2021-04-09 16:52:48 -0400361 return !fFailedInstantiation;
362}
Adlai Holler7df8d222021-03-19 12:27:49 -0400363
Adlai Hollercd2f96d2021-04-09 17:58:14 -0400364bool GrResourceAllocator::makeBudgetHeadroom() {
365 SkASSERT(fPlanned);
366 SkASSERT(!fFailedInstantiation);
367 size_t additionalBytesNeeded = 0;
368 for (Interval* cur = fFinishedIntvls.peekHead(); cur; cur = cur->next()) {
369 GrSurfaceProxy* proxy = cur->proxy();
370 if (SkBudgeted::kNo == proxy->isBudgeted() || proxy->isInstantiated()) {
371 continue;
372 }
373
374 // N.B Fully-lazy proxies were already instantiated in planAssignment
375 if (proxy->isLazy()) {
376 additionalBytesNeeded += proxy->gpuMemorySize();
377 } else {
378 Register* r = cur->getRegister();
379 SkASSERT(r);
380 if (!r->accountedForInBudget() && !r->existingSurface()) {
381 additionalBytesNeeded += proxy->gpuMemorySize();
382 }
383 r->setAccountedForInBudget();
384 }
385 }
386 return fDContext->priv().getResourceCache()->purgeToMakeHeadroom(additionalBytesNeeded);
387}
388
Adlai Hollerb51dd572021-04-15 11:01:46 -0400389void GrResourceAllocator::reset() {
390 // NOTE: We do not reset the failedInstantiation flag because we currently do not attempt
391 // to recover from failed instantiations. The user is responsible for checking this flag and
392 // bailing early.
393 SkDEBUGCODE(fPlanned = false;)
394 SkDEBUGCODE(fAssigned = false;)
395 SkASSERT(fActiveIntvls.empty());
396 fFinishedIntvls = IntervalList();
397 fIntvlList = IntervalList();
398 fIntvlHash.reset();
399 fUniqueKeyRegisters.reset();
400 fFreePool.reset();
401 fInternalAllocator.reset();
402}
403
Adlai Holleree2837b2021-04-09 16:52:48 -0400404bool GrResourceAllocator::assign() {
Adlai Hollerb51dd572021-04-15 11:01:46 -0400405 if (fFailedInstantiation) {
406 return false;
407 }
Adlai Holleree2837b2021-04-09 16:52:48 -0400408 SkASSERT(fPlanned && !fAssigned);
409 SkDEBUGCODE(fAssigned = true;)
Adlai Hollerca1137b2021-04-08 11:39:55 -0400410 auto resourceProvider = fDContext->priv().resourceProvider();
Adlai Holler7df8d222021-03-19 12:27:49 -0400411 while (Interval* cur = fFinishedIntvls.popHead()) {
412 if (fFailedInstantiation) {
413 break;
414 }
415 if (cur->proxy()->isInstantiated()) {
416 continue;
417 }
418 if (cur->proxy()->isLazy()) {
Adlai Hollerca1137b2021-04-08 11:39:55 -0400419 fFailedInstantiation = !cur->proxy()->priv().doLazyInstantiation(resourceProvider);
Adlai Holler7df8d222021-03-19 12:27:49 -0400420 continue;
421 }
422 Register* r = cur->getRegister();
423 SkASSERT(r);
Adlai Hollerca1137b2021-04-08 11:39:55 -0400424 fFailedInstantiation = !r->instantiateSurface(cur->proxy(), resourceProvider);
Adlai Holler7df8d222021-03-19 12:27:49 -0400425 }
Adlai Holler19fd5142021-03-08 10:19:30 -0700426 return !fFailedInstantiation;
Robert Phillips5af44de2017-07-18 14:49:38 -0400427}
Robert Phillips715d08c2018-07-18 13:56:48 -0400428
429#if GR_ALLOCATION_SPEW
430void GrResourceAllocator::dumpIntervals() {
Robert Phillips715d08c2018-07-18 13:56:48 -0400431 // Print all the intervals while computing their range
Robert Phillips3bf3d4a2019-03-27 07:09:09 -0400432 SkDebugf("------------------------------------------------------------\n");
433 unsigned int min = std::numeric_limits<unsigned int>::max();
Robert Phillips715d08c2018-07-18 13:56:48 -0400434 unsigned int max = 0;
435 for(const Interval* cur = fIntvlList.peekHead(); cur; cur = cur->next()) {
Greg Danielc61d7e32020-02-04 14:27:45 -0500436 SkDebugf("{ %3d,%3d }: [%2d, %2d] - refProxys:%d surfaceRefs:%d\n",
Robert Phillips715d08c2018-07-18 13:56:48 -0400437 cur->proxy()->uniqueID().asUInt(),
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400438 cur->proxy()->isInstantiated() ? cur->proxy()->underlyingUniqueID().asUInt() : -1,
Robert Phillips715d08c2018-07-18 13:56:48 -0400439 cur->start(),
440 cur->end(),
441 cur->proxy()->priv().getProxyRefCnt(),
Robert Phillipsb5204762019-06-19 14:12:13 -0400442 cur->proxy()->testingOnly_getBackingRefCnt());
Brian Osman788b9162020-02-07 10:36:46 -0500443 min = std::min(min, cur->start());
444 max = std::max(max, cur->end());
Robert Phillips715d08c2018-07-18 13:56:48 -0400445 }
446
447 // Draw a graph of the useage intervals
448 for(const Interval* cur = fIntvlList.peekHead(); cur; cur = cur->next()) {
449 SkDebugf("{ %3d,%3d }: ",
450 cur->proxy()->uniqueID().asUInt(),
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400451 cur->proxy()->isInstantiated() ? cur->proxy()->underlyingUniqueID().asUInt() : -1);
Robert Phillips715d08c2018-07-18 13:56:48 -0400452 for (unsigned int i = min; i <= max; ++i) {
453 if (i >= cur->start() && i <= cur->end()) {
454 SkDebugf("x");
455 } else {
456 SkDebugf(" ");
457 }
458 }
459 SkDebugf("\n");
460 }
461}
462#endif