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>
This commit is contained in:
parent
b18a947a35
commit
b149700e01
@ -83,6 +83,7 @@ GrCaps::GrCaps(const GrContextOptions& options) {
|
||||
fRequiresManualFBBarrierAfterTessellatedStencilDraw = false;
|
||||
fNativeDrawIndexedIndirectIsBroken = false;
|
||||
fAvoidReorderingRenderTasks = false;
|
||||
fAlwaysDrawQuadsIndexed = false;
|
||||
|
||||
fPreferVRAMUseOverFlushes = true;
|
||||
|
||||
|
@ -396,6 +396,9 @@ public:
|
||||
// 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 @@ protected:
|
||||
bool fRequiresManualFBBarrierAfterTessellatedStencilDraw : 1;
|
||||
bool fNativeDrawIndexedIndirectIsBroken : 1;
|
||||
bool fAvoidReorderingRenderTasks : 1;
|
||||
bool fAlwaysDrawQuadsIndexed : 1;
|
||||
|
||||
// ANGLE performance workaround
|
||||
bool fPreferVRAMUseOverFlushes : 1;
|
||||
|
@ -4155,6 +4155,12 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo,
|
||||
fShaderCaps->fShaderDerivativeSupport = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ctxInfo.renderer() == GrGLRenderer::kPowerVRRogue ||
|
||||
ctxInfo.renderer() == GrGLRenderer::kPowerVR54x) {
|
||||
// crbug.com/1203652
|
||||
fAlwaysDrawQuadsIndexed = true;
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLCaps::onApplyOptionsOverrides(const GrContextOptions& options) {
|
||||
|
@ -183,9 +183,10 @@ private:
|
||||
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 @@ private:
|
||||
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 @@ private:
|
||||
|
||||
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 @@ private:
|
||||
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 @@ private:
|
||||
return;
|
||||
}
|
||||
|
||||
const VertexSpec vertexSpec = this->vertexSpec();
|
||||
const VertexSpec vertexSpec = this->vertexSpec(flushState->caps());
|
||||
|
||||
if (vertexSpec.needsIndexBuffer() && !fIndexBuffer) {
|
||||
return;
|
||||
@ -376,13 +377,15 @@ private:
|
||||
}
|
||||
#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 @@ private:
|
||||
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 @@ private:
|
||||
|
||||
// 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 @@ private:
|
||||
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 @@ GrOp::Owner GrFillRectOp::MakeOp(GrRecordingContext* context,
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -244,10 +244,10 @@ static void write_2d_cov_uv_strict(GrVertexWriter* vb, const GrQuadPerEdgeAA::Ve
|
||||
|
||||
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;
|
||||
|
@ -41,7 +41,7 @@ namespace GrQuadPerEdgeAA {
|
||||
};
|
||||
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);
|
||||
|
@ -693,7 +693,7 @@ private:
|
||||
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 @@ private:
|
||||
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 @@ private:
|
||||
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 @@ private:
|
||||
if (!fDesc) {
|
||||
SkArenaAlloc* arena = target->allocator();
|
||||
fDesc = arena->make<Desc>();
|
||||
this->characterize(fDesc);
|
||||
this->characterize(fDesc, target->caps());
|
||||
SkASSERT(!fDesc->fPrePreparedVertices);
|
||||
}
|
||||
|
||||
|
@ -1164,13 +1164,6 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache9Verts, reporter, ctxInfo) {
|
||||
static void test_10(GrDirectContext* dContext, skiatest::Reporter* reporter,
|
||||
TestHelper::addAccessFP addAccess,
|
||||
TestHelper::checkFP check) {
|
||||
|
||||
if (GrBackendApi::kOpenGL != dContext->backend()) {
|
||||
// The lower-level backends have too much going on for the following simple purging
|
||||
// test to work
|
||||
return;
|
||||
}
|
||||
|
||||
TestHelper helper(dContext);
|
||||
|
||||
(helper.*addAccess)(helper.liveCanvas(), kImageWH, kNoID, false, false);
|
||||
@ -1224,8 +1217,25 @@ static void test_10(GrDirectContext* dContext, skiatest::Reporter* reporter,
|
||||
/*hits*/ 2, /*misses*/ 2, /*refs*/ 0, kNoID));
|
||||
}
|
||||
|
||||
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrThreadSafeCache10View, reporter, ctxInfo) {
|
||||
test_10(ctxInfo.directContext(), reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
|
||||
DEF_GPUTEST(GrThreadSafeCache10View, reporter, origOptions) {
|
||||
// Workarounds can affect the correctness of this test by causing extra allocations.
|
||||
GrContextOptions options = origOptions;
|
||||
options.fDisableDriverCorrectnessWorkarounds = true;
|
||||
for (int ct = 0; ct < sk_gpu_test::GrContextFactory::kContextTypeCnt; ++ct) {
|
||||
auto type = static_cast<sk_gpu_test::GrContextFactory::ContextType>(ct);
|
||||
if (sk_gpu_test::GrContextFactory::ContextTypeBackend(type) != GrBackendApi::kOpenGL) {
|
||||
// The lower-level backends have too much going on for the following simple purging
|
||||
// test to work. This will likely stop working on GL if we do a better job of tracking
|
||||
// actual purgeability WRT GPU work completion.
|
||||
continue;
|
||||
}
|
||||
sk_gpu_test::GrContextFactory factory(options);
|
||||
GrDirectContext* dContext = factory.get(type);
|
||||
if (!dContext) {
|
||||
continue;
|
||||
}
|
||||
test_10(dContext, reporter, &TestHelper::addViewAccess, &TestHelper::checkView);
|
||||
}
|
||||
}
|
||||
|
||||
// To enable test_10 with verts would require a bit more work, namely:
|
||||
|
Loading…
Reference in New Issue
Block a user