• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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