Reland "ccpr: Rework the path cache to support sporadic flushing"
This is a reland of d6fa45472cb82b7d8e58d0437f7723c672488b8b
Original change's description:
> ccpr: Rework the path cache to support sporadic flushing
>
> Removes the notion of a stashed atlas that we store from the previous
> flush. Now we just cache every atlas we ever render. Cached atlases
> can either be 16-bit or 8-bit.
>
> The "reuse" and "animation" cases should both behave exactly the same
> as before: Where before we would copy from the stashed atlas to 8-bit
> atlases, we now copy from a cached 16-bit atlas and then invalidate
> it. Where before we would recycle the stashed atlas's backing texture
> object, we now recycle this same texture object from an invalidated
> 16-bit cached atlas.
>
> The main difference is that cases like tiled rendering now work. If
> you draw your whole scene in one flush, you still get one big 16-bit
> cached atlas, just like the "stashed atlas" implementation. But if you
> draw your scene in tiles, you now get lots of little cached 16-bit
> atlases, which can be reused and eventually copied to 8-bit atlases.
>
> Bug: skia:8462
> Change-Id: Ibae65febb948230aaaf1f1361eef9c8f06ebef18
> Reviewed-on: https://skia-review.googlesource.com/c/179991
> Commit-Queue: Chris Dalton <csmartdalton@google.com>
> Reviewed-by: Robert Phillips <robertphillips@google.com>
Bug: skia:8462
Change-Id: I2f64b0c37e2cd644a202dfc786366dda5d238391
Reviewed-on: https://skia-review.googlesource.com/c/181450
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/src/gpu/ccpr/GrCCPerFlushResources.h b/src/gpu/ccpr/GrCCPerFlushResources.h
index 132068f..f363c16 100644
--- a/src/gpu/ccpr/GrCCPerFlushResources.h
+++ b/src/gpu/ccpr/GrCCPerFlushResources.h
@@ -14,6 +14,7 @@
#include "ccpr/GrCCStroker.h"
#include "ccpr/GrCCPathProcessor.h"
+class GrCCPathCache;
class GrCCPathCacheEntry;
class GrOnFlushResourceProvider;
class GrShape;
@@ -53,7 +54,8 @@
return 0 == fNumCachedPaths + fNumCopiedPaths[kFillIdx] + fNumCopiedPaths[kStrokeIdx] +
fNumRenderedPaths[kFillIdx] + fNumRenderedPaths[kStrokeIdx] + fNumClipPaths;
}
- void convertCopiesToRenders();
+ // Converts the copies to normal cached draws.
+ void cancelCopies();
};
/**
@@ -67,22 +69,19 @@
bool isMapped() const { return SkToBool(fPathInstanceData); }
- // Copies a path out of the the previous flush's stashed mainline coverage count atlas, and into
- // a cached, 8-bit, literal-coverage atlas. The actual source texture to copy from will be
- // provided at the time finalize() is called.
- GrCCAtlas* copyPathToCachedAtlas(const GrCCPathCacheEntry&, GrCCPathProcessor::DoEvenOddFill,
- SkIVector* newAtlasOffset);
+ // Copies a coverage-counted path out of the given texture proxy, and into a cached, 8-bit,
+ // literal coverage atlas. Updates the cache entry to reference the new atlas.
+ void upgradeEntryToLiteralCoverageAtlas(GrCCPathCache*, GrOnFlushResourceProvider*,
+ GrCCPathCacheEntry*, GrCCPathProcessor::DoEvenOddFill);
// These two methods render a path into a temporary coverage count atlas. See
- // GrCCPathProcessor::Instance for a description of the outputs. The returned atlases are
- // "const" to prevent the caller from assigning a unique key.
+ // GrCCPathProcessor::Instance for a description of the outputs.
//
// strokeDevWidth must be 0 for fills, 1 for hairlines, or the stroke width in device-space
// pixels for non-hairline strokes (implicitly requiring a rigid-body transform).
- const GrCCAtlas* renderShapeInAtlas(const SkIRect& clipIBounds, const SkMatrix&, const GrShape&,
- float strokeDevWidth, SkRect* devBounds,
- SkRect* devBounds45, SkIRect* devIBounds,
- SkIVector* devToAtlasOffset);
+ GrCCAtlas* renderShapeInAtlas(const SkIRect& clipIBounds, const SkMatrix&, const GrShape&,
+ float strokeDevWidth, SkRect* devBounds, SkRect* devBounds45,
+ SkIRect* devIBounds, SkIVector* devToAtlasOffset);
const GrCCAtlas* renderDeviceSpacePathInAtlas(const SkIRect& clipIBounds, const SkPath& devPath,
const SkIRect& devPathIBounds,
SkIVector* devToAtlasOffset);
@@ -100,11 +99,8 @@
return fPathInstanceData[fNextPathInstanceIdx++];
}
- // Finishes off the GPU buffers and renders the atlas(es). 'stashedAtlasProxy', if provided, is
- // the mainline coverage count atlas from the previous flush. It will be used as the source
- // texture for any copies setup by copyStashedPathToAtlas().
- bool finalize(GrOnFlushResourceProvider*, sk_sp<GrTextureProxy> stashedAtlasProxy,
- SkTArray<sk_sp<GrRenderTargetContext>>* out);
+ // Finishes off the GPU buffers and renders the atlas(es).
+ bool finalize(GrOnFlushResourceProvider*, SkTArray<sk_sp<GrRenderTargetContext>>* out);
// Accessors used by draw calls, once the resources have been finalized.
const GrCCFiller& filler() const { SkASSERT(!this->isMapped()); return fFiller; }
@@ -113,23 +109,9 @@
const GrBuffer* vertexBuffer() const { SkASSERT(!this->isMapped()); return fVertexBuffer.get();}
GrBuffer* instanceBuffer() const { SkASSERT(!this->isMapped()); return fInstanceBuffer.get(); }
- // Returns the mainline coverage count atlas that the client may stash for next flush, if any.
- // The caller is responsible to call getOrAssignUniqueKey() on this atlas if they wish to
- // actually stash it in order to copy paths into cached atlases.
- GrCCAtlas* nextAtlasToStash() {
- return fRenderedAtlasStack.empty() ? nullptr : &fRenderedAtlasStack.front();
- }
-
- // Returs true if the client has called getOrAssignUniqueKey() on our nextAtlasToStash().
- bool hasStashedAtlas() const {
- return !fRenderedAtlasStack.empty() && fRenderedAtlasStack.front().uniqueKey().isValid();
- }
- const GrUniqueKey& stashedAtlasKey() const {
- SkASSERT(this->hasStashedAtlas());
- return fRenderedAtlasStack.front().uniqueKey();
- }
-
private:
+ void recordCopyPathInstance(const GrCCPathCacheEntry&, const SkIVector& newAtlasOffset,
+ GrCCPathProcessor::DoEvenOddFill, sk_sp<GrTextureProxy> srcProxy);
bool placeRenderedPathInAtlas(const SkIRect& clipIBounds, const SkIRect& pathIBounds,
GrScissorTest*, SkIRect* clippedPathIBounds,
SkIVector* devToAtlasOffset);
@@ -149,6 +131,30 @@
SkDEBUGCODE(int fEndCopyInstance);
int fNextPathInstanceIdx;
SkDEBUGCODE(int fEndPathInstance);
+
+ // Represents a range of copy-path instances that all share the same source proxy. (i.e. Draw
+ // instances that copy a path mask from a 16-bit coverage count atlas into an 8-bit literal
+ // coverage atlas.)
+ struct CopyPathRange {
+ CopyPathRange() = default;
+ CopyPathRange(sk_sp<GrTextureProxy> srcProxy, int count)
+ : fSrcProxy(std::move(srcProxy)), fCount(count) {}
+ sk_sp<GrTextureProxy> fSrcProxy;
+ int fCount;
+ };
+
+ SkSTArray<4, CopyPathRange> fCopyPathRanges;
+ int fCurrCopyAtlasRangesIdx = 0;
+
+ // This is a list of coverage count atlas textures that have been invalidated due to us copying
+ // their paths into new 8-bit literal coverage atlases. Since copying is finished by the time
+ // we begin rendering new atlases, we can recycle these textures for the rendered atlases rather
+ // than allocating new texture objects upon instantiation.
+ SkSTArray<2, sk_sp<GrTexture>> fRecyclableAtlasTextures;
+
+public:
+ const GrTexture* testingOnly_frontCopyAtlasTexture() const;
+ const GrTexture* testingOnly_frontRenderedAtlasTexture() const;
};
inline void GrCCRenderedPathStats::statPath(const SkPath& path) {