xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrResourceAllocator.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2017 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #ifndef GrResourceAllocator_DEFINED
9*c8dee2aaSAndroid Build Coastguard Worker #define GrResourceAllocator_DEFINED
10*c8dee2aaSAndroid Build Coastguard Worker 
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkDebug.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkArenaAlloc.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkTHash.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkTMultiMap.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ResourceKey.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrCaps.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrHashMapWithCache.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurface.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurfaceProxy.h"
23*c8dee2aaSAndroid Build Coastguard Worker 
24*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
25*c8dee2aaSAndroid Build Coastguard Worker 
26*c8dee2aaSAndroid Build Coastguard Worker class GrDirectContext;
27*c8dee2aaSAndroid Build Coastguard Worker class GrResourceProvider;
28*c8dee2aaSAndroid Build Coastguard Worker 
29*c8dee2aaSAndroid Build Coastguard Worker // Print out explicit allocation information
30*c8dee2aaSAndroid Build Coastguard Worker #define GR_ALLOCATION_SPEW 0
31*c8dee2aaSAndroid Build Coastguard Worker 
32*c8dee2aaSAndroid Build Coastguard Worker // Print out information about interval creation
33*c8dee2aaSAndroid Build Coastguard Worker #define GR_TRACK_INTERVAL_CREATION 0
34*c8dee2aaSAndroid Build Coastguard Worker 
35*c8dee2aaSAndroid Build Coastguard Worker /*
36*c8dee2aaSAndroid Build Coastguard Worker  * The ResourceAllocator explicitly distributes GPU resources at flush time. It operates by
37*c8dee2aaSAndroid Build Coastguard Worker  * being given the usage intervals of the various proxies. It keeps these intervals in a singly
38*c8dee2aaSAndroid Build Coastguard Worker  * linked list sorted by increasing start index. (It also maintains a hash table from proxyID
39*c8dee2aaSAndroid Build Coastguard Worker  * to interval to find proxy reuse). The ResourceAllocator uses Registers (in the sense of register
40*c8dee2aaSAndroid Build Coastguard Worker  * allocation) to represent a future surface that will be used for each proxy during
41*c8dee2aaSAndroid Build Coastguard Worker  * `planAssignment`, and then assigns actual surfaces during `assign`.
42*c8dee2aaSAndroid Build Coastguard Worker  *
43*c8dee2aaSAndroid Build Coastguard Worker  * Note: the op indices (used in the usage intervals) come from the order of the ops in
44*c8dee2aaSAndroid Build Coastguard Worker  * their opsTasks after the opsTask DAG has been linearized.
45*c8dee2aaSAndroid Build Coastguard Worker  *
46*c8dee2aaSAndroid Build Coastguard Worker  * The planAssignment method traverses the sorted list and:
47*c8dee2aaSAndroid Build Coastguard Worker  *     moves intervals from the active list that have completed (returning their registers
48*c8dee2aaSAndroid Build Coastguard Worker  *     to the free pool) into the finished list (sorted by increasing start)
49*c8dee2aaSAndroid Build Coastguard Worker  *
50*c8dee2aaSAndroid Build Coastguard Worker  *     allocates a new register (preferably from the free pool) for the new interval
51*c8dee2aaSAndroid Build Coastguard Worker  *     adds the new interval to the active list (that is sorted by increasing end index)
52*c8dee2aaSAndroid Build Coastguard Worker  *
53*c8dee2aaSAndroid Build Coastguard Worker  * After assignment planning, the user can choose to call `makeBudgetHeadroom` which:
54*c8dee2aaSAndroid Build Coastguard Worker  *     computes how much VRAM would be needed for new resources for all extant Registers
55*c8dee2aaSAndroid Build Coastguard Worker  *
56*c8dee2aaSAndroid Build Coastguard Worker  *     asks the resource cache to purge enough resources to get that much free space
57*c8dee2aaSAndroid Build Coastguard Worker  *
58*c8dee2aaSAndroid Build Coastguard Worker  *     if it's not possible, do nothing and return false. The user may opt to reset
59*c8dee2aaSAndroid Build Coastguard Worker  *     the allocator and start over with a different DAG.
60*c8dee2aaSAndroid Build Coastguard Worker  *
61*c8dee2aaSAndroid Build Coastguard Worker  * If the user wants to commit to the current assignment plan, they call `assign` which:
62*c8dee2aaSAndroid Build Coastguard Worker  *     instantiates lazy proxies
63*c8dee2aaSAndroid Build Coastguard Worker  *
64*c8dee2aaSAndroid Build Coastguard Worker  *     instantantiates new surfaces for all registers that need them
65*c8dee2aaSAndroid Build Coastguard Worker  *
66*c8dee2aaSAndroid Build Coastguard Worker  *     assigns the surface for each register to all the proxies that will use it
67*c8dee2aaSAndroid Build Coastguard Worker  *
68*c8dee2aaSAndroid Build Coastguard Worker  *************************************************************************************************
69*c8dee2aaSAndroid Build Coastguard Worker  * How does instantiation failure handling work when explicitly allocating?
70*c8dee2aaSAndroid Build Coastguard Worker  *
71*c8dee2aaSAndroid Build Coastguard Worker  * In the gather usage intervals pass all the GrSurfaceProxies used in the flush should be
72*c8dee2aaSAndroid Build Coastguard Worker  * gathered (i.e., in OpsTask::gatherProxyIntervals).
73*c8dee2aaSAndroid Build Coastguard Worker  *
74*c8dee2aaSAndroid Build Coastguard Worker  * During addInterval, read-only lazy proxies are instantiated. If that fails, the resource
75*c8dee2aaSAndroid Build Coastguard Worker  * allocator will note the failure and ignore pretty much anything else until `reset`.
76*c8dee2aaSAndroid Build Coastguard Worker  *
77*c8dee2aaSAndroid Build Coastguard Worker  * During planAssignment, fully-lazy proxies are instantiated so that we can know their size for
78*c8dee2aaSAndroid Build Coastguard Worker  * budgeting purposes. If this fails, return false.
79*c8dee2aaSAndroid Build Coastguard Worker  *
80*c8dee2aaSAndroid Build Coastguard Worker  * During assign, partially-lazy proxies are instantiated and new surfaces are created for all other
81*c8dee2aaSAndroid Build Coastguard Worker  * proxies. If any of these fails, return false.
82*c8dee2aaSAndroid Build Coastguard Worker  *
83*c8dee2aaSAndroid Build Coastguard Worker  * The drawing manager will drop the flush if any proxies fail to instantiate.
84*c8dee2aaSAndroid Build Coastguard Worker  */
85*c8dee2aaSAndroid Build Coastguard Worker class GrResourceAllocator {
86*c8dee2aaSAndroid Build Coastguard Worker public:
GrResourceAllocator(GrDirectContext * dContext)87*c8dee2aaSAndroid Build Coastguard Worker     GrResourceAllocator(GrDirectContext* dContext)
88*c8dee2aaSAndroid Build Coastguard Worker             : fDContext(dContext) {}
89*c8dee2aaSAndroid Build Coastguard Worker 
90*c8dee2aaSAndroid Build Coastguard Worker     ~GrResourceAllocator();
91*c8dee2aaSAndroid Build Coastguard Worker 
curOp()92*c8dee2aaSAndroid Build Coastguard Worker     unsigned int curOp() const { return fNumOps; }
incOps()93*c8dee2aaSAndroid Build Coastguard Worker     void incOps() { fNumOps++; }
94*c8dee2aaSAndroid Build Coastguard Worker 
95*c8dee2aaSAndroid Build Coastguard Worker     /** Indicates whether a given call to addInterval represents an actual usage of the
96*c8dee2aaSAndroid Build Coastguard Worker      *  provided proxy. This is mainly here to accommodate deferred proxies attached to opsTasks.
97*c8dee2aaSAndroid Build Coastguard Worker      *  In that case we need to create an extra long interval for them (due to the upload) but
98*c8dee2aaSAndroid Build Coastguard Worker      *  don't want to count that usage/reference towards the proxy's recyclability.
99*c8dee2aaSAndroid Build Coastguard Worker      */
100*c8dee2aaSAndroid Build Coastguard Worker     enum class ActualUse : bool {
101*c8dee2aaSAndroid Build Coastguard Worker         kNo  = false,
102*c8dee2aaSAndroid Build Coastguard Worker         kYes = true
103*c8dee2aaSAndroid Build Coastguard Worker     };
104*c8dee2aaSAndroid Build Coastguard Worker 
105*c8dee2aaSAndroid Build Coastguard Worker     /** Indicates whether we allow a gpu texture assigned to a register to be recycled or not. This
106*c8dee2aaSAndroid Build Coastguard Worker      *  comes up when dealing with with Vulkan Secondary CommandBuffers since offscreens sampled
107*c8dee2aaSAndroid Build Coastguard Worker      *  into the scb will all be drawn before being sampled in the scb. This is because the scb
108*c8dee2aaSAndroid Build Coastguard Worker      *  will get submitted in a later command buffer. Thus offscreens cannot share an allocation or
109*c8dee2aaSAndroid Build Coastguard Worker      *  later reuses will overwrite earlier ones.
110*c8dee2aaSAndroid Build Coastguard Worker      */
111*c8dee2aaSAndroid Build Coastguard Worker     enum class AllowRecycling : bool {
112*c8dee2aaSAndroid Build Coastguard Worker         kNo  = false,
113*c8dee2aaSAndroid Build Coastguard Worker         kYes = true
114*c8dee2aaSAndroid Build Coastguard Worker     };
115*c8dee2aaSAndroid Build Coastguard Worker 
116*c8dee2aaSAndroid Build Coastguard Worker     // Add a usage interval from 'start' to 'end' inclusive. This is usually used for renderTargets.
117*c8dee2aaSAndroid Build Coastguard Worker     // If an existing interval already exists it will be expanded to include the new range.
118*c8dee2aaSAndroid Build Coastguard Worker     void addInterval(GrSurfaceProxy*, unsigned int start, unsigned int end, ActualUse actualUse,
119*c8dee2aaSAndroid Build Coastguard Worker                      AllowRecycling SkDEBUGCODE(, bool isDirectDstRead = false));
120*c8dee2aaSAndroid Build Coastguard Worker 
failedInstantiation()121*c8dee2aaSAndroid Build Coastguard Worker     bool failedInstantiation() const { return fFailedInstantiation; }
122*c8dee2aaSAndroid Build Coastguard Worker 
123*c8dee2aaSAndroid Build Coastguard Worker     // Generate an internal plan for resource allocation. After this you can optionally call
124*c8dee2aaSAndroid Build Coastguard Worker     // `makeBudgetHeadroom` to check whether that plan would go over our memory budget.
125*c8dee2aaSAndroid Build Coastguard Worker     // Fully-lazy proxies are also instantiated at this point so that their size can
126*c8dee2aaSAndroid Build Coastguard Worker     // be known accurately. Returns false if any lazy proxy failed to instantiate, true otherwise.
127*c8dee2aaSAndroid Build Coastguard Worker     bool planAssignment();
128*c8dee2aaSAndroid Build Coastguard Worker 
129*c8dee2aaSAndroid Build Coastguard Worker     // Figure out how much VRAM headroom this plan requires. If there's enough purgeable resources,
130*c8dee2aaSAndroid Build Coastguard Worker     // purge them and return true. Otherwise return false.
131*c8dee2aaSAndroid Build Coastguard Worker     bool makeBudgetHeadroom();
132*c8dee2aaSAndroid Build Coastguard Worker 
133*c8dee2aaSAndroid Build Coastguard Worker     // Clear all internal state in preparation for a new set of intervals.
134*c8dee2aaSAndroid Build Coastguard Worker     void reset();
135*c8dee2aaSAndroid Build Coastguard Worker 
136*c8dee2aaSAndroid Build Coastguard Worker     // Instantiate and assign resources to all proxies.
137*c8dee2aaSAndroid Build Coastguard Worker     bool assign();
138*c8dee2aaSAndroid Build Coastguard Worker 
139*c8dee2aaSAndroid Build Coastguard Worker #if GR_ALLOCATION_SPEW
140*c8dee2aaSAndroid Build Coastguard Worker     void dumpIntervals();
141*c8dee2aaSAndroid Build Coastguard Worker #endif
142*c8dee2aaSAndroid Build Coastguard Worker 
143*c8dee2aaSAndroid Build Coastguard Worker private:
144*c8dee2aaSAndroid Build Coastguard Worker     class Interval;
145*c8dee2aaSAndroid Build Coastguard Worker     class Register;
146*c8dee2aaSAndroid Build Coastguard Worker 
147*c8dee2aaSAndroid Build Coastguard Worker     // Remove dead intervals from the active list
148*c8dee2aaSAndroid Build Coastguard Worker     void expire(unsigned int curIndex);
149*c8dee2aaSAndroid Build Coastguard Worker 
150*c8dee2aaSAndroid Build Coastguard Worker     // These two methods wrap the interactions with the free pool
151*c8dee2aaSAndroid Build Coastguard Worker     void recycleRegister(Register* r);
152*c8dee2aaSAndroid Build Coastguard Worker     Register* findOrCreateRegisterFor(GrSurfaceProxy* proxy);
153*c8dee2aaSAndroid Build Coastguard Worker 
154*c8dee2aaSAndroid Build Coastguard Worker     struct FreePoolTraits {
GetKeyFreePoolTraits155*c8dee2aaSAndroid Build Coastguard Worker         static const skgpu::ScratchKey& GetKey(const Register& r) {
156*c8dee2aaSAndroid Build Coastguard Worker             return r.scratchKey();
157*c8dee2aaSAndroid Build Coastguard Worker         }
158*c8dee2aaSAndroid Build Coastguard Worker 
HashFreePoolTraits159*c8dee2aaSAndroid Build Coastguard Worker         static uint32_t Hash(const skgpu::ScratchKey& key) { return key.hash(); }
OnFreeFreePoolTraits160*c8dee2aaSAndroid Build Coastguard Worker         static void OnFree(Register* r) { }
161*c8dee2aaSAndroid Build Coastguard Worker     };
162*c8dee2aaSAndroid Build Coastguard Worker     typedef SkTMultiMap<Register, skgpu::ScratchKey, FreePoolTraits> FreePoolMultiMap;
163*c8dee2aaSAndroid Build Coastguard Worker 
164*c8dee2aaSAndroid Build Coastguard Worker     typedef skia_private::THashMap<uint32_t, Interval*, GrCheapHash> IntvlHash;
165*c8dee2aaSAndroid Build Coastguard Worker 
166*c8dee2aaSAndroid Build Coastguard Worker     struct UniqueKeyHash {
operatorUniqueKeyHash167*c8dee2aaSAndroid Build Coastguard Worker         uint32_t operator()(const skgpu::UniqueKey& key) const { return key.hash(); }
168*c8dee2aaSAndroid Build Coastguard Worker     };
169*c8dee2aaSAndroid Build Coastguard Worker     typedef skia_private::THashMap<skgpu::UniqueKey, Register*, UniqueKeyHash>
170*c8dee2aaSAndroid Build Coastguard Worker             UniqueKeyRegisterHash;
171*c8dee2aaSAndroid Build Coastguard Worker 
172*c8dee2aaSAndroid Build Coastguard Worker     // Each proxy – with some exceptions – is assigned a register. After all assignments are made,
173*c8dee2aaSAndroid Build Coastguard Worker     // another pass is performed to instantiate and assign actual surfaces to the proxies. Right
174*c8dee2aaSAndroid Build Coastguard Worker     // now these are performed in one call, but in the future they will be separable and the user
175*c8dee2aaSAndroid Build Coastguard Worker     // will be able to query re: memory cost before committing to surface creation.
176*c8dee2aaSAndroid Build Coastguard Worker     class Register {
177*c8dee2aaSAndroid Build Coastguard Worker     public:
178*c8dee2aaSAndroid Build Coastguard Worker         // It's OK to pass an invalid scratch key iff the proxy has a unique key.
179*c8dee2aaSAndroid Build Coastguard Worker         Register(GrSurfaceProxy* originatingProxy, skgpu::ScratchKey, GrResourceProvider*);
180*c8dee2aaSAndroid Build Coastguard Worker 
scratchKey()181*c8dee2aaSAndroid Build Coastguard Worker         const skgpu::ScratchKey& scratchKey() const { return fScratchKey; }
uniqueKey()182*c8dee2aaSAndroid Build Coastguard Worker         const skgpu::UniqueKey& uniqueKey() const { return fOriginatingProxy->getUniqueKey(); }
183*c8dee2aaSAndroid Build Coastguard Worker 
accountedForInBudget()184*c8dee2aaSAndroid Build Coastguard Worker         bool accountedForInBudget() const { return fAccountedForInBudget; }
setAccountedForInBudget()185*c8dee2aaSAndroid Build Coastguard Worker         void setAccountedForInBudget() { fAccountedForInBudget = true; }
186*c8dee2aaSAndroid Build Coastguard Worker 
existingSurface()187*c8dee2aaSAndroid Build Coastguard Worker         GrSurface* existingSurface() const { return fExistingSurface.get(); }
188*c8dee2aaSAndroid Build Coastguard Worker 
189*c8dee2aaSAndroid Build Coastguard Worker         // Can this register be used by other proxies after this one?
190*c8dee2aaSAndroid Build Coastguard Worker         bool isRecyclable(const GrCaps&, GrSurfaceProxy* proxy, int knownUseCount,
191*c8dee2aaSAndroid Build Coastguard Worker                           AllowRecycling) const;
192*c8dee2aaSAndroid Build Coastguard Worker 
193*c8dee2aaSAndroid Build Coastguard Worker         // Resolve the register allocation to an actual GrSurface. 'fOriginatingProxy'
194*c8dee2aaSAndroid Build Coastguard Worker         // is used to cache the allocation when a given register is used by multiple
195*c8dee2aaSAndroid Build Coastguard Worker         // proxies.
196*c8dee2aaSAndroid Build Coastguard Worker         bool instantiateSurface(GrSurfaceProxy*, GrResourceProvider*);
197*c8dee2aaSAndroid Build Coastguard Worker 
198*c8dee2aaSAndroid Build Coastguard Worker         SkDEBUGCODE(uint32_t uniqueID() const { return fUniqueID; })
199*c8dee2aaSAndroid Build Coastguard Worker 
200*c8dee2aaSAndroid Build Coastguard Worker     private:
201*c8dee2aaSAndroid Build Coastguard Worker         GrSurfaceProxy*   fOriginatingProxy;
202*c8dee2aaSAndroid Build Coastguard Worker         skgpu::ScratchKey fScratchKey; // free pool wants a reference to this.
203*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<GrSurface>  fExistingSurface; // queried from resource cache. may be null.
204*c8dee2aaSAndroid Build Coastguard Worker         bool              fAccountedForInBudget = false;
205*c8dee2aaSAndroid Build Coastguard Worker 
206*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
207*c8dee2aaSAndroid Build Coastguard Worker         uint32_t         fUniqueID;
208*c8dee2aaSAndroid Build Coastguard Worker 
209*c8dee2aaSAndroid Build Coastguard Worker         static uint32_t  CreateUniqueID();
210*c8dee2aaSAndroid Build Coastguard Worker #endif
211*c8dee2aaSAndroid Build Coastguard Worker     };
212*c8dee2aaSAndroid Build Coastguard Worker 
213*c8dee2aaSAndroid Build Coastguard Worker     class Interval {
214*c8dee2aaSAndroid Build Coastguard Worker     public:
Interval(GrSurfaceProxy * proxy,unsigned int start,unsigned int end)215*c8dee2aaSAndroid Build Coastguard Worker         Interval(GrSurfaceProxy* proxy, unsigned int start, unsigned int end)
216*c8dee2aaSAndroid Build Coastguard Worker                 : fProxy(proxy)
217*c8dee2aaSAndroid Build Coastguard Worker                 , fStart(start)
218*c8dee2aaSAndroid Build Coastguard Worker                 , fEnd(end) {
219*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(proxy);
220*c8dee2aaSAndroid Build Coastguard Worker             SkDEBUGCODE(fUniqueID = CreateUniqueID());
221*c8dee2aaSAndroid Build Coastguard Worker #if GR_TRACK_INTERVAL_CREATION
222*c8dee2aaSAndroid Build Coastguard Worker             SkString proxyStr = proxy->dump();
223*c8dee2aaSAndroid Build Coastguard Worker             SkDebugf("New intvl %d: %s [%d, %d]\n", fUniqueID, proxyStr.c_str(), start, end);
224*c8dee2aaSAndroid Build Coastguard Worker #endif
225*c8dee2aaSAndroid Build Coastguard Worker         }
226*c8dee2aaSAndroid Build Coastguard Worker 
proxy()227*c8dee2aaSAndroid Build Coastguard Worker         const GrSurfaceProxy* proxy() const { return fProxy; }
proxy()228*c8dee2aaSAndroid Build Coastguard Worker         GrSurfaceProxy* proxy() { return fProxy; }
229*c8dee2aaSAndroid Build Coastguard Worker 
start()230*c8dee2aaSAndroid Build Coastguard Worker         unsigned int start() const { return fStart; }
end()231*c8dee2aaSAndroid Build Coastguard Worker         unsigned int end() const { return fEnd; }
232*c8dee2aaSAndroid Build Coastguard Worker 
setNext(Interval * next)233*c8dee2aaSAndroid Build Coastguard Worker         void setNext(Interval* next) { fNext = next; }
next()234*c8dee2aaSAndroid Build Coastguard Worker         const Interval* next() const { return fNext; }
next()235*c8dee2aaSAndroid Build Coastguard Worker         Interval* next() { return fNext; }
236*c8dee2aaSAndroid Build Coastguard Worker 
getRegister()237*c8dee2aaSAndroid Build Coastguard Worker         Register* getRegister() const { return fRegister; }
setRegister(Register * r)238*c8dee2aaSAndroid Build Coastguard Worker         void setRegister(Register* r) { fRegister = r; }
239*c8dee2aaSAndroid Build Coastguard Worker 
addUse()240*c8dee2aaSAndroid Build Coastguard Worker         void addUse() { fUses++; }
uses()241*c8dee2aaSAndroid Build Coastguard Worker         int uses() const { return fUses; }
242*c8dee2aaSAndroid Build Coastguard Worker 
extendEnd(unsigned int newEnd)243*c8dee2aaSAndroid Build Coastguard Worker         void extendEnd(unsigned int newEnd) {
244*c8dee2aaSAndroid Build Coastguard Worker             if (newEnd > fEnd) {
245*c8dee2aaSAndroid Build Coastguard Worker                 fEnd = newEnd;
246*c8dee2aaSAndroid Build Coastguard Worker #if GR_TRACK_INTERVAL_CREATION
247*c8dee2aaSAndroid Build Coastguard Worker                 SkDebugf("intvl %d: extending from %d to %d\n", fUniqueID, fEnd, newEnd);
248*c8dee2aaSAndroid Build Coastguard Worker #endif
249*c8dee2aaSAndroid Build Coastguard Worker             }
250*c8dee2aaSAndroid Build Coastguard Worker         }
251*c8dee2aaSAndroid Build Coastguard Worker 
disallowRecycling()252*c8dee2aaSAndroid Build Coastguard Worker         void disallowRecycling() {
253*c8dee2aaSAndroid Build Coastguard Worker             fAllowRecycling = AllowRecycling::kNo;
254*c8dee2aaSAndroid Build Coastguard Worker         }
allowRecycling()255*c8dee2aaSAndroid Build Coastguard Worker         AllowRecycling allowRecycling() const { return fAllowRecycling; }
256*c8dee2aaSAndroid Build Coastguard Worker 
257*c8dee2aaSAndroid Build Coastguard Worker         SkDEBUGCODE(uint32_t uniqueID() const { return fUniqueID; })
258*c8dee2aaSAndroid Build Coastguard Worker 
259*c8dee2aaSAndroid Build Coastguard Worker     private:
260*c8dee2aaSAndroid Build Coastguard Worker         GrSurfaceProxy*  fProxy;
261*c8dee2aaSAndroid Build Coastguard Worker         unsigned int     fStart;
262*c8dee2aaSAndroid Build Coastguard Worker         unsigned int     fEnd;
263*c8dee2aaSAndroid Build Coastguard Worker         Interval*        fNext = nullptr;
264*c8dee2aaSAndroid Build Coastguard Worker         unsigned int     fUses = 0;
265*c8dee2aaSAndroid Build Coastguard Worker         Register*        fRegister = nullptr;
266*c8dee2aaSAndroid Build Coastguard Worker         AllowRecycling   fAllowRecycling = AllowRecycling::kYes;
267*c8dee2aaSAndroid Build Coastguard Worker 
268*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
269*c8dee2aaSAndroid Build Coastguard Worker         uint32_t        fUniqueID;
270*c8dee2aaSAndroid Build Coastguard Worker 
271*c8dee2aaSAndroid Build Coastguard Worker         static uint32_t CreateUniqueID();
272*c8dee2aaSAndroid Build Coastguard Worker #endif
273*c8dee2aaSAndroid Build Coastguard Worker     };
274*c8dee2aaSAndroid Build Coastguard Worker 
275*c8dee2aaSAndroid Build Coastguard Worker     class IntervalList {
276*c8dee2aaSAndroid Build Coastguard Worker     public:
277*c8dee2aaSAndroid Build Coastguard Worker         IntervalList() = default;
278*c8dee2aaSAndroid Build Coastguard Worker         // N.B. No need for a destructor – the arena allocator will clean up for us.
279*c8dee2aaSAndroid Build Coastguard Worker 
empty()280*c8dee2aaSAndroid Build Coastguard Worker         bool empty() const {
281*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(SkToBool(fHead) == SkToBool(fTail));
282*c8dee2aaSAndroid Build Coastguard Worker             return !SkToBool(fHead);
283*c8dee2aaSAndroid Build Coastguard Worker         }
peekHead()284*c8dee2aaSAndroid Build Coastguard Worker         const Interval* peekHead() const { return fHead; }
peekHead()285*c8dee2aaSAndroid Build Coastguard Worker         Interval* peekHead() { return fHead; }
286*c8dee2aaSAndroid Build Coastguard Worker         Interval* popHead();
287*c8dee2aaSAndroid Build Coastguard Worker         void insertByIncreasingStart(Interval*);
288*c8dee2aaSAndroid Build Coastguard Worker         void insertByIncreasingEnd(Interval*);
289*c8dee2aaSAndroid Build Coastguard Worker 
290*c8dee2aaSAndroid Build Coastguard Worker     private:
291*c8dee2aaSAndroid Build Coastguard Worker         SkDEBUGCODE(void validate() const;)
292*c8dee2aaSAndroid Build Coastguard Worker 
293*c8dee2aaSAndroid Build Coastguard Worker         Interval* fHead = nullptr;
294*c8dee2aaSAndroid Build Coastguard Worker         Interval* fTail = nullptr;
295*c8dee2aaSAndroid Build Coastguard Worker     };
296*c8dee2aaSAndroid Build Coastguard Worker 
297*c8dee2aaSAndroid Build Coastguard Worker     // Compositing use cases can create > 80 intervals.
298*c8dee2aaSAndroid Build Coastguard Worker     static const int kInitialArenaSize = 128 * sizeof(Interval);
299*c8dee2aaSAndroid Build Coastguard Worker 
300*c8dee2aaSAndroid Build Coastguard Worker     GrDirectContext*             fDContext;
301*c8dee2aaSAndroid Build Coastguard Worker     FreePoolMultiMap             fFreePool;          // Recently created/used GrSurfaces
302*c8dee2aaSAndroid Build Coastguard Worker     IntvlHash                    fIntvlHash;         // All the intervals, hashed by proxyID
303*c8dee2aaSAndroid Build Coastguard Worker 
304*c8dee2aaSAndroid Build Coastguard Worker     IntervalList                 fIntvlList;         // All the intervals sorted by increasing start
305*c8dee2aaSAndroid Build Coastguard Worker     IntervalList                 fActiveIntvls;      // List of live intervals during assignment
306*c8dee2aaSAndroid Build Coastguard Worker                                                      // (sorted by increasing end)
307*c8dee2aaSAndroid Build Coastguard Worker     IntervalList                 fFinishedIntvls;    // All the completed intervals
308*c8dee2aaSAndroid Build Coastguard Worker                                                      // (sorted by increasing start)
309*c8dee2aaSAndroid Build Coastguard Worker     UniqueKeyRegisterHash        fUniqueKeyRegisters;
310*c8dee2aaSAndroid Build Coastguard Worker     unsigned int                 fNumOps = 0;
311*c8dee2aaSAndroid Build Coastguard Worker 
312*c8dee2aaSAndroid Build Coastguard Worker     SkDEBUGCODE(bool             fPlanned = false;)
313*c8dee2aaSAndroid Build Coastguard Worker     SkDEBUGCODE(bool             fAssigned = false;)
314*c8dee2aaSAndroid Build Coastguard Worker 
315*c8dee2aaSAndroid Build Coastguard Worker     SkSTArenaAllocWithReset<kInitialArenaSize>   fInternalAllocator; // intervals & registers
316*c8dee2aaSAndroid Build Coastguard Worker     bool                                         fFailedInstantiation = false;
317*c8dee2aaSAndroid Build Coastguard Worker };
318*c8dee2aaSAndroid Build Coastguard Worker 
319*c8dee2aaSAndroid Build Coastguard Worker #endif // GrResourceAllocator_DEFINED
320