No VS specialization for identity or scale/trans in reduced shader mode

Modifies helpers on GrGLSLGeometryProcessor that insert, set, and make
keys for view/local matrix uniforms to not omit the uniform when
the matrix is identity or use a float4 when it is scale/trans. Always
uses a 3x3.

Bug: skia:11844
Change-Id: I0f25b60b46b8932d7e2cac4a50159d22b9cd84d2
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/395656
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/bench/VertexColorSpaceBench.cpp b/bench/VertexColorSpaceBench.cpp
index 2a79362..78e9099 100644
--- a/bench/VertexColorSpaceBench.cpp
+++ b/bench/VertexColorSpaceBench.cpp
@@ -75,12 +75,13 @@
                 fragBuilder->codeAppendf("half4 %s = %s;", args.fOutputColor, varying.fsIn());
 
                 // Position
-                this->writeOutputPosition(args.fVertBuilder, gpArgs, gp.fInPosition.name());
+                WriteOutputPosition(args.fVertBuilder, gpArgs, gp.fInPosition.name());
 
                 // Coverage
                 fragBuilder->codeAppendf("const half4 %s = half4(1);", args.fOutputCoverage);
             }
             void setData(const GrGLSLProgramDataManager& pdman,
+                         const GrShaderCaps&,
                          const GrGeometryProcessor& geomProc) override {
                 const GP& gp = geomProc.cast<GP>();
                 fColorSpaceHelper.setData(pdman, gp.fColorSpaceXform.get());
diff --git a/gm/clockwise.cpp b/gm/clockwise.cpp
index bfa7909..07d4967 100644
--- a/gm/clockwise.cpp
+++ b/gm/clockwise.cpp
@@ -104,7 +104,9 @@
 };
 
 class GLSLClockwiseTestProcessor : public GrGLSLGeometryProcessor {
-    void setData(const GrGLSLProgramDataManager&, const GrGeometryProcessor&) override {}
+    void setData(const GrGLSLProgramDataManager&,
+                 const GrShaderCaps&,
+                 const GrGeometryProcessor&) override {}
 
     void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
         const ClockwiseTestProcessor& proc = args.fGeomProc.cast<ClockwiseTestProcessor>();
diff --git a/gm/fwidth_squircle.cpp b/gm/fwidth_squircle.cpp
index 2998721..53c1b8e 100644
--- a/gm/fwidth_squircle.cpp
+++ b/gm/fwidth_squircle.cpp
@@ -126,6 +126,7 @@
     }
 
     void setData(const GrGLSLProgramDataManager& pdman,
+                 const GrShaderCaps&,
                  const GrGeometryProcessor& geomProc) override {
         const auto& proc = geomProc.cast<FwidthSquircleTestProcessor>();
         pdman.setSkMatrix(fViewMatrixHandle, proc.fViewMatrix);
diff --git a/gm/tessellation.cpp b/gm/tessellation.cpp
index 1562d1b..e27fa42 100644
--- a/gm/tessellation.cpp
+++ b/gm/tessellation.cpp
@@ -79,6 +79,7 @@
         }
         void writeFragmentShader(GrGLSLFPFragmentBuilder*, const char* color, const char* coverage);
         void setData(const GrGLSLProgramDataManager& pdman,
+                     const GrShaderCaps&,
                      const GrGeometryProcessor& geomProc) override {
             pdman.setSkMatrix(fViewMatrixUniform,
                               geomProc.cast<TessellationTestTriShader>().fViewMatrix);
@@ -201,6 +202,7 @@
         }
         void writeFragmentShader(GrGLSLFPFragmentBuilder*, const char* color, const char* coverage);
         void setData(const GrGLSLProgramDataManager& pdman,
+                     const GrShaderCaps&,
                      const GrGeometryProcessor& geomProc) override {
             pdman.setSkMatrix(fViewMatrixUniform,
                               geomProc.cast<TessellationTestRectShader>().fViewMatrix);
diff --git a/src/gpu/GrDefaultGeoProcFactory.cpp b/src/gpu/GrDefaultGeoProcFactory.cpp
index cc63d52..dc36fc1 100644
--- a/src/gpu/GrDefaultGeoProcFactory.cpp
+++ b/src/gpu/GrDefaultGeoProcFactory.cpp
@@ -107,21 +107,26 @@
             }
 
             // Setup position
-            this->writeOutputPosition(vertBuilder,
-                                      uniformHandler,
-                                      gpArgs,
-                                      gp.fInPosition.name(),
-                                      gp.viewMatrix(),
-                                      &fViewMatrixUniform);
+            WriteOutputPosition(vertBuilder,
+                                uniformHandler,
+                                *args.fShaderCaps,
+                                gpArgs,
+                                gp.fInPosition.name(),
+                                gp.viewMatrix(),
+                                &fViewMatrixUniform);
 
             // emit transforms using either explicit local coords or positions
             if (gp.fInLocalCoords.isInitialized()) {
                 SkASSERT(gp.localMatrix().isIdentity());
                 gpArgs->fLocalCoordVar = gp.fInLocalCoords.asShaderVar();
             } else if (gp.fLocalCoordsWillBeRead) {
-                this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs,
-                                      gp.fInPosition.asShaderVar(), gp.localMatrix(),
-                                      &fLocalMatrixUniform);
+                WriteLocalCoord(vertBuilder,
+                                uniformHandler,
+                                *args.fShaderCaps,
+                                gpArgs,
+                                gp.fInPosition.asShaderVar(),
+                                gp.localMatrix(),
+                                &fLocalMatrixUniform);
             }
 
             // Setup coverage as pass through
@@ -144,7 +149,7 @@
         }
 
         static inline void GenKey(const GrGeometryProcessor& gp,
-                                  const GrShaderCaps&,
+                                  const GrShaderCaps& shaderCaps,
                                   GrProcessorKeyBuilder* b) {
             const DefaultGeoProc& def = gp.cast<DefaultGeoProc>();
             uint32_t key = def.fFlags;
@@ -153,17 +158,24 @@
 
             bool usesLocalMatrix = def.localCoordsWillBeRead() &&
                                    !def.fInLocalCoords.isInitialized();
-            key = AddMatrixKeys(key, def.viewMatrix(),
+            key = AddMatrixKeys(shaderCaps,
+                                key,
+                                def.viewMatrix(),
                                 usesLocalMatrix ? def.localMatrix() : SkMatrix::I());
             b->add32(key);
         }
 
         void setData(const GrGLSLProgramDataManager& pdman,
+                     const GrShaderCaps& shaderCaps,
                      const GrGeometryProcessor& geomProc) override {
             const DefaultGeoProc& dgp = geomProc.cast<DefaultGeoProc>();
 
-            this->setTransform(pdman, fViewMatrixUniform, dgp.viewMatrix(), &fViewMatrixPrev);
-            this->setTransform(pdman, fLocalMatrixUniform, dgp.localMatrix(), &fLocalMatrixPrev);
+            SetTransform(pdman, shaderCaps, fViewMatrixUniform, dgp.viewMatrix(), &fViewMatrixPrev);
+            SetTransform(pdman,
+                         shaderCaps,
+                         fLocalMatrixUniform,
+                         dgp.localMatrix(),
+                         &fLocalMatrixPrev);
 
             if (!dgp.hasVertexColor() && dgp.color() != fColor) {
                 pdman.set4fv(fColorUniform, 1, dgp.color().vec());
diff --git a/src/gpu/d3d/GrD3DPipelineState.cpp b/src/gpu/d3d/GrD3DPipelineState.cpp
index 0734b8c..0eb671d 100644
--- a/src/gpu/d3d/GrD3DPipelineState.cpp
+++ b/src/gpu/d3d/GrD3DPipelineState.cpp
@@ -46,7 +46,7 @@
                                              const GrProgramInfo& programInfo) {
     this->setRenderTargetState(renderTarget, programInfo.origin());
 
-    fGeometryProcessor->setData(fDataManager, programInfo.geomProc());
+    fGeometryProcessor->setData(fDataManager, *gpu->caps()->shaderCaps(), programInfo.geomProc());
     for (int i = 0; i < programInfo.pipeline().numFragmentProcessors(); ++i) {
         auto& fp = programInfo.pipeline().getFragmentProcessor(i);
         for (auto [fp, impl] : GrGLSLFragmentProcessor::ParallelRange(fp, *fFPImpls[i])) {
diff --git a/src/gpu/dawn/GrDawnProgramBuilder.cpp b/src/gpu/dawn/GrDawnProgramBuilder.cpp
index 8a7b733..e75d894 100644
--- a/src/gpu/dawn/GrDawnProgramBuilder.cpp
+++ b/src/gpu/dawn/GrDawnProgramBuilder.cpp
@@ -498,7 +498,7 @@
     this->setRenderTargetState(renderTarget, programInfo.origin());
     const GrPipeline& pipeline = programInfo.pipeline();
     const GrGeometryProcessor& geomProc = programInfo.geomProc();
-    fGeometryProcessor->setData(fDataManager, geomProc);
+    fGeometryProcessor->setData(fDataManager, *gpu->caps()->shaderCaps(), geomProc);
 
     for (int i = 0; i < programInfo.pipeline().numFragmentProcessors(); ++i) {
         auto& fp = programInfo.pipeline().getFragmentProcessor(i);
diff --git a/src/gpu/effects/GrBezierEffect.cpp b/src/gpu/effects/GrBezierEffect.cpp
index 73d160f..fa4632b 100644
--- a/src/gpu/effects/GrBezierEffect.cpp
+++ b/src/gpu/effects/GrBezierEffect.cpp
@@ -25,11 +25,12 @@
                               GrProcessorKeyBuilder*);
 
     void setData(const GrGLSLProgramDataManager& pdman,
+                 const GrShaderCaps& shaderCaps,
                  const GrGeometryProcessor& geomProc) override {
         const GrConicEffect& ce = geomProc.cast<GrConicEffect>();
 
-        this->setTransform(pdman, fViewMatrixUniform, ce.viewMatrix(), &fViewMatrix);
-        this->setTransform(pdman, fLocalMatrixUniform, ce.localMatrix(), &fLocalMatrix);
+        SetTransform(pdman, shaderCaps,  fViewMatrixUniform,  ce.viewMatrix(), &fViewMatrix);
+        SetTransform(pdman, shaderCaps, fLocalMatrixUniform, ce.localMatrix(), &fLocalMatrix);
 
         if (ce.color() != fColor) {
             pdman.set4fv(fColorUniform, 1, ce.color().vec());
@@ -80,15 +81,21 @@
     this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform);
 
     // Setup position
-    this->writeOutputPosition(vertBuilder,
-                              uniformHandler,
-                              gpArgs,
-                              gp.inPosition().name(),
-                              gp.viewMatrix(),
-                              &fViewMatrixUniform);
+    WriteOutputPosition(vertBuilder,
+                        uniformHandler,
+                        *args.fShaderCaps,
+                        gpArgs,
+                        gp.inPosition().name(),
+                        gp.viewMatrix(),
+                        &fViewMatrixUniform);
     if (gp.usesLocalCoords()) {
-        this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, gp.inPosition().asShaderVar(),
-                              gp.localMatrix(), &fLocalMatrixUniform);
+        WriteLocalCoord(vertBuilder,
+                        uniformHandler,
+                        *args.fShaderCaps,
+                        gpArgs,
+                        gp.inPosition().asShaderVar(),
+                        gp.localMatrix(),
+                        &fLocalMatrixUniform);
     }
 
     // TODO: we should check on the number of bits float and half provide and use the smallest one
@@ -155,14 +162,16 @@
 }
 
 void GrGLConicEffect::GenKey(const GrGeometryProcessor& gp,
-                             const GrShaderCaps&,
+                             const GrShaderCaps& shaderCaps,
                              GrProcessorKeyBuilder* b) {
     const GrConicEffect& ce = gp.cast<GrConicEffect>();
     uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
     key |= 0xff != ce.coverageScale() ? 0x8 : 0x0;
     key |= ce.usesLocalCoords() ? 0x10 : 0x0;
-    key = AddMatrixKeys(key, ce.viewMatrix(), ce.usesLocalCoords() ? ce.localMatrix()
-                                                                   : SkMatrix::I());
+    key = AddMatrixKeys(shaderCaps,
+                        key,
+                        ce.viewMatrix(),
+                        ce.usesLocalCoords() ? ce.localMatrix() : SkMatrix::I());
     b->add32(key);
 }
 
@@ -220,11 +229,12 @@
                               GrProcessorKeyBuilder*);
 
     void setData(const GrGLSLProgramDataManager& pdman,
+                 const GrShaderCaps& shaderCaps,
                  const GrGeometryProcessor& geomProc) override {
         const GrQuadEffect& qe = geomProc.cast<GrQuadEffect>();
 
-        this->setTransform(pdman, fViewMatrixUniform, qe.viewMatrix(), &fViewMatrix);
-        this->setTransform(pdman, fLocalMatrixUniform, qe.localMatrix(), &fLocalMatrix);
+        SetTransform(pdman, shaderCaps,  fViewMatrixUniform,  qe.viewMatrix(), &fViewMatrix);
+        SetTransform(pdman, shaderCaps, fLocalMatrixUniform, qe.localMatrix(), &fLocalMatrix);
 
         if (qe.color() != fColor) {
             pdman.set4fv(fColorUniform, 1, qe.color().vec());
@@ -276,15 +286,21 @@
     this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform);
 
     // Setup position
-    this->writeOutputPosition(vertBuilder,
-                              uniformHandler,
-                              gpArgs,
-                              gp.inPosition().name(),
-                              gp.viewMatrix(),
-                              &fViewMatrixUniform);
+    WriteOutputPosition(vertBuilder,
+                        uniformHandler,
+                        *args.fShaderCaps,
+                        gpArgs,
+                        gp.inPosition().name(),
+                        gp.viewMatrix(),
+                        &fViewMatrixUniform);
     if (gp.usesLocalCoords()) {
-        this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, gp.inPosition().asShaderVar(),
-                              gp.localMatrix(), &fLocalMatrixUniform);
+        WriteLocalCoord(vertBuilder,
+                        uniformHandler,
+                        *args.fShaderCaps,
+                        gpArgs,
+                        gp.inPosition().asShaderVar(),
+                        gp.localMatrix(),
+                        &fLocalMatrixUniform);
     }
 
     fragBuilder->codeAppendf("half edgeAlpha;");
@@ -316,14 +332,16 @@
 }
 
 void GrGLQuadEffect::GenKey(const GrGeometryProcessor& gp,
-                            const GrShaderCaps&,
+                            const GrShaderCaps& shaderCaps,
                             GrProcessorKeyBuilder* b) {
     const GrQuadEffect& ce = gp.cast<GrQuadEffect>();
     uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
     key |= ce.coverageScale() != 0xff ? 0x8 : 0x0;
     key |= ce.usesLocalCoords()? 0x10 : 0x0;
-    key = AddMatrixKeys(key, ce.viewMatrix(), ce.usesLocalCoords() ? ce.localMatrix()
-                                                                   : SkMatrix::I());
+    key = AddMatrixKeys(shaderCaps,
+                        key,
+                        ce.viewMatrix(),
+                        ce.usesLocalCoords() ? ce.localMatrix() : SkMatrix::I());
     b->add32(key);
 }
 
diff --git a/src/gpu/effects/GrBitmapTextGeoProc.cpp b/src/gpu/effects/GrBitmapTextGeoProc.cpp
index 3331df8..9e1ba8b 100644
--- a/src/gpu/effects/GrBitmapTextGeoProc.cpp
+++ b/src/gpu/effects/GrBitmapTextGeoProc.cpp
@@ -55,8 +55,13 @@
 
         // Setup position
         gpArgs->fPositionVar = btgp.inPosition().asShaderVar();
-        this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, btgp.inPosition().asShaderVar(),
-                              btgp.localMatrix(), &fLocalMatrixUniform);
+        WriteLocalCoord(vertBuilder,
+                        uniformHandler,
+                        *args.fShaderCaps,
+                        gpArgs,
+                        btgp.inPosition().asShaderVar(),
+                        btgp.localMatrix(),
+                        &fLocalMatrixUniform);
 
         fragBuilder->codeAppend("half4 texColor;");
         append_multitexture_lookup(args, btgp.numTextureSamplers(),
@@ -72,6 +77,7 @@
     }
 
     void setData(const GrGLSLProgramDataManager& pdman,
+                 const GrShaderCaps& shaderCaps,
                  const GrGeometryProcessor& geomProc) override {
         const GrBitmapTextGeoProc& btgp = geomProc.cast<GrBitmapTextGeoProc>();
         if (btgp.color() != fColor && !btgp.hasVertexColor()) {
@@ -89,17 +95,19 @@
             fAtlasDimensions = atlasDimensions;
         }
 
-        this->setTransform(pdman, fLocalMatrixUniform, btgp.localMatrix(), &fLocalMatrix);
+        SetTransform(pdman, shaderCaps, fLocalMatrixUniform, btgp.localMatrix(), &fLocalMatrix);
     }
 
     static inline void GenKey(const GrGeometryProcessor& proc,
-                              const GrShaderCaps&,
+                              const GrShaderCaps& shaderCaps,
                               GrProcessorKeyBuilder* b) {
         const GrBitmapTextGeoProc& btgp = proc.cast<GrBitmapTextGeoProc>();
         b->addBool(btgp.usesW(), "usesW");
         static_assert(kLast_GrMaskFormat < (1u << 2));
         b->addBits(2, btgp.maskFormat(), "maskFormat");
-        b->addBits(kMatrixKeyBits, ComputeMatrixKey(btgp.localMatrix()), "localMatrixType");
+        b->addBits(kMatrixKeyBits,
+                   ComputeMatrixKey(shaderCaps, btgp.localMatrix()),
+                   "localMatrixType");
         b->add32(btgp.numTextureSamplers(),"numTextures");
     }
 
diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.cpp b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
index 413fe05..5cbdce7 100644
--- a/src/gpu/effects/GrDistanceFieldGeoProc.cpp
+++ b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
@@ -58,8 +58,13 @@
 
         // Setup position
         gpArgs->fPositionVar = dfTexEffect.inPosition().asShaderVar();
-        this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, gpArgs->fPositionVar,
-                              dfTexEffect.localMatrix(), &fLocalMatrixUniform);
+        WriteLocalCoord(vertBuilder,
+                        uniformHandler,
+                        *args.fShaderCaps,
+                        gpArgs,
+                        gpArgs->fPositionVar,
+                        dfTexEffect.localMatrix(),
+                        &fLocalMatrixUniform);
 
         // add varyings
         GrGLSLVarying uv, texIdx, st;
@@ -157,6 +162,7 @@
     }
 
     void setData(const GrGLSLProgramDataManager& pdman,
+                 const GrShaderCaps& shaderCaps,
                  const GrGeometryProcessor& geomProc) override {
         const GrDistanceFieldA8TextGeoProc& dfa8gp = geomProc.cast<GrDistanceFieldA8TextGeoProc>();
 
@@ -177,15 +183,15 @@
                         1.0f / atlasDimensions.fHeight);
             fAtlasDimensions = atlasDimensions;
         }
-        this->setTransform(pdman, fLocalMatrixUniform, dfa8gp.localMatrix(), &fLocalMatrix);
+        SetTransform(pdman, shaderCaps, fLocalMatrixUniform, dfa8gp.localMatrix(), &fLocalMatrix);
     }
 
     static inline void GenKey(const GrGeometryProcessor& gp,
-                              const GrShaderCaps&,
+                              const GrShaderCaps& shaderCaps,
                               GrProcessorKeyBuilder* b) {
         const GrDistanceFieldA8TextGeoProc& dfTexEffect = gp.cast<GrDistanceFieldA8TextGeoProc>();
         uint32_t key = dfTexEffect.getFlags();
-        key |= ComputeMatrixKey(dfTexEffect.localMatrix()) << 16;
+        key |= ComputeMatrixKey(shaderCaps, dfTexEffect.localMatrix()) << 16;
         b->add32(key);
         b->add32(dfTexEffect.numTextureSamplers());
     }
@@ -349,19 +355,24 @@
 
         if (dfPathEffect.matrix().hasPerspective()) {
             // Setup position (output position is transformed, local coords are pass through)
-            this->writeOutputPosition(vertBuilder,
-                                      uniformHandler,
-                                      gpArgs,
-                                      dfPathEffect.inPosition().name(),
-                                      dfPathEffect.matrix(),
-                                      &fMatrixUniform);
+            WriteOutputPosition(vertBuilder,
+                                uniformHandler,
+                                *args.fShaderCaps,
+                                gpArgs,
+                                dfPathEffect.inPosition().name(),
+                                dfPathEffect.matrix(),
+                                &fMatrixUniform);
             gpArgs->fLocalCoordVar = dfPathEffect.inPosition().asShaderVar();
         } else {
             // Setup position (output position is pass through, local coords are transformed)
-            this->writeOutputPosition(vertBuilder, gpArgs, dfPathEffect.inPosition().name());
-            this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs,
-                                  dfPathEffect.inPosition().asShaderVar(), dfPathEffect.matrix(),
-                                  &fMatrixUniform);
+            WriteOutputPosition(vertBuilder, gpArgs, dfPathEffect.inPosition().name());
+            WriteLocalCoord(vertBuilder,
+                            uniformHandler,
+                            *args.fShaderCaps,
+                            gpArgs,
+                            dfPathEffect.inPosition().asShaderVar(),
+                            dfPathEffect.matrix(),
+                            &fMatrixUniform);
         }
 
         // Use highp to work around aliasing issues
@@ -443,12 +454,13 @@
     }
 
     void setData(const GrGLSLProgramDataManager& pdman,
+                 const GrShaderCaps& shaderCaps,
                  const GrGeometryProcessor& geomProc) override {
         const GrDistanceFieldPathGeoProc& dfpgp = geomProc.cast<GrDistanceFieldPathGeoProc>();
 
         // We always set the matrix uniform; it's either used to transform from local to device
         // for the output position, or from device to local for the local coord variable.
-        this->setTransform(pdman, fMatrixUniform, dfpgp.matrix(), &fMatrix);
+        SetTransform(pdman, shaderCaps, fMatrixUniform, dfpgp.matrix(), &fMatrix);
 
         const SkISize& atlasDimensions = dfpgp.atlasDimensions();
         SkASSERT(SkIsPow2(atlasDimensions.fWidth) && SkIsPow2(atlasDimensions.fHeight));
@@ -461,12 +473,12 @@
     }
 
     static inline void GenKey(const GrGeometryProcessor& gp,
-                              const GrShaderCaps&,
+                              const GrShaderCaps& shaderCaps,
                               GrProcessorKeyBuilder* b) {
         const GrDistanceFieldPathGeoProc& dfTexEffect = gp.cast<GrDistanceFieldPathGeoProc>();
 
         uint32_t key = dfTexEffect.getFlags();
-        key |= ComputeMatrixKey(dfTexEffect.matrix()) << 16;
+        key |= ComputeMatrixKey(shaderCaps, dfTexEffect.matrix()) << 16;
         b->add32(key);
         b->add32(dfTexEffect.matrix().hasPerspective());
         b->add32(dfTexEffect.numTextureSamplers());
@@ -613,9 +625,13 @@
 
         // Setup position
         gpArgs->fPositionVar = dfTexEffect.inPosition().asShaderVar();
-        this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs,
-                              dfTexEffect.inPosition().asShaderVar(), dfTexEffect.localMatrix(),
-                              &fLocalMatrixUniform);
+        WriteLocalCoord(vertBuilder,
+                        uniformHandler,
+                        *args.fShaderCaps,
+                        gpArgs,
+                        dfTexEffect.inPosition().asShaderVar(),
+                        dfTexEffect.localMatrix(),
+                        &fLocalMatrixUniform);
 
         // set up varyings
         GrGLSLVarying uv, texIdx, st;
@@ -751,6 +767,7 @@
     }
 
     void setData(const GrGLSLProgramDataManager& pdman,
+                 const GrShaderCaps& shaderCaps,
                  const GrGeometryProcessor& geomProc) override {
         SkASSERT(fDistanceAdjustUni.isValid());
 
@@ -772,16 +789,16 @@
                         1.0f / atlasDimensions.fHeight);
             fAtlasDimensions = atlasDimensions;
         }
-        this->setTransform(pdman, fLocalMatrixUniform, dflcd.localMatrix(), &fLocalMatrix);
+        SetTransform(pdman, shaderCaps, fLocalMatrixUniform, dflcd.localMatrix(), &fLocalMatrix);
     }
 
     static inline void GenKey(const GrGeometryProcessor& gp,
-                              const GrShaderCaps&,
+                              const GrShaderCaps& shaderCaps,
                               GrProcessorKeyBuilder* b) {
         const GrDistanceFieldLCDTextGeoProc& dfTexEffect = gp.cast<GrDistanceFieldLCDTextGeoProc>();
 
         uint32_t key = (dfTexEffect.getFlags() << 16) |
-                       ComputeMatrixKey(dfTexEffect.localMatrix());
+                       ComputeMatrixKey(shaderCaps, dfTexEffect.localMatrix());
         b->add32(key);
         b->add32(dfTexEffect.numTextureSamplers());
     }
diff --git a/src/gpu/effects/GrShadowGeoProc.cpp b/src/gpu/effects/GrShadowGeoProc.cpp
index 6cdbecb..348c5cd 100644
--- a/src/gpu/effects/GrShadowGeoProc.cpp
+++ b/src/gpu/effects/GrShadowGeoProc.cpp
@@ -34,7 +34,7 @@
         varyingHandler->addPassThroughAttribute(rsgp.inColor(), args.fOutputColor);
 
         // Setup position
-        this->writeOutputPosition(vertBuilder, gpArgs, rsgp.inPosition().name());
+        WriteOutputPosition(vertBuilder, gpArgs, rsgp.inPosition().name());
         // No need for local coordinates, this GP does not combine with fragment processors
 
         fragBuilder->codeAppend("half d = length(shadowParams.xy);");
@@ -45,7 +45,9 @@
         fragBuilder->codeAppendf("half4 %s = half4(factor);", args.fOutputCoverage);
     }
 
-    void setData(const GrGLSLProgramDataManager&, const GrGeometryProcessor&) override {}
+    void setData(const GrGLSLProgramDataManager&,
+                 const GrShaderCaps&,
+                 const GrGeometryProcessor&) override {}
 
 private:
     using INHERITED = GrGLSLGeometryProcessor;
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 5f21218..8fc7b33 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -106,7 +106,9 @@
     // We must bind to texture units in the same order in which we set the uniforms in
     // GrGLProgramDataManager. That is, we bind textures for processors in this order:
     // primProc, fragProcs, XP.
-    fGeometryProcessor->setData(fProgramDataManager, programInfo.geomProc());
+    fGeometryProcessor->setData(fProgramDataManager,
+                                *fGpu->caps()->shaderCaps(),
+                                programInfo.geomProc());
 
     for (int i = 0; i < programInfo.pipeline().numFragmentProcessors(); ++i) {
         auto& fp = programInfo.pipeline().getFragmentProcessor(i);
diff --git a/src/gpu/glsl/GrGLSLGeometryProcessor.cpp b/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
index 35dcda5..a5a6e3f 100644
--- a/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
+++ b/src/gpu/glsl/GrGLSLGeometryProcessor.cpp
@@ -260,10 +260,11 @@
     }
 }
 
-void GrGLSLGeometryProcessor::setTransform(const GrGLSLProgramDataManager& pdman,
+void GrGLSLGeometryProcessor::SetTransform(const GrGLSLProgramDataManager& pdman,
+                                           const GrShaderCaps& shaderCaps,
                                            const UniformHandle& uniform,
                                            const SkMatrix& matrix,
-                                           SkMatrix* state) const {
+                                           SkMatrix* state) {
     if (!uniform.isValid() || (state && SkMatrixPriv::CheapEqual(*state, matrix))) {
         // No update needed
         return;
@@ -271,7 +272,7 @@
     if (state) {
         *state = matrix;
     }
-    if (matrix.isScaleTranslate()) {
+    if (matrix.isScaleTranslate() && !shaderCaps.reducedShaderMode()) {
         // ComputeMatrixKey and writeX() assume the uniform is a float4 (can't assert since nothing
         // is exposed on a handle, but should be caught lower down).
         float values[4] = {matrix.getScaleX(), matrix.getTranslateX(),
@@ -282,8 +283,21 @@
     }
 }
 
+static void write_passthrough_vertex_position(GrGLSLVertexBuilder* vertBuilder,
+                                              const GrShaderVar& inPos,
+                                              GrShaderVar* outPos) {
+    SkASSERT(inPos.getType() == kFloat3_GrSLType || inPos.getType() == kFloat2_GrSLType);
+    SkString outName = vertBuilder->newTmpVarName(inPos.getName().c_str());
+    outPos->set(inPos.getType(), outName.c_str());
+    vertBuilder->codeAppendf("float%d %s = %s;",
+                             GrSLTypeVecLength(inPos.getType()),
+                             outName.c_str(),
+                             inPos.getName().c_str());
+}
+
 static void write_vertex_position(GrGLSLVertexBuilder* vertBuilder,
                                   GrGLSLUniformHandler* uniformHandler,
+                                  const GrShaderCaps& shaderCaps,
                                   const GrShaderVar& inPos,
                                   const SkMatrix& matrix,
                                   const char* matrixName,
@@ -292,86 +306,106 @@
     SkASSERT(inPos.getType() == kFloat3_GrSLType || inPos.getType() == kFloat2_GrSLType);
     SkString outName = vertBuilder->newTmpVarName(inPos.getName().c_str());
 
-    if (matrix.isIdentity()) {
-        // Direct assignment, we won't use a uniform for the matrix.
-        outPos->set(inPos.getType(), outName.c_str());
-        vertBuilder->codeAppendf("float%d %s = %s;", GrSLTypeVecLength(inPos.getType()),
-                                                     outName.c_str(), inPos.getName().c_str());
-    } else {
-        SkASSERT(matrixUniform);
-
-        bool useCompactTransform = matrix.isScaleTranslate();
-        const char* mangledMatrixName;
-        *matrixUniform = uniformHandler->addUniform(nullptr,
-                                                        kVertex_GrShaderFlag,
-                                                        useCompactTransform ? kFloat4_GrSLType
-                                                                            : kFloat3x3_GrSLType,
-                                                        matrixName,
-                                                        &mangledMatrixName);
-
-        if (inPos.getType() == kFloat3_GrSLType) {
-            // A float3 stays a float3 whether or not the matrix adds perspective
-            if (useCompactTransform) {
-                vertBuilder->codeAppendf("float3 %s = %s.xz1 * %s + %s.yw0;\n",
-                                         outName.c_str(), mangledMatrixName,
-                                         inPos.getName().c_str(), mangledMatrixName);
-            } else {
-                vertBuilder->codeAppendf("float3 %s = %s * %s;\n", outName.c_str(),
-                                         mangledMatrixName, inPos.getName().c_str());
-            }
-            outPos->set(kFloat3_GrSLType, outName.c_str());
-        } else if (matrix.hasPerspective()) {
-            // A float2 is promoted to a float3 if we add perspective via the matrix
-            SkASSERT(!useCompactTransform);
-            vertBuilder->codeAppendf("float3 %s = (%s * %s.xy1);",
-                                     outName.c_str(), mangledMatrixName, inPos.getName().c_str());
-            outPos->set(kFloat3_GrSLType, outName.c_str());
-        } else {
-            if (useCompactTransform) {
-                vertBuilder->codeAppendf("float2 %s = %s.xz * %s + %s.yw;\n",
-                                         outName.c_str(), mangledMatrixName,
-                                         inPos.getName().c_str(), mangledMatrixName);
-            } else {
-                vertBuilder->codeAppendf("float2 %s = (%s * %s.xy1).xy;\n",
-                                         outName.c_str(), mangledMatrixName,
-                                         inPos.getName().c_str());
-            }
-            outPos->set(kFloat2_GrSLType, outName.c_str());
-        }
+    if (matrix.isIdentity() && !shaderCaps.reducedShaderMode()) {
+        write_passthrough_vertex_position(vertBuilder, inPos, outPos);
+        return;
     }
+    SkASSERT(matrixUniform);
+
+    bool useCompactTransform = matrix.isScaleTranslate() && !shaderCaps.reducedShaderMode();
+    const char* mangledMatrixName;
+    *matrixUniform = uniformHandler->addUniform(nullptr,
+                                                kVertex_GrShaderFlag,
+                                                useCompactTransform ? kFloat4_GrSLType
+                                                                    : kFloat3x3_GrSLType,
+                                                matrixName,
+                                                &mangledMatrixName);
+
+    if (inPos.getType() == kFloat3_GrSLType) {
+        // A float3 stays a float3 whether or not the matrix adds perspective
+        if (useCompactTransform) {
+            vertBuilder->codeAppendf("float3 %s = %s.xz1 * %s + %s.yw0;\n",
+                                     outName.c_str(),
+                                     mangledMatrixName,
+                                     inPos.getName().c_str(),
+                                     mangledMatrixName);
+        } else {
+            vertBuilder->codeAppendf("float3 %s = %s * %s;\n",
+                                     outName.c_str(),
+                                     mangledMatrixName,
+                                     inPos.getName().c_str());
+        }
+        outPos->set(kFloat3_GrSLType, outName.c_str());
+        return;
+    }
+    if (matrix.hasPerspective()) {
+        // A float2 is promoted to a float3 if we add perspective via the matrix
+        SkASSERT(!useCompactTransform);
+        vertBuilder->codeAppendf("float3 %s = (%s * %s.xy1);",
+                                 outName.c_str(),
+                                 mangledMatrixName,
+                                 inPos.getName().c_str());
+        outPos->set(kFloat3_GrSLType, outName.c_str());
+        return;
+    }
+    if (useCompactTransform) {
+        vertBuilder->codeAppendf("float2 %s = %s.xz * %s + %s.yw;\n",
+                                 outName.c_str(),
+                                 mangledMatrixName,
+                                 inPos.getName().c_str(),
+                                 mangledMatrixName);
+    } else {
+        vertBuilder->codeAppendf("float2 %s = (%s * %s.xy1).xy;\n",
+                                 outName.c_str(),
+                                 mangledMatrixName,
+                                 inPos.getName().c_str());
+    }
+    outPos->set(kFloat2_GrSLType, outName.c_str());
 }
 
-void GrGLSLGeometryProcessor::writeOutputPosition(GrGLSLVertexBuilder* vertBuilder,
+void GrGLSLGeometryProcessor::WriteOutputPosition(GrGLSLVertexBuilder* vertBuilder,
                                                   GrGPArgs* gpArgs,
                                                   const char* posName) {
     // writeOutputPosition assumes the incoming pos name points to a float2 variable
     GrShaderVar inPos(posName, kFloat2_GrSLType);
-    write_vertex_position(vertBuilder, nullptr, inPos, SkMatrix::I(), "viewMatrix",
-                          &gpArgs->fPositionVar, nullptr);
+    write_passthrough_vertex_position(vertBuilder, inPos, &gpArgs->fPositionVar);
 }
 
-void GrGLSLGeometryProcessor::writeOutputPosition(GrGLSLVertexBuilder* vertBuilder,
+void GrGLSLGeometryProcessor::WriteOutputPosition(GrGLSLVertexBuilder* vertBuilder,
                                                   GrGLSLUniformHandler* uniformHandler,
+                                                  const GrShaderCaps& shaderCaps,
                                                   GrGPArgs* gpArgs,
                                                   const char* posName,
                                                   const SkMatrix& mat,
                                                   UniformHandle* viewMatrixUniform) {
     GrShaderVar inPos(posName, kFloat2_GrSLType);
-    write_vertex_position(vertBuilder, uniformHandler, inPos, mat, "viewMatrix",
-                          &gpArgs->fPositionVar, viewMatrixUniform);
+    write_vertex_position(vertBuilder,
+                          uniformHandler,
+                          shaderCaps,
+                          inPos,
+                          mat,
+                          "viewMatrix",
+                          &gpArgs->fPositionVar,
+                          viewMatrixUniform);
 }
 
-void GrGLSLGeometryProcessor::writeLocalCoord(GrGLSLVertexBuilder* vertBuilder,
+void GrGLSLGeometryProcessor::WriteLocalCoord(GrGLSLVertexBuilder* vertBuilder,
                                               GrGLSLUniformHandler* uniformHandler,
+                                              const GrShaderCaps& shaderCaps,
                                               GrGPArgs* gpArgs,
                                               GrShaderVar localVar,
                                               const SkMatrix& localMatrix,
                                               UniformHandle* localMatrixUniform) {
-    write_vertex_position(vertBuilder, uniformHandler, localVar, localMatrix, "localMatrix",
-                          &gpArgs->fLocalCoordVar, localMatrixUniform);
+    write_vertex_position(vertBuilder,
+                          uniformHandler,
+                          shaderCaps,
+                          localVar,
+                          localMatrix,
+                          "localMatrix",
+                          &gpArgs->fLocalCoordVar,
+                          localMatrixUniform);
 }
 
-
 //////////////////////////////////////////////////////////////////////////////
 
 GrGLSLGeometryProcessor::FPCoordTransformHandler::FPCoordTransformHandler(
diff --git a/src/gpu/glsl/GrGLSLGeometryProcessor.h b/src/gpu/glsl/GrGLSLGeometryProcessor.h
index 6e94512..a52406a 100644
--- a/src/gpu/glsl/GrGLSLGeometryProcessor.h
+++ b/src/gpu/glsl/GrGLSLGeometryProcessor.h
@@ -126,7 +126,9 @@
      * The range will iterate over the transforms in the same order as the TransformHandler passed
      * to emitCode.
      */
-    virtual void setData(const GrGLSLProgramDataManager&, const GrGeometryProcessor&) = 0;
+    virtual void setData(const GrGLSLProgramDataManager&,
+                         const GrShaderCaps&,
+                         const GrGeometryProcessor&) = 0;
 
 protected:
     void setupUniformColor(GrGLSLFPFragmentBuilder* fragBuilder,
@@ -137,8 +139,11 @@
     // A helper for setting the matrix on a uniform handle initialized through
     // writeOutputPosition or writeLocalCoord. Automatically handles elided uniforms,
     // scale+translate matrices, and state tracking (if provided state pointer is non-null).
-    void setTransform(const GrGLSLProgramDataManager& pdman, const UniformHandle& uniform,
-                      const SkMatrix& matrix, SkMatrix* state=nullptr) const;
+    static void SetTransform(const GrGLSLProgramDataManager&,
+                             const GrShaderCaps&,
+                             const UniformHandle& uniform,
+                             const SkMatrix& matrix,
+                             SkMatrix* state = nullptr);
 
     struct GrGPArgs {
         // Used to specify the output variable used by the GP to store its device position. It can
@@ -158,42 +163,56 @@
     // view matrix and the output variable is 2D or 3D depending on whether the view matrix is
     // perspective. Both versions declare the output position variable and will set
     // GrGPArgs::fPositionVar.
-    void writeOutputPosition(GrGLSLVertexBuilder*, GrGPArgs*, const char* posName);
-    void writeOutputPosition(GrGLSLVertexBuilder*,
-                             GrGLSLUniformHandler* uniformHandler,
-                             GrGPArgs*,
-                             const char* posName,
-                             const SkMatrix& mat,
-                             UniformHandle* viewMatrixUniform);
+    static void WriteOutputPosition(GrGLSLVertexBuilder*, GrGPArgs*, const char* posName);
+    static void WriteOutputPosition(GrGLSLVertexBuilder*,
+                                    GrGLSLUniformHandler*,
+                                    const GrShaderCaps&,
+                                    GrGPArgs*,
+                                    const char* posName,
+                                    const SkMatrix& viewMatrix,
+                                    UniformHandle* viewMatrixUniform);
 
     // Helper to transform an existing variable by a given local matrix (e.g. the inverse view
     // matrix). It will declare the transformed local coord variable and will set
     // GrGPArgs::fLocalCoordVar.
-    void writeLocalCoord(GrGLSLVertexBuilder*, GrGLSLUniformHandler*, GrGPArgs*,
-                         GrShaderVar localVar, const SkMatrix& localMatrix,
-                         UniformHandle* localMatrixUniform);
+    static void WriteLocalCoord(GrGLSLVertexBuilder*,
+                                GrGLSLUniformHandler*,
+                                const GrShaderCaps&,
+                                GrGPArgs*,
+                                GrShaderVar localVar,
+                                const SkMatrix& localMatrix,
+                                UniformHandle* localMatrixUniform);
 
     // GPs that use writeOutputPosition and/or writeLocalCoord must incorporate the matrix type
     // into their key, and should use this function or one of the other related helpers.
-    static uint32_t ComputeMatrixKey(const SkMatrix& mat) {
-        if (mat.isIdentity()) {
-            return 0b00;
-        } else if (mat.isScaleTranslate()) {
-            return 0b01;
-        } else if (!mat.hasPerspective()) {
-            return 0b10;
-        } else {
-            return 0b11;
+    static uint32_t ComputeMatrixKey(const GrShaderCaps& caps, const SkMatrix& mat) {
+        if (!caps.reducedShaderMode()) {
+            if (mat.isIdentity()) {
+                return 0b00;
+            }
+            if (mat.isScaleTranslate()) {
+                return 0b01;
+            }
         }
+        if (!mat.hasPerspective()) {
+            return 0b10;
+        }
+        return 0b11;
     }
-    static uint32_t ComputeMatrixKeys(const SkMatrix& viewMatrix, const SkMatrix& localMatrix) {
-        return (ComputeMatrixKey(viewMatrix) << kMatrixKeyBits) | ComputeMatrixKey(localMatrix);
+    static uint32_t ComputeMatrixKeys(const GrShaderCaps& shaderCaps,
+                                      const SkMatrix& viewMatrix,
+                                      const SkMatrix& localMatrix) {
+        return (ComputeMatrixKey(shaderCaps, viewMatrix) << kMatrixKeyBits) |
+               ComputeMatrixKey(shaderCaps, localMatrix);
     }
-    static uint32_t AddMatrixKeys(uint32_t flags, const SkMatrix& viewMatrix,
+    static uint32_t AddMatrixKeys(const GrShaderCaps& shaderCaps,
+                                  uint32_t flags,
+                                  const SkMatrix& viewMatrix,
                                   const SkMatrix& localMatrix) {
         // Shifting to make room for the matrix keys shouldn't lose bits
         SkASSERT(((flags << (2 * kMatrixKeyBits)) >> (2 * kMatrixKeyBits)) == flags);
-        return (flags << (2 * kMatrixKeyBits)) | ComputeMatrixKeys(viewMatrix, localMatrix);
+        return (flags << (2 * kMatrixKeyBits)) |
+               ComputeMatrixKeys(shaderCaps, viewMatrix, localMatrix);
     }
     static constexpr int kMatrixKeyBits = 2;
 
diff --git a/src/gpu/mtl/GrMtlPipelineState.mm b/src/gpu/mtl/GrMtlPipelineState.mm
index 8bc5ab6..f2fcf1d 100644
--- a/src/gpu/mtl/GrMtlPipelineState.mm
+++ b/src/gpu/mtl/GrMtlPipelineState.mm
@@ -56,7 +56,7 @@
 void GrMtlPipelineState::setData(const GrRenderTarget* renderTarget,
                                  const GrProgramInfo& programInfo) {
     this->setRenderTargetState(renderTarget, programInfo.origin());
-    fGeometryProcessor->setData(fDataManager, programInfo.geomProc());
+    fGeometryProcessor->setData(fDataManager, *fGpu->caps()->shaderCaps(), programInfo.geomProc());
 
     for (int i = 0; i < programInfo.pipeline().numFragmentProcessors(); ++i) {
         auto& fp = programInfo.pipeline().getFragmentProcessor(i);
diff --git a/src/gpu/ops/GrAAConvexPathRenderer.cpp b/src/gpu/ops/GrAAConvexPathRenderer.cpp
index 9b79aac..d252b72 100644
--- a/src/gpu/ops/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAAConvexPathRenderer.cpp
@@ -586,11 +586,15 @@
             varyingHandler->addPassThroughAttribute(qe.fInColor, args.fOutputColor);
 
             // Setup position
-            this->writeOutputPosition(vertBuilder, gpArgs, qe.fInPosition.name());
+            WriteOutputPosition(vertBuilder, gpArgs, qe.fInPosition.name());
             if (qe.fUsesLocalCoords) {
-                this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs,
-                                      qe.fInPosition.asShaderVar(), qe.fLocalMatrix,
-                                      &fLocalMatrixUniform);
+                WriteLocalCoord(vertBuilder,
+                                uniformHandler,
+                                *args.fShaderCaps,
+                                gpArgs,
+                                qe.fInPosition.asShaderVar(),
+                                qe.fLocalMatrix,
+                                &fLocalMatrixUniform);
             }
 
             fragBuilder->codeAppendf("half edgeAlpha;");
@@ -615,17 +619,20 @@
         }
 
         static inline void GenKey(const GrGeometryProcessor& gp,
-                                  const GrShaderCaps&,
+                                  const GrShaderCaps& shaderCaps,
                                   GrProcessorKeyBuilder* b) {
             const QuadEdgeEffect& qee = gp.cast<QuadEdgeEffect>();
             b->addBool(qee.fUsesLocalCoords, "usesLocalCoords");
-            b->addBits(kMatrixKeyBits, ComputeMatrixKey(qee.fLocalMatrix), "localMatrixType");
+            b->addBits(kMatrixKeyBits,
+                       ComputeMatrixKey(shaderCaps, qee.fLocalMatrix),
+                       "localMatrixType");
         }
 
         void setData(const GrGLSLProgramDataManager& pdman,
+                     const GrShaderCaps& shaderCaps,
                      const GrGeometryProcessor& geomProc) override {
             const QuadEdgeEffect& qe = geomProc.cast<QuadEdgeEffect>();
-            this->setTransform(pdman, fLocalMatrixUniform, qe.fLocalMatrix, &fLocalMatrix);
+            SetTransform(pdman, shaderCaps, fLocalMatrixUniform, qe.fLocalMatrix, &fLocalMatrix);
         }
 
     private:
diff --git a/src/gpu/ops/GrDashOp.cpp b/src/gpu/ops/GrDashOp.cpp
index 40266df..ca29f73 100644
--- a/src/gpu/ops/GrDashOp.cpp
+++ b/src/gpu/ops/GrDashOp.cpp
@@ -867,7 +867,9 @@
                               const GrShaderCaps&,
                               GrProcessorKeyBuilder*);
 
-    void setData(const GrGLSLProgramDataManager&, const GrGeometryProcessor&) override;
+    void setData(const GrGLSLProgramDataManager&,
+                 const GrShaderCaps&,
+                 const GrGeometryProcessor&) override;
 
 private:
     UniformHandle fParamUniform;
@@ -916,10 +918,15 @@
     this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform);
 
     // Setup position
-    this->writeOutputPosition(vertBuilder, gpArgs, dce.fInPosition.name());
+    WriteOutputPosition(vertBuilder, gpArgs, dce.fInPosition.name());
     if (dce.usesLocalCoords()) {
-        this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, dce.fInPosition.asShaderVar(),
-                              dce.localMatrix(), &fLocalMatrixUniform);
+        WriteLocalCoord(vertBuilder,
+                        uniformHandler,
+                        *args.fShaderCaps,
+                        gpArgs,
+                        dce.fInPosition.asShaderVar(),
+                        dce.localMatrix(),
+                        &fLocalMatrixUniform);
     }
 
     // transforms all points so that we can compare them to our test circle
@@ -942,23 +949,24 @@
 }
 
 void GLDashingCircleEffect::setData(const GrGLSLProgramDataManager& pdman,
+                                    const GrShaderCaps& shaderCaps,
                                     const GrGeometryProcessor& geomProc) {
     const DashingCircleEffect& dce = geomProc.cast<DashingCircleEffect>();
     if (dce.color() != fColor) {
         pdman.set4fv(fColorUniform, 1, dce.color().vec());
         fColor = dce.color();
     }
-    this->setTransform(pdman, fLocalMatrixUniform, dce.localMatrix(), &fLocalMatrix);
+    SetTransform(pdman, shaderCaps, fLocalMatrixUniform, dce.localMatrix(), &fLocalMatrix);
 }
 
 void GLDashingCircleEffect::GenKey(const GrGeometryProcessor& gp,
-                                   const GrShaderCaps&,
+                                   const GrShaderCaps& shaderCaps,
                                    GrProcessorKeyBuilder* b) {
     const DashingCircleEffect& dce = gp.cast<DashingCircleEffect>();
     uint32_t key = 0;
     key |= dce.usesLocalCoords() ? 0x1 : 0x0;
     key |= static_cast<uint32_t>(dce.aaMode()) << 1;
-    key |= ComputeMatrixKey(dce.localMatrix()) << 3;
+    key |= ComputeMatrixKey(shaderCaps, dce.localMatrix()) << 3;
     b->add32(key);
 }
 
@@ -1079,7 +1087,9 @@
                               const GrShaderCaps&,
                               GrProcessorKeyBuilder*);
 
-    void setData(const GrGLSLProgramDataManager&, const GrGeometryProcessor&) override;
+    void setData(const GrGLSLProgramDataManager&,
+                 const GrShaderCaps&,
+                 const GrGeometryProcessor&) override;
 
 private:
     SkPMColor4f   fColor;
@@ -1120,10 +1130,15 @@
     this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor, &fColorUniform);
 
     // Setup position
-    this->writeOutputPosition(vertBuilder, gpArgs, de.fInPosition.name());
+    WriteOutputPosition(vertBuilder, gpArgs, de.fInPosition.name());
     if (de.usesLocalCoords()) {
-        this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs, de.fInPosition.asShaderVar(),
-                              de.localMatrix(), &fLocalMatrixUniform);
+        WriteLocalCoord(vertBuilder,
+                        uniformHandler,
+                        *args.fShaderCaps,
+                        gpArgs,
+                        de.fInPosition.asShaderVar(),
+                        de.localMatrix(),
+                        &fLocalMatrixUniform);
     }
 
     // transforms all points so that we can compare them to our test rect
@@ -1170,23 +1185,24 @@
 }
 
 void GLDashingLineEffect::setData(const GrGLSLProgramDataManager& pdman,
+                                  const GrShaderCaps& shaderCaps,
                                   const GrGeometryProcessor& geomProc) {
     const DashingLineEffect& de = geomProc.cast<DashingLineEffect>();
     if (de.color() != fColor) {
         pdman.set4fv(fColorUniform, 1, de.color().vec());
         fColor = de.color();
     }
-    this->setTransform(pdman, fLocalMatrixUniform, de.localMatrix(), &fLocalMatrix);
+    SetTransform(pdman, shaderCaps, fLocalMatrixUniform, de.localMatrix(), &fLocalMatrix);
 }
 
 void GLDashingLineEffect::GenKey(const GrGeometryProcessor& gp,
-                                 const GrShaderCaps&,
+                                 const GrShaderCaps& shaderCaps,
                                  GrProcessorKeyBuilder* b) {
     const DashingLineEffect& de = gp.cast<DashingLineEffect>();
     uint32_t key = 0;
     key |= de.usesLocalCoords() ? 0x1 : 0x0;
     key |= static_cast<int>(de.aaMode()) << 1;
-    key |= ComputeMatrixKey(de.localMatrix()) << 3;
+    key |= ComputeMatrixKey(shaderCaps, de.localMatrix()) << 3;
     b->add32(key);
 }
 
diff --git a/src/gpu/ops/GrDrawVerticesOp.cpp b/src/gpu/ops/GrDrawVerticesOp.cpp
index e89d8bf..4000a67 100644
--- a/src/gpu/ops/GrDrawVerticesOp.cpp
+++ b/src/gpu/ops/GrDrawVerticesOp.cpp
@@ -179,12 +179,13 @@
             }
 
             // Setup position
-            this->writeOutputPosition(vertBuilder,
-                                      uniformHandler,
-                                      gpArgs,
-                                      gp.positionAttr().name(),
-                                      gp.viewMatrix(),
-                                      &fViewMatrixUniform);
+            WriteOutputPosition(vertBuilder,
+                                uniformHandler,
+                                *args.fShaderCaps,
+                                gpArgs,
+                                gp.positionAttr().name(),
+                                gp.viewMatrix(),
+                                &fViewMatrixUniform);
 
             // emit transforms using either explicit local coords or positions
             const auto& coordsAttr = gp.localCoordsAttr().isInitialized() ? gp.localCoordsAttr()
@@ -300,12 +301,12 @@
         }
 
         static inline void GenKey(const GrGeometryProcessor& gp,
-                                  const GrShaderCaps&,
+                                  const GrShaderCaps& shaderCaps,
                                   GrProcessorKeyBuilder* b) {
             const VerticesGP& vgp = gp.cast<VerticesGP>();
             uint32_t key = 0;
             key |= (vgp.fColorArrayType == ColorArrayType::kSkColor) ? 0x1 : 0;
-            key |= ComputeMatrixKey(vgp.viewMatrix()) << 20;
+            key |= ComputeMatrixKey(shaderCaps, vgp.viewMatrix()) << 20;
             b->add32(key);
             b->add32(GrColorSpaceXform::XformKey(vgp.fColorSpaceXform.get()));
 
@@ -318,10 +319,11 @@
         }
 
         void setData(const GrGLSLProgramDataManager& pdman,
+                     const GrShaderCaps& shaderCaps,
                      const GrGeometryProcessor& geomProc) override {
             const VerticesGP& vgp = geomProc.cast<VerticesGP>();
 
-            this->setTransform(pdman, fViewMatrixUniform, vgp.viewMatrix(), &fViewMatrix);
+            SetTransform(pdman, shaderCaps, fViewMatrixUniform, vgp.viewMatrix(), &fViewMatrix);
 
             if (!vgp.colorAttr().isInitialized() && vgp.color() != fColor) {
                 pdman.set4fv(fColorUniform, 1, vgp.color().vec());
diff --git a/src/gpu/ops/GrFillRRectOp.cpp b/src/gpu/ops/GrFillRRectOp.cpp
index 537f149..38ff2c0 100644
--- a/src/gpu/ops/GrFillRRectOp.cpp
+++ b/src/gpu/ops/GrFillRRectOp.cpp
@@ -671,7 +671,9 @@
         f->codeAppendf("half4 %s = half4(coverage);", args.fOutputCoverage);
     }
 
-    void setData(const GrGLSLProgramDataManager&, const GrGeometryProcessor&) override {}
+    void setData(const GrGLSLProgramDataManager&,
+                 const GrShaderCaps&,
+                 const GrGeometryProcessor&) override {}
 };
 
 
diff --git a/src/gpu/ops/GrLatticeOp.cpp b/src/gpu/ops/GrLatticeOp.cpp
index 2794bf5..00ea878 100644
--- a/src/gpu/ops/GrLatticeOp.cpp
+++ b/src/gpu/ops/GrLatticeOp.cpp
@@ -49,6 +49,7 @@
         class GLSLProcessor : public GrGLSLGeometryProcessor {
         public:
             void setData(const GrGLSLProgramDataManager& pdman,
+                         const GrShaderCaps&,
                          const GrGeometryProcessor& geomProc) override {
                 const auto& latticeGP = geomProc.cast<LatticeGP>();
                 fColorSpaceXformHelper.setData(pdman, latticeGP.fColorSpaceXform.get());
@@ -62,7 +63,7 @@
                                                 latticeGP.fColorSpaceXform.get());
 
                 args.fVaryingHandler->emitAttributes(latticeGP);
-                this->writeOutputPosition(args.fVertBuilder, gpArgs, latticeGP.fInPosition.name());
+                WriteOutputPosition(args.fVertBuilder, gpArgs, latticeGP.fInPosition.name());
                 gpArgs->fLocalCoordVar = latticeGP.fInTextureCoords.asShaderVar();
 
                 args.fFragBuilder->codeAppend("float2 textureCoords;");
diff --git a/src/gpu/ops/GrOvalOpFactory.cpp b/src/gpu/ops/GrOvalOpFactory.cpp
index 715d9dc..1dd1799 100644
--- a/src/gpu/ops/GrOvalOpFactory.cpp
+++ b/src/gpu/ops/GrOvalOpFactory.cpp
@@ -156,10 +156,14 @@
             varyingHandler->addPassThroughAttribute(cgp.fInColor, args.fOutputColor);
 
             // Setup position
-            this->writeOutputPosition(vertBuilder, gpArgs, cgp.fInPosition.name());
-            this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs,
-                                  cgp.fInPosition.asShaderVar(), cgp.fLocalMatrix,
-                                  &fLocalMatrixUniform);
+            WriteOutputPosition(vertBuilder, gpArgs, cgp.fInPosition.name());
+            WriteLocalCoord(vertBuilder,
+                            uniformHandler,
+                            *args.fShaderCaps,
+                            gpArgs,
+                            cgp.fInPosition.asShaderVar(),
+                            cgp.fLocalMatrix,
+                            &fLocalMatrixUniform);
 
             fragBuilder->codeAppend("float d = length(circleEdge.xy);");
             fragBuilder->codeAppend("half distanceToOuterEdge = half(circleEdge.z * (1.0 - d));");
@@ -204,7 +208,7 @@
         }
 
         static void GenKey(const GrGeometryProcessor& gp,
-                           const GrShaderCaps&,
+                           const GrShaderCaps& shaderCaps,
                            GrProcessorKeyBuilder* b) {
             const CircleGeometryProcessor& cgp = gp.cast<CircleGeometryProcessor>();
             b->addBool(cgp.fStroke,                                     "stroked");
@@ -212,14 +216,19 @@
             b->addBool(cgp.fInIsectPlane.isInitialized(),               "isectPlane");
             b->addBool(cgp.fInUnionPlane.isInitialized(),               "unionPlane");
             b->addBool(cgp.fInRoundCapCenters.isInitialized(),          "roundCapCenters");
-            b->addBits(kMatrixKeyBits, ComputeMatrixKey(cgp.fLocalMatrix), "localMatrixType");
+            b->addBits(kMatrixKeyBits,
+                       ComputeMatrixKey(shaderCaps, cgp.fLocalMatrix),
+                       "localMatrixType");
         }
 
         void setData(const GrGLSLProgramDataManager& pdman,
+                     const GrShaderCaps& shaderCaps,
                      const GrGeometryProcessor& geomProc) override {
-            this->setTransform(pdman, fLocalMatrixUniform,
-                               geomProc.cast<CircleGeometryProcessor>().fLocalMatrix,
-                               &fLocalMatrix);
+            SetTransform(pdman,
+                         shaderCaps,
+                         fLocalMatrixUniform,
+                         geomProc.cast<CircleGeometryProcessor>().fLocalMatrix,
+                         &fLocalMatrix);
         }
 
     private:
@@ -388,10 +397,14 @@
                     GrGLSLVaryingHandler::Interpolation::kCanBeFlat);
 
             // Setup position
-            this->writeOutputPosition(vertBuilder, gpArgs, bcscgp.fInPosition.name());
-            this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs,
-                                  bcscgp.fInPosition.asShaderVar(), bcscgp.fLocalMatrix,
-                                  &fLocalMatrixUniform);
+            WriteOutputPosition(vertBuilder, gpArgs, bcscgp.fInPosition.name());
+            WriteLocalCoord(vertBuilder,
+                            uniformHandler,
+                            *args.fShaderCaps,
+                            gpArgs,
+                            bcscgp.fInPosition.asShaderVar(),
+                            bcscgp.fLocalMatrix,
+                            &fLocalMatrixUniform);
 
             GrShaderVar fnArgs[] = {
                     GrShaderVar("angleToEdge", kFloat_GrSLType),
@@ -468,18 +481,23 @@
         }
 
         static void GenKey(const GrGeometryProcessor& gp,
-                           const GrShaderCaps&,
+                           const GrShaderCaps& shaderCaps,
                            GrProcessorKeyBuilder* b) {
             const ButtCapDashedCircleGeometryProcessor& bcscgp =
                     gp.cast<ButtCapDashedCircleGeometryProcessor>();
-            b->addBits(kMatrixKeyBits, ComputeMatrixKey(bcscgp.fLocalMatrix), "localMatrixType");
+            b->addBits(kMatrixKeyBits,
+                       ComputeMatrixKey(shaderCaps, bcscgp.fLocalMatrix),
+                       "localMatrixType");
         }
 
         void setData(const GrGLSLProgramDataManager& pdman,
+                     const GrShaderCaps& shaderCaps,
                      const GrGeometryProcessor& geomProc) override {
-            this->setTransform(pdman, fLocalMatrixUniform,
-                               geomProc.cast<ButtCapDashedCircleGeometryProcessor>().fLocalMatrix,
-                               &fLocalMatrix);
+            SetTransform(pdman,
+                         shaderCaps,
+                         fLocalMatrixUniform,
+                         geomProc.cast<ButtCapDashedCircleGeometryProcessor>().fLocalMatrix,
+                         &fLocalMatrix);
         }
 
     private:
@@ -586,10 +604,14 @@
             varyingHandler->addPassThroughAttribute(egp.fInColor, args.fOutputColor);
 
             // Setup position
-            this->writeOutputPosition(vertBuilder, gpArgs, egp.fInPosition.name());
-            this->writeLocalCoord(vertBuilder, uniformHandler, gpArgs,
-                                  egp.fInPosition.asShaderVar(), egp.fLocalMatrix,
-                                  &fLocalMatrixUniform);
+            WriteOutputPosition(vertBuilder, gpArgs, egp.fInPosition.name());
+            WriteLocalCoord(vertBuilder,
+                            uniformHandler,
+                            *args.fShaderCaps,
+                            gpArgs,
+                            egp.fInPosition.asShaderVar(),
+                            egp.fLocalMatrix,
+                            &fLocalMatrixUniform);
 
             // For stroked ellipses, we use the full ellipse equation (x^2/a^2 + y^2/b^2 = 1)
             // to compute both the edges because we need two separate test equations for
@@ -658,17 +680,20 @@
         }
 
         static void GenKey(const GrGeometryProcessor& gp,
-                           const GrShaderCaps&,
+                           const GrShaderCaps& shaderCaps,
                            GrProcessorKeyBuilder* b) {
             const EllipseGeometryProcessor& egp = gp.cast<EllipseGeometryProcessor>();
             b->addBool(egp.fStroke, "stroked");
-            b->addBits(kMatrixKeyBits, ComputeMatrixKey(egp.fLocalMatrix), "localMatrixType");
+            b->addBits(kMatrixKeyBits,
+                       ComputeMatrixKey(shaderCaps, egp.fLocalMatrix),
+                       "localMatrixType");
         }
 
         void setData(const GrGLSLProgramDataManager& pdman,
+                     const GrShaderCaps& shaderCaps,
                      const GrGeometryProcessor& geomProc) override {
             const EllipseGeometryProcessor& egp = geomProc.cast<EllipseGeometryProcessor>();
-            this->setTransform(pdman, fLocalMatrixUniform, egp.fLocalMatrix, &fLocalMatrix);
+            SetTransform(pdman, shaderCaps, fLocalMatrixUniform, egp.fLocalMatrix, &fLocalMatrix);
         }
 
     private:
@@ -783,12 +808,13 @@
             varyingHandler->addPassThroughAttribute(diegp.fInColor, args.fOutputColor);
 
             // Setup position
-            this->writeOutputPosition(vertBuilder,
-                                      uniformHandler,
-                                      gpArgs,
-                                      diegp.fInPosition.name(),
-                                      diegp.fViewMatrix,
-                                      &fViewMatrixUniform);
+            WriteOutputPosition(vertBuilder,
+                                uniformHandler,
+                                *args.fShaderCaps,
+                                gpArgs,
+                                diegp.fInPosition.name(),
+                                diegp.fViewMatrix,
+                                &fViewMatrixUniform);
             gpArgs->fLocalCoordVar = diegp.fInPosition.asShaderVar();
 
             // for outer curve
@@ -851,18 +877,21 @@
         }
 
         static void GenKey(const GrGeometryProcessor& gp,
-                           const GrShaderCaps&,
+                           const GrShaderCaps& shaderCaps,
                            GrProcessorKeyBuilder* b) {
             const DIEllipseGeometryProcessor& diegp = gp.cast<DIEllipseGeometryProcessor>();
             b->addBits(2, static_cast<uint32_t>(diegp.fStyle), "style");
-            b->addBits(kMatrixKeyBits, ComputeMatrixKey(diegp.fViewMatrix), "viewMatrixType");
+            b->addBits(kMatrixKeyBits,
+                       ComputeMatrixKey(shaderCaps, diegp.fViewMatrix),
+                       "viewMatrixType");
         }
 
         void setData(const GrGLSLProgramDataManager& pdman,
+                     const GrShaderCaps& shaderCaps,
                      const GrGeometryProcessor& geomProc) override {
             const auto& diegp = geomProc.cast<DIEllipseGeometryProcessor>();
 
-            this->setTransform(pdman, fViewMatrixUniform, diegp.fViewMatrix, &fViewMatrix);
+            SetTransform(pdman, shaderCaps, fViewMatrixUniform, diegp.fViewMatrix, &fViewMatrix);
         }
 
     private:
diff --git a/src/gpu/ops/GrQuadPerEdgeAA.cpp b/src/gpu/ops/GrQuadPerEdgeAA.cpp
index eca3be8..a369bd0 100644
--- a/src/gpu/ops/GrQuadPerEdgeAA.cpp
+++ b/src/gpu/ops/GrQuadPerEdgeAA.cpp
@@ -599,6 +599,7 @@
         class GLSLProcessor : public GrGLSLGeometryProcessor {
         public:
             void setData(const GrGLSLProgramDataManager& pdman,
+                         const GrShaderCaps&,
                          const GrGeometryProcessor& geomProc) override {
                 const auto& gp = geomProc.cast<QuadPerEdgeAAGeometryProcessor>();
                 fTextureColorSpaceXformHelper.setData(pdman, gp.fTextureColorSpaceXform.get());
diff --git a/src/gpu/tessellate/GrDrawAtlasPathOp.cpp b/src/gpu/tessellate/GrDrawAtlasPathOp.cpp
index cc4e545..d2d5b77 100644
--- a/src/gpu/tessellate/GrDrawAtlasPathOp.cpp
+++ b/src/gpu/tessellate/GrDrawAtlasPathOp.cpp
@@ -99,6 +99,7 @@
     }
 
     void setData(const GrGLSLProgramDataManager& pdman,
+                 const GrShaderCaps&,
                  const GrGeometryProcessor& geomProc) override {
         const SkISize& dimensions = geomProc.cast<DrawAtlasPathShader>().fAtlasDimensions;
         pdman.set2f(fAtlasAdjustUniform, 1.f / dimensions.width(), 1.f / dimensions.height());
diff --git a/src/gpu/tessellate/GrFillPathShader.cpp b/src/gpu/tessellate/GrFillPathShader.cpp
index cbdbe5a..6274845 100644
--- a/src/gpu/tessellate/GrFillPathShader.cpp
+++ b/src/gpu/tessellate/GrFillPathShader.cpp
@@ -38,6 +38,7 @@
     }
 
     void setData(const GrGLSLProgramDataManager& pdman,
+                 const GrShaderCaps&,
                  const GrGeometryProcessor& geomProc) override {
         const GrFillPathShader& shader = geomProc.cast<GrFillPathShader>();
         pdman.setSkMatrix(fViewMatrixUniform, shader.viewMatrix());
diff --git a/src/gpu/tessellate/GrStencilPathShader.cpp b/src/gpu/tessellate/GrStencilPathShader.cpp
index 81db042..cf4e8bb 100644
--- a/src/gpu/tessellate/GrStencilPathShader.cpp
+++ b/src/gpu/tessellate/GrStencilPathShader.cpp
@@ -94,6 +94,7 @@
     }
 
     void setData(const GrGLSLProgramDataManager& pdman,
+                 const GrShaderCaps&,
                  const GrGeometryProcessor& geomProc) override {
         const auto& shader = geomProc.cast<GrStencilPathShader>();
         if (!shader.viewMatrix().isIdentity()) {
diff --git a/src/gpu/tessellate/GrStrokeTessellateShader.cpp b/src/gpu/tessellate/GrStrokeTessellateShader.cpp
index 40a76f7..52c4b56 100644
--- a/src/gpu/tessellate/GrStrokeTessellateShader.cpp
+++ b/src/gpu/tessellate/GrStrokeTessellateShader.cpp
@@ -415,6 +415,7 @@
     }
 
     void setData(const GrGLSLProgramDataManager& pdman,
+                 const GrShaderCaps&,
                  const GrGeometryProcessor& geomProc) override {
         const auto& shader = geomProc.cast<GrStrokeTessellateShader>();
         const auto& stroke = shader.fStroke;
@@ -1254,6 +1255,7 @@
     }
 
     void setData(const GrGLSLProgramDataManager& pdman,
+                 const GrShaderCaps&,
                  const GrGeometryProcessor& geomProc) override {
         const auto& shader = geomProc.cast<GrStrokeTessellateShader>();
         const auto& stroke = shader.fStroke;
diff --git a/src/gpu/vk/GrVkPipelineState.cpp b/src/gpu/vk/GrVkPipelineState.cpp
index d80b4fc..b861017 100644
--- a/src/gpu/vk/GrVkPipelineState.cpp
+++ b/src/gpu/vk/GrVkPipelineState.cpp
@@ -78,7 +78,7 @@
                                            GrVkCommandBuffer* commandBuffer) {
     this->setRenderTargetState(renderTarget, programInfo.origin());
 
-    fGeometryProcessor->setData(fDataManager, programInfo.geomProc());
+    fGeometryProcessor->setData(fDataManager, *gpu->caps()->shaderCaps(), programInfo.geomProc());
     for (int i = 0; i < programInfo.pipeline().numFragmentProcessors(); ++i) {
         auto& fp = programInfo.pipeline().getFragmentProcessor(i);
         for (auto [fp, impl] : GrGLSLFragmentProcessor::ParallelRange(fp, *fFPImpls[i])) {
diff --git a/tests/GrMeshTest.cpp b/tests/GrMeshTest.cpp
index a0b6315..6b842ef 100644
--- a/tests/GrMeshTest.cpp
+++ b/tests/GrMeshTest.cpp
@@ -494,7 +494,9 @@
 };
 
 class GLSLMeshTestProcessor : public GrGLSLGeometryProcessor {
-    void setData(const GrGLSLProgramDataManager&, const GrGeometryProcessor&) final {}
+    void setData(const GrGLSLProgramDataManager&,
+                 const GrShaderCaps&,
+                 const GrGeometryProcessor&) final {}
 
     void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) final {
         const GrMeshTestProcessor& mp = args.fGeomProc.cast<GrMeshTestProcessor>();
diff --git a/tests/GrPipelineDynamicStateTest.cpp b/tests/GrPipelineDynamicStateTest.cpp
index 724a857e..bf857f6 100644
--- a/tests/GrPipelineDynamicStateTest.cpp
+++ b/tests/GrPipelineDynamicStateTest.cpp
@@ -90,7 +90,9 @@
 constexpr GrGeometryProcessor::Attribute GrPipelineDynamicStateTestProcessor::kAttributes[];
 
 class GLSLPipelineDynamicStateTestProcessor : public GrGLSLGeometryProcessor {
-    void setData(const GrGLSLProgramDataManager&, const GrGeometryProcessor&) final {}
+    void setData(const GrGLSLProgramDataManager&,
+                 const GrShaderCaps&,
+                 const GrGeometryProcessor&) final {}
 
     void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) final {
         const GrPipelineDynamicStateTestProcessor& mp =
diff --git a/tests/PrimitiveProcessorTest.cpp b/tests/PrimitiveProcessorTest.cpp
index 816caaa..1ebb961 100644
--- a/tests/PrimitiveProcessorTest.cpp
+++ b/tests/PrimitiveProcessorTest.cpp
@@ -80,14 +80,14 @@
                     void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
                         const GP& gp = args.fGeomProc.cast<GP>();
                         args.fVaryingHandler->emitAttributes(gp);
-                        this->writeOutputPosition(args.fVertBuilder, gpArgs,
-                                                  gp.fAttributes[0].name());
+                        WriteOutputPosition(args.fVertBuilder, gpArgs, gp.fAttributes[0].name());
                         GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
                         fragBuilder->codeAppendf("const half4 %s = half4(1);", args.fOutputColor);
                         fragBuilder->codeAppendf("const half4 %s = half4(1);",
                                                  args.fOutputCoverage);
                     }
                     void setData(const GrGLSLProgramDataManager&,
+                                 const GrShaderCaps&,
                                  const GrGeometryProcessor&) override {}
                 };
                 return new GLSLGP();
diff --git a/tools/flags/CommonFlagsConfig.h b/tools/flags/CommonFlagsConfig.h
index f74851a..1283f6c 100644
--- a/tools/flags/CommonFlagsConfig.h
+++ b/tools/flags/CommonFlagsConfig.h
@@ -67,7 +67,7 @@
                            bool                      testPrecompile,
                            bool                      useDDLSink,
                            bool                      OOPRish,
-                           bool reducedShaders,
+                           bool                      reducedShaders,
                            SurfType);
 
     const SkCommandLineConfigGpu* asConfigGpu() const override { return this; }
diff --git a/tools/gpu/TestOps.cpp b/tools/gpu/TestOps.cpp
index 0ba4f5f..e4136ba 100644
--- a/tools/gpu/TestOps.cpp
+++ b/tools/gpu/TestOps.cpp
@@ -36,8 +36,9 @@
         return new GLSLGP();
     }
 
-    void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
-        GLSLGP::GenKey(*this, b);
+    void getGLSLProcessorKey(const GrShaderCaps& shaderCaps,
+                             GrProcessorKeyBuilder* b) const override {
+        GLSLGP::GenKey(*this, shaderCaps, b);
     }
 
     bool wideColor() const { return fInColor.cpuType() != kUByte4_norm_GrVertexAttribType; }
@@ -46,13 +47,14 @@
     class GLSLGP : public GrGLSLGeometryProcessor {
     public:
         void setData(const GrGLSLProgramDataManager& pdman,
+                     const GrShaderCaps& shaderCaps,
                      const GrGeometryProcessor& geomProc) override {
             const auto& gp = geomProc.cast<GP>();
-            this->setTransform(pdman, fLocalMatrixUni, gp.fLocalMatrix);
+            SetTransform(pdman, shaderCaps, fLocalMatrixUni, gp.fLocalMatrix);
         }
 
-        static void GenKey(const GP& gp, GrProcessorKeyBuilder* b) {
-            b->add32(ComputeMatrixKey(gp.fLocalMatrix));
+        static void GenKey(const GP& gp, const GrShaderCaps& shaderCaps, GrProcessorKeyBuilder* b) {
+            b->add32(ComputeMatrixKey(shaderCaps, gp.fLocalMatrix));
         }
 
     private:
@@ -66,10 +68,14 @@
             args.fFragBuilder->codeAppendf("half4 %s = %s;",
                                            args.fOutputColor, colorVarying.fsIn());
             args.fFragBuilder->codeAppendf("const half4 %s = half4(1);", args.fOutputCoverage);
-            this->writeOutputPosition(args.fVertBuilder, gpArgs, gp.fInPosition.name());
-            this->writeLocalCoord(args.fVertBuilder, args.fUniformHandler, gpArgs,
-                                  gp.fInLocalCoords.asShaderVar(), gp.fLocalMatrix,
-                                  &fLocalMatrixUni);
+            WriteOutputPosition(args.fVertBuilder, gpArgs, gp.fInPosition.name());
+            WriteLocalCoord(args.fVertBuilder,
+                            args.fUniformHandler,
+                            *args.fShaderCaps,
+                            gpArgs,
+                            gp.fInLocalCoords.asShaderVar(),
+                            gp.fLocalMatrix,
+                            &fLocalMatrixUni);
         }
 
         UniformHandle fLocalMatrixUni;