Fix tessellation checks for "usesVaryingCoords"

We can't use our hardware tessellation back door if any FPs in the
program have varyings. Before this CL, we were forgetting to check the
clip FP for strokes, and weren't checking any FPs yet for fills.

Bug: skia:10419
Change-Id: Ica631ab3cf0407fb359c02c6d53f88f5f301cddc
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/417237
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
This commit is contained in:
Chris Dalton 2021-06-09 13:49:43 -06:00 committed by Skia Commit-Bot
parent 03f1d12b64
commit bd727d0620
12 changed files with 44 additions and 28 deletions

View File

@ -113,18 +113,22 @@ protected:
DEF_PATH_TESS_BENCH(GrPathOuterCurveTessellator, make_cubic_path(8), SkMatrix::I()) {
SkArenaAlloc arena(1024);
GrPipeline noVaryingsPipeline(GrScissorTest::kDisabled, SkBlendMode::kSrcOver,
GrSwizzle::RGBA());
auto tess = GrPathCurveTessellator::Make(&arena, fMatrix, SK_PMColor4fTRANSPARENT,
GrPathCurveTessellator::DrawInnerFan::kNo,
fTarget->caps().minPathVerbsForHwTessellation(),
fTarget->caps());
noVaryingsPipeline, fTarget->caps());
tess->prepare(fTarget.get(), SkRectPriv::MakeLargest(), fPath, nullptr);
}
DEF_PATH_TESS_BENCH(GrPathWedgeTessellator, make_cubic_path(8), SkMatrix::I()) {
SkArenaAlloc arena(1024);
GrPipeline noVaryingsPipeline(GrScissorTest::kDisabled, SkBlendMode::kSrcOver,
GrSwizzle::RGBA());
auto tess = GrPathWedgeTessellator::Make(&arena, fMatrix, SK_PMColor4fTRANSPARENT,
fTarget->caps().minPathVerbsForHwTessellation(),
fTarget->caps());
noVaryingsPipeline, fTarget->caps());
tess->prepare(fTarget.get(), SkRectPriv::MakeLargest(), fPath, nullptr);
}

View File

@ -74,30 +74,34 @@ private:
const GrCaps& caps = flushState->caps();
int numVerbsToGetMiddleOut = 0;
int numVerbsToGetTessellation = caps.minPathVerbsForHwTessellation();
auto pipeline = GrSimpleMeshDrawOpHelper::CreatePipeline(flushState, std::move(fProcessors),
fPipelineFlags);
switch (fMode) {
using DrawInnerFan = GrPathCurveTessellator::DrawInnerFan;
case Mode::kWedgeMiddleOut:
fTessellator = GrPathWedgeTessellator::Make(alloc, fMatrix, kCyan,
numVerbsToGetMiddleOut, caps);
numVerbsToGetMiddleOut, *pipeline,
caps);
break;
case Mode::kCurveMiddleOut:
fTessellator = GrPathCurveTessellator::Make(alloc, fMatrix, kCyan,
DrawInnerFan::kYes,
numVerbsToGetMiddleOut, caps);
numVerbsToGetMiddleOut, *pipeline,
caps);
break;
case Mode::kWedgeTessellate:
fTessellator = GrPathWedgeTessellator::Make(alloc, fMatrix, kCyan,
numVerbsToGetTessellation, caps);
numVerbsToGetTessellation, *pipeline,
caps);
break;
case Mode::kCurveTessellate:
fTessellator = GrPathCurveTessellator::Make(alloc, fMatrix, kCyan,
DrawInnerFan::kYes,
numVerbsToGetTessellation, caps);
numVerbsToGetTessellation, *pipeline,
caps);
break;
}
fTessellator->prepare(flushState, this->bounds(), fPath);
auto pipeline = GrSimpleMeshDrawOpHelper::CreatePipeline(flushState, std::move(fProcessors),
fPipelineFlags);
fProgram = GrTessellationShader::MakeProgram({alloc, flushState->writeView(),
&flushState->dstProxyView(),
flushState->renderPassBarriers(),

View File

@ -110,6 +110,15 @@ public:
bool isColorFragmentProcessor(int idx) const { return idx < fNumColorProcessors; }
bool isCoverageFragmentProcessor(int idx) const { return idx >= fNumColorProcessors; }
bool usesVaryingCoords() const {
for (const auto& fp : fFragmentProcessors) {
if (fp->usesVaryingCoords()) {
return true;
}
}
return false;
}
void visitTextureEffects(const std::function<void(const GrTextureEffect&)>&) const;
const GrXferProcessor& getXferProcessor() const {

View File

@ -43,11 +43,6 @@ public:
return fCoverageFragmentProcessor.get();
}
bool usesVaryingCoords() const {
return (fColorFragmentProcessor && fColorFragmentProcessor->usesVaryingCoords()) ||
(fCoverageFragmentProcessor && fCoverageFragmentProcessor->usesVaryingCoords());
}
const GrXferProcessor* xferProcessor() const {
SkASSERT(this->isFinalized());
return fXP.fProcessor;

View File

@ -137,10 +137,12 @@ private:
GrPathTessellator* GrPathCurveTessellator::Make(SkArenaAlloc* arena, const SkMatrix& viewMatrix,
const SkPMColor4f& color, DrawInnerFan drawInnerFan,
int numPathVerbs, const GrCaps& caps) {
int numPathVerbs, const GrPipeline& pipeline,
const GrCaps& caps) {
using PatchType = GrPathTessellationShader::PatchType;
GrPathTessellationShader* shader;
if (caps.shaderCaps()->tessellationSupport() &&
!pipeline.usesVaryingCoords() && // Our tessellation back door doesn't handle varyings.
numPathVerbs >= caps.minPathVerbsForHwTessellation()) {
shader = GrPathTessellationShader::MakeHardwareTessellationShader(arena, viewMatrix, color,
PatchType::kCurves);

View File

@ -25,7 +25,8 @@ public:
// Creates a curve tessellator with the shader type best suited for the given path description.
static GrPathTessellator* Make(SkArenaAlloc*, const SkMatrix& viewMatrix, const SkPMColor4f&,
DrawInnerFan, int numPathVerbs, const GrCaps&);
DrawInnerFan, int numPathVerbs, const GrPipeline&,
const GrCaps&);
void prepare(GrMeshDrawOp::Target*, const SkRect& cullBounds, const SkPath&,
const BreadcrumbTriangleList*) override;

View File

@ -192,7 +192,8 @@ void GrPathInnerTriangulateOp::prePreparePrograms(const GrTessellationShader::Pr
fTessellator = GrPathCurveTessellator::Make(args.fArena, fViewMatrix,
SK_PMColor4fTRANSPARENT,
GrPathCurveTessellator::DrawInnerFan::kNo,
fPath.countVerbs(), *args.fCaps);
fPath.countVerbs(), *pipelineForStencils,
*args.fCaps);
const GrUserStencilSettings* stencilPathSettings =
GrPathTessellationShader::StencilPathSettings(fPath.getFillType());
fStencilCurvesProgram = GrTessellationShader::MakeProgram(args, fTessellator->shader(),

View File

@ -113,11 +113,12 @@ void GrPathStencilCoverOp::prePreparePrograms(const GrTessellationShader::Progra
fTessellator = GrPathCurveTessellator::Make(args.fArena, fViewMatrix,
SK_PMColor4fTRANSPARENT,
GrPathCurveTessellator::DrawInnerFan::kNo,
fPath.countVerbs(), *args.fCaps);
fPath.countVerbs(), *stencilPipeline,
*args.fCaps);
} else {
fTessellator = GrPathWedgeTessellator::Make(args.fArena, fViewMatrix,
SK_PMColor4fTRANSPARENT, fPath.countVerbs(),
*args.fCaps);
*stencilPipeline, *args.fCaps);
}
fStencilPathProgram = GrTessellationShader::MakeProgram(args, fTessellator->shader(),
stencilPipeline, stencilPathSettings);

View File

@ -227,10 +227,11 @@ private:
GrPathTessellator* GrPathWedgeTessellator::Make(SkArenaAlloc* arena, const SkMatrix& viewMatrix,
const SkPMColor4f& color, int numPathVerbs,
const GrCaps& caps) {
const GrPipeline& pipeline, const GrCaps& caps) {
using PatchType = GrPathTessellationShader::PatchType;
GrPathTessellationShader* shader;
if (caps.shaderCaps()->tessellationSupport() &&
!pipeline.usesVaryingCoords() && // Our tessellation back door doesn't handle varyings.
numPathVerbs >= caps.minPathVerbsForHwTessellation()) {
shader = GrPathTessellationShader::MakeHardwareTessellationShader(arena, viewMatrix, color,
PatchType::kWedges);

View File

@ -19,7 +19,7 @@ class GrPathWedgeTessellator : public GrPathTessellator {
public:
// Creates a wedge tessellator with the shader type best suited for the given path description.
static GrPathTessellator* Make(SkArenaAlloc*, const SkMatrix& viewMatrix, const SkPMColor4f&,
int numPathVerbs, const GrCaps&);
int numPathVerbs, const GrPipeline&, const GrCaps&);
void prepare(GrMeshDrawOp::Target*, const SkRect& cullBounds, const SkPath&,
const BreadcrumbTriangleList*) override;

View File

@ -146,12 +146,11 @@ constexpr static GrUserStencilSettings kTestAndResetStencil(
GrUserStencilOp::kReplace,
0xffff>());
bool GrStrokeTessellateOp::canUseHardwareTessellation(int numVerbs, const GrCaps& caps) {
SkASSERT(!fStencilProgram && !fFillProgram); // Ensure we haven't std::moved fProcessors.
bool can_use_hardware_tessellation(int numVerbs, const GrPipeline& pipeline, const GrCaps& caps) {
if (!caps.shaderCaps()->tessellationSupport()) {
return false;
}
if (fProcessors.usesVaryingCoords()) {
if (pipeline.usesVaryingCoords()) {
// Our back door for HW tessellation shaders isn't currently capable of passing varyings to
// the fragment shader, so if the processors have varyings, we need to use instanced draws
// instead.
@ -185,7 +184,10 @@ void GrStrokeTessellateOp::prePrepareTessellator(GrTessellationShader::ProgramAr
}
SkRect strokeCullBounds = this->bounds().makeOutset(devInflationRadius, devInflationRadius);
if (this->canUseHardwareTessellation(fTotalCombinedVerbCnt, caps)) {
auto* pipeline = GrTessellationShader::MakePipeline(args, fAAType, std::move(clip),
std::move(fProcessors));
if (can_use_hardware_tessellation(fTotalCombinedVerbCnt, *pipeline, caps)) {
// Only use hardware tessellation if we're drawing a somewhat large number of verbs.
// Otherwise we seem to be better off using instanced draws.
fTessellator = arena->make<GrStrokeHardwareTessellator>(fShaderFlags, *caps.shaderCaps(),
@ -199,8 +201,6 @@ void GrStrokeTessellateOp::prePrepareTessellator(GrTessellationShader::ProgramAr
strokeCullBounds);
}
auto* pipeline = GrTessellationShader::MakePipeline(args, fAAType, std::move(clip),
std::move(fProcessors));
auto fillStencil = &GrUserStencilSettings::kUnused;
if (fNeedsStencil) {
fStencilProgram = GrTessellationShader::MakeProgram(args, fTessellator->shader(), pipeline,

View File

@ -41,8 +41,6 @@ private:
return allStatesEnabled || (fTotalCombinedVerbCnt <= kMaxVerbsToEnableDynamicState);
}
bool canUseHardwareTessellation(int numVerbs, const GrCaps& caps);
const char* name() const override { return "GrStrokeTessellateOp"; }
void visitProxies(const VisitProxyFunc& fn) const override;
bool usesMSAA() const override { return fAAType == GrAAType::kMSAA; }