Increase batching for AA fill rects.

This allows batching of rects provided without a local matrix when local coords are required and when the view matrix changes.

It also allows batching of rects with a local matrix with rects without a local matrix.
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2116823002

Review-Url: https://codereview.chromium.org/2116823002
This commit is contained in:
bsalomon 2016-07-01 11:02:39 -07:00 committed by Commit bot
parent 6abd1d192e
commit e525ecaf63

View File

@ -13,9 +13,9 @@
#include "GrResourceKey.h"
#include "GrResourceProvider.h"
#include "GrTypes.h"
#include "GrVertexBatch.h"
#include "SkMatrix.h"
#include "SkRect.h"
#include "GrVertexBatch.h"
GR_DECLARE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey);
@ -45,35 +45,6 @@ const GrBuffer* get_index_buffer(GrResourceProvider* resourceProvider) {
gAAFillRectIndexBufferKey);
}
static sk_sp<GrGeometryProcessor> create_fill_rect_gp(
const SkMatrix& viewMatrix,
const GrXPOverridesForBatch& overrides,
GrDefaultGeoProcFactory::LocalCoords::Type localCoordsType) {
using namespace GrDefaultGeoProcFactory;
Color color(Color::kAttribute_Type);
Coverage::Type coverageType;
// TODO remove coverage if coverage is ignored
/*if (coverageIgnored) {
coverageType = Coverage::kNone_Type;
} else*/ if (overrides.canTweakAlphaForCoverage()) {
coverageType = Coverage::kSolid_Type;
} else {
coverageType = Coverage::kAttribute_Type;
}
Coverage coverage(coverageType);
// We assume the caller has inverted the viewmatrix
if (LocalCoords::kHasExplicit_Type == localCoordsType) {
LocalCoords localCoords(localCoordsType);
return GrDefaultGeoProcFactory::Make(color, coverage, localCoords, SkMatrix::I());
} else {
LocalCoords localCoords(overrides.readsLocalCoords() ? localCoordsType :
LocalCoords::kUnused_Type);
return MakeForDeviceSpace(color, coverage, localCoords, viewMatrix);
}
}
static void generate_aa_fill_rect_geometry(intptr_t verts,
size_t vertexStride,
GrColor color,
@ -137,7 +108,7 @@ static void generate_aa_fill_rect_geometry(intptr_t verts,
if (localMatrix) {
SkMatrix invViewMatrix;
if (!viewMatrix.invert(&invViewMatrix)) {
SkASSERT(false);
SkDebugf("View matrix is non-invertible, local coords will be wrong.");
invViewMatrix = SkMatrix::I();
}
SkMatrix localCoordMatrix;
@ -186,28 +157,37 @@ static void generate_aa_fill_rect_geometry(intptr_t verts,
}
}
}
class AAFillRectNoLocalMatrixBatch : public GrVertexBatch {
class AAFillRectBatch : public GrVertexBatch {
public:
DEFINE_BATCH_CLASS_ID
AAFillRectNoLocalMatrixBatch(GrColor color,
const SkMatrix& viewMatrix,
const SkRect& rect,
const SkRect& devRect) : INHERITED(ClassID()) {
fRects.emplace_back(RectInfo{color, viewMatrix, rect, devRect});
AAFillRectBatch(GrColor color,
const SkMatrix& viewMatrix,
const SkRect& rect,
const SkRect& devRect,
const SkMatrix* localMatrix) : INHERITED(ClassID()) {
if (localMatrix) {
void* mem = fRectData.push_back_n(sizeof(RectWithLocalMatrixInfo));
new (mem) RectWithLocalMatrixInfo(color, viewMatrix, rect, devRect, *localMatrix);
} else {
void* mem = fRectData.push_back_n(sizeof(RectInfo));
new (mem) RectInfo(color, viewMatrix, rect, devRect);
}
fBounds = devRect;
fRectCnt = 1;
}
const char* name() const override { return "AAFillRectBatchNoLocalMatrix"; }
const char* name() const override { return "AAFillRectBatch"; }
SkString dumpInfo() const override {
SkString str;
str.appendf("# batched: %d\n", fRects.count());
for (int i = 0; i < fRects.count(); ++i) {
const RectInfo& info = fRects[i];
str.appendf("# batched: %d\n", fRectCnt);
const RectInfo* info = this->first();
for (int i = 0; i < fRectCnt; ++i) {
const SkRect& rect = info->rect();
str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
i, info.fColor,
info.fRect.fLeft, info.fRect.fTop, info.fRect.fRight, info.fRect.fBottom);
i, info->color(), rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
info = this->next(info);
}
str.append(INHERITED::dumpInfo());
return str;
@ -217,30 +197,39 @@ public:
GrInitInvariantOutput* coverage,
GrBatchToXPOverrides* overrides) const override {
// When this is called on a batch, there is only one rect
color->setKnownFourComponents(fRects[0].fColor);
color->setKnownFourComponents(this->first()->color());
coverage->setUnknownSingleComponent();
}
void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
overrides.getOverrideColorIfSet(&fRects[0].fColor);
GrColor color;
if (overrides.getOverrideColorIfSet(&color)) {
this->first()->setColor(color);
}
fOverrides = overrides;
}
private:
AAFillRectNoLocalMatrixBatch() : INHERITED(ClassID()) {}
void onPrepareDraws(Target* target) const override {
sk_sp<GrGeometryProcessor> gp =
create_fill_rect_gp(fRects[0].fViewMatrix, fOverrides,
GrDefaultGeoProcFactory::LocalCoords::kUsePosition_Type);
bool needLocalCoords = fOverrides.readsLocalCoords();
using namespace GrDefaultGeoProcFactory;
Color color(Color::kAttribute_Type);
Coverage::Type coverageType;
if (fOverrides.canTweakAlphaForCoverage()) {
coverageType = Coverage::kSolid_Type;
} else {
coverageType = Coverage::kAttribute_Type;
}
Coverage coverage(coverageType);
LocalCoords lc = needLocalCoords ? LocalCoords::kHasExplicit_Type
: LocalCoords::kUnused_Type;
sk_sp<GrGeometryProcessor> gp = GrDefaultGeoProcFactory::Make(color, coverage, lc,
SkMatrix::I());
if (!gp) {
SkDebugf("Couldn't create GrGeometryProcessor\n");
return;
}
SkASSERT(fOverrides.canTweakAlphaForCoverage() ?
gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) :
gp->getVertexStride() ==
sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr));
size_t vertexStride = gp->getVertexStride();
@ -248,171 +237,104 @@ private:
InstancedHelper helper;
void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
indexBuffer, kVertsPerAAFillRect,
kIndicesPerAAFillRect, fRects.count());
kIndicesPerAAFillRect, fRectCnt);
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;
}
for (int i = 0; i < fRects.count(); i++) {
const RectInfo* info = this->first();
const SkMatrix* localMatrix = nullptr;
for (int i = 0; i < fRectCnt; i++) {
intptr_t verts = reinterpret_cast<intptr_t>(vertices) +
i * kVertsPerAAFillRect * vertexStride;
generate_aa_fill_rect_geometry(verts, vertexStride,
fRects[i].fColor, fRects[i].fViewMatrix,
fRects[i].fRect, fRects[i].fDevRect, fOverrides,
nullptr);
if (needLocalCoords) {
if (info->hasLocalMatrix()) {
localMatrix = &static_cast<const RectWithLocalMatrixInfo*>(info)->localMatrix();
} else {
localMatrix = &SkMatrix::I();
}
}
generate_aa_fill_rect_geometry(verts, vertexStride, info->color(),
info->viewMatrix(), info->rect(),
info->devRect(), fOverrides, localMatrix);
info = this->next(info);
}
helper.recordDraw(target, gp.get());
}
bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
AAFillRectNoLocalMatrixBatch* that = t->cast<AAFillRectNoLocalMatrixBatch>();
AAFillRectBatch* that = t->cast<AAFillRectBatch>();
if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
that->bounds(), caps)) {
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
// using vertex attributes in these cases, but haven't investigated that
if (fOverrides.readsLocalCoords() &&
!fRects[0].fViewMatrix.cheapEqualTo(that->fRects[0].fViewMatrix)) {
return false;
}
// In the event of two batches, one who can tweak, one who cannot, we just fall back to
// not tweaking
if (fOverrides.canTweakAlphaForCoverage() && !that->fOverrides.canTweakAlphaForCoverage()) {
fOverrides = that->fOverrides;
}
fRects.push_back_n(that->fRects.count(), that->fRects.begin());
fRectData.push_back_n(that->fRectData.count(), that->fRectData.begin());
fRectCnt += that->fRectCnt;
this->joinBounds(that->bounds());
return true;
}
struct RectInfo {
public:
RectInfo(GrColor color, const SkMatrix& viewMatrix, const SkRect& rect,
const SkRect& devRect)
: RectInfo(color, viewMatrix, rect, devRect, HasLocalMatrix::kNo) {}
bool hasLocalMatrix() const { return HasLocalMatrix::kYes == fHasLocalMatrix; }
GrColor color() const { return fColor; }
const SkMatrix& viewMatrix() const { return fViewMatrix; }
const SkRect& rect() const { return fRect; }
const SkRect& devRect() const { return fDevRect; }
void setColor(GrColor color) { fColor = color; }
protected:
enum class HasLocalMatrix : uint32_t { kNo, kYes };
RectInfo(GrColor color, const SkMatrix& viewMatrix, const SkRect& rect,
const SkRect& devRect, HasLocalMatrix hasLM)
: fHasLocalMatrix(hasLM)
, fColor(color)
, fViewMatrix(viewMatrix)
, fRect(rect)
, fDevRect(devRect) {}
HasLocalMatrix fHasLocalMatrix;
GrColor fColor;
SkMatrix fViewMatrix;
SkRect fRect;
SkRect fDevRect;
};
GrXPOverridesForBatch fOverrides;
SkSTArray<1, RectInfo, true> fRects;
typedef GrVertexBatch INHERITED;
};
class AAFillRectLocalMatrixBatch : public GrVertexBatch {
public:
DEFINE_BATCH_CLASS_ID
AAFillRectLocalMatrixBatch(GrColor color,
const SkMatrix& viewMatrix,
const SkMatrix& localMatrix,
const SkRect& rect,
const SkRect& devRect) : INHERITED(ClassID()) {
fRects.emplace_back(RectInfo{color, viewMatrix, localMatrix, rect, devRect});
fBounds = devRect;
}
const char* name() const override { return "AAFillRectBatchLocalMatrix"; }
SkString dumpInfo() const override {
SkString str;
str.appendf("# batched: %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, info.fColor,
info.fRect.fLeft, info.fRect.fTop, info.fRect.fRight, info.fRect.fBottom);
}
str.append(INHERITED::dumpInfo());
return str;
}
void computePipelineOptimizations(GrInitInvariantOutput* color,
GrInitInvariantOutput* coverage,
GrBatchToXPOverrides* overrides) const override {
// When this is called on a batch, there is only one rect
color->setKnownFourComponents(fRects[0].fColor);
coverage->setUnknownSingleComponent();
}
void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
overrides.getOverrideColorIfSet(&fRects[0].fColor);
fOverrides = overrides;
}
private:
AAFillRectLocalMatrixBatch() : INHERITED(ClassID()) {}
void onPrepareDraws(Target* target) const override {
sk_sp<GrGeometryProcessor> gp =
create_fill_rect_gp(fRects[0].fViewMatrix, fOverrides,
GrDefaultGeoProcFactory::LocalCoords::kHasExplicit_Type);
if (!gp) {
SkDebugf("Couldn't create GrGeometryProcessor\n");
return;
}
SkASSERT(fOverrides.canTweakAlphaForCoverage() ?
gp->getVertexStride() ==
sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr) :
gp->getVertexStride() ==
sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordCoverage));
size_t vertexStride = gp->getVertexStride();
SkAutoTUnref<const GrBuffer> indexBuffer(get_index_buffer(target->resourceProvider()));
InstancedHelper helper;
void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
indexBuffer, kVertsPerAAFillRect,
kIndicesPerAAFillRect, fRects.count());
if (!vertices || !indexBuffer) {
SkDebugf("Could not allocate vertices\n");
return;
}
for (int i = 0; i < fRects.count(); i++) {
intptr_t verts = reinterpret_cast<intptr_t>(vertices) +
i * kVertsPerAAFillRect * vertexStride;
generate_aa_fill_rect_geometry(verts, vertexStride, fRects[i].fColor,
fRects[i].fViewMatrix, fRects[i].fRect,
fRects[i].fDevRect, fOverrides,
&fRects[i].fLocalMatrix);
}
helper.recordDraw(target, gp.get());
}
bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
AAFillRectLocalMatrixBatch* that = t->cast<AAFillRectLocalMatrixBatch>();
if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
that->bounds(), caps)) {
return false;
}
// In the event of two batches, one who can tweak, one who cannot, we just fall back to
// not tweaking
if (fOverrides.canTweakAlphaForCoverage() && !that->fOverrides.canTweakAlphaForCoverage()) {
fOverrides = that->fOverrides;
}
fRects.push_back_n(that->fRects.count(), that->fRects.begin());
this->joinBounds(that->bounds());
return true;
}
struct RectInfo {
GrColor fColor;
SkMatrix fViewMatrix;
struct RectWithLocalMatrixInfo : public RectInfo {
public:
RectWithLocalMatrixInfo(GrColor color, const SkMatrix& viewMatrix, const SkRect& rect,
const SkRect& devRect, const SkMatrix& localMatrix)
: RectInfo(color, viewMatrix, rect, devRect, HasLocalMatrix::kYes)
, fLocalMatrix(localMatrix) {}
const SkMatrix& localMatrix() const { return fLocalMatrix; }
private:
SkMatrix fLocalMatrix;
SkRect fRect;
SkRect fDevRect;
};
RectInfo* first() { return reinterpret_cast<RectInfo*>(fRectData.begin()); }
const RectInfo* first() const { return reinterpret_cast<const RectInfo*>(fRectData.begin()); }
const RectInfo* next(const RectInfo* prev) const {
intptr_t next = reinterpret_cast<intptr_t>(prev) +
(prev->hasLocalMatrix() ? sizeof(RectWithLocalMatrixInfo)
: sizeof(RectInfo));
return reinterpret_cast<const RectInfo*>(next);
}
GrXPOverridesForBatch fOverrides;
SkSTArray<1, RectInfo, true> fRects;
SkSTArray<4 * sizeof(RectWithLocalMatrixInfo), uint8_t, true> fRectData;
int fRectCnt;
typedef GrVertexBatch INHERITED;
};
@ -423,7 +345,7 @@ GrDrawBatch* Create(GrColor color,
const SkMatrix& viewMatrix,
const SkRect& rect,
const SkRect& devRect) {
return new AAFillRectNoLocalMatrixBatch(color, viewMatrix, rect, devRect);
return new AAFillRectBatch(color, viewMatrix, rect, devRect, nullptr);
}
GrDrawBatch* Create(GrColor color,
@ -431,7 +353,7 @@ GrDrawBatch* Create(GrColor color,
const SkMatrix& localMatrix,
const SkRect& rect,
const SkRect& devRect) {
return new AAFillRectLocalMatrixBatch(color, viewMatrix, localMatrix, rect, devRect);
return new AAFillRectBatch(color, viewMatrix, rect, devRect, &localMatrix);
}
GrDrawBatch* Create(GrColor color,