SkString dumpInfo() const override {
SkString str;
- str.appendf("# batched: %d\n", fRectCnt);
+ str.appendf("# combined: %d\n", fRectCnt);
const RectInfo* info = this->first();
for (int i = 0; i < fRectCnt; ++i) {
const SkRect& rect = info->rect();
return false;
}
- // TODO we can actually batch hairlines if they are the same color in a kind of bulk method
- // but we haven't implemented this yet
+ // TODO we can actually combine hairlines if they are the same color in a kind of bulk
+ // method but we haven't implemented this yet
// TODO investigate going to vertex color and coverage?
if (this->coverage() != that->coverage()) {
return false;
}
optimizations.getOverrideColorIfSet(&fPaths[0].fColor);
- // setup batch properties
fColor = fPaths[0].fColor;
fUsesLocalCoords = optimizations.readsLocalCoords();
fCoverageIgnored = !optimizations.readsCoverage();
return false;
}
- // TODO batch across miterstroke changes
+ // TODO combine across miterstroke changes
if (this->miterStroke() != that->miterStroke()) {
return false;
}
// We apply the viewmatrix to the rect points on the cpu. However, if the pipeline uses
- // local coords then we won't be able to batch. We could actually upload the viewmatrix
+ // local coords then we won't be able to combine. We could actually upload the viewmatrix
// using vertex attributes in these cases, but haven't investigated that
if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
return false;
this->setBounds(bounds, HasAABloat::kYes, IsZeroArea::kNo);
}
- const char* name() const override { return "AnalyticRectBatch"; }
+ const char* name() const override { return "AnalyticRectOp"; }
SkString dumpInfo() const override {
SkString string;
, fColor(color) {
SkIRect rtRect = SkIRect::MakeWH(rt->width(), rt->height());
if (fClip.scissorEnabled()) {
- // Don't let scissors extend outside the RT. This may improve batching.
+ // Don't let scissors extend outside the RT. This may improve op combining.
if (!fClip.intersect(rtRect)) {
return;
}
GrColor color = GrRandomColor(random);
SkMatrix viewMatrix = GrTest::TestMatrix(random);
- // For now just hairlines because the other types of draws require two batches.
- // TODO we should figure out a way to combine the stencil and cover steps into one batch
+ // For now just hairlines because the other types of draws require two ops.
+ // TODO we should figure out a way to combine the stencil and cover steps into one op.
GrStyle style(SkStrokeRec::kHairline_InitStyle);
SkPath path = GrTest::TestPath(random);
}
}
- // setup batch properties
fColorIgnored = !optimizations.readsColor();
fColor = fGeoData[0].fColor;
// We'd like to assert this, but we can't because of GLPrograms test
* found in the LICENSE file.
*/
-#ifndef GrDrawBatch_DEFINED
-#define GrDrawBatch_DEFINED
+#ifndef GrDrawOp_DEFINED
+#define GrDrawOp_DEFINED
#include <functional>
#include "GrOp.h"
};
/**
- * Base class for GrOps that draw. These batches have a GrPipeline installed by GrOpList.
+ * Base class for GrOps that draw. These ops have a GrPipeline installed by GrOpList.
*/
class GrDrawOp : public GrOp {
public:
return false;
}
- if (!this->batchablePrimitiveType() || this->primitiveType() != that->primitiveType()) {
+ if (!this->combinablePrimitive() || this->primitiveType() != that->primitiveType()) {
return false;
}
void onPrepareDraws(Target*) const override;
GrPrimitiveType primitiveType() const { return fPrimitiveType; }
- bool batchablePrimitiveType() const {
+ bool combinablePrimitive() const {
return kTriangles_GrPrimitiveType == fPrimitiveType ||
kLines_GrPrimitiveType == fPrimitiveType ||
kPoints_GrPrimitiveType == fPrimitiveType;
* found in the LICENSE file.
*/
-#ifndef GrVertexBatch_DEFINED
-#define GrVertexBatch_DEFINED
+#ifndef GrMeshDrawOp_DEFINED
+#define GrMeshDrawOp_DEFINED
#include "GrDrawOp.h"
#include "GrGeometryProcessor.h"
protected:
/** Helper for rendering instances using an instanced index index buffer. This class creates the
- space for the vertices and flushes the draws to the batch target. */
+ space for the vertices and flushes the draws to the GrMeshDrawOp::Target. */
class InstancedHelper {
public:
InstancedHelper() {}
void* init(Target*, GrPrimitiveType, size_t vertexStride, const GrBuffer*,
int verticesPerInstance, int indicesPerInstance, int instancesToDraw);
- /** Call after init() to issue draws to the batch target.*/
+ /** Call after init() to issue draws to the GrMeshDrawOp::Target.*/
void recordDraw(Target*, const GrGeometryProcessor*);
private:
virtual void onPrepareDraws(Target*) const = 0;
// A set of contiguous draws that share a draw token and primitive processor. The draws all use
- // the batch's pipeline. The meshes for the draw are stored in the fMeshes array and each
+ // the op's pipeline. The meshes for the draw are stored in the fMeshes array and each
// Queued draw uses fMeshCnt meshes from the fMeshes array. The reason for coallescing meshes
// that share a primitive processor into a QueuedDraw is that it allows the Gpu object to setup
// the shared state once and then issue draws for each mesh.
GrPendingProgramElement<const GrGeometryProcessor> fGeometryProcessor;
};
- // All draws in all the vertex batches have implicit tokens based on the order they are
- // enqueued globally across all batches. This is the offset of the first entry in fQueuedDraws.
+ // All draws in all the GrMeshDrawOps have implicit tokens based on the order they are enqueued
+ // globally across all ops. This is the offset of the first entry in fQueuedDraws.
// fQueuedDraws[i]'s token is fBaseDrawToken + i.
GrDrawOpUploadToken fBaseDrawToken;
static const int kVertsPerInstance = 4;
static const int kIndicesPerInstance = 6;
-/** We always use per-vertex colors so that rects can be batched across color changes. Sometimes
+/** We always use per-vertex colors so that rects can be combined across color changes. Sometimes
we have explicit local coords and sometimes not. We *could* always provide explicit local
coords and just duplicate the positions when the caller hasn't provided a local coord rect,
but we haven't seen a use case which frequently switches between local rect and no local
SkString dumpInfo() const override {
SkString str;
- str.appendf("# batched: %d\n", fRects.count());
+ str.appendf("# combined: %d\n", fRects.count());
for (int i = 0; i < fRects.count(); ++i) {
const RectInfo& info = fRects[i];
str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n", i,
static const int kVertsPerInstance = 4;
static const int kIndicesPerInstance = 6;
-/** We always use per-vertex colors so that rects can be batched across color changes. Sometimes
+/** We always use per-vertex colors so that rects can be combined across color changes. Sometimes
we have explicit local coords and sometimes not. We *could* always provide explicit local
coords and just duplicate the positions when the caller hasn't provided a local coord rect,
but we haven't seen a use case which frequently switches between local rect and no local
}
}
-// We handle perspective in the local matrix or viewmatrix with special batches
+// We handle perspective in the local matrix or viewmatrix with special ops.
class NonAAFillRectPerspectiveOp final : public GrMeshDrawOp {
public:
DEFINE_OP_CLASS_ID
this->setTransformedBounds(rect, viewMatrix, HasAABloat::kNo, IsZeroArea::kNo);
}
- const char* name() const override { return "NonAAFillRectPerspectiveBatch"; }
+ const char* name() const override { return "NonAAFillRectPerspectiveOp"; }
SkString dumpInfo() const override {
SkString str;
- str.appendf("# batched: %d\n", fRects.count());
+ str.appendf("# combined: %d\n", fRects.count());
for (int i = 0; i < fRects.count(); ++i) {
const RectInfo& geo = fRects[0];
str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n", i,
return false;
}
- // We could batch across perspective vm changes if we really wanted to
+ // We could combine across perspective vm changes if we really wanted to.
if (!fViewMatrix.cheapEqualTo(that->fViewMatrix)) {
return false;
}
return false;
}
- // In the event of two batches, one who can tweak, one who cannot, we just fall back to
- // not tweaking
+ // In the event of two ops, one who can tweak, one who cannot, we just fall back to not
+ // tweaking.
if (fOptimizations.canTweakAlphaForCoverage() &&
!that->fOptimizations.canTweakAlphaForCoverage()) {
fOptimizations = that->fOptimizations;
public:
DEFINE_OP_CLASS_ID
- const char* name() const override { return "NonAAStrokeRectBatch"; }
+ const char* name() const override { return "NonAAStrokeRectOp"; }
SkString dumpInfo() const override {
SkString string;
}
bool onCombineIfPossible(GrOp* t, const GrCaps&) override {
- // NonAA stroke rects cannot batch right now
- // TODO make these batchable
+ // NonAA stroke rects cannot combine right now
+ // TODO make these combinable.
return false;
}
* found in the LICENSE file.
*/
-#ifndef GrBatch_DEFINED
-#define GrBatch_DEFINED
+#ifndef GrOp_DEFINED
+#define GrOp_DEFINED
#include "../private/SkAtomics.h"
#include "GrGpuResource.h"
class GrOpFlushState;
/**
- * GrOp is the base class for all Ganesh deferred GPU operations. To facilitate reorderable
- * batching, Ganesh does not generate geometry inline with draw calls. Instead, it captures the
- * arguments to the draw and then generates the geometry on demand. This gives GrOp subclasses
- * complete freedom to decide how/what they can batch.
+ * GrOp is the base class for all Ganesh deferred GPU operations. To facilitate reordering and to
+ * minimize draw calls, Ganesh does not generate geometry inline with draw calls. Instead, it
+ * captures the arguments to the draw and then generates the geometry when flushing. This gives GrOp
+ * subclasses complete freedom to decide how/when to combine in order to produce fewer draw calls
+ * and minimize state changes.
*
* Ops of the same subclass may be merged using combineIfPossible. When two ops merge, one
* takes on the union of the data and the other is left empty. The merged op becomes responsible
/** Issues the op's commands to GrGpu. */
void draw(GrOpFlushState* state, const SkRect& bounds) { this->onDraw(state, bounds); }
- /** Used to block batching across render target changes. Remove this once we store
+ /** Used to block combining across render target changes. Remove this once we store
GrOps for different RTs in different targets. */
// TODO: this needs to be updated to return GrSurfaceProxy::UniqueID
virtual GrGpuResource::UniqueID renderTargetUniqueID() const = 0;
* Additional clip planes are supported for rendering circular arcs. The additional planes are
* either intersected or unioned together. Up to three planes are supported (an initial plane,
* a plane intersected with the initial plane, and a plane unioned with the first two). Only two
- * are useful for any given arc, but having all three in one instance allows batching different
+ * are useful for any given arc, but having all three in one instance allows combining different
* types of arcs.
*/
SkASSERT(rrect.isSimple());
SkASSERT(!rrect.isOval());
- // RRect batchs only handle simple, but not too simple, rrects
- // do any matrix crunching before we reset the draw state for device coords
+ // RRect ops only handle simple, but not too simple, rrects.
+ // Do any matrix crunching before we reset the draw state for device coords.
const SkRect& rrectBounds = rrect.getBounds();
SkRect bounds;
viewMatrix.mapRect(&bounds, rrectBounds);
class SkStrokeRec;
/**
- * A factory for returning batches which can draw rectangles.
+ * A factory for returning GrDrawOps which can draw rectangles.
*/
namespace GrRectOpFactory {
SkString dumpInfo() const override {
SkString str;
- str.appendf("# batched: %d\n", fRegions.count());
+ str.appendf("# combined: %d\n", fRegions.count());
for (int i = 0; i < fRegions.count(); ++i) {
const RegionInfo& info = fRegions[i];
str.appendf("%d: Color: 0x%08x, Region with %d rects\n", i, info.fColor,
///////////////////////////////////////////////////////////////////////////////
-sk_sp<GrDrawOp> make_shadow_circle_batch(GrColor color,
- const SkMatrix& viewMatrix,
- const SkRect& oval,
- SkScalar blurRadius,
- const SkStrokeRec& stroke,
- const GrShaderCaps* shaderCaps) {
+sk_sp<GrDrawOp> make_shadow_circle_op(GrColor color,
+ const SkMatrix& viewMatrix,
+ const SkRect& oval,
+ SkScalar blurRadius,
+ const SkStrokeRec& stroke,
+ const GrShaderCaps* shaderCaps) {
// we can only draw circles
SkScalar width = oval.width();
SkASSERT(SkScalarNearlyEqual(width, oval.height()) && viewMatrix.isSimilarity());
GrStyle(stroke, nullptr));
}
-static sk_sp<GrDrawOp> make_shadow_rrect_batch(GrColor color,
- const SkMatrix& viewMatrix,
- const SkRRect& rrect,
- SkScalar blurRadius,
- const SkStrokeRec& stroke) {
+static sk_sp<GrDrawOp> make_shadow_rrect_op(GrColor color,
+ const SkMatrix& viewMatrix,
+ const SkRRect& rrect,
+ SkScalar blurRadius,
+ const SkStrokeRec& stroke) {
SkASSERT(viewMatrix.rectStaysRect());
SkASSERT(rrect.isSimple());
SkASSERT(!rrect.isOval());
- // Shadow rrect batchs only handle simple circular rrects
- // do any matrix crunching before we reset the draw state for device coords
+ // Shadow rrect ops only handle simple circular rrects.
+ // Do any matrix crunching before we reset the draw state for device coords.
const SkRect& rrectBounds = rrect.getBounds();
SkRect bounds;
viewMatrix.mapRect(&bounds, rrectBounds);
const SkStrokeRec& stroke,
const GrShaderCaps* shaderCaps) {
if (rrect.isOval()) {
- return make_shadow_circle_batch(color, viewMatrix, rrect.getBounds(), blurRadius, stroke,
- shaderCaps);
+ return make_shadow_circle_op(color, viewMatrix, rrect.getBounds(), blurRadius, stroke,
+ shaderCaps);
}
if (!viewMatrix.rectStaysRect() || !rrect.isSimple()) {
return nullptr;
}
- return make_shadow_rrect_batch(color, viewMatrix, rrect, blurRadius, stroke);
+ return make_shadow_rrect_op(color, viewMatrix, rrect, blurRadius, stroke);
}
}
///////////////////////////////////////////////////////////////////////////////
GrColor color = GrRandomColor(random);
const SkRRect& rrect = GrTest::TestRRectSimple(random);
SkScalar blurRadius = random->nextSScalar1() * 72.f;
- return make_shadow_rrect_batch(color, viewMatrix, rrect, blurRadius,
- GrTest::TestStrokeRec(random));
+ return make_shadow_rrect_op(color, viewMatrix, rrect, blurRadius,
+ GrTest::TestStrokeRec(random));
}
#endif
#include "ops/GrMeshDrawOp.h"
/*
- * A simple solid color batch only for testing purposes which actually doesn't batch at all. It
- * saves having to fill out some boiler plate methods.
+ * A simple solid color GrMeshDrawOp for testing purposes which doesn't ever combine. Subclassing
+ * this in tests saves having to fill out some boiler plate methods.
*/
class GrTestMeshDrawOp : public GrMeshDrawOp {
public:
this->setBounds(bounds, HasAABloat::kYes, IsZeroArea::kYes);
}
+ GrColor color() const { return fColor; }
+
+ struct Optimizations {
+ bool fColorIgnored = false;
+ bool fUsesLocalCoords = false;
+ bool fCoverageIgnored = false;
+ };
+
+ const Optimizations optimizations() const { return fOptimizations; }
+
+private:
void getPipelineAnalysisInput(GrPipelineAnalysisDrawOpInput* input) const override {
input->pipelineColorInput()->setKnownFourComponents(fColor);
input->pipelineCoverageInput()->setUnknownSingleComponent();
fOptimizations.fCoverageIgnored = !optimizations.readsCoverage();
}
- struct Optimizations {
- bool fColorIgnored = false;
- bool fUsesLocalCoords = false;
- bool fCoverageIgnored = false;
- };
-
- GrColor color() const { return fColor; }
- const Optimizations optimizations() const { return fOptimizations; }
-
-private:
bool onCombineIfPossible(GrOp*, const GrCaps&) override { return false; }
GrColor fColor;