Make the intervals in GrResourceAllocator use SkArenaAlloc
Change-Id: I3190396fe34c01c232654fcb225dbf76df3137b4
Reviewed-on: https://skia-review.googlesource.com/66463
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index 6076609..9b15f3c 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -171,12 +171,12 @@
}
#endif
-#ifdef MDB_ALLOC_RESOURCES
GrResourceAllocator alloc(fContext->resourceProvider());
for (int i = 0; i < fOpLists.count(); ++i) {
fOpLists[i]->gatherProxyIntervals(&alloc);
}
+#ifdef MDB_ALLOC_RESOURCES
alloc.assign();
#endif
diff --git a/src/gpu/GrRenderTargetOpList.cpp b/src/gpu/GrRenderTargetOpList.cpp
index af870ca..09486c7 100644
--- a/src/gpu/GrRenderTargetOpList.cpp
+++ b/src/gpu/GrRenderTargetOpList.cpp
@@ -257,6 +257,10 @@
}
void GrRenderTargetOpList::gatherProxyIntervals(GrResourceAllocator* alloc) const {
+ if (!fRecordedOps.count()) {
+ return;
+ }
+
unsigned int cur = alloc->numOps();
// Add the interval for all the writes to this opList's target
@@ -266,12 +270,12 @@
alloc->addInterval(p);
};
for (int i = 0; i < fRecordedOps.count(); ++i) {
- SkASSERT(alloc->curOp() == cur+i);
-
const GrOp* op = fRecordedOps[i].fOp.get(); // only diff from the GrTextureOpList version
- op->visitProxies(gather);
+ if (op) {
+ op->visitProxies(gather);
- alloc->incOps();
+ alloc->incOps();
+ }
}
}
diff --git a/src/gpu/GrResourceAllocator.cpp b/src/gpu/GrResourceAllocator.cpp
index ba62854..62f780b 100644
--- a/src/gpu/GrResourceAllocator.cpp
+++ b/src/gpu/GrResourceAllocator.cpp
@@ -17,13 +17,19 @@
if (Interval* intvl = fIntvlHash.find(proxy->uniqueID().asUInt())) {
// Revise the interval for an existing use
- SkASSERT(intvl->fEnd < start);
+ //SkASSERT(intvl->fEnd <= end);
intvl->fEnd = end;
return;
}
- // TODO: given the usage pattern an arena allocation scheme would work well here
- Interval* newIntvl = new Interval(proxy, start, end);
+ Interval* newIntvl;
+ if (fFreeIntervalList) {
+ newIntvl = fFreeIntervalList;
+ fFreeIntervalList = newIntvl->fNext;
+ newIntvl->resetTo(proxy, start, end);
+ } else {
+ newIntvl = fIntervalAllocator.make<Interval>(proxy, start, end);
+ }
fIntvlList.insertByIncreasingStart(newIntvl);
fIntvlHash.add(newIntvl);
@@ -109,7 +115,10 @@
while (!fActiveIntvls.empty() && fActiveIntvls.peekHead()->fEnd < curIndex) {
Interval* temp = fActiveIntvls.popHead();
this->freeUpSurface(temp->fProxy->priv().peekSurface());
- delete temp;
+
+ // Add temp to the free interval list so it can be reused
+ temp->fNext = fFreeIntervalList;
+ fFreeIntervalList = temp;
}
}
diff --git a/src/gpu/GrResourceAllocator.h b/src/gpu/GrResourceAllocator.h
index 966359c..3be4836 100644
--- a/src/gpu/GrResourceAllocator.h
+++ b/src/gpu/GrResourceAllocator.h
@@ -11,6 +11,8 @@
#include "GrGpuResourcePriv.h"
#include "GrSurface.h"
#include "GrSurfaceProxy.h"
+
+#include "SkArenaAlloc.h"
#include "SkTDynamicHash.h"
#include "SkTMultiMap.h"
@@ -86,6 +88,16 @@
SkASSERT(proxy);
}
+ void resetTo(GrSurfaceProxy* proxy, unsigned int start, unsigned int end) {
+ SkASSERT(proxy);
+
+ fProxy = proxy;
+ fProxyID = proxy->uniqueID().asUInt();
+ fStart = start;
+ fEnd = end;
+ fNext = nullptr;
+ }
+
// for SkTDynamicHash
static const uint32_t& GetKey(const Interval& intvl) {
return intvl.fProxyID;
@@ -103,11 +115,8 @@
public:
IntervalList() = default;
~IntervalList() {
- while (fHead) {
- Interval* temp = fHead;
- fHead = temp->fNext;
- delete temp;
- }
+ // The only time we delete an IntervalList is in the GrResourceAllocator dtor.
+ // Since the arena allocator will clean up for us we don't bother here.
}
bool empty() const { return !SkToBool(fHead); }
@@ -120,6 +129,9 @@
Interval* fHead = nullptr;
};
+ // Gathered statistics indicate that 99% of flushes will be covered by <= 12 Intervals
+ static const int kInitialArenaSize = 12 * sizeof(Interval);
+
GrResourceProvider* fResourceProvider;
FreePoolMultiMap fFreePool; // Recently created/used GrSurfaces
IntvlHash fIntvlHash; // All the intervals, hashed by proxyID
@@ -129,6 +141,10 @@
// (sorted by increasing end)
unsigned int fNumOps = 0;
SkDEBUGCODE(bool fAssigned = false;)
+
+ char fStorage[kInitialArenaSize];
+ SkArenaAlloc fIntervalAllocator { fStorage, kInitialArenaSize, 0 };
+ Interval* fFreeIntervalList = nullptr;
};
#endif // GrResourceAllocator_DEFINED
diff --git a/src/gpu/GrTextureOpList.cpp b/src/gpu/GrTextureOpList.cpp
index cf00309..9a3d15b 100644
--- a/src/gpu/GrTextureOpList.cpp
+++ b/src/gpu/GrTextureOpList.cpp
@@ -124,6 +124,10 @@
}
void GrTextureOpList::gatherProxyIntervals(GrResourceAllocator* alloc) const {
+ if (!fRecordedOps.count()) {
+ return;
+ }
+
unsigned int cur = alloc->numOps();
// Add the interval for all the writes to this opList's target
@@ -133,12 +137,12 @@
alloc->addInterval(p);
};
for (int i = 0; i < fRecordedOps.count(); ++i) {
- SkASSERT(alloc->curOp() == cur+i);
-
const GrOp* op = fRecordedOps[i].get(); // only diff from the GrRenderTargetOpList version
- op->visitProxies(gather);
+ if (op) {
+ op->visitProxies(gather);
- alloc->incOps();
+ alloc->incOps();
+ }
}
}