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:
parent
03f1d12b64
commit
bd727d0620
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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(),
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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(),
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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; }
|
||||
|
Loading…
Reference in New Issue
Block a user