Avoid non-indexed quad draws on PowerVR Rogue and 54x
Bug: chromium:1203652
Change-Id: Id83ac81c40eda2653e97a7c8ae9326c273f0f00b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/420537
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrCaps.cpp b/src/gpu/GrCaps.cpp
index abe11a6..f2aea46 100644
--- a/src/gpu/GrCaps.cpp
+++ b/src/gpu/GrCaps.cpp
@@ -83,6 +83,7 @@
fRequiresManualFBBarrierAfterTessellatedStencilDraw = false;
fNativeDrawIndexedIndirectIsBroken = false;
fAvoidReorderingRenderTasks = false;
+ fAlwaysDrawQuadsIndexed = false;
fPreferVRAMUseOverFlushes = true;
diff --git a/src/gpu/GrCaps.h b/src/gpu/GrCaps.h
index 59a8970..aafdb86 100644
--- a/src/gpu/GrCaps.h
+++ b/src/gpu/GrCaps.h
@@ -396,6 +396,9 @@
// Should we disable GrTessellationPathRenderer due to a faulty driver?
bool disableTessellationPathRenderer() const { return fDisableTessellationPathRenderer; }
+ // Always use an index buffer to draw quads
+ bool alwaysDrawQuadsIndexed() const { return fAlwaysDrawQuadsIndexed; }
+
// Returns how to sample the dst values for the passed in GrRenderTargetProxy.
GrDstSampleFlags getDstSampleFlagsForProxy(const GrRenderTargetProxy*) const;
@@ -565,6 +568,7 @@
bool fRequiresManualFBBarrierAfterTessellatedStencilDraw : 1;
bool fNativeDrawIndexedIndirectIsBroken : 1;
bool fAvoidReorderingRenderTasks : 1;
+ bool fAlwaysDrawQuadsIndexed : 1;
// ANGLE performance workaround
bool fPreferVRAMUseOverFlushes : 1;
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index e4b267a..bf9103f 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -4155,6 +4155,12 @@
fShaderCaps->fShaderDerivativeSupport = false;
}
#endif
+
+ if (ctxInfo.renderer() == GrGLRenderer::kPowerVRRogue ||
+ ctxInfo.renderer() == GrGLRenderer::kPowerVR54x) {
+ // crbug.com/1203652
+ fAlwaysDrawQuadsIndexed = true;
+ }
}
void GrGLCaps::onApplyOptionsOverrides(const GrContextOptions& options) {
diff --git a/src/gpu/ops/GrFillRectOp.cpp b/src/gpu/ops/GrFillRectOp.cpp
index a0e8405..e926401 100644
--- a/src/gpu/ops/GrFillRectOp.cpp
+++ b/src/gpu/ops/GrFillRectOp.cpp
@@ -183,9 +183,10 @@
int numQuads() const final { return fQuads.count(); }
#endif
- VertexSpec vertexSpec() const {
+ VertexSpec vertexSpec(const GrCaps& caps) const {
auto indexBufferOption = GrQuadPerEdgeAA::CalcIndexBufferOption(fHelper.aaType(),
- fQuads.count());
+ fQuads.count(),
+ caps);
return VertexSpec(fQuads.deviceQuadType(), fColorType, fQuads.localQuadType(),
fHelper.usesLocalCoords(), GrQuadPerEdgeAA::Subset::kNo,
@@ -204,7 +205,7 @@
const GrDstProxyView& dstProxyView,
GrXferBarrierFlags renderPassXferBarriers,
GrLoadOp colorLoadOp) override {
- const VertexSpec vertexSpec = this->vertexSpec();
+ const VertexSpec vertexSpec = this->vertexSpec(*caps);
GrGeometryProcessor* gp = GrQuadPerEdgeAA::MakeProcessor(arena, vertexSpec);
SkASSERT(gp->vertexStride() == vertexSpec.vertexSize());
@@ -231,7 +232,7 @@
SkArenaAlloc* arena = rContext->priv().recordTimeAllocator();
- const VertexSpec vertexSpec = this->vertexSpec();
+ const VertexSpec vertexSpec = this->vertexSpec(*rContext->priv().caps());
const int totalNumVertices = fQuads.count() * vertexSpec.verticesPerQuad();
const size_t totalVertexSizeInBytes = vertexSpec.vertexSize() * totalNumVertices;
@@ -259,7 +260,7 @@
void onPrepareDraws(GrMeshDrawTarget* target) override {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
- const VertexSpec vertexSpec = this->vertexSpec();
+ const VertexSpec vertexSpec = this->vertexSpec(target->caps());
// Make sure that if the op thought it was a solid color, the vertex spec does not use
// local coords.
@@ -297,7 +298,7 @@
return;
}
- const VertexSpec vertexSpec = this->vertexSpec();
+ const VertexSpec vertexSpec = this->vertexSpec(flushState->caps());
if (vertexSpec.needsIndexBuffer() && !fIndexBuffer) {
return;
@@ -376,13 +377,15 @@
}
#endif
- bool canAddQuads(int numQuads, GrAAType aaType) {
+ bool canAddQuads(int numQuads, GrAAType aaType, const GrCaps& caps) {
// The new quad's aa type should be the same as the first quad's or none, except when the
// first quad's aa type was already downgraded to none, in which case the stored type must
// be lifted to back to the requested type.
int quadCount = fQuads.count() + numQuads;
if (aaType != fHelper.aaType() && aaType != GrAAType::kNone) {
- auto indexBufferOption = GrQuadPerEdgeAA::CalcIndexBufferOption(aaType, quadCount);
+ auto indexBufferOption = GrQuadPerEdgeAA::CalcIndexBufferOption(aaType,
+ quadCount,
+ caps);
if (quadCount > GrQuadPerEdgeAA::QuadLimit(indexBufferOption)) {
// Promoting to the new aaType would've caused an overflow of the indexBuffer
// limit
@@ -394,7 +397,8 @@
fHelper.setAAType(aaType);
} else {
auto indexBufferOption = GrQuadPerEdgeAA::CalcIndexBufferOption(fHelper.aaType(),
- quadCount);
+ quadCount,
+ caps);
if (quadCount > GrQuadPerEdgeAA::QuadLimit(indexBufferOption)) {
return false; // This op can't grow any more
}
@@ -405,7 +409,7 @@
// Similar to onCombineIfPossible, but adds a quad assuming its op would have been compatible.
// But since it's avoiding the op list management, it must update the op's bounds.
- bool addQuad(DrawQuad* quad, const SkPMColor4f& color, GrAAType aaType) {
+ bool addQuad(DrawQuad* quad, const SkPMColor4f& color, GrAAType aaType, const GrCaps& caps) {
SkRect newBounds = this->bounds();
newBounds.joinPossiblyEmptyRect(quad->fDevice.bounds());
@@ -415,7 +419,7 @@
if (count == 0 ) {
// Just skip the append (trivial success)
return true;
- } else if (!this->canAddQuads(count, aaType)) {
+ } else if (!this->canAddQuads(count, aaType, caps)) {
// Not enough room in the index buffer for the AA type
return false;
} else {
@@ -504,7 +508,7 @@
GrQuadUtils::ResolveAAType(aaType, quads[i].fAAFlags, quad.fDevice,
&resolvedAA, &quad.fEdgeFlags);
- if (!fillRects->addQuad(&quad, quads[i].fColor, resolvedAA)) {
+ if (!fillRects->addQuad(&quad, quads[i].fColor, resolvedAA, *context->priv().caps())) {
break;
}
diff --git a/src/gpu/ops/GrQuadPerEdgeAA.cpp b/src/gpu/ops/GrQuadPerEdgeAA.cpp
index 307eb0a..4ce8103 100644
--- a/src/gpu/ops/GrQuadPerEdgeAA.cpp
+++ b/src/gpu/ops/GrQuadPerEdgeAA.cpp
@@ -244,10 +244,10 @@
namespace GrQuadPerEdgeAA {
-IndexBufferOption CalcIndexBufferOption(GrAAType aa, int numQuads) {
+IndexBufferOption CalcIndexBufferOption(GrAAType aa, int numQuads, const GrCaps& caps) {
if (aa == GrAAType::kCoverage) {
return IndexBufferOption::kPictureFramed;
- } else if (numQuads > 1) {
+ } else if (numQuads > 1 || caps.alwaysDrawQuadsIndexed()) {
return IndexBufferOption::kIndexedRects;
} else {
return IndexBufferOption::kTriStrips;
diff --git a/src/gpu/ops/GrQuadPerEdgeAA.h b/src/gpu/ops/GrQuadPerEdgeAA.h
index ffcaf8c..546667f 100644
--- a/src/gpu/ops/GrQuadPerEdgeAA.h
+++ b/src/gpu/ops/GrQuadPerEdgeAA.h
@@ -41,7 +41,7 @@
};
static const int kIndexBufferOptionCount = static_cast<int>(IndexBufferOption::kLast) + 1;
- IndexBufferOption CalcIndexBufferOption(GrAAType aa, int numQuads);
+ IndexBufferOption CalcIndexBufferOption(GrAAType aa, int numQuads, const GrCaps&);
// Gets the minimum ColorType that can represent a color.
ColorType MinColorType(SkPMColor4f);
diff --git a/src/gpu/ops/GrTextureOp.cpp b/src/gpu/ops/GrTextureOp.cpp
index c1c8a46..233add0 100644
--- a/src/gpu/ops/GrTextureOp.cpp
+++ b/src/gpu/ops/GrTextureOp.cpp
@@ -693,7 +693,7 @@
SkArenaAlloc* arena = context->priv().recordTimeAllocator();
fDesc = arena->make<Desc>();
- this->characterize(fDesc);
+ this->characterize(fDesc, *context->priv().caps());
fDesc->allocatePrePreparedVertices(arena);
FillInVertices(*context->priv().caps(), this, fDesc, fDesc->fPrePreparedVertices);
@@ -788,7 +788,7 @@
int numQuads() const final { return this->totNumQuads(); }
#endif
- void characterize(Desc* desc) const {
+ void characterize(Desc* desc, const GrCaps& caps) const {
SkDEBUGCODE(this->validate();)
GrQuad::Type quadType = GrQuad::Type::kAxisAligned;
@@ -829,7 +829,8 @@
SkASSERT(!CombinedQuadCountWillOverflow(overallAAType, false, desc->fNumTotalQuads));
auto indexBufferOption = GrQuadPerEdgeAA::CalcIndexBufferOption(overallAAType,
- maxQuadsPerMesh);
+ maxQuadsPerMesh,
+ caps);
desc->fVertexSpec = VertexSpec(quadType, colorType, srcQuadType, /* hasLocal */ true,
subset, overallAAType, /* alpha as coverage */ true,
@@ -875,7 +876,7 @@
if (!fDesc) {
SkArenaAlloc* arena = target->allocator();
fDesc = arena->make<Desc>();
- this->characterize(fDesc);
+ this->characterize(fDesc, target->caps());
SkASSERT(!fDesc->fPrePreparedVertices);
}