Revert "Revert "Change how vertex/instance attributes are handled in geometry processors.""

This reverts commit 5045e501d2aec23e5f1e4b46346033ac3202c6b0.

TBR=csmartdalton@google.com

Change-Id: Ifbf5f1d8f8ef340fdc69653e931b6d68d4bf0854
Reviewed-on: https://skia-review.googlesource.com/135862
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/effects/GrBezierEffect.cpp b/src/gpu/effects/GrBezierEffect.cpp
index 3dee2f4..d68b1bf 100644
--- a/src/gpu/effects/GrBezierEffect.cpp
+++ b/src/gpu/effects/GrBezierEffect.cpp
@@ -79,7 +79,7 @@
 
     GrGLSLVarying v(kFloat4_GrSLType);
     varyingHandler->addVarying("ConicCoeffs", &v);
-    vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inConicCoeffs()->name());
+    vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inConicCoeffs().name());
 
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     // Setup pass through color
@@ -89,7 +89,7 @@
     this->writeOutputPosition(vertBuilder,
                               uniformHandler,
                               gpArgs,
-                              gp.inPosition()->name(),
+                              gp.inPosition().name(),
                               gp.viewMatrix(),
                               &fViewMatrixUniform);
 
@@ -97,7 +97,7 @@
     this->emitTransforms(vertBuilder,
                          varyingHandler,
                          uniformHandler,
-                         gp.inPosition()->asShaderVar(),
+                         gp.inPosition().asShaderVar(),
                          gp.localMatrix(),
                          args.fFPCoordTransformHandler);
 
@@ -219,6 +219,8 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
+constexpr GrPrimitiveProcessor::Attribute GrConicEffect::kAttributes[];
+
 GrConicEffect::~GrConicEffect() {}
 
 void GrConicEffect::getGLSLProcessorKey(const GrShaderCaps& caps,
@@ -240,8 +242,7 @@
     , fUsesLocalCoords(usesLocalCoords)
     , fCoverageScale(coverage)
     , fEdgeType(edgeType) {
-    fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType);
-    fInConicCoeffs = &this->addVertexAttrib("inConicCoeffs", kHalf4_GrVertexAttribType);
+    this->setVertexAttributeCnt(2);
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -331,7 +332,7 @@
 
     GrGLSLVarying v(kHalf4_GrSLType);
     varyingHandler->addVarying("HairQuadEdge", &v);
-    vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inHairQuadEdge()->name());
+    vertBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inHairQuadEdge().name());
 
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     // Setup pass through color
@@ -341,7 +342,7 @@
     this->writeOutputPosition(vertBuilder,
                               uniformHandler,
                               gpArgs,
-                              gp.inPosition()->name(),
+                              gp.inPosition().name(),
                               gp.viewMatrix(),
                               &fViewMatrixUniform);
 
@@ -349,7 +350,7 @@
     this->emitTransforms(vertBuilder,
                          varyingHandler,
                          uniformHandler,
-                         gp.inPosition()->asShaderVar(),
+                         gp.inPosition().asShaderVar(),
                          gp.localMatrix(),
                          args.fFPCoordTransformHandler);
 
@@ -420,6 +421,8 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
+constexpr GrPrimitiveProcessor::Attribute GrQuadEffect::kAttributes[];
+
 GrQuadEffect::~GrQuadEffect() {}
 
 void GrQuadEffect::getGLSLProcessorKey(const GrShaderCaps& caps,
@@ -441,8 +444,7 @@
     , fUsesLocalCoords(usesLocalCoords)
     , fCoverageScale(coverage)
     , fEdgeType(edgeType) {
-    fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType);
-    fInHairQuadEdge = &this->addVertexAttrib("inHairQuadEdge", kHalf4_GrVertexAttribType);
+    this->setVertexAttributeCnt(2);
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -544,7 +546,7 @@
     this->writeOutputPosition(vertBuilder,
                               uniformHandler,
                               gpArgs,
-                              gp.inPosition()->name(),
+                              gp.inPosition().name(),
                               gp.viewMatrix(),
                               &fViewMatrixUniform);
 
@@ -576,7 +578,7 @@
     this->emitTransforms(vertBuilder,
                          varyingHandler,
                          uniformHandler,
-                         gp.inPosition()->asShaderVar(),
+                         gp.inPosition().asShaderVar(),
                          args.fFPCoordTransformHandler);
 
     GrShaderVar edgeAlpha("edgeAlpha", kFloat_GrSLType, 0);
@@ -647,6 +649,8 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
+constexpr GrPrimitiveProcessor::Attribute GrCubicEffect::kInPosition;
+
 GrCubicEffect::~GrCubicEffect() {}
 
 void GrCubicEffect::getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
@@ -664,7 +668,7 @@
     , fViewMatrix(viewMatrix)
     , fDevKLMMatrix(devKLMMatrix)
     , fEdgeType(edgeType) {
-    fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType);
+    this->setVertexAttributeCnt(1);
 }
 
 //////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/effects/GrBezierEffect.h b/src/gpu/effects/GrBezierEffect.h
index 1744704..eebe42a 100644
--- a/src/gpu/effects/GrBezierEffect.h
+++ b/src/gpu/effects/GrBezierEffect.h
@@ -93,8 +93,8 @@
 
     const char* name() const override { return "Conic"; }
 
-    inline const Attribute* inPosition() const { return fInPosition; }
-    inline const Attribute* inConicCoeffs() const { return fInConicCoeffs; }
+    inline const Attribute& inPosition() const { return kAttributes[0]; }
+    inline const Attribute& inConicCoeffs() const { return kAttributes[1]; }
     inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); }
     inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); }
     inline GrClipEdgeType getEdgeType() const { return fEdgeType; }
@@ -112,14 +112,16 @@
     GrConicEffect(GrColor, const SkMatrix& viewMatrix, uint8_t coverage, GrClipEdgeType,
                   const SkMatrix& localMatrix, bool usesLocalCoords);
 
+    const Attribute& onVertexAttribute(int i) const override { return kAttributes[i]; }
+
     GrColor             fColor;
     SkMatrix            fViewMatrix;
     SkMatrix            fLocalMatrix;
     bool                fUsesLocalCoords;
     uint8_t             fCoverageScale;
     GrClipEdgeType fEdgeType;
-    const Attribute*    fInPosition;
-    const Attribute*    fInConicCoeffs;
+    static constexpr Attribute kAttributes[] = {{"inPosition", kFloat2_GrVertexAttribType},
+                                                {"inConicCoeffs", kHalf4_GrVertexAttribType}};
 
     GR_DECLARE_GEOMETRY_PROCESSOR_TEST
 
@@ -175,8 +177,8 @@
 
     const char* name() const override { return "Quad"; }
 
-    inline const Attribute* inPosition() const { return fInPosition; }
-    inline const Attribute* inHairQuadEdge() const { return fInHairQuadEdge; }
+    inline const Attribute& inPosition() const { return kAttributes[0]; }
+    inline const Attribute& inHairQuadEdge() const { return kAttributes[1]; }
     inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); }
     inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); }
     inline GrClipEdgeType getEdgeType() const { return fEdgeType; }
@@ -194,14 +196,17 @@
     GrQuadEffect(GrColor, const SkMatrix& viewMatrix, uint8_t coverage, GrClipEdgeType,
                  const SkMatrix& localMatrix, bool usesLocalCoords);
 
-    GrColor             fColor;
-    SkMatrix            fViewMatrix;
-    SkMatrix            fLocalMatrix;
-    bool                fUsesLocalCoords;
-    uint8_t             fCoverageScale;
+    const Attribute& onVertexAttribute(int i) const override { return kAttributes[i]; }
+
+    GrColor fColor;
+    SkMatrix fViewMatrix;
+    SkMatrix fLocalMatrix;
+    bool fUsesLocalCoords;
+    uint8_t fCoverageScale;
     GrClipEdgeType fEdgeType;
-    const Attribute*    fInPosition;
-    const Attribute*    fInHairQuadEdge;
+
+    static constexpr Attribute kAttributes[] = {{"inPosition", kFloat2_GrVertexAttribType},
+                                                {"inHairQuadEdge", kHalf4_GrVertexAttribType}};
 
     GR_DECLARE_GEOMETRY_PROCESSOR_TEST
 
@@ -263,7 +268,7 @@
 
     const char* name() const override { return "Cubic"; }
 
-    inline const Attribute* inPosition() const { return fInPosition; }
+    inline const Attribute& inPosition() const { return kInPosition; }
     inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); }
     inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); }
     inline GrClipEdgeType getEdgeType() const { return fEdgeType; }
@@ -280,11 +285,14 @@
     GrCubicEffect(GrColor, const SkMatrix& viewMatrix, const SkMatrix& devKLMMatrix,
                   GrClipEdgeType);
 
-    GrColor             fColor;
-    SkMatrix            fViewMatrix;
-    SkMatrix            fDevKLMMatrix;
+    const Attribute& onVertexAttribute(int) const override { return kInPosition; }
+
+    GrColor fColor;
+    SkMatrix fViewMatrix;
+    SkMatrix fDevKLMMatrix;
     GrClipEdgeType fEdgeType;
-    const Attribute*    fInPosition;
+
+    static constexpr Attribute kInPosition = {"inPosition", kFloat2_GrVertexAttribType};
 
     GR_DECLARE_GEOMETRY_PROCESSOR_TEST
 
diff --git a/src/gpu/effects/GrBitmapTextGeoProc.cpp b/src/gpu/effects/GrBitmapTextGeoProc.cpp
index 4089555..2594f40 100644
--- a/src/gpu/effects/GrBitmapTextGeoProc.cpp
+++ b/src/gpu/effects/GrBitmapTextGeoProc.cpp
@@ -40,7 +40,7 @@
         GrGLSLVarying uv(kFloat2_GrSLType);
         GrSLType texIdxType = args.fShaderCaps->integerSupport() ? kInt_GrSLType : kFloat_GrSLType;
         GrGLSLVarying texIdx(texIdxType);
-        append_index_uv_varyings(args, btgp.inTextureCoords()->name(), atlasSizeInvName, &uv,
+        append_index_uv_varyings(args, btgp.inTextureCoords().name(), atlasSizeInvName, &uv,
                                  &texIdx, nullptr);
 
         GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
@@ -53,13 +53,13 @@
         }
 
         // Setup position
-        gpArgs->fPositionVar = btgp.inPosition()->asShaderVar();
+        gpArgs->fPositionVar = btgp.inPosition().asShaderVar();
 
         // emit transforms
         this->emitTransforms(vertBuilder,
                              varyingHandler,
                              uniformHandler,
-                             btgp.inPosition()->asShaderVar(),
+                             btgp.inPosition().asShaderVar(),
                              btgp.localMatrix(),
                              args.fFPCoordTransformHandler);
 
@@ -129,23 +129,26 @@
         , fColor(color)
         , fLocalMatrix(localMatrix)
         , fUsesW(usesW)
-        , fInColor(nullptr)
         , fMaskFormat(format) {
     SkASSERT(numActiveProxies <= kMaxTextures);
 
     if (usesW) {
-        fInPosition = &this->addVertexAttrib("inPosition", kFloat3_GrVertexAttribType);
+        fInPosition = {"inPosition", kFloat3_GrVertexAttribType};
     } else {
-        fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType);
+        fInPosition = {"inPosition", kFloat2_GrVertexAttribType};
     }
+    fInTextureCoords = {"inTextureCoords", kUShort2_GrVertexAttribType};
+    int cnt = 2;
 
     bool hasVertexColor = kA8_GrMaskFormat == fMaskFormat ||
                           kA565_GrMaskFormat == fMaskFormat;
     if (hasVertexColor) {
-        fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType);
+        fInColor = {"inColor", kUByte4_norm_GrVertexAttribType};
+        ++cnt;
     }
 
-    fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kUShort2_GrVertexAttribType);
+    this->setVertexAttributeCnt(cnt);
+
     for (int i = 0; i < numActiveProxies; ++i) {
         SkASSERT(proxies[i]);
 
@@ -154,6 +157,10 @@
     }
 }
 
+const GrPrimitiveProcessor::Attribute& GrBitmapTextGeoProc::onVertexAttribute(int i) const {
+    return IthInitializedAttribute(i, fInPosition, fInColor, fInTextureCoords);
+}
+
 void GrBitmapTextGeoProc::addNewProxies(const sk_sp<GrTextureProxy>* proxies,
                                         int numActiveProxies,
                                         const GrSamplerState& params) {
diff --git a/src/gpu/effects/GrBitmapTextGeoProc.h b/src/gpu/effects/GrBitmapTextGeoProc.h
index 40ba855..5e44497 100644
--- a/src/gpu/effects/GrBitmapTextGeoProc.h
+++ b/src/gpu/effects/GrBitmapTextGeoProc.h
@@ -36,12 +36,12 @@
 
     const char* name() const override { return "Texture"; }
 
-    const Attribute* inPosition() const { return fInPosition; }
-    const Attribute* inColor() const { return fInColor; }
-    const Attribute* inTextureCoords() const { return fInTextureCoords; }
+    const Attribute& inPosition() const { return fInPosition; }
+    const Attribute& inColor() const { return fInColor; }
+    const Attribute& inTextureCoords() const { return fInTextureCoords; }
     GrMaskFormat maskFormat() const { return fMaskFormat; }
     GrColor color() const { return fColor; }
-    bool hasVertexColor() const { return SkToBool(fInColor); }
+    bool hasVertexColor() const { return fInColor.isInitialized(); }
     const SkMatrix& localMatrix() const { return fLocalMatrix; }
     bool usesW() const { return fUsesW; }
 
@@ -58,13 +58,15 @@
                         const GrSamplerState& params, GrMaskFormat format,
                         const SkMatrix& localMatrix, bool usesW);
 
+    const Attribute& onVertexAttribute(int i) const override;
+
     GrColor          fColor;
     SkMatrix         fLocalMatrix;
     bool             fUsesW;
     TextureSampler   fTextureSamplers[kMaxTextures];
-    const Attribute* fInPosition;
-    const Attribute* fInColor;
-    const Attribute* fInTextureCoords;
+    Attribute        fInPosition;
+    Attribute        fInColor;
+    Attribute        fInTextureCoords;
     GrMaskFormat     fMaskFormat;
 
     GR_DECLARE_GEOMETRY_PROCESSOR_TEST
diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.cpp b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
index 5ac7398..4d5d50b 100644
--- a/src/gpu/effects/GrDistanceFieldGeoProc.cpp
+++ b/src/gpu/effects/GrDistanceFieldGeoProc.cpp
@@ -54,13 +54,13 @@
         varyingHandler->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor);
 
         // Setup position
-        gpArgs->fPositionVar = dfTexEffect.inPosition()->asShaderVar();
+        gpArgs->fPositionVar = dfTexEffect.inPosition().asShaderVar();
 
         // emit transforms
         this->emitTransforms(vertBuilder,
                              varyingHandler,
                              uniformHandler,
-                             dfTexEffect.inPosition()->asShaderVar(),
+                             dfTexEffect.inPosition().asShaderVar(),
                              dfTexEffect.localMatrix(),
                              args.fFPCoordTransformHandler);
 
@@ -69,7 +69,7 @@
         GrSLType texIdxType = args.fShaderCaps->integerSupport() ? kInt_GrSLType : kFloat_GrSLType;
         GrGLSLVarying texIdx(texIdxType);
         GrGLSLVarying st(kFloat2_GrSLType);
-        append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->name(), atlasSizeInvName, &uv,
+        append_index_uv_varyings(args, dfTexEffect.inTextureCoords().name(), atlasSizeInvName, &uv,
                                  &texIdx, &st);
 
         bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask) ==
@@ -206,32 +206,34 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-GrDistanceFieldA8TextGeoProc::GrDistanceFieldA8TextGeoProc(
-        const sk_sp<GrTextureProxy>* proxies,
-        int numProxies,
-        const GrSamplerState& params,
+constexpr GrPrimitiveProcessor::Attribute GrDistanceFieldA8TextGeoProc::kInColor;
+constexpr GrPrimitiveProcessor::Attribute GrDistanceFieldA8TextGeoProc::kInTextureCoords;
+
+GrDistanceFieldA8TextGeoProc::GrDistanceFieldA8TextGeoProc(const sk_sp<GrTextureProxy>* proxies,
+                                                           int numProxies,
+                                                           const GrSamplerState& params,
 #ifdef SK_GAMMA_APPLY_TO_A8
-        float distanceAdjust,
+                                                           float distanceAdjust,
 #endif
-        uint32_t flags,
-        const SkMatrix& localMatrix)
+                                                           uint32_t flags,
+                                                           const SkMatrix& localMatrix)
         : INHERITED(kGrDistanceFieldA8TextGeoProc_ClassID)
+        , fLocalMatrix(localMatrix)
+        , fFlags(flags & kNonLCD_DistanceFieldEffectMask)
 #ifdef SK_GAMMA_APPLY_TO_A8
         , fDistanceAdjust(distanceAdjust)
 #endif
-        , fFlags(flags & kNonLCD_DistanceFieldEffectMask)
-        , fInColor(nullptr)
-        , fLocalMatrix(localMatrix) {
+{
     SkASSERT(numProxies <= kMaxTextures);
-
     SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
+
     if (flags & kPerspective_DistanceFieldEffectFlag) {
-        fInPosition = &this->addVertexAttrib("inPosition", kFloat3_GrVertexAttribType);
+        fInPosition = {"inPosition", kFloat3_GrVertexAttribType};
     } else {
-        fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType);
+        fInPosition = {"inPosition", kFloat2_GrVertexAttribType};
     }
-    fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType);
-    fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kUShort2_GrVertexAttribType);
+    this->setVertexAttributeCnt(3);
+
     for (int i = 0; i < numProxies; ++i) {
         SkASSERT(proxies[i]);
 
@@ -337,8 +339,8 @@
         GrSLType texIdxType = args.fShaderCaps->integerSupport() ? kInt_GrSLType : kFloat_GrSLType;
         GrGLSLVarying texIdx(texIdxType);
         GrGLSLVarying st(kFloat2_GrSLType);
-        append_index_uv_varyings(args, dfPathEffect.inTextureCoords()->name(), atlasSizeInvName,
-                                 &uv, &texIdx, &st);
+        append_index_uv_varyings(args, dfPathEffect.inTextureCoords().name(), atlasSizeInvName, &uv,
+                                 &texIdx, &st);
 
         // setup pass through color
         varyingHandler->addPassThroughAttribute(dfPathEffect.inColor(), args.fOutputColor);
@@ -348,7 +350,7 @@
             this->writeOutputPosition(vertBuilder,
                                       uniformHandler,
                                       gpArgs,
-                                      dfPathEffect.inPosition()->name(),
+                                      dfPathEffect.inPosition().name(),
                                       dfPathEffect.matrix(),
                                       &fMatrixUniform);
 
@@ -356,17 +358,17 @@
             this->emitTransforms(vertBuilder,
                                  varyingHandler,
                                  uniformHandler,
-                                 dfPathEffect.inPosition()->asShaderVar(),
+                                 dfPathEffect.inPosition().asShaderVar(),
                                  args.fFPCoordTransformHandler);
         } else {
             // Setup position
-            this->writeOutputPosition(vertBuilder, gpArgs, dfPathEffect.inPosition()->name());
+            this->writeOutputPosition(vertBuilder, gpArgs, dfPathEffect.inPosition().name());
 
             // emit transforms
             this->emitTransforms(vertBuilder,
                                  varyingHandler,
                                  uniformHandler,
-                                 dfPathEffect.inPosition()->asShaderVar(),
+                                 dfPathEffect.inPosition().asShaderVar(),
                                  dfPathEffect.matrix(),
                                  args.fFPCoordTransformHandler);
         }
@@ -499,22 +501,22 @@
 };
 
 ///////////////////////////////////////////////////////////////////////////////
-GrDistanceFieldPathGeoProc::GrDistanceFieldPathGeoProc(
-                                                 const SkMatrix& matrix,
-                                                 const sk_sp<GrTextureProxy>* proxies,
-                                                 int numProxies,
-                                                 const GrSamplerState& params,
-                                                 uint32_t flags)
+constexpr GrPrimitiveProcessor::Attribute GrDistanceFieldPathGeoProc::kInPosition;
+constexpr GrPrimitiveProcessor::Attribute GrDistanceFieldPathGeoProc::kInColor;
+constexpr GrPrimitiveProcessor::Attribute GrDistanceFieldPathGeoProc::kInTextureCoords;
+
+GrDistanceFieldPathGeoProc::GrDistanceFieldPathGeoProc(const SkMatrix& matrix,
+                                                       const sk_sp<GrTextureProxy>* proxies,
+                                                       int numProxies,
+                                                       const GrSamplerState& params,
+                                                       uint32_t flags)
         : INHERITED(kGrDistanceFieldPathGeoProc_ClassID)
         , fMatrix(matrix)
-        , fFlags(flags & kNonLCD_DistanceFieldEffectMask)
-        , fInColor(nullptr) {
+        , fFlags(flags & kNonLCD_DistanceFieldEffectMask) {
     SkASSERT(numProxies <= kMaxTextures);
-
     SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
-    fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType);
-    fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType);
-    fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kUShort2_GrVertexAttribType);
+
+    this->setVertexAttributeCnt(3);
     for (int i = 0; i < numProxies; ++i) {
         SkASSERT(proxies[i]);
 
@@ -548,6 +550,10 @@
     return new GrGLDistanceFieldPathGeoProc();
 }
 
+const GrPrimitiveProcessor::Attribute& GrDistanceFieldPathGeoProc::onVertexAttribute(int i) const {
+    return IthAttribute(i, kInPosition, kInColor, kInTextureCoords);
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldPathGeoProc);
@@ -614,13 +620,13 @@
         varyingHandler->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor);
 
         // Setup position
-        gpArgs->fPositionVar = dfTexEffect.inPosition()->asShaderVar();
+        gpArgs->fPositionVar = dfTexEffect.inPosition().asShaderVar();
 
         // emit transforms
         this->emitTransforms(vertBuilder,
                              varyingHandler,
                              uniformHandler,
-                             dfTexEffect.inPosition()->asShaderVar(),
+                             dfTexEffect.inPosition().asShaderVar(),
                              dfTexEffect.localMatrix(),
                              args.fFPCoordTransformHandler);
 
@@ -629,7 +635,7 @@
         GrSLType texIdxType = args.fShaderCaps->integerSupport() ? kInt_GrSLType : kFloat_GrSLType;
         GrGLSLVarying texIdx(texIdxType);
         GrGLSLVarying st(kFloat2_GrSLType);
-        append_index_uv_varyings(args, dfTexEffect.inTextureCoords()->name(), atlasSizeInvName, &uv,
+        append_index_uv_varyings(args, dfTexEffect.inTextureCoords().name(), atlasSizeInvName, &uv,
                                  &texIdx, &st);
 
         GrGLSLVarying delta(kFloat_GrSLType);
@@ -802,27 +808,30 @@
 };
 
 ///////////////////////////////////////////////////////////////////////////////
-GrDistanceFieldLCDTextGeoProc::GrDistanceFieldLCDTextGeoProc(
-                                                 const sk_sp<GrTextureProxy>* proxies,
-                                                 int numProxies,
-                                                 const GrSamplerState& params,
-                                                 DistanceAdjust distanceAdjust,
-                                                 uint32_t flags,
-                                                 const SkMatrix& localMatrix)
-        : INHERITED(kGrDistanceFieldLCDTextGeoProc_ClassID)
-        , fDistanceAdjust(distanceAdjust)
-        , fFlags(flags & kLCD_DistanceFieldEffectMask)
-        , fLocalMatrix(localMatrix) {
-    SkASSERT(numProxies <= kMaxTextures);
 
+constexpr GrPrimitiveProcessor::Attribute GrDistanceFieldLCDTextGeoProc::kInColor;
+constexpr GrPrimitiveProcessor::Attribute GrDistanceFieldLCDTextGeoProc::kInTextureCoords;
+
+GrDistanceFieldLCDTextGeoProc::GrDistanceFieldLCDTextGeoProc(const sk_sp<GrTextureProxy>* proxies,
+                                                             int numProxies,
+                                                             const GrSamplerState& params,
+                                                             DistanceAdjust distanceAdjust,
+                                                             uint32_t flags,
+                                                             const SkMatrix& localMatrix)
+        : INHERITED(kGrDistanceFieldLCDTextGeoProc_ClassID)
+        , fLocalMatrix(localMatrix)
+        , fDistanceAdjust(distanceAdjust)
+        , fFlags(flags & kLCD_DistanceFieldEffectMask) {
+    SkASSERT(numProxies <= kMaxTextures);
     SkASSERT(!(flags & ~kLCD_DistanceFieldEffectMask) && (flags & kUseLCD_DistanceFieldEffectFlag));
+
     if (fFlags & kPerspective_DistanceFieldEffectFlag) {
-        fInPosition = &this->addVertexAttrib("inPosition", kFloat3_GrVertexAttribType);
+        fInPosition = {"inPosition", kFloat3_GrVertexAttribType};
     } else {
-        fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType);
+        fInPosition = {"inPosition", kFloat2_GrVertexAttribType};
     }
-    fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType);
-    fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kUShort2_GrVertexAttribType);
+    this->setVertexAttributeCnt(3);
+
     for (int i = 0; i < numProxies; ++i) {
         SkASSERT(proxies[i]);
 
@@ -855,6 +864,11 @@
     return new GrGLDistanceFieldLCDTextGeoProc();
 }
 
+const GrPrimitiveProcessor::Attribute& GrDistanceFieldLCDTextGeoProc::onVertexAttribute(
+        int i) const {
+    return IthAttribute(i, fInPosition, kInColor, kInTextureCoords);
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldLCDTextGeoProc);
diff --git a/src/gpu/effects/GrDistanceFieldGeoProc.h b/src/gpu/effects/GrDistanceFieldGeoProc.h
index 5ba19ed..71626fa 100644
--- a/src/gpu/effects/GrDistanceFieldGeoProc.h
+++ b/src/gpu/effects/GrDistanceFieldGeoProc.h
@@ -76,9 +76,9 @@
 
     const char* name() const override { return "DistanceFieldA8Text"; }
 
-    const Attribute* inPosition() const { return fInPosition; }
-    const Attribute* inColor() const { return fInColor; }
-    const Attribute* inTextureCoords() const { return fInTextureCoords; }
+    const Attribute& inPosition() const { return fInPosition; }
+    const Attribute& inColor() const { return kInColor; }
+    const Attribute& inTextureCoords() const { return kInTextureCoords; }
     const SkMatrix& localMatrix() const { return fLocalMatrix; }
 #ifdef SK_GAMMA_APPLY_TO_A8
     float getDistanceAdjust() const { return fDistanceAdjust; }
@@ -100,17 +100,22 @@
 #endif
                                  uint32_t flags, const SkMatrix& localMatrix);
 
+    const Attribute& onVertexAttribute(int i) const override {
+        return IthAttribute(i, fInPosition, kInColor, kInTextureCoords);
+    }
+
     static constexpr int kMaxTextures = 4;
 
     TextureSampler   fTextureSamplers[kMaxTextures];
+    SkMatrix         fLocalMatrix;
+    Attribute        fInPosition;
+    uint32_t         fFlags;
 #ifdef SK_GAMMA_APPLY_TO_A8
     float            fDistanceAdjust;
 #endif
-    uint32_t         fFlags;
-    const Attribute* fInPosition;
-    const Attribute* fInColor;
-    const Attribute* fInTextureCoords;
-    SkMatrix         fLocalMatrix;
+
+    static constexpr Attribute kInColor = {"inColor", kUByte4_norm_GrVertexAttribType};
+    static constexpr Attribute kInTextureCoords = {"inTextureCoords", kUShort2_GrVertexAttribType};
 
     GR_DECLARE_GEOMETRY_PROCESSOR_TEST
 
@@ -139,9 +144,9 @@
 
     const char* name() const override { return "DistanceFieldPath"; }
 
-    const Attribute* inPosition() const { return fInPosition; }
-    const Attribute* inColor() const { return fInColor; }
-    const Attribute* inTextureCoords() const { return fInTextureCoords; }
+    const Attribute& inPosition() const { return kInPosition; }
+    const Attribute& inColor() const { return kInColor; }
+    const Attribute& inTextureCoords() const { return kInTextureCoords; }
     const SkMatrix& matrix() const { return fMatrix; }
     uint32_t getFlags() const { return fFlags; }
 
@@ -159,12 +164,14 @@
                                int numActiveProxies,
                                const GrSamplerState&, uint32_t flags);
 
+    const Attribute& onVertexAttribute(int i) const override;
+
     SkMatrix         fMatrix;      // view matrix if perspective, local matrix otherwise
     TextureSampler   fTextureSamplers[kMaxTextures];
     uint32_t         fFlags;
-    const Attribute* fInPosition;
-    const Attribute* fInColor;
-    const Attribute* fInTextureCoords;
+    static constexpr Attribute kInPosition = {"inPosition", kFloat2_GrVertexAttribType};
+    static constexpr Attribute kInColor = {"inColor", kUByte4_norm_GrVertexAttribType};
+    static constexpr Attribute kInTextureCoords = {"inTextureCoords", kUShort2_GrVertexAttribType};
 
     GR_DECLARE_GEOMETRY_PROCESSOR_TEST
 
@@ -209,9 +216,9 @@
 
     const char* name() const override { return "DistanceFieldLCDText"; }
 
-    const Attribute* inPosition() const { return fInPosition; }
-    const Attribute* inColor() const { return fInColor; }
-    const Attribute* inTextureCoords() const { return fInTextureCoords; }
+    const Attribute& inPosition() const { return fInPosition; }
+    const Attribute& inColor() const { return kInColor; }
+    const Attribute& inTextureCoords() const { return kInTextureCoords; }
     DistanceAdjust getDistanceAdjust() const { return fDistanceAdjust; }
     uint32_t getFlags() const { return fFlags; }
     const SkMatrix& localMatrix() const { return fLocalMatrix; }
@@ -227,15 +234,18 @@
                                   const GrSamplerState& params, DistanceAdjust wa, uint32_t flags,
                                   const SkMatrix& localMatrix);
 
+    const Attribute& onVertexAttribute(int) const override;
+
     static constexpr int kMaxTextures = 4;
 
     TextureSampler   fTextureSamplers[kMaxTextures];
-    DistanceAdjust   fDistanceAdjust;
-    uint32_t         fFlags;
-    const Attribute* fInPosition;
-    const Attribute* fInColor;
-    const Attribute* fInTextureCoords;
     const SkMatrix   fLocalMatrix;
+    DistanceAdjust   fDistanceAdjust;
+    Attribute        fInPosition;
+    uint32_t         fFlags;
+
+    static constexpr Attribute kInColor = {"inColor", kUByte4_norm_GrVertexAttribType};
+    static constexpr Attribute kInTextureCoords = {"inTextureCoords", kUShort2_GrVertexAttribType};
 
     GR_DECLARE_GEOMETRY_PROCESSOR_TEST
 
diff --git a/src/gpu/effects/GrShadowGeoProc.cpp b/src/gpu/effects/GrShadowGeoProc.cpp
index 52bf287..bf78f41 100644
--- a/src/gpu/effects/GrShadowGeoProc.cpp
+++ b/src/gpu/effects/GrShadowGeoProc.cpp
@@ -33,13 +33,13 @@
         varyingHandler->addPassThroughAttribute(rsgp.inColor(), args.fOutputColor);
 
         // Setup position
-        this->writeOutputPosition(vertBuilder, gpArgs, rsgp.inPosition()->name());
+        this->writeOutputPosition(vertBuilder, gpArgs, rsgp.inPosition().name());
 
         // emit transforms
         this->emitTransforms(vertBuilder,
                              varyingHandler,
                              uniformHandler,
-                             rsgp.inPosition()->asShaderVar(),
+                             rsgp.inPosition().asShaderVar(),
                              args.fFPCoordTransformHandler);
 
         fragBuilder->codeAppend("half d = length(shadowParams.xy);");
@@ -62,11 +62,8 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-GrRRectShadowGeoProc::GrRRectShadowGeoProc()
-: INHERITED(kGrRRectShadowGeoProc_ClassID) {
-    fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType);
-    fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType);
-    fInShadowParams = &this->addVertexAttrib("inShadowParams", kHalf4_GrVertexAttribType);
+GrRRectShadowGeoProc::GrRRectShadowGeoProc() : INHERITED(kGrRRectShadowGeoProc_ClassID) {
+    this->setVertexAttributeCnt(3);
 }
 
 GrGLSLPrimitiveProcessor* GrRRectShadowGeoProc::createGLSLInstance(const GrShaderCaps&) const {
@@ -75,6 +72,10 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+constexpr GrPrimitiveProcessor::Attribute GrRRectShadowGeoProc::kInPosition;
+constexpr GrPrimitiveProcessor::Attribute GrRRectShadowGeoProc::kInColor;
+constexpr GrPrimitiveProcessor::Attribute GrRRectShadowGeoProc::kInShadowParams;
+
 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrRRectShadowGeoProc);
 
 #if GR_TEST_UTILS
diff --git a/src/gpu/effects/GrShadowGeoProc.h b/src/gpu/effects/GrShadowGeoProc.h
index 0b4baf4..df3e501 100644
--- a/src/gpu/effects/GrShadowGeoProc.h
+++ b/src/gpu/effects/GrShadowGeoProc.h
@@ -25,9 +25,9 @@
 
     const char* name() const override { return "RRectShadow"; }
 
-    const Attribute* inPosition() const { return fInPosition; }
-    const Attribute* inColor() const { return fInColor; }
-    const Attribute* inShadowParams() const { return fInShadowParams; }
+    const Attribute& inPosition() const { return kInPosition; }
+    const Attribute& inColor() const { return kInColor; }
+    const Attribute& inShadowParams() const { return kInShadowParams; }
     GrColor color() const { return fColor; }
 
     void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {}
@@ -37,10 +37,15 @@
 private:
     GrRRectShadowGeoProc();
 
+    const Attribute& onVertexAttribute(int i) const override {
+        return IthAttribute(i, kInPosition, kInColor, kInShadowParams);
+    }
+
     GrColor          fColor;
-    const Attribute* fInPosition;
-    const Attribute* fInColor;
-    const Attribute* fInShadowParams;
+
+    static constexpr Attribute kInPosition = {"inPosition", kFloat2_GrVertexAttribType};
+    static constexpr Attribute kInColor = {"inColor", kUByte4_norm_GrVertexAttribType};
+    static constexpr Attribute kInShadowParams = {"inShadowParams", kHalf4_GrVertexAttribType};
 
     GR_DECLARE_GEOMETRY_PROCESSOR_TEST