ccpr: Cleanup on-flush path stats
Adds a wrapper struct to limit the number of free variables. Fixes a bug where we preallocated draw instances for clip paths. Counts conic weights and preallocates their buffer as well. Bug: skia: Change-Id: I72779c9017322a0dc64461c8cb927f975406b9af Reviewed-on: https://skia-review.googlesource.com/126844 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Chris Dalton <csmartdalton@google.com>
This commit is contained in:
parent
e8f9e913b6
commit
3917b1e9bc
@ -49,9 +49,10 @@ public:
|
||||
bool operator==(const PrimitiveTallies&);
|
||||
};
|
||||
|
||||
GrCCGeometry(int numSkPoints = 0, int numSkVerbs = 0)
|
||||
GrCCGeometry(int numSkPoints = 0, int numSkVerbs = 0, int numConicWeights = 0)
|
||||
: fPoints(numSkPoints * 3) // Reserve for a 3x expansion in points and verbs.
|
||||
, fVerbs(numSkVerbs * 3) {}
|
||||
, fVerbs(numSkVerbs * 3)
|
||||
, fConicWeights(numConicWeights * 3/2) {}
|
||||
|
||||
const SkTArray<SkPoint, true>& points() const { SkASSERT(!fBuildingContour); return fPoints; }
|
||||
const SkTArray<Verb, true>& verbs() const { SkASSERT(!fBuildingContour); return fVerbs; }
|
||||
@ -124,8 +125,8 @@ private:
|
||||
SkDEBUGCODE(bool fBuildingContour = false);
|
||||
|
||||
SkSTArray<128, SkPoint, true> fPoints;
|
||||
SkSTArray<32, float, true> fConicWeights;
|
||||
SkSTArray<128, Verb, true> fVerbs;
|
||||
SkSTArray<32, float, true> fConicWeights;
|
||||
};
|
||||
|
||||
inline void GrCCGeometry::PrimitiveTallies::operator+=(const PrimitiveTallies& b) {
|
||||
|
@ -21,13 +21,13 @@
|
||||
using TriPointInstance = GrCCCoverageProcessor::TriPointInstance;
|
||||
using QuadPointInstance = GrCCCoverageProcessor::QuadPointInstance;
|
||||
|
||||
GrCCPathParser::GrCCPathParser(int maxTotalPaths, int maxPathPoints, int numSkPoints,
|
||||
int numSkVerbs)
|
||||
: fLocalDevPtsBuffer(maxPathPoints + 1) // Overallocate by one point to accomodate for
|
||||
// overflow with Sk4f. (See parsePath.)
|
||||
, fGeometry(numSkPoints, numSkVerbs)
|
||||
, fPathsInfo(maxTotalPaths)
|
||||
, fScissorSubBatches(maxTotalPaths)
|
||||
GrCCPathParser::GrCCPathParser(int numPaths, const PathStats& pathStats)
|
||||
// Overallocate by one point to accomodate for overflow with Sk4f. (See parsePath.)
|
||||
: fLocalDevPtsBuffer(pathStats.fMaxPointsPerPath + 1)
|
||||
, fGeometry(pathStats.fNumTotalSkPoints, pathStats.fNumTotalSkVerbs,
|
||||
pathStats.fNumTotalConicWeights)
|
||||
, fPathsInfo(numPaths)
|
||||
, fScissorSubBatches(numPaths)
|
||||
, fTotalPrimitiveCounts{PrimitiveTallies(), PrimitiveTallies()} {
|
||||
// Batches decide what to draw by looking where the previous one ended. Define initial batches
|
||||
// that "end" at the beginning of the data. These will not be drawn, but will only be be read by
|
||||
|
@ -10,9 +10,11 @@
|
||||
|
||||
#include "GrMesh.h"
|
||||
#include "GrNonAtomicRef.h"
|
||||
#include "GrTessellator.h"
|
||||
#include "SkPath.h"
|
||||
#include "SkPathPriv.h"
|
||||
#include "SkRect.h"
|
||||
#include "SkRefCnt.h"
|
||||
#include "GrTessellator.h"
|
||||
#include "ccpr/GrCCCoverageProcessor.h"
|
||||
#include "ccpr/GrCCGeometry.h"
|
||||
#include "ops/GrDrawOp.h"
|
||||
@ -32,7 +34,16 @@ public:
|
||||
enum class ScissorMode : int { kNonScissored = 0, kScissored = 1 };
|
||||
static constexpr int kNumScissorModes = 2;
|
||||
|
||||
GrCCPathParser(int maxTotalPaths, int maxPathPoints, int numSkPoints, int numSkVerbs);
|
||||
struct PathStats {
|
||||
int fMaxPointsPerPath = 0;
|
||||
int fNumTotalSkPoints = 0;
|
||||
int fNumTotalSkVerbs = 0;
|
||||
int fNumTotalConicWeights = 0;
|
||||
|
||||
void statPath(const SkPath&);
|
||||
};
|
||||
|
||||
GrCCPathParser(int numPaths, const PathStats&);
|
||||
|
||||
~GrCCPathParser() {
|
||||
// Enforce the contract that the client always calls saveParsedPath or discardParsedPath.
|
||||
@ -151,4 +162,11 @@ private:
|
||||
mutable SkSTArray<32, GrPipeline::DynamicState> fDynamicStatesScratchBuffer;
|
||||
};
|
||||
|
||||
inline void GrCCPathParser::PathStats::statPath(const SkPath& path) {
|
||||
fMaxPointsPerPath = SkTMax(fMaxPointsPerPath, path.countPoints());
|
||||
fNumTotalSkPoints += path.countPoints();
|
||||
fNumTotalSkVerbs += path.countVerbs();
|
||||
fNumTotalConicWeights += SkPathPriv::ConicWeightCnt(path);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -254,6 +254,7 @@ void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlush
|
||||
using PathInstance = GrCCPathProcessor::Instance;
|
||||
|
||||
SkASSERT(!fFlushing);
|
||||
SkASSERT(fFlushingRTPathIters.empty());
|
||||
SkASSERT(!fPerFlushIndexBuffer);
|
||||
SkASSERT(!fPerFlushVertexBuffer);
|
||||
SkASSERT(!fPerFlushInstanceBuffer);
|
||||
@ -267,40 +268,38 @@ void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlush
|
||||
|
||||
fPerFlushResourcesAreValid = false;
|
||||
|
||||
// Count the paths that are being flushed.
|
||||
int maxTotalPaths = 0, maxPathPoints = 0, numSkPoints = 0, numSkVerbs = 0;
|
||||
SkDEBUGCODE(int numClipPaths = 0);
|
||||
// Count up the paths about to be flushed so we can preallocate buffers.
|
||||
int numPathDraws = 0;
|
||||
int numClipPaths = 0;
|
||||
GrCCPathParser::PathStats flushingPathStats;
|
||||
fFlushingRTPathIters.reserve(numOpListIDs);
|
||||
for (int i = 0; i < numOpListIDs; ++i) {
|
||||
auto it = fRTPendingPathsMap.find(opListIDs[i]);
|
||||
if (fRTPendingPathsMap.end() == it) {
|
||||
auto iter = fRTPendingPathsMap.find(opListIDs[i]);
|
||||
if (fRTPendingPathsMap.end() == iter) {
|
||||
continue;
|
||||
}
|
||||
const RTPendingPaths& rtPendingPaths = it->second;
|
||||
const RTPendingPaths& rtPendingPaths = iter->second;
|
||||
|
||||
SkTInternalLList<DrawPathsOp>::Iter drawOpsIter;
|
||||
drawOpsIter.init(rtPendingPaths.fDrawOps,
|
||||
SkTInternalLList<DrawPathsOp>::Iter::kHead_IterStart);
|
||||
while (DrawPathsOp* op = drawOpsIter.get()) {
|
||||
for (const DrawPathsOp::SingleDraw* draw = op->head(); draw; draw = draw->fNext) {
|
||||
++maxTotalPaths;
|
||||
maxPathPoints = SkTMax(draw->fPath.countPoints(), maxPathPoints);
|
||||
numSkPoints += draw->fPath.countPoints();
|
||||
numSkVerbs += draw->fPath.countVerbs();
|
||||
++numPathDraws;
|
||||
flushingPathStats.statPath(draw->fPath);
|
||||
}
|
||||
drawOpsIter.next();
|
||||
}
|
||||
|
||||
maxTotalPaths += rtPendingPaths.fClipPaths.size();
|
||||
SkDEBUGCODE(numClipPaths += rtPendingPaths.fClipPaths.size());
|
||||
numClipPaths += rtPendingPaths.fClipPaths.size();
|
||||
for (const auto& clipsIter : rtPendingPaths.fClipPaths) {
|
||||
const SkPath& path = clipsIter.second.deviceSpacePath();
|
||||
maxPathPoints = SkTMax(path.countPoints(), maxPathPoints);
|
||||
numSkPoints += path.countPoints();
|
||||
numSkVerbs += path.countVerbs();
|
||||
flushingPathStats.statPath(clipsIter.second.deviceSpacePath());
|
||||
}
|
||||
|
||||
fFlushingRTPathIters.push_back(std::move(iter));
|
||||
}
|
||||
|
||||
if (!maxTotalPaths) {
|
||||
if (0 == numPathDraws + numClipPaths) {
|
||||
return; // Nothing to draw.
|
||||
}
|
||||
|
||||
@ -318,7 +317,7 @@ void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlush
|
||||
}
|
||||
|
||||
fPerFlushInstanceBuffer =
|
||||
onFlushRP->makeBuffer(kVertex_GrBufferType, maxTotalPaths * sizeof(PathInstance));
|
||||
onFlushRP->makeBuffer(kVertex_GrBufferType, numPathDraws * sizeof(PathInstance));
|
||||
if (!fPerFlushInstanceBuffer) {
|
||||
SkDebugf("WARNING: failed to allocate path instance buffer. No paths will be drawn.\n");
|
||||
return;
|
||||
@ -328,35 +327,31 @@ void GrCoverageCountingPathRenderer::preFlush(GrOnFlushResourceProvider* onFlush
|
||||
SkASSERT(pathInstanceData);
|
||||
int pathInstanceIdx = 0;
|
||||
|
||||
fPerFlushPathParser = sk_make_sp<GrCCPathParser>(maxTotalPaths, maxPathPoints, numSkPoints,
|
||||
numSkVerbs);
|
||||
SkDEBUGCODE(int skippedTotalPaths = 0);
|
||||
fPerFlushPathParser = sk_make_sp<GrCCPathParser>(numPathDraws + numClipPaths,
|
||||
flushingPathStats);
|
||||
SkDEBUGCODE(int numSkippedPaths = 0);
|
||||
|
||||
// Allocate atlas(es) and fill out GPU instance buffers.
|
||||
for (int i = 0; i < numOpListIDs; ++i) {
|
||||
auto it = fRTPendingPathsMap.find(opListIDs[i]);
|
||||
if (fRTPendingPathsMap.end() == it) {
|
||||
continue;
|
||||
}
|
||||
RTPendingPaths& rtPendingPaths = it->second;
|
||||
for (const auto& iter : fFlushingRTPathIters) {
|
||||
RTPendingPaths* rtPendingPaths = &iter->second;
|
||||
|
||||
SkTInternalLList<DrawPathsOp>::Iter drawOpsIter;
|
||||
drawOpsIter.init(rtPendingPaths.fDrawOps,
|
||||
drawOpsIter.init(rtPendingPaths->fDrawOps,
|
||||
SkTInternalLList<DrawPathsOp>::Iter::kHead_IterStart);
|
||||
while (DrawPathsOp* op = drawOpsIter.get()) {
|
||||
pathInstanceIdx = op->setupResources(onFlushRP, pathInstanceData, pathInstanceIdx);
|
||||
drawOpsIter.next();
|
||||
SkDEBUGCODE(skippedTotalPaths += op->numSkippedInstances_debugOnly());
|
||||
SkDEBUGCODE(numSkippedPaths += op->numSkippedInstances_debugOnly());
|
||||
}
|
||||
|
||||
for (auto& clipsIter : rtPendingPaths.fClipPaths) {
|
||||
for (auto& clipsIter : rtPendingPaths->fClipPaths) {
|
||||
clipsIter.second.placePathInAtlas(this, onFlushRP, fPerFlushPathParser.get());
|
||||
}
|
||||
}
|
||||
|
||||
fPerFlushInstanceBuffer->unmap();
|
||||
|
||||
SkASSERT(pathInstanceIdx == maxTotalPaths - skippedTotalPaths - numClipPaths);
|
||||
SkASSERT(pathInstanceIdx == numPathDraws - numSkippedPaths);
|
||||
|
||||
if (!fPerFlushAtlases.empty()) {
|
||||
auto coverageCountBatchID = fPerFlushPathParser->closeCurrentBatch();
|
||||
@ -528,8 +523,9 @@ void GrCoverageCountingPathRenderer::postFlush(GrDeferredUploadToken, const uint
|
||||
fPerFlushVertexBuffer.reset();
|
||||
fPerFlushIndexBuffer.reset();
|
||||
// We wait to erase these until after flush, once Ops and FPs are done accessing their data.
|
||||
for (int i = 0; i < numOpListIDs; ++i) {
|
||||
fRTPendingPathsMap.erase(opListIDs[i]);
|
||||
for (const auto& iter : fFlushingRTPathIters) {
|
||||
fRTPendingPathsMap.erase(iter);
|
||||
}
|
||||
fFlushingRTPathIters.reset();
|
||||
SkDEBUGCODE(fFlushing = false);
|
||||
}
|
||||
|
@ -220,6 +220,7 @@ private:
|
||||
|
||||
// A map from render target ID to the individual render target's pending paths.
|
||||
std::map<uint32_t, RTPendingPaths> fRTPendingPathsMap;
|
||||
SkSTArray<4, std::map<uint32_t, RTPendingPaths>::iterator> fFlushingRTPathIters;
|
||||
SkDEBUGCODE(int fPendingDrawOpsCount = 0);
|
||||
|
||||
sk_sp<const GrBuffer> fPerFlushIndexBuffer;
|
||||
|
Loading…
Reference in New Issue
Block a user