1 /* 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 8 #ifndef GrResourceAllocator_DEFINED 9 #define GrResourceAllocator_DEFINED 10 11 #include "GrSurfaceProxy.h" 12 #include "SkTDynamicHash.h" 13 14 class GrResourceProvider; 15 16 /* 17 * The ResourceAllocator explicitly distributes GPU resources at flush time. It operates by 18 * being given the usage intervals of the various proxies. It keeps these intervals in a singly 19 * linked list sorted by increasing start index. (It also maintains a hash table from proxyID 20 * to interval to find proxy reuse). When it comes time to allocate the resources it 21 * traverses the sorted list and: 22 * removes intervals from the active list that have completed (returning their GrSurfaces 23 * to the free pool) 24 25 * allocates a new resource (preferably from the free pool) for the new interval 26 * adds the new interval to the active list (that is sorted by increasing end index) 27 * 28 * Note: the op indices (used in the usage intervals) come from the order of the ops in 29 * their opLists after the opList DAG has been linearized. 30 */ 31 class GrResourceAllocator { 32 public: GrResourceAllocator(GrResourceProvider * resourceProvider)33 GrResourceAllocator(GrResourceProvider* resourceProvider) 34 : fResourceProvider(resourceProvider) { 35 } 36 curOp()37 unsigned int curOp() const { return fNumOps; } incOps()38 void incOps() { fNumOps++; } numOps()39 unsigned int numOps() const { return fNumOps; } 40 41 // Add a usage interval from start to end inclusive. This is usually used for renderTargets. 42 // If an existing interval already exists it will be expanded to include the new range. 43 void addInterval(GrSurfaceProxy*, unsigned int start, unsigned int end); 44 45 // Add an interval that spans just the current op. Usually this is for texture uses. 46 // If an existing interval already exists it will be expanded to include the new operation. addInterval(GrSurfaceProxy * proxy)47 void addInterval(GrSurfaceProxy* proxy) { 48 this->addInterval(proxy, fNumOps, fNumOps); 49 } 50 51 void assign(); 52 53 private: 54 class Interval; 55 56 // Remove dead intervals from the active list 57 void expire(unsigned int curIndex); 58 59 // These two methods wrap the interactions with the free pool 60 void freeUpSurface(GrSurface* surface); 61 sk_sp<GrSurface> findSurfaceFor(GrSurfaceProxy* proxy); 62 63 struct UniqueHashTraits { GetKeyUniqueHashTraits64 static const GrUniqueKey& GetKey(const GrSurface& s) { return s.getUniqueKey(); } 65 HashUniqueHashTraits66 static uint32_t Hash(const GrUniqueKey& key) { return key.hash(); } 67 }; 68 typedef SkTDynamicHash<GrSurface, GrUniqueKey, UniqueHashTraits> UniqueHash; 69 typedef SkTDynamicHash<Interval, unsigned int> IntvlHash; 70 71 class Interval { 72 public: Interval(GrSurfaceProxy * proxy,unsigned int start,unsigned int end)73 Interval(GrSurfaceProxy* proxy, unsigned int start, unsigned int end) 74 : fProxy(proxy) 75 , fProxyID(proxy->uniqueID().asUInt()) 76 , fStart(start) 77 , fEnd(end) 78 , fNext(nullptr) { 79 SkASSERT(proxy); 80 } 81 82 // for SkTDynamicHash GetKey(const Interval & intvl)83 static const uint32_t& GetKey(const Interval& intvl) { 84 return intvl.fProxyID; 85 } Hash(const uint32_t & key)86 static uint32_t Hash(const uint32_t& key) { return key; } 87 88 GrSurfaceProxy* fProxy; 89 uint32_t fProxyID; // This is here b.c. DynamicHash requires a ref to the key 90 unsigned int fStart; 91 unsigned int fEnd; 92 Interval* fNext; 93 }; 94 95 class IntervalList { 96 public: 97 IntervalList() = default; ~IntervalList()98 ~IntervalList() { 99 while (fHead) { 100 Interval* temp = fHead; 101 fHead = temp->fNext; 102 delete temp; 103 } 104 } 105 empty()106 bool empty() const { return !SkToBool(fHead); } peekHead()107 const Interval* peekHead() const { return fHead; } 108 Interval* popHead(); 109 void insertByIncreasingStart(Interval*); 110 void insertByIncreasingEnd(Interval*); 111 112 private: 113 Interval* fHead = nullptr; 114 }; 115 116 GrResourceProvider* fResourceProvider; 117 UniqueHash fFreePool; // Recently created/used GrSurfaces 118 IntvlHash fIntvlHash; // All the intervals, hashed by proxyID 119 120 IntervalList fIntvlList; // All the intervals sorted by increasing start 121 IntervalList fActiveIntvls; // List of live intervals during assignment 122 // (sorted by increasing end) 123 unsigned int fNumOps = 0; 124 SkDEBUGCODE(bool fAssigned = false;) 125 }; 126 127 #endif // GrResourceAllocator_DEFINED 128