From 64d06ba8973b366f771986357d4ee521f48462f7 Mon Sep 17 00:00:00 2001 From: Chris Dalton Date: Tue, 25 May 2021 15:16:29 -0600 Subject: [PATCH] Delete identity matrix shaders from tessellation Every shader always has a matrix now. The 4 FMAs (literally) that this saved by specializing the shader weren't worth it. Bug: skia:10419 Change-Id: I506dbd6d723f6dd022345956fdb5b60b0dd94932 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/412416 Reviewed-by: Brian Salomon Commit-Queue: Chris Dalton --- src/gpu/tessellate/GrFillPathShader.cpp | 39 ++++++++------- src/gpu/tessellate/GrFillPathShader.h | 12 ++--- src/gpu/tessellate/GrStencilPathShader.cpp | 49 +++++++++---------- src/gpu/tessellate/GrStencilPathShader.h | 4 +- .../GrStrokeInstancedShaderImpl.cpp | 22 ++++----- src/gpu/tessellate/GrStrokeShader.cpp | 15 ++---- .../GrStrokeTessellationShaderImpl.cpp | 46 ++++++++--------- 7 files changed, 86 insertions(+), 101 deletions(-) diff --git a/src/gpu/tessellate/GrFillPathShader.cpp b/src/gpu/tessellate/GrFillPathShader.cpp index a91736bdaf..ad9f72d357 100644 --- a/src/gpu/tessellate/GrFillPathShader.cpp +++ b/src/gpu/tessellate/GrFillPathShader.cpp @@ -17,14 +17,18 @@ public: void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override { auto& shader = args.fGeomProc.cast(); - const char* viewMatrix; - fViewMatrixUniform = args.fUniformHandler->addUniform( - nullptr, kVertex_GrShaderFlag, kFloat3x3_GrSLType, "view_matrix", &viewMatrix); - args.fVaryingHandler->emitAttributes(shader); + const char* affineMatrix, *translate; + fAffineMatrixUniform = args.fUniformHandler->addUniform( + nullptr, kVertex_GrShaderFlag, kFloat4_GrSLType, "affineMatrix", &affineMatrix); + fTranslateUniform = args.fUniformHandler->addUniform( + nullptr, kVertex_GrShaderFlag, kFloat2_GrSLType, "translate", &translate); + + args.fVertBuilder->codeAppendf("float2x2 AFFINE_MATRIX = float2x2(%s);", affineMatrix); + args.fVertBuilder->codeAppendf("float2 TRANSLATE = %s;", translate); args.fVertBuilder->codeAppend("float2 localcoord, vertexpos;"); - shader.emitVertexCode(this, args.fVertBuilder, viewMatrix, args.fUniformHandler); + shader.emitVertexCode(this, args.fVertBuilder, args.fUniformHandler); gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertexpos"); gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "localcoord"); @@ -41,13 +45,16 @@ public: const GrShaderCaps&, const GrGeometryProcessor& geomProc) override { const GrFillPathShader& shader = geomProc.cast(); - pdman.setSkMatrix(fViewMatrixUniform, shader.viewMatrix()); + const SkMatrix& m = shader.viewMatrix(); + pdman.set4f(fAffineMatrixUniform, m.getScaleX(), m.getSkewY(), m.getSkewX(), m.getScaleY()); + pdman.set2f(fTranslateUniform, m.getTranslateX(), m.getTranslateY()); const SkPMColor4f& color = shader.fColor; pdman.set4f(fColorUniform, color.fR, color.fG, color.fB, color.fA); } - GrGLSLUniformHandler::UniformHandle fViewMatrixUniform; + GrGLSLUniformHandler::UniformHandle fAffineMatrixUniform; + GrGLSLUniformHandler::UniformHandle fTranslateUniform; GrGLSLUniformHandler::UniformHandle fColorUniform; }; @@ -55,14 +62,14 @@ GrGLSLGeometryProcessor* GrFillPathShader::createGLSLInstance(const GrShaderCaps return new Impl; } -void GrFillTriangleShader::emitVertexCode(Impl*, GrGLSLVertexBuilder* v, const char* viewMatrix, +void GrFillTriangleShader::emitVertexCode(Impl*, GrGLSLVertexBuilder* v, GrGLSLUniformHandler* uniformHandler) const { - v->codeAppendf(R"( + v->codeAppend(R"( localcoord = input_point; - vertexpos = (%s * float3(localcoord, 1)).xy;)", viewMatrix); + vertexpos = AFFINE_MATRIX * localcoord + TRANSLATE;)"); } -void GrFillCubicHullShader::emitVertexCode(Impl*, GrGLSLVertexBuilder* v, const char* viewMatrix, +void GrFillCubicHullShader::emitVertexCode(Impl*, GrGLSLVertexBuilder* v, GrGLSLUniformHandler* uniformHandler) const { v->codeAppend(R"( float4x2 P = float4x2(input_points_0_1, input_points_2_3); @@ -118,21 +125,19 @@ void GrFillCubicHullShader::emitVertexCode(Impl*, GrGLSLVertexBuilder* v, const vertexidx = (vertexidx + 1) & 3; } - localcoord = P[vertexidx];)"); - - v->codeAppendf("vertexpos = (%s * float3(localcoord, 1)).xy;", viewMatrix); + localcoord = P[vertexidx]; + vertexpos = AFFINE_MATRIX * localcoord + TRANSLATE;)"); } void GrFillBoundingBoxShader::emitVertexCode(Impl* impl, GrGLSLVertexBuilder* v, - const char* viewMatrix, GrGLSLUniformHandler* uniformHandler) const { v->codeAppendf(R"( // Bloat the bounding box by 1/4px to avoid potential T-junctions at the edges. - float2x2 M_ = inverse(float2x2(%s)); + float2x2 M_ = inverse(AFFINE_MATRIX); float2 bloat = float2(abs(M_[0]) + abs(M_[1])) * .25; // Find the vertex position. float2 T = float2(sk_VertexID & 1, sk_VertexID >> 1); localcoord = mix(pathBounds.xy - bloat, pathBounds.zw + bloat, T); - vertexpos = (%s * float3(localcoord, 1)).xy;)", viewMatrix, viewMatrix); + vertexpos = AFFINE_MATRIX * localcoord + TRANSLATE;)"); } diff --git a/src/gpu/tessellate/GrFillPathShader.h b/src/gpu/tessellate/GrFillPathShader.h index 10597698d0..53cf455d13 100644 --- a/src/gpu/tessellate/GrFillPathShader.h +++ b/src/gpu/tessellate/GrFillPathShader.h @@ -56,8 +56,7 @@ public: protected: class Impl; - virtual void emitVertexCode(Impl*, GrGLSLVertexBuilder*, const char* viewMatrix, - GrGLSLUniformHandler*) const = 0; + virtual void emitVertexCode(Impl*, GrGLSLVertexBuilder*, GrGLSLUniformHandler*) const = 0; private: const SkPMColor4f fColor; @@ -76,8 +75,7 @@ public: private: const char* name() const override { return "GrFillTriangleShader"; } - void emitVertexCode(Impl*, GrGLSLVertexBuilder*, const char* viewMatrix, - GrGLSLUniformHandler*) const override; + void emitVertexCode(Impl*, GrGLSLVertexBuilder*, GrGLSLUniformHandler*) const override; }; // Fills an array of convex hulls surrounding 4-point cubic instances. @@ -94,8 +92,7 @@ public: private: const char* name() const override { return "GrFillCubicHullShader"; } - void emitVertexCode(Impl*, GrGLSLVertexBuilder*, const char* viewMatrix, - GrGLSLUniformHandler*) const override; + void emitVertexCode(Impl*, GrGLSLVertexBuilder*, GrGLSLUniformHandler*) const override; }; // Fills a path's bounding box, with subpixel outset to avoid possible T-junctions with extreme @@ -114,8 +111,7 @@ public: private: const char* name() const override { return "GrFillBoundingBoxShader"; } - void emitVertexCode(Impl*, GrGLSLVertexBuilder*, const char* viewMatrix, - GrGLSLUniformHandler*) const override; + void emitVertexCode(Impl*, GrGLSLVertexBuilder*, GrGLSLUniformHandler*) const override; }; #endif diff --git a/src/gpu/tessellate/GrStencilPathShader.cpp b/src/gpu/tessellate/GrStencilPathShader.cpp index 52344c3850..516d28444f 100644 --- a/src/gpu/tessellate/GrStencilPathShader.cpp +++ b/src/gpu/tessellate/GrStencilPathShader.cpp @@ -57,24 +57,23 @@ protected: args.fVaryingHandler->emitAttributes(shader); auto v = args.fVertBuilder; - GrShaderVar vertexPos = (*shader.vertexAttributes().begin()).asShaderVar(); - if (!shader.viewMatrix().isIdentity()) { - const char* viewMatrix; - fViewMatrixUniform = args.fUniformHandler->addUniform( - nullptr, kVertex_GrShaderFlag, kFloat3x3_GrSLType, "view_matrix", &viewMatrix); - v->codeAppendf("float2 vertexpos = (%s * float3(inputPoint, 1)).xy;", viewMatrix); - if (shader.willUseTessellationShaders()) { - // If y is infinity then x is a conic weight. Don't transform. - v->codeAppendf("vertexpos = (isinf(inputPoint.y)) ? inputPoint : vertexpos;"); - } - vertexPos.set(kFloat2_GrSLType, "vertexpos"); + const char* affineMatrix, *translate; + fAffineMatrixUniform = args.fUniformHandler->addUniform( + nullptr, kVertex_GrShaderFlag, kFloat4_GrSLType, "affineMatrix", &affineMatrix); + fTranslateUniform = args.fUniformHandler->addUniform( + nullptr, kVertex_GrShaderFlag, kFloat2_GrSLType, "translate", &translate); + v->codeAppendf("float2 vertexpos = float2x2(%s) * inputPoint + %s;", + affineMatrix, translate); + if (shader.willUseTessellationShaders()) { + // If y is infinity then x is a conic weight. Don't transform. + v->codeAppendf("vertexpos = (isinf(inputPoint.y)) ? inputPoint : vertexpos;"); } if (!shader.willUseTessellationShaders()) { // This is the case for the triangle shader. - gpArgs->fPositionVar = vertexPos; + gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertexpos"); } else { v->declareGlobal(GrShaderVar("P", kFloat2_GrSLType, GrShaderVar::TypeModifier::Out)); - v->codeAppendf("P = %s;", vertexPos.c_str()); + v->codeAppendf("P = %s;", "vertexpos"); } // The fragment shader is normally disabled, but output fully opaque white. @@ -85,13 +84,13 @@ protected: void setData(const GrGLSLProgramDataManager& pdman, const GrShaderCaps&, const GrGeometryProcessor& geomProc) override { - const auto& shader = geomProc.cast(); - if (!shader.viewMatrix().isIdentity()) { - pdman.setSkMatrix(fViewMatrixUniform, shader.viewMatrix()); - } + const SkMatrix& m = geomProc.cast().viewMatrix(); + pdman.set4f(fAffineMatrixUniform, m.getScaleX(), m.getSkewY(), m.getSkewX(), m.getScaleY()); + pdman.set2f(fTranslateUniform, m.getTranslateX(), m.getTranslateY()); } - GrGLSLUniformHandler::UniformHandle fViewMatrixUniform; + GrGLSLUniformHandler::UniformHandle fAffineMatrixUniform; + GrGLSLUniformHandler::UniformHandle fTranslateUniform; }; GrGLSLGeometryProcessor* GrStencilPathShader::createGLSLInstance(const GrShaderCaps&) const { @@ -375,13 +374,13 @@ class GrCurveMiddleOutShader::Impl : public GrStencilPathShader::Impl { float T = find_middle_out_T(); pos = eval_rational_cubic(P, T); })"); - if (!shader.viewMatrix().isIdentity()) { - const char* viewMatrix; - fViewMatrixUniform = args.fUniformHandler->addUniform( - nullptr, kVertex_GrShaderFlag, kFloat3x3_GrSLType, "view_matrix", &viewMatrix); - args.fVertBuilder->codeAppendf(R"( - pos = (%s * float3(pos, 1)).xy;)", viewMatrix); - } + const char* affineMatrix, *translate; + fAffineMatrixUniform = args.fUniformHandler->addUniform( + nullptr, kVertex_GrShaderFlag, kFloat4_GrSLType, "affineMatrix", &affineMatrix); + fTranslateUniform = args.fUniformHandler->addUniform( + nullptr, kVertex_GrShaderFlag, kFloat2_GrSLType, "translate", &translate); + args.fVertBuilder->codeAppendf(R"( + pos = float2x2(%s) * pos + %s;)", affineMatrix, translate); gpArgs->fPositionVar.set(kFloat2_GrSLType, "pos"); // The fragment shader is normally disabled, but output fully opaque white. diff --git a/src/gpu/tessellate/GrStencilPathShader.h b/src/gpu/tessellate/GrStencilPathShader.h index a938812597..a5c1990cec 100644 --- a/src/gpu/tessellate/GrStencilPathShader.h +++ b/src/gpu/tessellate/GrStencilPathShader.h @@ -85,9 +85,7 @@ public: protected: constexpr static Attribute kSinglePointAttrib{"inputPoint", kFloat2_GrVertexAttribType, kFloat2_GrSLType}; - void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override { - b->add32(this->viewMatrix().isIdentity()); - } + void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {} GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const override; class Impl; diff --git a/src/gpu/tessellate/GrStrokeInstancedShaderImpl.cpp b/src/gpu/tessellate/GrStrokeInstancedShaderImpl.cpp index 0374666cfe..02c8d62223 100644 --- a/src/gpu/tessellate/GrStrokeInstancedShaderImpl.cpp +++ b/src/gpu/tessellate/GrStrokeInstancedShaderImpl.cpp @@ -79,17 +79,15 @@ void GrStrokeInstancedShaderImpl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { } // View matrix uniforms. - if (!shader.viewMatrix().isIdentity()) { - const char* translateName, *affineMatrixName; - fAffineMatrixUniform = args.fUniformHandler->addUniform( - nullptr, kVertex_GrShaderFlag, kFloat4_GrSLType, "affineMatrix", - &affineMatrixName); - fTranslateUniform = args.fUniformHandler->addUniform( - nullptr, kVertex_GrShaderFlag, kFloat2_GrSLType, "translate", &translateName); - args.fVertBuilder->codeAppendf("float2x2 AFFINE_MATRIX = float2x2(%s);\n", - affineMatrixName); - args.fVertBuilder->codeAppendf("float2 TRANSLATE = %s;\n", translateName); - } + const char* translateName, *affineMatrixName; + fAffineMatrixUniform = args.fUniformHandler->addUniform(nullptr, kVertex_GrShaderFlag, + kFloat4_GrSLType, "affineMatrix", + &affineMatrixName); + fTranslateUniform = args.fUniformHandler->addUniform(nullptr, kVertex_GrShaderFlag, + kFloat2_GrSLType, "translate", + &translateName); + args.fVertBuilder->codeAppendf("float2x2 AFFINE_MATRIX = float2x2(%s);\n", affineMatrixName); + args.fVertBuilder->codeAppendf("float2 TRANSLATE = %s;\n", translateName); // Tessellation code. args.fVertBuilder->codeAppend(R"( @@ -103,7 +101,7 @@ void GrStrokeInstancedShaderImpl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { P[3] = P[2]; // Setting p3 equal to p2 works for the remaining rotational logic. })"); } - if (shader.stroke().isHairlineStyle() && !shader.viewMatrix().isIdentity()) { + if (shader.stroke().isHairlineStyle()) { // Hairline case. Transform the points before tessellation. We can still hold off on the // translate until the end; we just need to perform the scale and skew right now. args.fVertBuilder->codeAppend(R"( diff --git a/src/gpu/tessellate/GrStrokeShader.cpp b/src/gpu/tessellate/GrStrokeShader.cpp index 661b5e0ff5..5abed42266 100644 --- a/src/gpu/tessellate/GrStrokeShader.cpp +++ b/src/gpu/tessellate/GrStrokeShader.cpp @@ -251,11 +251,7 @@ void GrStrokeShaderImpl::emitTessellationCode(const GrStrokeShader& shader, SkSt float2 ortho = normalize(float2(tangent.y, -tangent.x)); strokeCoord += ortho * (STROKE_RADIUS * strokeOutset);)"); - if (shader.viewMatrix().isIdentity()) { - // No transform matrix. - gpArgs->fPositionVar.set(kFloat2_GrSLType, "strokeCoord"); - gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "strokeCoord"); - } else if (!shader.stroke().isHairlineStyle()) { + if (!shader.stroke().isHairlineStyle()) { // Normal case. Do the transform after tessellation. code->append(R"( float2 devCoord = AFFINE_MATRIX * strokeCoord + TRANSLATE;)"); @@ -322,11 +318,9 @@ void GrStrokeShaderImpl::setData(const GrGLSLProgramDataManager& pdman, const Gr // Set up the view matrix, if any. const SkMatrix& m = shader.viewMatrix(); - if (!m.isIdentity()) { - pdman.set2f(fTranslateUniform, m.getTranslateX(), m.getTranslateY()); - pdman.set4f(fAffineMatrixUniform, m.getScaleX(), m.getSkewY(), m.getSkewX(), - m.getScaleY()); - } + pdman.set2f(fTranslateUniform, m.getTranslateX(), m.getTranslateY()); + pdman.set4f(fAffineMatrixUniform, m.getScaleX(), m.getSkewY(), m.getSkewX(), + m.getScaleY()); if (!shader.hasDynamicColor()) { pdman.set4fv(fColorUniform, 1, shader.color().vec()); @@ -344,7 +338,6 @@ void GrStrokeShader::getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuil key = (key << 2) | (uint32_t)fMode; key = (key << 2) | ((keyNeedsJoin) ? fStroke.getJoin() : 0); key = (key << 1) | (uint32_t)fStroke.isHairlineStyle(); - key = (key << 1) | (uint32_t)this->viewMatrix().isIdentity(); b->add32(key); } diff --git a/src/gpu/tessellate/GrStrokeTessellationShaderImpl.cpp b/src/gpu/tessellate/GrStrokeTessellationShaderImpl.cpp index f7d2a6fcca..169cca82be 100644 --- a/src/gpu/tessellate/GrStrokeTessellationShaderImpl.cpp +++ b/src/gpu/tessellate/GrStrokeTessellationShaderImpl.cpp @@ -87,22 +87,20 @@ void GrStrokeTessellationShaderImpl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs float JOIN_TYPE = dynamicStrokeAttr.y;)", parametricPrecisionName); } - if (!shader.viewMatrix().isIdentity()) { - fTranslateUniform = uniHandler->addUniform(nullptr, kTessEvaluation_GrShaderFlag, - kFloat2_GrSLType, "translate", nullptr); - const char* affineMatrixName; - // Hairlines apply the affine matrix in their vertex shader, prior to tessellation. - // Otherwise the entire view matrix gets applied at the end of the tess eval shader. - auto affineMatrixVisibility = kTessEvaluation_GrShaderFlag; - if (shader.stroke().isHairlineStyle()) { - affineMatrixVisibility |= kVertex_GrShaderFlag; - } - fAffineMatrixUniform = uniHandler->addUniform(nullptr, affineMatrixVisibility, - kFloat4_GrSLType, "affineMatrix", - &affineMatrixName); - if (affineMatrixVisibility & kVertex_GrShaderFlag) { - v->codeAppendf("float2x2 AFFINE_MATRIX = float2x2(%s);\n", affineMatrixName); - } + fTranslateUniform = uniHandler->addUniform(nullptr, kTessEvaluation_GrShaderFlag, + kFloat2_GrSLType, "translate", nullptr); + // View matrix uniforms. + const char* affineMatrixName; + // Hairlines apply the affine matrix in their vertex shader, prior to tessellation. + // Otherwise the entire view matrix gets applied at the end of the tess eval shader. + auto affineMatrixVisibility = kTessEvaluation_GrShaderFlag; + if (shader.stroke().isHairlineStyle()) { + affineMatrixVisibility |= kVertex_GrShaderFlag; + } + fAffineMatrixUniform = uniHandler->addUniform(nullptr, affineMatrixVisibility, kFloat4_GrSLType, + "affineMatrix", &affineMatrixName); + if (affineMatrixVisibility & kVertex_GrShaderFlag) { + v->codeAppendf("float2x2 AFFINE_MATRIX = float2x2(%s);\n", affineMatrixName); } v->codeAppend(R"( @@ -110,7 +108,7 @@ void GrStrokeTessellationShaderImpl::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs float2 prevControlPoint = prevCtrlPtAttr; float4x2 P = float4x2(pts01Attr, pts23Attr);)"); - if (shader.stroke().isHairlineStyle() && !shader.viewMatrix().isIdentity()) { + if (shader.stroke().isHairlineStyle()) { // Hairline case. Transform the points before tessellation. We can still hold off on the // translate until the end; we just need to perform the scale and skew right now. if (shader.hasConics()) { @@ -558,14 +556,12 @@ SkString GrStrokeTessellationShaderImpl::getTessEvaluationShaderGLSL( code.appendf("#define STROKE_RADIUS tcsStrokeRadius\n"); } - if (!shader.viewMatrix().isIdentity()) { - const char* translateName = uniformHandler.getUniformCStr(fTranslateUniform); - code.appendf("uniform vec2 %s;\n", translateName); - code.appendf("#define TRANSLATE %s\n", translateName); - const char* affineMatrixName = uniformHandler.getUniformCStr(fAffineMatrixUniform); - code.appendf("uniform vec4 %s;\n", affineMatrixName); - code.appendf("#define AFFINE_MATRIX mat2(%s)\n", affineMatrixName); - } + const char* translateName = uniformHandler.getUniformCStr(fTranslateUniform); + code.appendf("uniform vec2 %s;\n", translateName); + code.appendf("#define TRANSLATE %s\n", translateName); + const char* affineMatrixName = uniformHandler.getUniformCStr(fAffineMatrixUniform); + code.appendf("uniform vec4 %s;\n", affineMatrixName); + code.appendf("#define AFFINE_MATRIX mat2(%s)\n", affineMatrixName); code.append(R"( in vec4 tcsPts01[];