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