In FPs, store pointers for all child slots, even nullptr

This simplifies things like ConstantOutputForConstantInput and
invokeChild. It also removes the need for child indices: generated
FPs now directly refer to their children by slot number.

Change-Id: I69bbb042d5d72d21b999256f969c467702d0774d
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/302436
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
diff --git a/src/effects/SkTableColorFilter.cpp b/src/effects/SkTableColorFilter.cpp
index f067909..34aebda 100644
--- a/src/effects/SkTableColorFilter.cpp
+++ b/src/effects/SkTableColorFilter.cpp
@@ -269,12 +269,6 @@
         return std::unique_ptr<GrFragmentProcessor>(new ColorTableEffect(*this));
     }
 
-    bool hasInputFP() const {
-        // We always have a texture-effect child processor at index 0.
-        // If we have an input FP, it will be at child index 1.
-        return this->numChildProcessors() > 1;
-    }
-
     static constexpr int kTexEffectFPIndex = 0;
     static constexpr int kInputFPIndex = 1;
 
@@ -312,11 +306,8 @@
     class Impl : public GrGLSLFragmentProcessor {
     public:
         void emitCode(EmitArgs& args) override {
-            const ColorTableEffect& proc = args.fFp.cast<ColorTableEffect>();
             GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
-            SkString inputColor = proc.hasInputFP()
-                         ? this->invokeChild(kInputFPIndex, args.fInputColor, args)
-                         : SkString(args.fInputColor);
+            SkString inputColor = this->invokeChild(kInputFPIndex, args.fInputColor, args);
             SkString a = this->invokeChild(kTexEffectFPIndex, args, "half2(coord.a, 0.5)");
             SkString r = this->invokeChild(kTexEffectFPIndex, args, "half2(coord.r, 1.5)");
             SkString g = this->invokeChild(kTexEffectFPIndex, args, "half2(coord.g, 2.5)");
diff --git a/src/gpu/GrColorSpaceXform.cpp b/src/gpu/GrColorSpaceXform.cpp
index 002c453..37ce793 100644
--- a/src/gpu/GrColorSpaceXform.cpp
+++ b/src/gpu/GrColorSpaceXform.cpp
@@ -64,9 +64,7 @@
 
         fColorSpaceHelper.emitCode(uniformHandler, proc.colorXform());
 
-        SkString childColor = this->numChildProcessors()
-                     ? this->invokeChild(0, args.fInputColor, args)
-                     : SkString(args.fInputColor);
+        SkString childColor = this->invokeChild(0, args.fInputColor, args);
 
         SkString xformedColor;
         fragBuilder->appendColorGamutXform(&xformedColor, childColor.c_str(), &fColorSpaceHelper);
@@ -128,9 +126,7 @@
 
 SkPMColor4f GrColorSpaceXformEffect::constantOutputForConstantInput(
         const SkPMColor4f& input) const {
-    const auto c0 = this->numChildProcessors()
-                            ? ConstantOutputForConstantInput(this->childProcessor(0), input)
-                            : input;
+    const auto c0 = ConstantOutputForConstantInput(this->childProcessor(0), input);
     return this->fColorXform->apply(c0.unpremul()).premul();
 }
 
diff --git a/src/gpu/GrFragmentProcessor.cpp b/src/gpu/GrFragmentProcessor.cpp
index dc36c09..24f678c 100644
--- a/src/gpu/GrFragmentProcessor.cpp
+++ b/src/gpu/GrFragmentProcessor.cpp
@@ -31,7 +31,12 @@
         return false;
     }
     for (int i = 0; i < this->numChildProcessors(); ++i) {
-        if (!this->childProcessor(i).isEqual(that.childProcessor(i))) {
+        auto thisChild = this->childProcessor(i),
+             thatChild = that .childProcessor(i);
+        if (SkToBool(thisChild) != SkToBool(thatChild)) {
+            return false;
+        }
+        if (thisChild && !thisChild->isEqual(*thatChild)) {
             return false;
         }
     }
@@ -51,7 +56,9 @@
         func(*te);
     }
     for (auto& child : fChildProcessors) {
-        child->visitTextureEffects(func);
+        if (child) {
+            child->visitTextureEffects(func);
+        }
     }
 }
 
@@ -73,7 +80,8 @@
     GrGLSLFragmentProcessor* glFragProc = this->onCreateGLSLInstance();
     glFragProc->fChildProcessors.push_back_n(fChildProcessors.count());
     for (int i = 0; i < fChildProcessors.count(); ++i) {
-        glFragProc->fChildProcessors[i] = fChildProcessors[i]->createGLSLInstance();
+        glFragProc->fChildProcessors[i] =
+                fChildProcessors[i] ? fChildProcessors[i]->createGLSLInstance() : nullptr;
     }
     return glFragProc;
 }
@@ -83,16 +91,23 @@
     if (!(fFlags & flag)) {
         fFlags |= flag;
         for (auto& child : fChildProcessors) {
-            child->addAndPushFlagToChildren(flag);
+            if (child) {
+                child->addAndPushFlagToChildren(flag);
+            }
         }
     }
 #ifdef SK_DEBUG
     for (auto& child : fChildProcessors) {
-        SkASSERT(child->fFlags & flag);
+        SkASSERT(!child || (child->fFlags & flag));
     }
 #endif
 }
 
+int GrFragmentProcessor::numNonNullChildProcessors() const {
+    return std::count_if(fChildProcessors.begin(), fChildProcessors.end(),
+                         [](const auto& c) { return c != nullptr; });
+}
+
 #ifdef SK_DEBUG
 bool GrFragmentProcessor::isInstantiated() const {
     bool result = true;
@@ -105,10 +120,11 @@
 }
 #endif
 
-int GrFragmentProcessor::registerChild(std::unique_ptr<GrFragmentProcessor> child,
-                                       SkSL::SampleUsage sampleUsage) {
+void GrFragmentProcessor::registerChild(std::unique_ptr<GrFragmentProcessor> child,
+                                        SkSL::SampleUsage sampleUsage) {
     if (!child) {
-        return -1;
+        fChildProcessors.push_back(nullptr);
+        return;
     }
 
     // The child should not have been attached to another FP already and not had any sampling
@@ -156,7 +172,6 @@
 
     fRequestedFeatures |= child->fRequestedFeatures;
 
-    int index = fChildProcessors.count();
     // Record that the child is attached to us; this FP is the source of any uniform data needed
     // to evaluate the child sample matrix.
     child->fParent = this;
@@ -165,17 +180,15 @@
     // Sanity check: our sample strategy comes from a parent we shouldn't have yet.
     SkASSERT(!this->isSampledWithExplicitCoords() && !this->hasPerspectiveTransform() &&
              !fUsage.isSampled() && !fParent);
-    return index;
-}
-
-int GrFragmentProcessor::cloneAndRegisterChildProcessor(const GrFragmentProcessor& fp) {
-    std::unique_ptr<GrFragmentProcessor> clone = fp.clone();
-    return this->registerChild(std::move(clone), fp.sampleUsage());
 }
 
 void GrFragmentProcessor::cloneAndRegisterAllChildProcessors(const GrFragmentProcessor& src) {
     for (int i = 0; i < src.numChildProcessors(); ++i) {
-        this->cloneAndRegisterChildProcessor(src.childProcessor(i));
+        if (auto fp = src.childProcessor(i)) {
+            this->registerChild(fp->clone(), fp->sampleUsage());
+        } else {
+            this->registerChild(nullptr);
+        }
     }
 }
 
@@ -233,7 +246,7 @@
         const GrSwizzle& swizzle() const { return fSwizzle; }
 
         std::unique_ptr<GrFragmentProcessor> clone() const override {
-            return Make(this->childProcessor(0).clone(), fSwizzle);
+            return Make(this->childProcessor(0)->clone(), fSwizzle);
         }
 
     private:
@@ -300,7 +313,7 @@
         const char* name() const override { return "Premultiply"; }
 
         std::unique_ptr<GrFragmentProcessor> clone() const override {
-            return Make(this->childProcessor(0).clone());
+            return Make(this->childProcessor(0)->clone());
         }
 
     private:
@@ -378,8 +391,12 @@
         std::unique_ptr<GrFragmentProcessor> clone() const override {
             SkSTArray<4, std::unique_ptr<GrFragmentProcessor>> children(this->numChildProcessors());
             for (int i = 0; i < this->numChildProcessors(); ++i) {
-                if (!children.push_back(this->childProcessor(i).clone())) {
-                    return nullptr;
+                if (this->childProcessor(i)) {
+                    if (!children.push_back(this->childProcessor(i)->clone())) {
+                        return nullptr;
+                    }
+                } else {
+                    children.push_back(nullptr);
                 }
             }
             return Make(children.begin(), this->numChildProcessors());
@@ -484,7 +501,9 @@
     const GrFragmentProcessor* back = fFPStack.back();
     fFPStack.pop_back();
     for (int i = back->numChildProcessors() - 1; i >= 0; --i) {
-        fFPStack.push_back(&back->childProcessor(i));
+        if (auto child = back->childProcessor(i)) {
+            fFPStack.push_back(child);
+        }
     }
     return *this;
 }
diff --git a/src/gpu/GrFragmentProcessor.h b/src/gpu/GrFragmentProcessor.h
index 812f06f..ac7570e 100644
--- a/src/gpu/GrFragmentProcessor.h
+++ b/src/gpu/GrFragmentProcessor.h
@@ -123,17 +123,22 @@
 
     void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
         this->onGetGLSLProcessorKey(caps, b);
-        for (int i = 0; i < fChildProcessors.count(); ++i) {
-            fChildProcessors[i]->getGLSLProcessorKey(caps, b);
+        for (const auto& child : fChildProcessors) {
+            if (child) {
+                child->getGLSLProcessorKey(caps, b);
+            }
         }
     }
 
     int numVaryingCoordsUsed() const { return this->usesVaryingCoordsDirectly() ? 1 : 0; }
 
     int numChildProcessors() const { return fChildProcessors.count(); }
+    int numNonNullChildProcessors() const;
 
-    GrFragmentProcessor& childProcessor(int index) { return *fChildProcessors[index]; }
-    const GrFragmentProcessor& childProcessor(int index) const { return *fChildProcessors[index]; }
+    GrFragmentProcessor* childProcessor(int index) { return fChildProcessors[index].get(); }
+    const GrFragmentProcessor* childProcessor(int index) const {
+        return fChildProcessors[index].get();
+    }
 
     SkDEBUGCODE(bool isInstantiated() const;)
 
@@ -331,7 +336,7 @@
 
     /** Useful when you can't call fp->optimizationFlags() on a base class object from a subclass.*/
     static OptimizationFlags ProcessorOptimizationFlags(const GrFragmentProcessor* fp) {
-        return fp->optimizationFlags();
+        return fp ? fp->optimizationFlags() : kAll_OptimizationFlags;
     }
 
     /**
@@ -339,10 +344,14 @@
      * constantOutputForConstantInput. It must only be called when
      * hasConstantOutputForConstantInput() is known to be true.
      */
-    static SkPMColor4f ConstantOutputForConstantInput(const GrFragmentProcessor& fp,
+    static SkPMColor4f ConstantOutputForConstantInput(const GrFragmentProcessor* fp,
                                                       const SkPMColor4f& input) {
-        SkASSERT(fp.hasConstantOutputForConstantInput());
-        return fp.constantOutputForConstantInput(input);
+        if (fp) {
+            SkASSERT(fp->hasConstantOutputForConstantInput());
+            return fp->constantOutputForConstantInput(input);
+        } else {
+            return input;
+        }
     }
 
     /**
@@ -356,15 +365,8 @@
      *
      * The SampleUsage parameter describes all of the ways that the child is sampled by the parent.
      */
-    int registerChild(std::unique_ptr<GrFragmentProcessor> child,
-                      SkSL::SampleUsage sampleUsage = SkSL::SampleUsage::PassThrough());
-
-    /**
-     * This method takes an existing fragment processor, clones it, registers it as a child of this
-     * fragment processor, and returns its child index. It also takes care of any boilerplate in the
-     * cloning process.
-     */
-    int cloneAndRegisterChildProcessor(const GrFragmentProcessor& fp);
+    void registerChild(std::unique_ptr<GrFragmentProcessor> child,
+                       SkSL::SampleUsage sampleUsage = SkSL::SampleUsage::PassThrough());
 
     /**
      * This method takes an existing fragment processor, clones all of its children, and registers
diff --git a/src/gpu/GrProcessor.h b/src/gpu/GrProcessor.h
index ec1e09d..f57ca8d 100644
--- a/src/gpu/GrProcessor.h
+++ b/src/gpu/GrProcessor.h
@@ -60,6 +60,8 @@
 class GrProcessor {
 public:
     enum ClassID {
+        kNull_ClassID,  // Reserved ID for missing (null) processors
+
         kBigKeyProcessor_ClassID,
         kBlockInputFragmentProcessor_ClassID,
         kButtCapStrokedCircleGeometryProcessor_ClassID,
diff --git a/src/gpu/GrProcessorSet.cpp b/src/gpu/GrProcessorSet.cpp
index b8f077d..5426abd 100644
--- a/src/gpu/GrProcessorSet.cpp
+++ b/src/gpu/GrProcessorSet.cpp
@@ -87,10 +87,11 @@
     for (int i = 0; i < indentCnt; ++i) {
         indentString.append("    ");
     }
-    result.appendf("%s%s %s \n", indentString.c_str(), fp->name(), fp->dumpInfo().c_str());
-    if (fp->numChildProcessors()) {
+    result.appendf("%s%s %s \n", indentString.c_str(), fp ? fp->name() : "null",
+                   fp ? fp->dumpInfo().c_str() : "");
+    if (fp && fp->numChildProcessors()) {
         for (int i = 0; i < fp->numChildProcessors(); ++i) {
-            result += dump_fragment_processor_tree(&fp->childProcessor(i), indentCnt + 1);
+            result += dump_fragment_processor_tree(fp->childProcessor(i), indentCnt + 1);
         }
     }
     return result;
diff --git a/src/gpu/GrProcessorUnitTest.cpp b/src/gpu/GrProcessorUnitTest.cpp
index d257e44..58b8fc0 100644
--- a/src/gpu/GrProcessorUnitTest.cpp
+++ b/src/gpu/GrProcessorUnitTest.cpp
@@ -114,7 +114,7 @@
     do {
         fp = GrFragmentProcessorTestFactory::Make(data);
         SkASSERT(fp);
-    } while (fp->numChildProcessors() != 0);
+    } while (fp->numNonNullChildProcessors() != 0);
     return fp;
 }
 #endif
diff --git a/src/gpu/GrProgramDesc.cpp b/src/gpu/GrProgramDesc.cpp
index 3383fcf..6c5be18 100644
--- a/src/gpu/GrProgramDesc.cpp
+++ b/src/gpu/GrProgramDesc.cpp
@@ -148,8 +148,13 @@
                                         const GrCaps& caps,
                                         GrProcessorKeyBuilder* b) {
     for (int i = 0; i < fp.numChildProcessors(); ++i) {
-        if (!gen_frag_proc_and_meta_keys(primProc, fp.childProcessor(i), caps, b)) {
-            return false;
+        if (auto child = fp.childProcessor(i)) {
+            if (!gen_frag_proc_and_meta_keys(primProc, *child, caps, b)) {
+                return false;
+            }
+        } else {
+            // Fold in a sentinel value as the "class ID" for any null children
+            b->add32(GrProcessor::ClassID::kNull_ClassID);
         }
     }
 
diff --git a/src/gpu/ccpr/GrCCClipProcessor.cpp b/src/gpu/ccpr/GrCCClipProcessor.cpp
index baa27e9..f62c657 100644
--- a/src/gpu/ccpr/GrCCClipProcessor.cpp
+++ b/src/gpu/ccpr/GrCCClipProcessor.cpp
@@ -31,10 +31,7 @@
     auto view = make_view(caps, clipPath->atlasLazyProxy(), fIsCoverageCount);
     auto texEffect = GrTextureEffect::Make(std::move(view), kUnknown_SkAlphaType);
     this->registerChild(std::move(texEffect), SkSL::SampleUsage::Explicit());
-
-    if (inputFP != nullptr) {
-        this->registerChild(std::move(inputFP));
-    }
+    this->registerChild(std::move(inputFP));
 }
 
 GrCCClipProcessor::GrCCClipProcessor(const GrCCClipProcessor& that)
@@ -66,12 +63,6 @@
            that.fIsCoverageCount == fIsCoverageCount && that.fMustCheckBounds == fMustCheckBounds;
 }
 
-bool GrCCClipProcessor::hasInputFP() const {
-    // We always have a `texEffect`, and this accounts for one child.
-    // The second child will be the input FP, if we have one.
-    return this->numChildProcessors() > 1;
-}
-
 class GrCCClipProcessor::Impl : public GrGLSLFragmentProcessor {
 public:
     void emitCode(EmitArgs& args) override {
@@ -123,9 +114,7 @@
         }
 
         constexpr int kInputFPIndex = 1;
-        SkString inputColor = proc.hasInputFP()
-            ? this->invokeChild(kInputFPIndex, args.fInputColor, args)
-            : SkString(args.fInputColor);
+        SkString inputColor = this->invokeChild(kInputFPIndex, args.fInputColor, args);
 
         f->codeAppendf("%s = %s * coverage;", args.fOutputColor, inputColor.c_str());
     }
diff --git a/src/gpu/ccpr/GrCCClipProcessor.h b/src/gpu/ccpr/GrCCClipProcessor.h
index 536bb8e..f5d1194 100644
--- a/src/gpu/ccpr/GrCCClipProcessor.h
+++ b/src/gpu/ccpr/GrCCClipProcessor.h
@@ -32,7 +32,6 @@
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
     bool onIsEqual(const GrFragmentProcessor&) const override;
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
-    bool hasInputFP() const;
 
 private:
     explicit GrCCClipProcessor(const GrCCClipProcessor&);
diff --git a/src/gpu/effects/GrClampFragmentProcessor.fp b/src/gpu/effects/GrClampFragmentProcessor.fp
index ed6771c..06c1aa9 100644
--- a/src/gpu/effects/GrClampFragmentProcessor.fp
+++ b/src/gpu/effects/GrClampFragmentProcessor.fp
@@ -26,9 +26,7 @@
 
 @class {
     SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
-        SkPMColor4f input = this->numChildProcessors()
-                            ? ConstantOutputForConstantInput(this->childProcessor(0), inColor)
-                            : inColor;
+        SkPMColor4f input = ConstantOutputForConstantInput(this->childProcessor(0), inColor);
         float clampedAlpha = SkTPin(input.fA, 0.f, 1.f);
         float clampVal = clampToPremul ? clampedAlpha : 1.f;
         return {SkTPin(input.fR, 0.f, clampVal),
diff --git a/src/gpu/effects/GrColorMatrixFragmentProcessor.fp b/src/gpu/effects/GrColorMatrixFragmentProcessor.fp
index 5e07a14..d5e399c 100644
--- a/src/gpu/effects/GrColorMatrixFragmentProcessor.fp
+++ b/src/gpu/effects/GrColorMatrixFragmentProcessor.fp
@@ -35,9 +35,7 @@
 
 @class {
     SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
-        SkPMColor4f input = this->numChildProcessors()
-                            ? ConstantOutputForConstantInput(this->childProcessor(0), inColor)
-                            : inColor;
+        SkPMColor4f input = ConstantOutputForConstantInput(this->childProcessor(0), inColor);
         SkColor4f color;
         if (unpremulInput) {
             color = input.unpremul();
diff --git a/src/gpu/effects/GrConvexPolyEffect.cpp b/src/gpu/effects/GrConvexPolyEffect.cpp
index 3dfe6c2..c2be2d1 100644
--- a/src/gpu/effects/GrConvexPolyEffect.cpp
+++ b/src/gpu/effects/GrConvexPolyEffect.cpp
@@ -66,9 +66,7 @@
         fragBuilder->codeAppend("\talpha = 1.0 - alpha;\n");
     }
 
-    SkString inputSample = cpe.hasInputFP()
-                ? this->invokeChild(/*childIndex=*/0, args.fInputColor, args)
-                : SkString(args.fInputColor);
+    SkString inputSample = this->invokeChild(/*childIndex=*/0, args.fInputColor, args);
 
     fragBuilder->codeAppendf("\t%s = %s * alpha;\n", args.fOutputColor, inputSample.c_str());
 }
diff --git a/src/gpu/effects/GrConvexPolyEffect.h b/src/gpu/effects/GrConvexPolyEffect.h
index 36fbc73..f7fb2bd 100644
--- a/src/gpu/effects/GrConvexPolyEffect.h
+++ b/src/gpu/effects/GrConvexPolyEffect.h
@@ -69,8 +69,6 @@
 
     const SkScalar* getEdges() const { return fEdges; }
 
-    bool hasInputFP() const { return numChildProcessors() > 0; }
-
 private:
     GrConvexPolyEffect(std::unique_ptr<GrFragmentProcessor> inputFP,
                        GrClipEdgeType edgeType,
diff --git a/src/gpu/effects/GrHSLToRGBFilterEffect.fp b/src/gpu/effects/GrHSLToRGBFilterEffect.fp
index 029f7b2..35a7a92 100644
--- a/src/gpu/effects/GrHSLToRGBFilterEffect.fp
+++ b/src/gpu/effects/GrHSLToRGBFilterEffect.fp
@@ -38,9 +38,7 @@
     #include "include/private/SkNx.h"
 
     SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
-        SkPMColor4f c = this->numChildProcessors()
-                            ? ConstantOutputForConstantInput(this->childProcessor(0), inColor)
-                            : inColor;
+        SkPMColor4f c = ConstantOutputForConstantInput(this->childProcessor(0), inColor);
         const auto H = c[0],
                    S = c[1],
                    L = c[2],
diff --git a/src/gpu/effects/GrLumaColorFilterEffect.fp b/src/gpu/effects/GrLumaColorFilterEffect.fp
index 6718845..19be77a 100644
--- a/src/gpu/effects/GrLumaColorFilterEffect.fp
+++ b/src/gpu/effects/GrLumaColorFilterEffect.fp
@@ -16,9 +16,7 @@
     #include "include/private/SkColorData.h"
 
     SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
-        SkPMColor4f input = this->numChildProcessors()
-                ? ConstantOutputForConstantInput(this->childProcessor(inputFP_index), inColor)
-                : inColor;
+        SkPMColor4f input = ConstantOutputForConstantInput(this->childProcessor(0), inColor);
         float luma = SK_ITU_BT709_LUM_COEFF_R * input.fR +
                      SK_ITU_BT709_LUM_COEFF_G * input.fG +
                      SK_ITU_BT709_LUM_COEFF_B * input.fB;
diff --git a/src/gpu/effects/GrMixerEffect.fp b/src/gpu/effects/GrMixerEffect.fp
index b598711..c406b9a 100644
--- a/src/gpu/effects/GrMixerEffect.fp
+++ b/src/gpu/effects/GrMixerEffect.fp
@@ -14,14 +14,9 @@
 
 @class {
     SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& in) const override {
-        const SkPMColor4f inColor = (inputFP_index >= 0)
-              ? ConstantOutputForConstantInput(this->childProcessor(inputFP_index), in)
-              : in;
-        const SkPMColor4f c0 =
-                ConstantOutputForConstantInput(this->childProcessor(fp0_index), inColor);
-        const SkPMColor4f c1 = (fp1_index >= 0)
-              ? ConstantOutputForConstantInput(this->childProcessor(fp1_index), inColor)
-              : inColor;
+        const SkPMColor4f inColor = ConstantOutputForConstantInput(this->childProcessor(0), in);
+        const SkPMColor4f c0 = ConstantOutputForConstantInput(this->childProcessor(1), inColor);
+        const SkPMColor4f c1 = ConstantOutputForConstantInput(this->childProcessor(2), inColor);
         return {
             c0.fR + (c1.fR - c0.fR) * weight,
             c0.fG + (c1.fG - c0.fG) * weight,
@@ -32,9 +27,9 @@
 }
 
 @optimizationFlags {
-    (inputFP ? ProcessorOptimizationFlags(inputFP.get()) : kAll_OptimizationFlags) &
-    (fp1 ?     ProcessorOptimizationFlags(fp1.get())     : kAll_OptimizationFlags) &
-     ProcessorOptimizationFlags(fp0.get())
+    ProcessorOptimizationFlags(inputFP.get()) &
+    ProcessorOptimizationFlags(fp1.get()) &
+    ProcessorOptimizationFlags(fp0.get())
 }
 
 void main() {
diff --git a/src/gpu/effects/GrRGBToHSLFilterEffect.fp b/src/gpu/effects/GrRGBToHSLFilterEffect.fp
index b30d798..309a151 100644
--- a/src/gpu/effects/GrRGBToHSLFilterEffect.fp
+++ b/src/gpu/effects/GrRGBToHSLFilterEffect.fp
@@ -58,9 +58,7 @@
     #include "include/private/SkColorData.h"
 
     SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
-        SkPMColor4f c = this->numChildProcessors()
-                            ? ConstantOutputForConstantInput(this->childProcessor(0), inColor)
-                            : inColor;
+        SkPMColor4f c = ConstantOutputForConstantInput(this->childProcessor(0), inColor);
         const auto p = (c.fG < c.fB) ? SkPMColor4f{ c.fB, c.fG, -1,  2/3.f }
                                      : SkPMColor4f{ c.fG, c.fB,  0, -1/3.f },
                    q = (c.fR < p[0]) ? SkPMColor4f{ p[0], c.fR, p[1], p[3] }
diff --git a/src/gpu/effects/GrRRectEffect.cpp b/src/gpu/effects/GrRRectEffect.cpp
index 9e3e334..90186b9 100644
--- a/src/gpu/effects/GrRRectEffect.cpp
+++ b/src/gpu/effects/GrRRectEffect.cpp
@@ -60,10 +60,6 @@
 
     GrClipEdgeType getEdgeType() const { return fEdgeType; }
 
-    bool hasInputFP() const {
-        return this->numChildProcessors() > 0;
-    }
-
 private:
     CircularRRectEffect(std::unique_ptr<GrFragmentProcessor> inputFP,
                         GrClipEdgeType, uint32_t circularCornerFlags, const SkRRect&);
@@ -300,9 +296,7 @@
         fragBuilder->codeAppend("alpha = 1.0 - alpha;");
     }
 
-    SkString inputSample = crre.hasInputFP()
-                ? this->invokeChild(/*childIndex=*/0, args.fInputColor, args)
-                : SkString(args.fInputColor);
+    SkString inputSample = this->invokeChild(/*childIndex=*/0, args.fInputColor, args);
 
     fragBuilder->codeAppendf("%s = %s * alpha;", args.fOutputColor, inputSample.c_str());
 }
@@ -421,10 +415,6 @@
 
     GrClipEdgeType getEdgeType() const { return fEdgeType; }
 
-    bool hasInputFP() const {
-        return this->numChildProcessors() > 0;
-    }
-
 private:
     EllipticalRRectEffect(std::unique_ptr<GrFragmentProcessor>, GrClipEdgeType, const SkRRect&);
     EllipticalRRectEffect(const EllipticalRRectEffect& that);
@@ -633,9 +623,7 @@
         fragBuilder->codeAppend("half alpha = clamp(0.5 + approx_dist, 0.0, 1.0);");
     }
 
-    SkString inputSample = erre.hasInputFP()
-                ? this->invokeChild(/*childIndex=*/0, args.fInputColor, args)
-                : SkString(args.fInputColor);
+    SkString inputSample = this->invokeChild(/*childIndex=*/0, args.fInputColor, args);
 
     fragBuilder->codeAppendf("%s = %s * alpha;", args.fOutputColor, inputSample.c_str());
 }
diff --git a/src/gpu/effects/GrSkSLFP.cpp b/src/gpu/effects/GrSkSLFP.cpp
index d7d05d68..e77e43e 100644
--- a/src/gpu/effects/GrSkSLFP.cpp
+++ b/src/gpu/effects/GrSkSLFP.cpp
@@ -247,7 +247,7 @@
 std::unique_ptr<GrFragmentProcessor> GrSkSLFP::clone() const {
     std::unique_ptr<GrSkSLFP> result(new GrSkSLFP(*this));
     for (int i = 0; i < this->numChildProcessors(); ++i) {
-        result->addChild(this->childProcessor(i).clone());
+        result->addChild(this->childProcessor(i)->clone());
     }
     return std::unique_ptr<GrFragmentProcessor>(result.release());
 }
diff --git a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
index e60aa40..882f897 100644
--- a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
+++ b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
@@ -55,13 +55,7 @@
 #ifdef SK_DEBUG
     SkString dumpInfo() const override {
         SkString str;
-
         str.appendf("Mode: %s", SkBlendMode_Name(fMode));
-
-        for (int i = 0; i < this->numChildProcessors(); ++i) {
-            str.appendf(" [%s %s]",
-                        this->childProcessor(i).name(), this->childProcessor(i).dumpInfo().c_str());
-        }
         return str;
     }
 #endif
@@ -70,8 +64,6 @@
 
     SkBlendMode getMode() const { return fMode; }
     ComposeBehavior composeBehavior() const { return fComposeBehavior; }
-    int srcFPIndex() const { return fSrcFPIndex; }
-    int dstFPIndex() const { return fDstFPIndex; }
 
 private:
     ComposeFragmentProcessor(std::unique_ptr<GrFragmentProcessor> src,
@@ -84,16 +76,14 @@
             fComposeBehavior = (src && dst) ? ComposeBehavior::kComposeTwoBehavior
                                             : ComposeBehavior::kComposeOneBehavior;
         }
-        fSrcFPIndex = this->registerChild(std::move(src));
-        fDstFPIndex = this->registerChild(std::move(dst));
+        this->registerChild(std::move(src));
+        this->registerChild(std::move(dst));
     }
 
     ComposeFragmentProcessor(const ComposeFragmentProcessor& that)
             : INHERITED(kComposeFragmentProcessor_ClassID, ProcessorOptimizationFlags(&that))
             , fMode(that.fMode)
-            , fComposeBehavior(that.fComposeBehavior)
-            , fSrcFPIndex(that.fSrcFPIndex)
-            , fDstFPIndex(that.fDstFPIndex) {
+            , fComposeBehavior(that.fComposeBehavior) {
         this->cloneAndRegisterAllChildProcessors(that);
     }
 
@@ -190,30 +180,30 @@
     }
 
     SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
-        const auto* src = (fSrcFPIndex >= 0) ? &this->childProcessor(fSrcFPIndex) : nullptr;
-        const auto* dst = (fDstFPIndex >= 0) ? &this->childProcessor(fDstFPIndex) : nullptr;
+        const auto* src = this->childProcessor(0);
+        const auto* dst = this->childProcessor(1);
 
         switch (fComposeBehavior) {
             case ComposeBehavior::kComposeOneBehavior: {
-                SkPMColor4f srcColor = src ? ConstantOutputForConstantInput(*src, SK_PMColor4fWHITE)
+                SkPMColor4f srcColor = src ? ConstantOutputForConstantInput(src, SK_PMColor4fWHITE)
                                            : input;
-                SkPMColor4f dstColor = dst ? ConstantOutputForConstantInput(*dst, SK_PMColor4fWHITE)
+                SkPMColor4f dstColor = dst ? ConstantOutputForConstantInput(dst, SK_PMColor4fWHITE)
                                            : input;
                 return SkBlendMode_Apply(fMode, srcColor, dstColor);
             }
 
             case ComposeBehavior::kComposeTwoBehavior: {
                 SkPMColor4f opaqueInput = { input.fR, input.fG, input.fB, 1 };
-                SkPMColor4f srcColor = ConstantOutputForConstantInput(*src, opaqueInput);
-                SkPMColor4f dstColor = ConstantOutputForConstantInput(*dst, opaqueInput);
+                SkPMColor4f srcColor = ConstantOutputForConstantInput(src, opaqueInput);
+                SkPMColor4f dstColor = ConstantOutputForConstantInput(dst, opaqueInput);
                 SkPMColor4f result = SkBlendMode_Apply(fMode, srcColor, dstColor);
                 return result * input.fA;
             }
 
             case ComposeBehavior::kSkModeBehavior: {
-                SkPMColor4f srcColor = src ? ConstantOutputForConstantInput(*src, SK_PMColor4fWHITE)
+                SkPMColor4f srcColor = src ? ConstantOutputForConstantInput(src, SK_PMColor4fWHITE)
                                            : input;
-                SkPMColor4f dstColor = dst ? ConstantOutputForConstantInput(*dst, input)
+                SkPMColor4f dstColor = dst ? ConstantOutputForConstantInput(dst, input)
                                            : input;
                 return SkBlendMode_Apply(fMode, srcColor, dstColor);
             }
@@ -228,8 +218,6 @@
 
     SkBlendMode fMode;
     ComposeBehavior fComposeBehavior;
-    int fSrcFPIndex = -1;
-    int fDstFPIndex = -1;
 
     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
 
@@ -284,8 +272,6 @@
     const ComposeFragmentProcessor& cs = args.fFp.cast<ComposeFragmentProcessor>();
     SkBlendMode mode = cs.getMode();
     ComposeBehavior behavior = cs.composeBehavior();
-    int srcFPIndex = cs.srcFPIndex();
-    int dstFPIndex = cs.dstFPIndex();
 
     // Load the input color and make an opaque copy if needed.
     fragBuilder->codeAppendf("// %s Xfer Mode: %s\n",
@@ -295,25 +281,25 @@
     switch (behavior) {
         case ComposeBehavior::kComposeOneBehavior:
             // Compose-one operations historically leave the alpha on the input color.
-            srcColor = (srcFPIndex >= 0) ? this->invokeChild(srcFPIndex, args)
-                                         : SkString(args.fInputColor);
-            dstColor = (dstFPIndex >= 0) ? this->invokeChild(dstFPIndex, args)
-                                         : SkString(args.fInputColor);
+            srcColor = cs.childProcessor(0) ? this->invokeChild(0, args)
+                                            : SkString(args.fInputColor);
+            dstColor = cs.childProcessor(1) ? this->invokeChild(1, args)
+                                            : SkString(args.fInputColor);
             break;
 
         case ComposeBehavior::kComposeTwoBehavior:
             // Compose-two operations historically have forced the input color to opaque.
             fragBuilder->codeAppendf("half4 inputOpaque = %s.rgb1;\n", args.fInputColor);
-            srcColor = this->invokeChild(srcFPIndex, "inputOpaque", args);
-            dstColor = this->invokeChild(dstFPIndex, "inputOpaque", args);
+            srcColor = this->invokeChild(0, "inputOpaque", args);
+            dstColor = this->invokeChild(1, "inputOpaque", args);
             break;
 
         case ComposeBehavior::kSkModeBehavior:
             // SkModeColorFilter operations act like ComposeOne, but pass the input color to dst.
-            srcColor = (srcFPIndex >= 0) ? this->invokeChild(srcFPIndex, args)
-                                         : SkString(args.fInputColor);
-            dstColor = (dstFPIndex >= 0) ? this->invokeChild(dstFPIndex, args.fInputColor, args)
-                                         : SkString(args.fInputColor);
+            srcColor = cs.childProcessor(0) ? this->invokeChild(0, args)
+                                            : SkString(args.fInputColor);
+            dstColor = cs.childProcessor(1) ? this->invokeChild(1, args.fInputColor, args)
+                                            : SkString(args.fInputColor);
             break;
 
         default:
diff --git a/src/gpu/effects/generated/GrAARectEffect.cpp b/src/gpu/effects/generated/GrAARectEffect.cpp
index 233c42a..51de12f 100644
--- a/src/gpu/effects/generated/GrAARectEffect.cpp
+++ b/src/gpu/effects/generated/GrAARectEffect.cpp
@@ -58,12 +58,7 @@
                 args.fUniformHandler->getUniformCStr(rectUniformVar), (int)_outer.edgeType,
                 (int)_outer.edgeType);
         SkString _input1677(args.fInputColor);
-        SkString _sample1677;
-        if (_outer.inputFP_index >= 0) {
-            _sample1677 = this->invokeChild(_outer.inputFP_index, _input1677.c_str(), args);
-        } else {
-            _sample1677.swap(_input1677);
-        }
+        SkString _sample1677 = this->invokeChild(0, _input1677.c_str(), args);
         fragBuilder->codeAppendf(
                 R"SkSL(
 half4 inputColor = %s;
@@ -110,9 +105,7 @@
         : INHERITED(kGrAARectEffect_ClassID, src.optimizationFlags())
         , edgeType(src.edgeType)
         , rect(src.rect) {
-    if (src.inputFP_index >= 0) {
-        inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
-    }
+    this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrAARectEffect::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrAARectEffect(*this));
diff --git a/src/gpu/effects/generated/GrAARectEffect.h b/src/gpu/effects/generated/GrAARectEffect.h
index 899000d..04bb662 100644
--- a/src/gpu/effects/generated/GrAARectEffect.h
+++ b/src/gpu/effects/generated/GrAARectEffect.h
@@ -27,7 +27,6 @@
     GrAARectEffect(const GrAARectEffect& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "AARectEffect"; }
-    int inputFP_index = -1;
     GrClipEdgeType edgeType;
     SkRect rect;
 
@@ -41,7 +40,7 @@
                                 kCompatibleWithCoverageAsAlpha_OptimizationFlag)
             , edgeType(edgeType)
             , rect(rect) {
-        inputFP_index = this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.cpp b/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.cpp
index c9f7c7b..a5db45f 100644
--- a/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.cpp
+++ b/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.cpp
@@ -33,16 +33,10 @@
         outerThresholdVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
                                                              kHalf_GrSLType, "outerThreshold");
         SkString _input515(args.fInputColor);
-        SkString _sample515;
-        if (_outer.inputFP_index >= 0) {
-            _sample515 = this->invokeChild(_outer.inputFP_index, _input515.c_str(), args);
-        } else {
-            _sample515.swap(_input515);
-        }
+        SkString _sample515 = this->invokeChild(0, _input515.c_str(), args);
         fragBuilder->codeAppendf(
                 R"SkSL(half4 color = %s;)SkSL", _sample515.c_str());
-        SkString _sample567;
-        _sample567 = this->invokeChild(_outer.maskFP_index, args);
+        SkString _sample567 = this->invokeChild(1, args);
         fragBuilder->codeAppendf(
                 R"SkSL(
 half4 mask_color = %s;
@@ -97,10 +91,7 @@
         : INHERITED(kGrAlphaThresholdFragmentProcessor_ClassID, src.optimizationFlags())
         , innerThreshold(src.innerThreshold)
         , outerThreshold(src.outerThreshold) {
-    if (src.inputFP_index >= 0) {
-        inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
-    }
-    { maskFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.maskFP_index)); }
+    this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrAlphaThresholdFragmentProcessor::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrAlphaThresholdFragmentProcessor(*this));
diff --git a/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.h b/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.h
index 077b011..f90243b 100644
--- a/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.h
+++ b/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.h
@@ -28,8 +28,6 @@
     GrAlphaThresholdFragmentProcessor(const GrAlphaThresholdFragmentProcessor& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "AlphaThresholdFragmentProcessor"; }
-    int inputFP_index = -1;
-    int maskFP_index = -1;
     float innerThreshold;
     float outerThreshold;
 
@@ -45,9 +43,9 @@
                                                          : kNone_OptimizationFlags))
             , innerThreshold(innerThreshold)
             , outerThreshold(outerThreshold) {
-        inputFP_index = this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
         SkASSERT(maskFP);
-        maskFP_index = this->registerChild(std::move(maskFP), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(maskFP), SkSL::SampleUsage::PassThrough());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/effects/generated/GrArithmeticProcessor.cpp b/src/gpu/effects/generated/GrArithmeticProcessor.cpp
index 447ec3a..1e3a4f8 100644
--- a/src/gpu/effects/generated/GrArithmeticProcessor.cpp
+++ b/src/gpu/effects/generated/GrArithmeticProcessor.cpp
@@ -30,16 +30,10 @@
         kVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, kFloat4_GrSLType,
                                                 "k");
         SkString _input385(args.fInputColor);
-        SkString _sample385;
-        if (_outer.srcFP_index >= 0) {
-            _sample385 = this->invokeChild(_outer.srcFP_index, _input385.c_str(), args);
-        } else {
-            _sample385.swap(_input385);
-        }
+        SkString _sample385 = this->invokeChild(0, _input385.c_str(), args);
         fragBuilder->codeAppendf(
                 R"SkSL(half4 src = %s;)SkSL", _sample385.c_str());
-        SkString _sample428;
-        _sample428 = this->invokeChild(_outer.dstFP_index, args);
+        SkString _sample428 = this->invokeChild(1, args);
         fragBuilder->codeAppendf(
                 R"SkSL(
 half4 dst = %s;
@@ -82,10 +76,7 @@
         : INHERITED(kGrArithmeticProcessor_ClassID, src.optimizationFlags())
         , k(src.k)
         , enforcePMColor(src.enforcePMColor) {
-    if (src.srcFP_index >= 0) {
-        srcFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.srcFP_index));
-    }
-    { dstFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.dstFP_index)); }
+    this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrArithmeticProcessor::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrArithmeticProcessor(*this));
diff --git a/src/gpu/effects/generated/GrArithmeticProcessor.h b/src/gpu/effects/generated/GrArithmeticProcessor.h
index a32b907..0a8b9f6 100644
--- a/src/gpu/effects/generated/GrArithmeticProcessor.h
+++ b/src/gpu/effects/generated/GrArithmeticProcessor.h
@@ -31,8 +31,6 @@
     GrArithmeticProcessor(const GrArithmeticProcessor& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "ArithmeticProcessor"; }
-    int srcFP_index = -1;
-    int dstFP_index = -1;
     SkV4 k;
     bool enforcePMColor;
 
@@ -44,9 +42,9 @@
             : INHERITED(kGrArithmeticProcessor_ClassID, (OptimizationFlags)kNone_OptimizationFlags)
             , k(k)
             , enforcePMColor(enforcePMColor) {
-        srcFP_index = this->registerChild(std::move(srcFP), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(srcFP), SkSL::SampleUsage::PassThrough());
         SkASSERT(dstFP);
-        dstFP_index = this->registerChild(std::move(dstFP), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(dstFP), SkSL::SampleUsage::PassThrough());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.cpp b/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.cpp
index 3d5b7b1..7b73f7d 100644
--- a/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.cpp
+++ b/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.cpp
@@ -27,12 +27,7 @@
         auto mode = _outer.mode;
         (void)mode;
         SkString _input308(args.fInputColor);
-        SkString _sample308;
-        if (_outer.inputFP_index >= 0) {
-            _sample308 = this->invokeChild(_outer.inputFP_index, _input308.c_str(), args);
-        } else {
-            _sample308.swap(_input308);
-        }
+        SkString _sample308 = this->invokeChild(0, _input308.c_str(), args);
         fragBuilder->codeAppendf(
                 R"SkSL(half inputAlpha = %s.w;
 half factor = 1.0 - inputAlpha;
@@ -70,9 +65,7 @@
         const GrBlurredEdgeFragmentProcessor& src)
         : INHERITED(kGrBlurredEdgeFragmentProcessor_ClassID, src.optimizationFlags())
         , mode(src.mode) {
-    if (src.inputFP_index >= 0) {
-        inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
-    }
+    this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrBlurredEdgeFragmentProcessor::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrBlurredEdgeFragmentProcessor(*this));
diff --git a/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.h b/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.h
index 9b46ad0..e2e5f64 100644
--- a/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.h
+++ b/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.h
@@ -27,14 +27,13 @@
     GrBlurredEdgeFragmentProcessor(const GrBlurredEdgeFragmentProcessor& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "BlurredEdgeFragmentProcessor"; }
-    int inputFP_index = -1;
     Mode mode;
 
 private:
     GrBlurredEdgeFragmentProcessor(std::unique_ptr<GrFragmentProcessor> inputFP, Mode mode)
             : INHERITED(kGrBlurredEdgeFragmentProcessor_ClassID, kNone_OptimizationFlags)
             , mode(mode) {
-        inputFP_index = this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.cpp b/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.cpp
index 269dfdc..90dca9a 100644
--- a/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.cpp
+++ b/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.cpp
@@ -305,19 +305,13 @@
                 args.fUniformHandler->getUniformCStr(circleDataVar),
                 args.fUniformHandler->getUniformCStr(circleDataVar));
         SkString _input13941(args.fInputColor);
-        SkString _sample13941;
-        if (_outer.inputFP_index >= 0) {
-            _sample13941 = this->invokeChild(_outer.inputFP_index, _input13941.c_str(), args);
-        } else {
-            _sample13941.swap(_input13941);
-        }
+        SkString _sample13941 = this->invokeChild(0, _input13941.c_str(), args);
         fragBuilder->codeAppendf(
                 R"SkSL(
 half4 inputColor = %s;)SkSL",
                 _sample13941.c_str());
         SkString _coords14001("float2(half2(dist, 0.5))");
-        SkString _sample14001;
-        _sample14001 = this->invokeChild(_outer.blurProfile_index, args, _coords14001.c_str());
+        SkString _sample14001 = this->invokeChild(1, args, _coords14001.c_str());
         fragBuilder->codeAppendf(
                 R"SkSL(
 %s = inputColor * %s.w;
@@ -362,13 +356,7 @@
         , circleRect(src.circleRect)
         , solidRadius(src.solidRadius)
         , textureRadius(src.textureRadius) {
-    if (src.inputFP_index >= 0) {
-        inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
-    }
-    {
-        blurProfile_index =
-                this->cloneAndRegisterChildProcessor(src.childProcessor(src.blurProfile_index));
-    }
+    this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrCircleBlurFragmentProcessor::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrCircleBlurFragmentProcessor(*this));
diff --git a/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.h b/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.h
index 65a4902..bba26d0 100644
--- a/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.h
+++ b/src/gpu/effects/generated/GrCircleBlurFragmentProcessor.h
@@ -27,11 +27,9 @@
     GrCircleBlurFragmentProcessor(const GrCircleBlurFragmentProcessor& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "CircleBlurFragmentProcessor"; }
-    int inputFP_index = -1;
     SkRect circleRect;
     float solidRadius;
     float textureRadius;
-    int blurProfile_index = -1;
 
 private:
     GrCircleBlurFragmentProcessor(std::unique_ptr<GrFragmentProcessor> inputFP,
@@ -46,10 +44,9 @@
             , circleRect(circleRect)
             , solidRadius(solidRadius)
             , textureRadius(textureRadius) {
-        inputFP_index = this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
         SkASSERT(blurProfile);
-        blurProfile_index =
-                this->registerChild(std::move(blurProfile), SkSL::SampleUsage::Explicit());
+        this->registerChild(std::move(blurProfile), SkSL::SampleUsage::Explicit());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/effects/generated/GrCircleEffect.cpp b/src/gpu/effects/generated/GrCircleEffect.cpp
index f9df3c9..f90c8f7 100644
--- a/src/gpu/effects/generated/GrCircleEffect.cpp
+++ b/src/gpu/effects/generated/GrCircleEffect.cpp
@@ -49,12 +49,7 @@
                 args.fUniformHandler->getUniformCStr(circleVar),
                 args.fUniformHandler->getUniformCStr(circleVar));
         SkString _input2509(args.fInputColor);
-        SkString _sample2509;
-        if (_outer.inputFP_index >= 0) {
-            _sample2509 = this->invokeChild(_outer.inputFP_index, _input2509.c_str(), args);
-        } else {
-            _sample2509.swap(_input2509);
-        }
+        SkString _sample2509 = this->invokeChild(0, _input2509.c_str(), args);
         fragBuilder->codeAppendf(
                 R"SkSL(
 half4 inputColor = %s;
@@ -121,9 +116,7 @@
         , edgeType(src.edgeType)
         , center(src.center)
         , radius(src.radius) {
-    if (src.inputFP_index >= 0) {
-        inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
-    }
+    this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrCircleEffect::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrCircleEffect(*this));
diff --git a/src/gpu/effects/generated/GrCircleEffect.h b/src/gpu/effects/generated/GrCircleEffect.h
index 1a6ae18..4d529d9 100644
--- a/src/gpu/effects/generated/GrCircleEffect.h
+++ b/src/gpu/effects/generated/GrCircleEffect.h
@@ -33,7 +33,6 @@
     GrCircleEffect(const GrCircleEffect& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "CircleEffect"; }
-    int inputFP_index = -1;
     GrClipEdgeType edgeType;
     SkPoint center;
     float radius;
@@ -50,7 +49,7 @@
             , edgeType(edgeType)
             , center(center)
             , radius(radius) {
-        inputFP_index = this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/effects/generated/GrClampFragmentProcessor.cpp b/src/gpu/effects/generated/GrClampFragmentProcessor.cpp
index f218bf8..bad6524 100644
--- a/src/gpu/effects/generated/GrClampFragmentProcessor.cpp
+++ b/src/gpu/effects/generated/GrClampFragmentProcessor.cpp
@@ -26,12 +26,7 @@
         auto clampToPremul = _outer.clampToPremul;
         (void)clampToPremul;
         SkString _input464(args.fInputColor);
-        SkString _sample464;
-        if (_outer.inputFP_index >= 0) {
-            _sample464 = this->invokeChild(_outer.inputFP_index, _input464.c_str(), args);
-        } else {
-            _sample464.swap(_input464);
-        }
+        SkString _sample464 = this->invokeChild(0, _input464.c_str(), args);
         fragBuilder->codeAppendf(
                 R"SkSL(half4 inputColor = %s;
 @if (%s) {
@@ -65,9 +60,7 @@
 GrClampFragmentProcessor::GrClampFragmentProcessor(const GrClampFragmentProcessor& src)
         : INHERITED(kGrClampFragmentProcessor_ClassID, src.optimizationFlags())
         , clampToPremul(src.clampToPremul) {
-    if (src.inputFP_index >= 0) {
-        inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
-    }
+    this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrClampFragmentProcessor::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrClampFragmentProcessor(*this));
diff --git a/src/gpu/effects/generated/GrClampFragmentProcessor.h b/src/gpu/effects/generated/GrClampFragmentProcessor.h
index 5a91f5f..fa95acc 100644
--- a/src/gpu/effects/generated/GrClampFragmentProcessor.h
+++ b/src/gpu/effects/generated/GrClampFragmentProcessor.h
@@ -19,9 +19,7 @@
 class GrClampFragmentProcessor : public GrFragmentProcessor {
 public:
     SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
-        SkPMColor4f input = this->numChildProcessors() ? ConstantOutputForConstantInput(
-                                                                 this->childProcessor(0), inColor)
-                                                       : inColor;
+        SkPMColor4f input = ConstantOutputForConstantInput(this->childProcessor(0), inColor);
         float clampedAlpha = SkTPin(input.fA, 0.f, 1.f);
         float clampVal = clampToPremul ? clampedAlpha : 1.f;
         return {SkTPin(input.fR, 0.f, clampVal), SkTPin(input.fG, 0.f, clampVal),
@@ -35,7 +33,6 @@
     GrClampFragmentProcessor(const GrClampFragmentProcessor& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "ClampFragmentProcessor"; }
-    int inputFP_index = -1;
     bool clampToPremul;
 
 private:
@@ -46,7 +43,7 @@
                                 (kConstantOutputForConstantInput_OptimizationFlag |
                                  kPreservesOpaqueInput_OptimizationFlag))
             , clampToPremul(clampToPremul) {
-        inputFP_index = this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.cpp b/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.cpp
index ad8eca8..fc79771 100644
--- a/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.cpp
+++ b/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.cpp
@@ -39,12 +39,7 @@
         vVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, kHalf4_GrSLType,
                                                 "v");
         SkString _input585(args.fInputColor);
-        SkString _sample585;
-        if (_outer.inputFP_index >= 0) {
-            _sample585 = this->invokeChild(_outer.inputFP_index, _input585.c_str(), args);
-        } else {
-            _sample585.swap(_input585);
-        }
+        SkString _sample585 = this->invokeChild(0, _input585.c_str(), args);
         fragBuilder->codeAppendf(
                 R"SkSL(half4 inputColor = %s;
 @if (%s) {
@@ -123,9 +118,7 @@
         , unpremulInput(src.unpremulInput)
         , clampRGBOutput(src.clampRGBOutput)
         , premulOutput(src.premulOutput) {
-    if (src.inputFP_index >= 0) {
-        inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
-    }
+    this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrColorMatrixFragmentProcessor::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrColorMatrixFragmentProcessor(*this));
diff --git a/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.h b/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.h
index 8747e62..498fc4d 100644
--- a/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.h
+++ b/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.h
@@ -19,9 +19,7 @@
 class GrColorMatrixFragmentProcessor : public GrFragmentProcessor {
 public:
     SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
-        SkPMColor4f input = this->numChildProcessors() ? ConstantOutputForConstantInput(
-                                                                 this->childProcessor(0), inColor)
-                                                       : inColor;
+        SkPMColor4f input = ConstantOutputForConstantInput(this->childProcessor(0), inColor);
         SkColor4f color;
         if (unpremulInput) {
             color = input.unpremul();
@@ -61,7 +59,6 @@
     GrColorMatrixFragmentProcessor(const GrColorMatrixFragmentProcessor& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "ColorMatrixFragmentProcessor"; }
-    int inputFP_index = -1;
     SkM44 m;
     SkV4 v;
     bool unpremulInput;
@@ -84,7 +81,7 @@
             , unpremulInput(unpremulInput)
             , clampRGBOutput(clampRGBOutput)
             , premulOutput(premulOutput) {
-        inputFP_index = this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/effects/generated/GrComposeLerpEffect.cpp b/src/gpu/effects/generated/GrComposeLerpEffect.cpp
index 3a4a323..905b406 100644
--- a/src/gpu/effects/generated/GrComposeLerpEffect.cpp
+++ b/src/gpu/effects/generated/GrComposeLerpEffect.cpp
@@ -27,23 +27,13 @@
         (void)weight;
         weightVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
                                                      kFloat_GrSLType, "weight");
-        SkString _sample290;
-        if (_outer.child1_index >= 0) {
-            _sample290 = this->invokeChild(_outer.child1_index, args);
-        } else {
-            _sample290 = "half4(1)";
-        }
-        SkString _sample358;
-        if (_outer.child2_index >= 0) {
-            _sample358 = this->invokeChild(_outer.child2_index, args);
-        } else {
-            _sample358 = "half4(1)";
-        }
+        SkString _sample290 = this->invokeChild(0, args);
+        SkString _sample358 = this->invokeChild(1, args);
         fragBuilder->codeAppendf(
                 R"SkSL(%s = mix(%s ? %s : %s, %s ? %s : %s, half(%s));
 )SkSL",
-                args.fOutputColor, _outer.child1_index >= 0 ? "true" : "false", _sample290.c_str(),
-                args.fInputColor, _outer.child2_index >= 0 ? "true" : "false", _sample358.c_str(),
+                args.fOutputColor, _outer.childProcessor(0) ? "true" : "false", _sample290.c_str(),
+                args.fInputColor, _outer.childProcessor(1) ? "true" : "false", _sample358.c_str(),
                 args.fInputColor, args.fUniformHandler->getUniformCStr(weightVar));
     }
 
@@ -68,12 +58,7 @@
 }
 GrComposeLerpEffect::GrComposeLerpEffect(const GrComposeLerpEffect& src)
         : INHERITED(kGrComposeLerpEffect_ClassID, src.optimizationFlags()), weight(src.weight) {
-    if (src.child1_index >= 0) {
-        child1_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child1_index));
-    }
-    if (src.child2_index >= 0) {
-        child2_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child2_index));
-    }
+    this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrComposeLerpEffect::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrComposeLerpEffect(*this));
diff --git a/src/gpu/effects/generated/GrComposeLerpEffect.h b/src/gpu/effects/generated/GrComposeLerpEffect.h
index 590d86d..716ba36 100644
--- a/src/gpu/effects/generated/GrComposeLerpEffect.h
+++ b/src/gpu/effects/generated/GrComposeLerpEffect.h
@@ -27,8 +27,6 @@
     GrComposeLerpEffect(const GrComposeLerpEffect& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "ComposeLerpEffect"; }
-    int child1_index = -1;
-    int child2_index = -1;
     float weight;
 
 private:
@@ -36,8 +34,8 @@
                         std::unique_ptr<GrFragmentProcessor> child2,
                         float weight)
             : INHERITED(kGrComposeLerpEffect_ClassID, kNone_OptimizationFlags), weight(weight) {
-        child1_index = this->registerChild(std::move(child1), SkSL::SampleUsage::PassThrough());
-        child2_index = this->registerChild(std::move(child2), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(child1), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(child2), SkSL::SampleUsage::PassThrough());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/effects/generated/GrConfigConversionEffect.cpp b/src/gpu/effects/generated/GrConfigConversionEffect.cpp
index 9f3422a..1ad460d 100644
--- a/src/gpu/effects/generated/GrConfigConversionEffect.cpp
+++ b/src/gpu/effects/generated/GrConfigConversionEffect.cpp
@@ -27,8 +27,7 @@
         (void)pmConversion;
 
         fragBuilder->forceHighPrecision();
-        SkString _sample5730;
-        _sample5730 = this->invokeChild(_outer.inputFP_index, args);
+        SkString _sample5730 = this->invokeChild(0, args);
         fragBuilder->codeAppendf(
                 R"SkSL(%s = floor(%s * 255.0 + 0.5) / 255.0;
 @switch (%d) {
@@ -65,7 +64,7 @@
 GrConfigConversionEffect::GrConfigConversionEffect(const GrConfigConversionEffect& src)
         : INHERITED(kGrConfigConversionEffect_ClassID, src.optimizationFlags())
         , pmConversion(src.pmConversion) {
-    { inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index)); }
+    this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrConfigConversionEffect::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrConfigConversionEffect(*this));
diff --git a/src/gpu/effects/generated/GrConfigConversionEffect.h b/src/gpu/effects/generated/GrConfigConversionEffect.h
index 613c1a2..de1787a 100644
--- a/src/gpu/effects/generated/GrConfigConversionEffect.h
+++ b/src/gpu/effects/generated/GrConfigConversionEffect.h
@@ -37,7 +37,6 @@
     GrConfigConversionEffect(const GrConfigConversionEffect& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "ConfigConversionEffect"; }
-    int inputFP_index = -1;
     PMConversion pmConversion;
 
 private:
@@ -46,7 +45,7 @@
             : INHERITED(kGrConfigConversionEffect_ClassID, kNone_OptimizationFlags)
             , pmConversion(pmConversion) {
         SkASSERT(inputFP);
-        inputFP_index = this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/effects/generated/GrConstColorProcessor.cpp b/src/gpu/effects/generated/GrConstColorProcessor.cpp
index c14bdeb..0d887a5 100644
--- a/src/gpu/effects/generated/GrConstColorProcessor.cpp
+++ b/src/gpu/effects/generated/GrConstColorProcessor.cpp
@@ -60,7 +60,9 @@
     return true;
 }
 GrConstColorProcessor::GrConstColorProcessor(const GrConstColorProcessor& src)
-        : INHERITED(kGrConstColorProcessor_ClassID, src.optimizationFlags()), color(src.color) {}
+        : INHERITED(kGrConstColorProcessor_ClassID, src.optimizationFlags()), color(src.color) {
+    this->cloneAndRegisterAllChildProcessors(src);
+}
 std::unique_ptr<GrFragmentProcessor> GrConstColorProcessor::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrConstColorProcessor(*this));
 }
diff --git a/src/gpu/effects/generated/GrDeviceSpaceEffect.cpp b/src/gpu/effects/generated/GrDeviceSpaceEffect.cpp
index 915479c..b765e33 100644
--- a/src/gpu/effects/generated/GrDeviceSpaceEffect.cpp
+++ b/src/gpu/effects/generated/GrDeviceSpaceEffect.cpp
@@ -25,9 +25,7 @@
         (void)_outer;
         SkString _input203(args.fInputColor);
         SkString _coords203("sk_FragCoord.xy");
-        SkString _sample203;
-        _sample203 =
-                this->invokeChild(_outer.fp_index, _input203.c_str(), args, _coords203.c_str());
+        SkString _sample203 = this->invokeChild(0, _input203.c_str(), args, _coords203.c_str());
         fragBuilder->codeAppendf(
                 R"SkSL(%s = %s;
 )SkSL",
@@ -50,7 +48,7 @@
 }
 GrDeviceSpaceEffect::GrDeviceSpaceEffect(const GrDeviceSpaceEffect& src)
         : INHERITED(kGrDeviceSpaceEffect_ClassID, src.optimizationFlags()) {
-    { fp_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.fp_index)); }
+    this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrDeviceSpaceEffect::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrDeviceSpaceEffect(*this));
diff --git a/src/gpu/effects/generated/GrDeviceSpaceEffect.h b/src/gpu/effects/generated/GrDeviceSpaceEffect.h
index bd40d38..68432b3 100644
--- a/src/gpu/effects/generated/GrDeviceSpaceEffect.h
+++ b/src/gpu/effects/generated/GrDeviceSpaceEffect.h
@@ -28,14 +28,13 @@
     GrDeviceSpaceEffect(const GrDeviceSpaceEffect& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "DeviceSpaceEffect"; }
-    int fp_index = -1;
 
 private:
     GrDeviceSpaceEffect(std::unique_ptr<GrFragmentProcessor> fp)
             : INHERITED(kGrDeviceSpaceEffect_ClassID,
                         (OptimizationFlags)ProcessorOptimizationFlags(fp.get())) {
         SkASSERT(fp);
-        fp_index = this->registerChild(std::move(fp), SkSL::SampleUsage::Explicit());
+        this->registerChild(std::move(fp), SkSL::SampleUsage::Explicit());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/effects/generated/GrDitherEffect.cpp b/src/gpu/effects/generated/GrDitherEffect.cpp
index 6bdb808..643ef17 100644
--- a/src/gpu/effects/generated/GrDitherEffect.cpp
+++ b/src/gpu/effects/generated/GrDitherEffect.cpp
@@ -28,8 +28,7 @@
         rangeVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, kHalf_GrSLType,
                                                     "range");
         SkString _input302(args.fInputColor);
-        SkString _sample302;
-        _sample302 = this->invokeChild(_outer.inputFP_index, _input302.c_str(), args);
+        SkString _sample302 = this->invokeChild(0, _input302.c_str(), args);
         fragBuilder->codeAppendf(
                 R"SkSL(half4 color = %s;
 half value;
@@ -71,7 +70,7 @@
 }
 GrDitherEffect::GrDitherEffect(const GrDitherEffect& src)
         : INHERITED(kGrDitherEffect_ClassID, src.optimizationFlags()), range(src.range) {
-    { inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index)); }
+    this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrDitherEffect::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrDitherEffect(*this));
diff --git a/src/gpu/effects/generated/GrDitherEffect.h b/src/gpu/effects/generated/GrDitherEffect.h
index 43505e5..6eac049 100644
--- a/src/gpu/effects/generated/GrDitherEffect.h
+++ b/src/gpu/effects/generated/GrDitherEffect.h
@@ -28,7 +28,6 @@
     GrDitherEffect(const GrDitherEffect& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "DitherEffect"; }
-    int inputFP_index = -1;
     float range;
 
 private:
@@ -39,7 +38,7 @@
                                 kPreservesOpaqueInput_OptimizationFlag)
             , range(range) {
         SkASSERT(inputFP);
-        inputFP_index = this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/effects/generated/GrEllipseEffect.cpp b/src/gpu/effects/generated/GrEllipseEffect.cpp
index 0a75b96..28390d6 100644
--- a/src/gpu/effects/generated/GrEllipseEffect.cpp
+++ b/src/gpu/effects/generated/GrEllipseEffect.cpp
@@ -81,12 +81,7 @@
                 scaleVar.isValid() ? args.fUniformHandler->getUniformCStr(scaleVar) : "float2(0)",
                 (int)_outer.edgeType);
         SkString _input4481(args.fInputColor);
-        SkString _sample4481;
-        if (_outer.inputFP_index >= 0) {
-            _sample4481 = this->invokeChild(_outer.inputFP_index, _input4481.c_str(), args);
-        } else {
-            _sample4481.swap(_input4481);
-        }
+        SkString _sample4481 = this->invokeChild(0, _input4481.c_str(), args);
         fragBuilder->codeAppendf(
                 R"SkSL(
 half4 inputColor = %s;
@@ -161,9 +156,7 @@
         , edgeType(src.edgeType)
         , center(src.center)
         , radii(src.radii) {
-    if (src.inputFP_index >= 0) {
-        inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
-    }
+    this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrEllipseEffect::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrEllipseEffect(*this));
diff --git a/src/gpu/effects/generated/GrEllipseEffect.h b/src/gpu/effects/generated/GrEllipseEffect.h
index e52e5b7..cd63743 100644
--- a/src/gpu/effects/generated/GrEllipseEffect.h
+++ b/src/gpu/effects/generated/GrEllipseEffect.h
@@ -43,7 +43,6 @@
     GrEllipseEffect(const GrEllipseEffect& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "EllipseEffect"; }
-    int inputFP_index = -1;
     GrClipEdgeType edgeType;
     SkPoint center;
     SkPoint radii;
@@ -60,7 +59,7 @@
             , edgeType(edgeType)
             , center(center)
             , radii(radii) {
-        inputFP_index = this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/effects/generated/GrHSLToRGBFilterEffect.cpp b/src/gpu/effects/generated/GrHSLToRGBFilterEffect.cpp
index 91796e1..efdaaef 100644
--- a/src/gpu/effects/generated/GrHSLToRGBFilterEffect.cpp
+++ b/src/gpu/effects/generated/GrHSLToRGBFilterEffect.cpp
@@ -24,12 +24,7 @@
         const GrHSLToRGBFilterEffect& _outer = args.fFp.cast<GrHSLToRGBFilterEffect>();
         (void)_outer;
         SkString _input523(args.fInputColor);
-        SkString _sample523;
-        if (_outer.inputFP_index >= 0) {
-            _sample523 = this->invokeChild(_outer.inputFP_index, _input523.c_str(), args);
-        } else {
-            _sample523.swap(_input523);
-        }
+        SkString _sample523 = this->invokeChild(0, _input523.c_str(), args);
         fragBuilder->codeAppendf(
                 R"SkSL(half4 inputColor = %s;
 half3 hsl = inputColor.xyz;
@@ -59,9 +54,7 @@
 }
 GrHSLToRGBFilterEffect::GrHSLToRGBFilterEffect(const GrHSLToRGBFilterEffect& src)
         : INHERITED(kGrHSLToRGBFilterEffect_ClassID, src.optimizationFlags()) {
-    if (src.inputFP_index >= 0) {
-        inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
-    }
+    this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrHSLToRGBFilterEffect::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrHSLToRGBFilterEffect(*this));
diff --git a/src/gpu/effects/generated/GrHSLToRGBFilterEffect.h b/src/gpu/effects/generated/GrHSLToRGBFilterEffect.h
index 796c0a0..9c3d45a 100644
--- a/src/gpu/effects/generated/GrHSLToRGBFilterEffect.h
+++ b/src/gpu/effects/generated/GrHSLToRGBFilterEffect.h
@@ -22,9 +22,7 @@
 #include "include/private/SkNx.h"
 
     SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
-        SkPMColor4f c = this->numChildProcessors()
-                                ? ConstantOutputForConstantInput(this->childProcessor(0), inColor)
-                                : inColor;
+        SkPMColor4f c = ConstantOutputForConstantInput(this->childProcessor(0), inColor);
         const auto H = c[0], S = c[1], L = c[2], C = (1 - std::abs(2 * L - 1)) * S;
 
         const auto p = H + Sk4f(0, 2 / 3.f, 1 / 3.f, 0),
@@ -40,7 +38,6 @@
     GrHSLToRGBFilterEffect(const GrHSLToRGBFilterEffect& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "HSLToRGBFilterEffect"; }
-    int inputFP_index = -1;
 
 private:
     GrHSLToRGBFilterEffect(std::unique_ptr<GrFragmentProcessor> inputFP)
@@ -49,7 +46,7 @@
                                                     : kAll_OptimizationFlags) &
                                 (kConstantOutputForConstantInput_OptimizationFlag |
                                  kPreservesOpaqueInput_OptimizationFlag)) {
-        inputFP_index = this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/effects/generated/GrHighContrastFilterEffect.cpp b/src/gpu/effects/generated/GrHighContrastFilterEffect.cpp
index 5b1453f..6e061a1 100644
--- a/src/gpu/effects/generated/GrHighContrastFilterEffect.cpp
+++ b/src/gpu/effects/generated/GrHighContrastFilterEffect.cpp
@@ -48,12 +48,7 @@
 )SkSL",
                                   &HSLToRGB_name);
         SkString _input896(args.fInputColor);
-        SkString _sample896;
-        if (_outer.inputFP_index >= 0) {
-            _sample896 = this->invokeChild(_outer.inputFP_index, _input896.c_str(), args);
-        } else {
-            _sample896.swap(_input896);
-        }
+        SkString _sample896 = this->invokeChild(0, _input896.c_str(), args);
         fragBuilder->codeAppendf(
                 R"SkSL(
 half4 inColor = %s;
@@ -163,9 +158,7 @@
         , invertBrightness(src.invertBrightness)
         , invertLightness(src.invertLightness)
         , linearize(src.linearize) {
-    if (src.inputFP_index >= 0) {
-        inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
-    }
+    this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrHighContrastFilterEffect::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrHighContrastFilterEffect(*this));
diff --git a/src/gpu/effects/generated/GrHighContrastFilterEffect.h b/src/gpu/effects/generated/GrHighContrastFilterEffect.h
index eef7955..626f5ef 100644
--- a/src/gpu/effects/generated/GrHighContrastFilterEffect.h
+++ b/src/gpu/effects/generated/GrHighContrastFilterEffect.h
@@ -37,7 +37,6 @@
     GrHighContrastFilterEffect(const GrHighContrastFilterEffect& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "HighContrastFilterEffect"; }
-    int inputFP_index = -1;
     float contrastMod;
     bool hasContrast;
     bool grayscale;
@@ -61,7 +60,7 @@
             , invertBrightness(invertBrightness)
             , invertLightness(invertLightness)
             , linearize(linearize) {
-        inputFP_index = this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/effects/generated/GrLumaColorFilterEffect.cpp b/src/gpu/effects/generated/GrLumaColorFilterEffect.cpp
index ec9045b..67fc006 100644
--- a/src/gpu/effects/generated/GrLumaColorFilterEffect.cpp
+++ b/src/gpu/effects/generated/GrLumaColorFilterEffect.cpp
@@ -23,20 +23,15 @@
         GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
         const GrLumaColorFilterEffect& _outer = args.fFp.cast<GrLumaColorFilterEffect>();
         (void)_outer;
-        SkString _input953(args.fInputColor);
-        SkString _sample953;
-        if (_outer.inputFP_index >= 0) {
-            _sample953 = this->invokeChild(_outer.inputFP_index, _input953.c_str(), args);
-        } else {
-            _sample953.swap(_input953);
-        }
+        SkString _input870(args.fInputColor);
+        SkString _sample870 = this->invokeChild(0, _input870.c_str(), args);
         fragBuilder->codeAppendf(
                 R"SkSL(half4 inputColor = %s;
 
 half luma = clamp(dot(half3(0.2125999927520752, 0.71520000696182251, 0.072200000286102295), inputColor.xyz), 0.0, 1.0);
 %s = half4(0.0, 0.0, 0.0, luma);
 )SkSL",
-                _sample953.c_str(), args.fOutputColor);
+                _sample870.c_str(), args.fOutputColor);
     }
 
 private:
@@ -55,9 +50,7 @@
 }
 GrLumaColorFilterEffect::GrLumaColorFilterEffect(const GrLumaColorFilterEffect& src)
         : INHERITED(kGrLumaColorFilterEffect_ClassID, src.optimizationFlags()) {
-    if (src.inputFP_index >= 0) {
-        inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
-    }
+    this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrLumaColorFilterEffect::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrLumaColorFilterEffect(*this));
diff --git a/src/gpu/effects/generated/GrLumaColorFilterEffect.h b/src/gpu/effects/generated/GrLumaColorFilterEffect.h
index dfbef4c..86910b4 100644
--- a/src/gpu/effects/generated/GrLumaColorFilterEffect.h
+++ b/src/gpu/effects/generated/GrLumaColorFilterEffect.h
@@ -21,10 +21,7 @@
 #include "include/private/SkColorData.h"
 
     SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
-        SkPMColor4f input = this->numChildProcessors()
-                                    ? ConstantOutputForConstantInput(
-                                              this->childProcessor(inputFP_index), inColor)
-                                    : inColor;
+        SkPMColor4f input = ConstantOutputForConstantInput(this->childProcessor(0), inColor);
         float luma = SK_ITU_BT709_LUM_COEFF_R * input.fR + SK_ITU_BT709_LUM_COEFF_G * input.fG +
                      SK_ITU_BT709_LUM_COEFF_B * input.fB;
         return {0, 0, 0, SkTPin(luma, 0.0f, 1.0f)};
@@ -36,7 +33,6 @@
     GrLumaColorFilterEffect(const GrLumaColorFilterEffect& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "LumaColorFilterEffect"; }
-    int inputFP_index = -1;
 
 private:
     GrLumaColorFilterEffect(std::unique_ptr<GrFragmentProcessor> inputFP)
@@ -44,7 +40,7 @@
                         (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get())
                                                     : kAll_OptimizationFlags) &
                                 kConstantOutputForConstantInput_OptimizationFlag) {
-        inputFP_index = this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/effects/generated/GrMagnifierEffect.cpp b/src/gpu/effects/generated/GrMagnifierEffect.cpp
index 118e1b6..39b8bef 100644
--- a/src/gpu/effects/generated/GrMagnifierEffect.cpp
+++ b/src/gpu/effects/generated/GrMagnifierEffect.cpp
@@ -70,8 +70,7 @@
                 args.fUniformHandler->getUniformCStr(xInvInsetVar),
                 args.fUniformHandler->getUniformCStr(yInvInsetVar));
         SkString _coords1043 = SkStringPrintf("mix(%s, zoom_coord, weight)", args.fSampleCoord);
-        SkString _sample1043;
-        _sample1043 = this->invokeChild(_outer.src_index, args, _coords1043.c_str());
+        SkString _sample1043 = this->invokeChild(0, args, _coords1043.c_str());
         fragBuilder->codeAppendf(
                 R"SkSL(
 %s = %s;
@@ -141,7 +140,7 @@
         , yInvZoom(src.yInvZoom)
         , xInvInset(src.xInvInset)
         , yInvInset(src.yInvInset) {
-    { src_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.src_index)); }
+    this->cloneAndRegisterAllChildProcessors(src);
     this->setUsesSampleCoordsDirectly();
 }
 std::unique_ptr<GrFragmentProcessor> GrMagnifierEffect::clone() const {
diff --git a/src/gpu/effects/generated/GrMagnifierEffect.h b/src/gpu/effects/generated/GrMagnifierEffect.h
index 86f6ecc..29322b8 100644
--- a/src/gpu/effects/generated/GrMagnifierEffect.h
+++ b/src/gpu/effects/generated/GrMagnifierEffect.h
@@ -31,7 +31,6 @@
     GrMagnifierEffect(const GrMagnifierEffect& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "MagnifierEffect"; }
-    int src_index = -1;
     SkIRect bounds;
     SkRect srcRect;
     float xInvZoom;
@@ -56,7 +55,7 @@
             , yInvInset(yInvInset) {
         this->setUsesSampleCoordsDirectly();
         SkASSERT(src);
-        src_index = this->registerChild(std::move(src), SkSL::SampleUsage::Explicit());
+        this->registerChild(std::move(src), SkSL::SampleUsage::Explicit());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/effects/generated/GrMixerEffect.cpp b/src/gpu/effects/generated/GrMixerEffect.cpp
index f48b2e6..951c8f9 100644
--- a/src/gpu/effects/generated/GrMixerEffect.cpp
+++ b/src/gpu/effects/generated/GrMixerEffect.cpp
@@ -27,30 +27,19 @@
         (void)weight;
         weightVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
                                                      kHalf_GrSLType, "weight");
-        SkString _input1335(args.fInputColor);
-        SkString _sample1335;
-        if (_outer.inputFP_index >= 0) {
-            _sample1335 = this->invokeChild(_outer.inputFP_index, _input1335.c_str(), args);
-        } else {
-            _sample1335.swap(_input1335);
-        }
+        SkString _input1099(args.fInputColor);
+        SkString _sample1099 = this->invokeChild(0, _input1099.c_str(), args);
         fragBuilder->codeAppendf(
-                R"SkSL(half4 inColor = %s;)SkSL", _sample1335.c_str());
-        SkString _input1386("inColor");
-        SkString _sample1386;
-        _sample1386 = this->invokeChild(_outer.fp0_index, _input1386.c_str(), args);
-        SkString _input1408("inColor");
-        SkString _sample1408;
-        if (_outer.fp1_index >= 0) {
-            _sample1408 = this->invokeChild(_outer.fp1_index, _input1408.c_str(), args);
-        } else {
-            _sample1408.swap(_input1408);
-        }
+                R"SkSL(half4 inColor = %s;)SkSL", _sample1099.c_str());
+        SkString _input1150("inColor");
+        SkString _sample1150 = this->invokeChild(1, _input1150.c_str(), args);
+        SkString _input1172("inColor");
+        SkString _sample1172 = this->invokeChild(2, _input1172.c_str(), args);
         fragBuilder->codeAppendf(
                 R"SkSL(
 %s = mix(%s, %s, %s);
 )SkSL",
-                args.fOutputColor, _sample1386.c_str(), _sample1408.c_str(),
+                args.fOutputColor, _sample1150.c_str(), _sample1172.c_str(),
                 args.fUniformHandler->getUniformCStr(weightVar));
     }
 
@@ -75,13 +64,7 @@
 }
 GrMixerEffect::GrMixerEffect(const GrMixerEffect& src)
         : INHERITED(kGrMixerEffect_ClassID, src.optimizationFlags()), weight(src.weight) {
-    if (src.inputFP_index >= 0) {
-        inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
-    }
-    { fp0_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.fp0_index)); }
-    if (src.fp1_index >= 0) {
-        fp1_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.fp1_index));
-    }
+    this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrMixerEffect::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrMixerEffect(*this));
diff --git a/src/gpu/effects/generated/GrMixerEffect.h b/src/gpu/effects/generated/GrMixerEffect.h
index 4db609e..70e04ae 100644
--- a/src/gpu/effects/generated/GrMixerEffect.h
+++ b/src/gpu/effects/generated/GrMixerEffect.h
@@ -19,15 +19,9 @@
 class GrMixerEffect : public GrFragmentProcessor {
 public:
     SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& in) const override {
-        const SkPMColor4f inColor =
-                (inputFP_index >= 0)
-                        ? ConstantOutputForConstantInput(this->childProcessor(inputFP_index), in)
-                        : in;
-        const SkPMColor4f c0 =
-                ConstantOutputForConstantInput(this->childProcessor(fp0_index), inColor);
-        const SkPMColor4f c1 = (fp1_index >= 0) ? ConstantOutputForConstantInput(
-                                                          this->childProcessor(fp1_index), inColor)
-                                                : inColor;
+        const SkPMColor4f inColor = ConstantOutputForConstantInput(this->childProcessor(0), in);
+        const SkPMColor4f c0 = ConstantOutputForConstantInput(this->childProcessor(1), inColor);
+        const SkPMColor4f c1 = ConstantOutputForConstantInput(this->childProcessor(2), inColor);
         return {c0.fR + (c1.fR - c0.fR) * weight, c0.fG + (c1.fG - c0.fG) * weight,
                 c0.fB + (c1.fB - c0.fB) * weight, c0.fA + (c1.fA - c0.fA) * weight};
     }
@@ -41,9 +35,6 @@
     GrMixerEffect(const GrMixerEffect& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "MixerEffect"; }
-    int inputFP_index = -1;
-    int fp0_index = -1;
-    int fp1_index = -1;
     float weight;
 
 private:
@@ -52,16 +43,14 @@
                   std::unique_ptr<GrFragmentProcessor> fp1,
                   float weight)
             : INHERITED(kGrMixerEffect_ClassID,
-                        (OptimizationFlags)(inputFP ? ProcessorOptimizationFlags(inputFP.get())
-                                                    : kAll_OptimizationFlags) &
-                                (fp1 ? ProcessorOptimizationFlags(fp1.get())
-                                     : kAll_OptimizationFlags) &
+                        (OptimizationFlags)ProcessorOptimizationFlags(inputFP.get()) &
+                                ProcessorOptimizationFlags(fp1.get()) &
                                 ProcessorOptimizationFlags(fp0.get()))
             , weight(weight) {
-        inputFP_index = this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
         SkASSERT(fp0);
-        fp0_index = this->registerChild(std::move(fp0), SkSL::SampleUsage::PassThrough());
-        fp1_index = this->registerChild(std::move(fp1), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(fp0), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(fp1), SkSL::SampleUsage::PassThrough());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp b/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp
index deae796..1f458d5 100644
--- a/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp
+++ b/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp
@@ -47,8 +47,7 @@
                 _outer.literalColor.fR, _outer.literalColor.fG, _outer.literalColor.fB,
                 _outer.literalColor.fA);
         SkString _input1992("constColor");
-        SkString _sample1992;
-        _sample1992 = this->invokeChild(_outer.fp_index, _input1992.c_str(), args);
+        SkString _sample1992 = this->invokeChild(0, _input1992.c_str(), args);
         fragBuilder->codeAppendf(
                 R"SkSL(
 %s = %s;
@@ -98,7 +97,7 @@
         , useUniform(src.useUniform)
         , uniformColor(src.uniformColor)
         , literalColor(src.literalColor) {
-    { fp_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.fp_index)); }
+    this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrOverrideInputFragmentProcessor::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrOverrideInputFragmentProcessor(*this));
diff --git a/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h b/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h
index e5c1280..e2cd742 100644
--- a/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h
+++ b/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h
@@ -44,7 +44,6 @@
     GrOverrideInputFragmentProcessor(const GrOverrideInputFragmentProcessor& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "OverrideInputFragmentProcessor"; }
-    int fp_index = -1;
     bool useUniform;
     SkPMColor4f uniformColor;
     SkPMColor4f literalColor;
@@ -60,7 +59,7 @@
             , uniformColor(uniformColor)
             , literalColor(literalColor) {
         SkASSERT(fp);
-        fp_index = this->registerChild(std::move(fp), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(fp), SkSL::SampleUsage::PassThrough());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/effects/generated/GrRGBToHSLFilterEffect.cpp b/src/gpu/effects/generated/GrRGBToHSLFilterEffect.cpp
index a2acd52..b0ba354 100644
--- a/src/gpu/effects/generated/GrRGBToHSLFilterEffect.cpp
+++ b/src/gpu/effects/generated/GrRGBToHSLFilterEffect.cpp
@@ -24,12 +24,7 @@
         const GrRGBToHSLFilterEffect& _outer = args.fFp.cast<GrRGBToHSLFilterEffect>();
         (void)_outer;
         SkString _input1173(args.fInputColor);
-        SkString _sample1173;
-        if (_outer.inputFP_index >= 0) {
-            _sample1173 = this->invokeChild(_outer.inputFP_index, _input1173.c_str(), args);
-        } else {
-            _sample1173.swap(_input1173);
-        }
+        SkString _sample1173 = this->invokeChild(0, _input1173.c_str(), args);
         fragBuilder->codeAppendf(
                 R"SkSL(half4 c = %s;
 half4 p = c.y < c.z ? half4(c.zy, -1.0, 0.66666666666666663) : half4(c.yz, 0.0, -0.33333333333333331);
@@ -62,9 +57,7 @@
 }
 GrRGBToHSLFilterEffect::GrRGBToHSLFilterEffect(const GrRGBToHSLFilterEffect& src)
         : INHERITED(kGrRGBToHSLFilterEffect_ClassID, src.optimizationFlags()) {
-    if (src.inputFP_index >= 0) {
-        inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
-    }
+    this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrRGBToHSLFilterEffect::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrRGBToHSLFilterEffect(*this));
diff --git a/src/gpu/effects/generated/GrRGBToHSLFilterEffect.h b/src/gpu/effects/generated/GrRGBToHSLFilterEffect.h
index a86d395..f4efdd9 100644
--- a/src/gpu/effects/generated/GrRGBToHSLFilterEffect.h
+++ b/src/gpu/effects/generated/GrRGBToHSLFilterEffect.h
@@ -21,9 +21,7 @@
 #include "include/private/SkColorData.h"
 
     SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
-        SkPMColor4f c = this->numChildProcessors()
-                                ? ConstantOutputForConstantInput(this->childProcessor(0), inColor)
-                                : inColor;
+        SkPMColor4f c = ConstantOutputForConstantInput(this->childProcessor(0), inColor);
         const auto p = (c.fG < c.fB) ? SkPMColor4f{c.fB, c.fG, -1, 2 / 3.f}
                                      : SkPMColor4f{c.fG, c.fB, 0, -1 / 3.f},
                    q = (c.fR < p[0]) ? SkPMColor4f{p[0], c.fR, p[1], p[3]}
@@ -42,7 +40,6 @@
     GrRGBToHSLFilterEffect(const GrRGBToHSLFilterEffect& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "RGBToHSLFilterEffect"; }
-    int inputFP_index = -1;
 
 private:
     GrRGBToHSLFilterEffect(std::unique_ptr<GrFragmentProcessor> inputFP)
@@ -51,7 +48,7 @@
                                                     : kAll_OptimizationFlags) &
                                 (kConstantOutputForConstantInput_OptimizationFlag |
                                  kPreservesOpaqueInput_OptimizationFlag)) {
-        inputFP_index = this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/effects/generated/GrRRectBlurEffect.cpp b/src/gpu/effects/generated/GrRRectBlurEffect.cpp
index 6ef1e25..a2587e1 100644
--- a/src/gpu/effects/generated/GrRRectBlurEffect.cpp
+++ b/src/gpu/effects/generated/GrRRectBlurEffect.cpp
@@ -95,19 +95,13 @@
                 args.fUniformHandler->getUniformCStr(blurRadiusVar),
                 args.fUniformHandler->getUniformCStr(cornerRadiusVar));
         SkString _input9600(args.fInputColor);
-        SkString _sample9600;
-        if (_outer.inputFP_index >= 0) {
-            _sample9600 = this->invokeChild(_outer.inputFP_index, _input9600.c_str(), args);
-        } else {
-            _sample9600.swap(_input9600);
-        }
+        SkString _sample9600 = this->invokeChild(0, _input9600.c_str(), args);
         fragBuilder->codeAppendf(
                 R"SkSL(
 half4 inputColor = %s;)SkSL",
                 _sample9600.c_str());
         SkString _coords9660("float2(texCoord)");
-        SkString _sample9660;
-        _sample9660 = this->invokeChild(_outer.ninePatchFP_index, args, _coords9660.c_str());
+        SkString _sample9660 = this->invokeChild(1, args, _coords9660.c_str());
         fragBuilder->codeAppendf(
                 R"SkSL(
 %s = inputColor * %s;
@@ -160,13 +154,7 @@
         , sigma(src.sigma)
         , rect(src.rect)
         , cornerRadius(src.cornerRadius) {
-    if (src.inputFP_index >= 0) {
-        inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
-    }
-    {
-        ninePatchFP_index =
-                this->cloneAndRegisterChildProcessor(src.childProcessor(src.ninePatchFP_index));
-    }
+    this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrRRectBlurEffect::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrRRectBlurEffect(*this));
diff --git a/src/gpu/effects/generated/GrRRectBlurEffect.h b/src/gpu/effects/generated/GrRRectBlurEffect.h
index aaa71ef..da12a9c 100644
--- a/src/gpu/effects/generated/GrRRectBlurEffect.h
+++ b/src/gpu/effects/generated/GrRRectBlurEffect.h
@@ -118,11 +118,9 @@
     GrRRectBlurEffect(const GrRRectBlurEffect& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "RRectBlurEffect"; }
-    int inputFP_index = -1;
     float sigma;
     SkRect rect;
     float cornerRadius;
-    int ninePatchFP_index = -1;
 
 private:
     GrRRectBlurEffect(std::unique_ptr<GrFragmentProcessor> inputFP,
@@ -137,10 +135,9 @@
             , sigma(sigma)
             , rect(rect)
             , cornerRadius(cornerRadius) {
-        inputFP_index = this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
         SkASSERT(ninePatchFP);
-        ninePatchFP_index =
-                this->registerChild(std::move(ninePatchFP), SkSL::SampleUsage::Explicit());
+        this->registerChild(std::move(ninePatchFP), SkSL::SampleUsage::Explicit());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/effects/generated/GrRectBlurEffect.cpp b/src/gpu/effects/generated/GrRectBlurEffect.cpp
index e55c300..a8f8f85 100644
--- a/src/gpu/effects/generated/GrRectBlurEffect.cpp
+++ b/src/gpu/effects/generated/GrRectBlurEffect.cpp
@@ -54,15 +54,13 @@
                 rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)",
                 rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)");
         SkString _coords7211("float2(half2(xy.x, 0.5))");
-        SkString _sample7211;
-        _sample7211 = this->invokeChild(_outer.integral_index, args, _coords7211.c_str());
+        SkString _sample7211 = this->invokeChild(1, args, _coords7211.c_str());
         fragBuilder->codeAppendf(
                 R"SkSL(
     xCoverage = %s.w;)SkSL",
                 _sample7211.c_str());
         SkString _coords7269("float2(half2(xy.y, 0.5))");
-        SkString _sample7269;
-        _sample7269 = this->invokeChild(_outer.integral_index, args, _coords7269.c_str());
+        SkString _sample7269 = this->invokeChild(1, args, _coords7269.c_str());
         fragBuilder->codeAppendf(
                 R"SkSL(
     yCoverage = %s.w;
@@ -81,33 +79,24 @@
                 rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)",
                 rectHVar.isValid() ? args.fUniformHandler->getUniformCStr(rectHVar) : "half4(0)");
         SkString _coords8636("float2(half2(rect.x, 0.5))");
-        SkString _sample8636;
-        _sample8636 = this->invokeChild(_outer.integral_index, args, _coords8636.c_str());
+        SkString _sample8636 = this->invokeChild(1, args, _coords8636.c_str());
         SkString _coords8699("float2(half2(rect.z, 0.5))");
-        SkString _sample8699;
-        _sample8699 = this->invokeChild(_outer.integral_index, args, _coords8699.c_str());
+        SkString _sample8699 = this->invokeChild(1, args, _coords8699.c_str());
         fragBuilder->codeAppendf(
                 R"SkSL(
     xCoverage = (1.0 - %s.w) - %s.w;)SkSL",
                 _sample8636.c_str(), _sample8699.c_str());
         SkString _coords8763("float2(half2(rect.y, 0.5))");
-        SkString _sample8763;
-        _sample8763 = this->invokeChild(_outer.integral_index, args, _coords8763.c_str());
+        SkString _sample8763 = this->invokeChild(1, args, _coords8763.c_str());
         SkString _coords8826("float2(half2(rect.w, 0.5))");
-        SkString _sample8826;
-        _sample8826 = this->invokeChild(_outer.integral_index, args, _coords8826.c_str());
+        SkString _sample8826 = this->invokeChild(1, args, _coords8826.c_str());
         fragBuilder->codeAppendf(
                 R"SkSL(
     yCoverage = (1.0 - %s.w) - %s.w;
 })SkSL",
                 _sample8763.c_str(), _sample8826.c_str());
         SkString _input8895(args.fInputColor);
-        SkString _sample8895;
-        if (_outer.inputFP_index >= 0) {
-            _sample8895 = this->invokeChild(_outer.inputFP_index, _input8895.c_str(), args);
-        } else {
-            _sample8895.swap(_input8895);
-        }
+        SkString _sample8895 = this->invokeChild(0, _input8895.c_str(), args);
         fragBuilder->codeAppendf(
                 R"SkSL(
 half4 inputColor = %s;
@@ -158,13 +147,7 @@
         : INHERITED(kGrRectBlurEffect_ClassID, src.optimizationFlags())
         , rect(src.rect)
         , isFast(src.isFast) {
-    if (src.inputFP_index >= 0) {
-        inputFP_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.inputFP_index));
-    }
-    {
-        integral_index =
-                this->cloneAndRegisterChildProcessor(src.childProcessor(src.integral_index));
-    }
+    this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrRectBlurEffect::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrRectBlurEffect(*this));
diff --git a/src/gpu/effects/generated/GrRectBlurEffect.h b/src/gpu/effects/generated/GrRectBlurEffect.h
index 5734c30..663c309 100644
--- a/src/gpu/effects/generated/GrRectBlurEffect.h
+++ b/src/gpu/effects/generated/GrRectBlurEffect.h
@@ -126,9 +126,7 @@
     GrRectBlurEffect(const GrRectBlurEffect& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "RectBlurEffect"; }
-    int inputFP_index = -1;
     SkRect rect;
-    int integral_index = -1;
     bool isFast;
 
 private:
@@ -143,9 +141,9 @@
                                 kCompatibleWithCoverageAsAlpha_OptimizationFlag)
             , rect(rect)
             , isFast(isFast) {
-        inputFP_index = this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
         SkASSERT(integral);
-        integral_index = this->registerChild(std::move(integral), SkSL::SampleUsage::Explicit());
+        this->registerChild(std::move(integral), SkSL::SampleUsage::Explicit());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/glsl/GrGLSLFragmentProcessor.cpp b/src/gpu/glsl/GrGLSLFragmentProcessor.cpp
index eb84ee8..01900b2 100644
--- a/src/gpu/glsl/GrGLSLFragmentProcessor.cpp
+++ b/src/gpu/glsl/GrGLSLFragmentProcessor.cpp
@@ -18,6 +18,7 @@
 
 void GrGLSLFragmentProcessor::emitChildFunction(int childIndex, EmitArgs& args) {
     SkASSERT(childIndex >= 0);
+    SkASSERT(args.fFp.childProcessor(childIndex));
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     while (childIndex >= (int) fFunctionNames.size()) {
         fFunctionNames.emplace_back();
@@ -29,7 +30,7 @@
         EmitArgs childArgs(fragBuilder,
                            args.fUniformHandler,
                            args.fShaderCaps,
-                           args.fFp.childProcessor(childIndex),
+                           *args.fFp.childProcessor(childIndex),
                            "_output",
                            "_input",
                            "_coords",
@@ -41,7 +42,16 @@
 
 SkString GrGLSLFragmentProcessor::invokeChild(int childIndex, const char* inputColor,
                                               EmitArgs& args, SkSL::String skslCoords) {
+    if (!inputColor) {
+        inputColor = "half4(1)";
+    }
+
     SkASSERT(childIndex >= 0);
+    const GrFragmentProcessor* childProc = args.fFp.childProcessor(childIndex);
+    if (!childProc) {
+        return SkString(inputColor);
+    }
+
     this->emitChildFunction(childIndex, args);
 
     if (skslCoords.empty()) {
@@ -49,49 +59,53 @@
         skslCoords = args.fSampleCoord;
     }
 
-    const GrFragmentProcessor& childProc = args.fFp.childProcessor(childIndex);
-
-    if (childProc.isSampledWithExplicitCoords()) {
+    if (childProc->isSampledWithExplicitCoords()) {
         // The child's function takes a half4 color and a float2 coordinate
         return SkStringPrintf("%s(%s, %s)", fFunctionNames[childIndex].c_str(),
-                                            inputColor ? inputColor : "half4(1)",
-                                            skslCoords.c_str());
+                                            inputColor, skslCoords.c_str());
     } else {
         // The child's function just takes a color. We should only get here for a call to sample
         // without explicit coordinates. Assert that the child has no sample matrix and skslCoords
         // is _coords (a uniform matrix sample call would go through invokeChildWithMatrix, and if
         // a child was sampled with sample(matrix) and sample(), it should have been flagged as
         // variable and hit the branch above).
-        SkASSERT(skslCoords == args.fSampleCoord && !childProc.sampleUsage().hasMatrix());
-        return SkStringPrintf("%s(%s)", fFunctionNames[childIndex].c_str(),
-                                        inputColor ? inputColor : "half4(1)");
+        SkASSERT(skslCoords == args.fSampleCoord && !childProc->sampleUsage().hasMatrix());
+        return SkStringPrintf("%s(%s)", fFunctionNames[childIndex].c_str(), inputColor);
     }
 }
 
 SkString GrGLSLFragmentProcessor::invokeChildWithMatrix(int childIndex, const char* inputColor,
                                                         EmitArgs& args,
                                                         SkSL::String skslMatrix) {
+    if (!inputColor) {
+        inputColor = "half4(1)";
+    }
+
     SkASSERT(childIndex >= 0);
+    const GrFragmentProcessor* childProc = args.fFp.childProcessor(childIndex);
+    if (!childProc) {
+        return SkString(inputColor);
+    }
+
     this->emitChildFunction(childIndex, args);
 
-    const GrFragmentProcessor& childProc = args.fFp.childProcessor(childIndex);
-    SkASSERT(childProc.sampleUsage().hasMatrix());
+    SkASSERT(childProc->sampleUsage().hasMatrix());
 
     // Since this is uniform, the provided sksl expression should exactly match the expression
     // stored on the FP, or it should match the mangled uniform name.
     if (skslMatrix.empty()) {
         // Empty matrix expression replaces with the sample matrix expression stored on the FP, but
         // that is only valid for uniform sampled FPs
-        SkASSERT(childProc.sampleUsage().hasUniformMatrix());
-        skslMatrix.assign(childProc.sampleUsage().fExpression);
+        SkASSERT(childProc->sampleUsage().hasUniformMatrix());
+        skslMatrix.assign(childProc->sampleUsage().fExpression);
     }
 
-    if (childProc.sampleUsage().hasUniformMatrix()) {
+    if (childProc->sampleUsage().hasUniformMatrix()) {
         // Attempt to resolve the uniform name from the raw name stored in the sample usage.
         // Since this is uniform, the provided expression better match what was given to the FP.
-        SkASSERT(childProc.sampleUsage().fExpression == skslMatrix);
+        SkASSERT(childProc->sampleUsage().fExpression == skslMatrix);
         GrShaderVar uniform = args.fUniformHandler->getUniformMapping(
-                args.fFp, SkString(childProc.sampleUsage().fExpression));
+                args.fFp, SkString(childProc->sampleUsage().fExpression));
         if (uniform.getType() != kVoid_GrSLType) {
             // Found the uniform, so replace the expression with the actual uniform name
             SkASSERT(uniform.getType() == kFloat3x3_GrSLType);
@@ -108,28 +122,24 @@
     //
     // In all other cases, we need to insert sksl to compute matrix * parent coords and then invoke
     // the function.
-    if (childProc.isSampledWithExplicitCoords()) {
+    if (childProc->isSampledWithExplicitCoords()) {
         // Only check perspective for this specific matrix transform, not the aggregate FP property.
         // Any parent perspective will have already been applied when evaluated in the FS.
-        if (childProc.sampleUsage().fHasPerspective) {
+        if (childProc->sampleUsage().fHasPerspective) {
             return SkStringPrintf("%s(%s, proj((%s) * %s.xy1))", fFunctionNames[childIndex].c_str(),
-                                  inputColor ? inputColor : "half4(1)", skslMatrix.c_str(),
-                                  args.fSampleCoord);
+                                  inputColor, skslMatrix.c_str(), args.fSampleCoord);
         } else {
-            return SkStringPrintf("%s(%s, ((%s) * %s.xy1).xy)",
-                                  fFunctionNames[childIndex].c_str(),
-                                  inputColor ? inputColor : "half4(1)",
-                                  skslMatrix.c_str(), args.fSampleCoord);
+            return SkStringPrintf("%s(%s, ((%s) * %s.xy1).xy)", fFunctionNames[childIndex].c_str(),
+                                  inputColor, skslMatrix.c_str(), args.fSampleCoord);
         }
     } else {
         // A variable matrix expression should mark the child as explicitly sampled. A no-op
         // matrix should match sample(color), not sample(color, matrix).
-        SkASSERT(childProc.sampleUsage().hasUniformMatrix());
+        SkASSERT(childProc->sampleUsage().hasUniformMatrix());
 
         // Since this is uniform and not explicitly sampled, it's transform has been promoted to
         // the vertex shader and the signature doesn't take a float2 coord.
-        return SkStringPrintf("%s(%s)", fFunctionNames[childIndex].c_str(),
-                                        inputColor ? inputColor : "half4(1)");
+        return SkStringPrintf("%s(%s)", fFunctionNames[childIndex].c_str(), inputColor);
     }
 }
 
@@ -175,7 +185,9 @@
     const GrGLSLFragmentProcessor* back = fFPStack.back();
     fFPStack.pop_back();
     for (int i = back->numChildProcessors() - 1; i >= 0; --i) {
-        fFPStack.push_back(back->childProcessor(i));
+        if (auto child = back->childProcessor(i)) {
+            fFPStack.push_back(child);
+        }
     }
     return *this;
 }
diff --git a/src/gpu/glsl/GrGLSLFragmentProcessor.h b/src/gpu/glsl/GrGLSLFragmentProcessor.h
index 6610e09..b8c4fb6 100644
--- a/src/gpu/glsl/GrGLSLFragmentProcessor.h
+++ b/src/gpu/glsl/GrGLSLFragmentProcessor.h
@@ -53,7 +53,8 @@
         int count() const { return (fFP->*COUNT)(); }
 
         BuilderInputProvider childInputs(int childIdx) const {
-            const GrFragmentProcessor* child = &fFP->childProcessor(childIdx);
+            const GrFragmentProcessor* child = fFP->childProcessor(childIdx);
+            SkASSERT(child);
             int numToSkip = 0;
             for (const auto& fp : GrFragmentProcessor::FPRange(*fFP)) {
                 if (&fp == child) {
diff --git a/src/gpu/gradients/generated/GrClampedGradientEffect.cpp b/src/gpu/gradients/generated/GrClampedGradientEffect.cpp
index 7e309c3..4d9447b 100644
--- a/src/gpu/gradients/generated/GrClampedGradientEffect.cpp
+++ b/src/gpu/gradients/generated/GrClampedGradientEffect.cpp
@@ -35,8 +35,7 @@
                                                               kHalf4_GrSLType, "leftBorderColor");
         rightBorderColorVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag,
                                                                kHalf4_GrSLType, "rightBorderColor");
-        SkString _sample1099;
-        _sample1099 = this->invokeChild(_outer.gradLayout_index, args);
+        SkString _sample1099 = this->invokeChild(1, args);
         fragBuilder->codeAppendf(
                 R"SkSL(half4 t = %s;
 if (!%s && t.y < 0.0) {
@@ -47,14 +46,12 @@
     %s = %s;
 } else {)SkSL",
                 _sample1099.c_str(),
-                (_outer.childProcessor(_outer.gradLayout_index).preservesOpaqueInput() ? "true"
-                                                                                       : "false"),
+                (_outer.childProcessor(1)->preservesOpaqueInput() ? "true" : "false"),
                 args.fOutputColor, args.fOutputColor,
                 args.fUniformHandler->getUniformCStr(leftBorderColorVar), args.fOutputColor,
                 args.fUniformHandler->getUniformCStr(rightBorderColorVar));
         SkString _input1767("t");
-        SkString _sample1767;
-        _sample1767 = this->invokeChild(_outer.colorizer_index, _input1767.c_str(), args);
+        SkString _sample1767 = this->invokeChild(0, _input1767.c_str(), args);
         fragBuilder->codeAppendf(
                 R"SkSL(
     %s = %s;
@@ -111,14 +108,7 @@
         , rightBorderColor(src.rightBorderColor)
         , makePremul(src.makePremul)
         , colorsAreOpaque(src.colorsAreOpaque) {
-    {
-        colorizer_index =
-                this->cloneAndRegisterChildProcessor(src.childProcessor(src.colorizer_index));
-    }
-    {
-        gradLayout_index =
-                this->cloneAndRegisterChildProcessor(src.childProcessor(src.gradLayout_index));
-    }
+    this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrClampedGradientEffect::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrClampedGradientEffect(*this));
diff --git a/src/gpu/gradients/generated/GrClampedGradientEffect.h b/src/gpu/gradients/generated/GrClampedGradientEffect.h
index c2cc784..e9dc2f2 100644
--- a/src/gpu/gradients/generated/GrClampedGradientEffect.h
+++ b/src/gpu/gradients/generated/GrClampedGradientEffect.h
@@ -32,8 +32,6 @@
     GrClampedGradientEffect(const GrClampedGradientEffect& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "ClampedGradientEffect"; }
-    int colorizer_index = -1;
-    int gradLayout_index = -1;
     SkPMColor4f leftBorderColor;
     SkPMColor4f rightBorderColor;
     bool makePremul;
@@ -56,11 +54,9 @@
             , makePremul(makePremul)
             , colorsAreOpaque(colorsAreOpaque) {
         SkASSERT(colorizer);
-        colorizer_index =
-                this->registerChild(std::move(colorizer), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(colorizer), SkSL::SampleUsage::PassThrough());
         SkASSERT(gradLayout);
-        gradLayout_index =
-                this->registerChild(std::move(gradLayout), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(gradLayout), SkSL::SampleUsage::PassThrough());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/gradients/generated/GrDualIntervalGradientColorizer.cpp b/src/gpu/gradients/generated/GrDualIntervalGradientColorizer.cpp
index 323fec5..d0e985f 100644
--- a/src/gpu/gradients/generated/GrDualIntervalGradientColorizer.cpp
+++ b/src/gpu/gradients/generated/GrDualIntervalGradientColorizer.cpp
@@ -129,7 +129,9 @@
         , bias01(src.bias01)
         , scale23(src.scale23)
         , bias23(src.bias23)
-        , threshold(src.threshold) {}
+        , threshold(src.threshold) {
+    this->cloneAndRegisterAllChildProcessors(src);
+}
 std::unique_ptr<GrFragmentProcessor> GrDualIntervalGradientColorizer::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrDualIntervalGradientColorizer(*this));
 }
diff --git a/src/gpu/gradients/generated/GrLinearGradientLayout.cpp b/src/gpu/gradients/generated/GrLinearGradientLayout.cpp
index 69f391f..3aca4bc 100644
--- a/src/gpu/gradients/generated/GrLinearGradientLayout.cpp
+++ b/src/gpu/gradients/generated/GrLinearGradientLayout.cpp
@@ -46,6 +46,7 @@
 }
 GrLinearGradientLayout::GrLinearGradientLayout(const GrLinearGradientLayout& src)
         : INHERITED(kGrLinearGradientLayout_ClassID, src.optimizationFlags()) {
+    this->cloneAndRegisterAllChildProcessors(src);
     this->setUsesSampleCoordsDirectly();
 }
 std::unique_ptr<GrFragmentProcessor> GrLinearGradientLayout::clone() const {
diff --git a/src/gpu/gradients/generated/GrRadialGradientLayout.cpp b/src/gpu/gradients/generated/GrRadialGradientLayout.cpp
index 602a648..2cc1d47 100644
--- a/src/gpu/gradients/generated/GrRadialGradientLayout.cpp
+++ b/src/gpu/gradients/generated/GrRadialGradientLayout.cpp
@@ -46,6 +46,7 @@
 }
 GrRadialGradientLayout::GrRadialGradientLayout(const GrRadialGradientLayout& src)
         : INHERITED(kGrRadialGradientLayout_ClassID, src.optimizationFlags()) {
+    this->cloneAndRegisterAllChildProcessors(src);
     this->setUsesSampleCoordsDirectly();
 }
 std::unique_ptr<GrFragmentProcessor> GrRadialGradientLayout::clone() const {
diff --git a/src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.cpp b/src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.cpp
index 4a524a1..abb1abe 100644
--- a/src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.cpp
+++ b/src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.cpp
@@ -79,7 +79,9 @@
         const GrSingleIntervalGradientColorizer& src)
         : INHERITED(kGrSingleIntervalGradientColorizer_ClassID, src.optimizationFlags())
         , start(src.start)
-        , end(src.end) {}
+        , end(src.end) {
+    this->cloneAndRegisterAllChildProcessors(src);
+}
 std::unique_ptr<GrFragmentProcessor> GrSingleIntervalGradientColorizer::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrSingleIntervalGradientColorizer(*this));
 }
diff --git a/src/gpu/gradients/generated/GrSweepGradientLayout.cpp b/src/gpu/gradients/generated/GrSweepGradientLayout.cpp
index 2f07145..5ca21ae 100644
--- a/src/gpu/gradients/generated/GrSweepGradientLayout.cpp
+++ b/src/gpu/gradients/generated/GrSweepGradientLayout.cpp
@@ -84,6 +84,7 @@
         : INHERITED(kGrSweepGradientLayout_ClassID, src.optimizationFlags())
         , bias(src.bias)
         , scale(src.scale) {
+    this->cloneAndRegisterAllChildProcessors(src);
     this->setUsesSampleCoordsDirectly();
 }
 std::unique_ptr<GrFragmentProcessor> GrSweepGradientLayout::clone() const {
diff --git a/src/gpu/gradients/generated/GrTextureGradientColorizer.cpp b/src/gpu/gradients/generated/GrTextureGradientColorizer.cpp
index cef854e..391a81d 100644
--- a/src/gpu/gradients/generated/GrTextureGradientColorizer.cpp
+++ b/src/gpu/gradients/generated/GrTextureGradientColorizer.cpp
@@ -26,8 +26,7 @@
         fragBuilder->codeAppendf(
                 R"SkSL(half2 coord = half2(%s.x, 0.5);)SkSL", args.fInputColor);
         SkString _coords327("float2(coord)");
-        SkString _sample327;
-        _sample327 = this->invokeChild(_outer.textureFP_index, args, _coords327.c_str());
+        SkString _sample327 = this->invokeChild(0, args, _coords327.c_str());
         fragBuilder->codeAppendf(
                 R"SkSL(
 %s = %s;
@@ -51,10 +50,7 @@
 }
 GrTextureGradientColorizer::GrTextureGradientColorizer(const GrTextureGradientColorizer& src)
         : INHERITED(kGrTextureGradientColorizer_ClassID, src.optimizationFlags()) {
-    {
-        textureFP_index =
-                this->cloneAndRegisterChildProcessor(src.childProcessor(src.textureFP_index));
-    }
+    this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrTextureGradientColorizer::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrTextureGradientColorizer(*this));
diff --git a/src/gpu/gradients/generated/GrTextureGradientColorizer.h b/src/gpu/gradients/generated/GrTextureGradientColorizer.h
index 507e1a7..6216513 100644
--- a/src/gpu/gradients/generated/GrTextureGradientColorizer.h
+++ b/src/gpu/gradients/generated/GrTextureGradientColorizer.h
@@ -26,13 +26,12 @@
     GrTextureGradientColorizer(const GrTextureGradientColorizer& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "TextureGradientColorizer"; }
-    int textureFP_index = -1;
 
 private:
     GrTextureGradientColorizer(std::unique_ptr<GrFragmentProcessor> textureFP)
             : INHERITED(kGrTextureGradientColorizer_ClassID, kNone_OptimizationFlags) {
         SkASSERT(textureFP);
-        textureFP_index = this->registerChild(std::move(textureFP), SkSL::SampleUsage::Explicit());
+        this->registerChild(std::move(textureFP), SkSL::SampleUsage::Explicit());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/gradients/generated/GrTiledGradientEffect.cpp b/src/gpu/gradients/generated/GrTiledGradientEffect.cpp
index 3d9dc96..8fa986f 100644
--- a/src/gpu/gradients/generated/GrTiledGradientEffect.cpp
+++ b/src/gpu/gradients/generated/GrTiledGradientEffect.cpp
@@ -29,8 +29,7 @@
         (void)makePremul;
         auto colorsAreOpaque = _outer.colorsAreOpaque;
         (void)colorsAreOpaque;
-        SkString _sample453;
-        _sample453 = this->invokeChild(_outer.gradLayout_index, args);
+        SkString _sample453 = this->invokeChild(1, args);
         fragBuilder->codeAppendf(
                 R"SkSL(half4 t = %s;
 if (!%s && t.y < 0.0) {
@@ -47,12 +46,10 @@
         t.x = fract(t.x);
     })SkSL",
                 _sample453.c_str(),
-                (_outer.childProcessor(_outer.gradLayout_index).preservesOpaqueInput() ? "true"
-                                                                                       : "false"),
+                (_outer.childProcessor(1)->preservesOpaqueInput() ? "true" : "false"),
                 args.fOutputColor, (_outer.mirror ? "true" : "false"));
         SkString _input1464("t");
-        SkString _sample1464;
-        _sample1464 = this->invokeChild(_outer.colorizer_index, _input1464.c_str(), args);
+        SkString _sample1464 = this->invokeChild(0, _input1464.c_str(), args);
         fragBuilder->codeAppendf(
                 R"SkSL(
     %s = %s;
@@ -90,14 +87,7 @@
         , mirror(src.mirror)
         , makePremul(src.makePremul)
         , colorsAreOpaque(src.colorsAreOpaque) {
-    {
-        colorizer_index =
-                this->cloneAndRegisterChildProcessor(src.childProcessor(src.colorizer_index));
-    }
-    {
-        gradLayout_index =
-                this->cloneAndRegisterChildProcessor(src.childProcessor(src.gradLayout_index));
-    }
+    this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrTiledGradientEffect::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrTiledGradientEffect(*this));
diff --git a/src/gpu/gradients/generated/GrTiledGradientEffect.h b/src/gpu/gradients/generated/GrTiledGradientEffect.h
index 561712d..3042743 100644
--- a/src/gpu/gradients/generated/GrTiledGradientEffect.h
+++ b/src/gpu/gradients/generated/GrTiledGradientEffect.h
@@ -30,8 +30,6 @@
     GrTiledGradientEffect(const GrTiledGradientEffect& src);
     std::unique_ptr<GrFragmentProcessor> clone() const override;
     const char* name() const override { return "TiledGradientEffect"; }
-    int colorizer_index = -1;
-    int gradLayout_index = -1;
     bool mirror;
     bool makePremul;
     bool colorsAreOpaque;
@@ -51,11 +49,9 @@
             , makePremul(makePremul)
             , colorsAreOpaque(colorsAreOpaque) {
         SkASSERT(colorizer);
-        colorizer_index =
-                this->registerChild(std::move(colorizer), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(colorizer), SkSL::SampleUsage::PassThrough());
         SkASSERT(gradLayout);
-        gradLayout_index =
-                this->registerChild(std::move(gradLayout), SkSL::SampleUsage::PassThrough());
+        this->registerChild(std::move(gradLayout), SkSL::SampleUsage::PassThrough());
     }
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
diff --git a/src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.cpp b/src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.cpp
index 2dda47f..1dd4aab 100644
--- a/src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.cpp
+++ b/src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.cpp
@@ -178,6 +178,7 @@
         , isSwapped(src.isSwapped)
         , isNativelyFocal(src.isNativelyFocal)
         , focalParams(src.focalParams) {
+    this->cloneAndRegisterAllChildProcessors(src);
     this->setUsesSampleCoordsDirectly();
 }
 std::unique_ptr<GrFragmentProcessor> GrTwoPointConicalGradientLayout::clone() const {
diff --git a/src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.cpp b/src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.cpp
index 38368db..d3a6d16 100644
--- a/src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.cpp
+++ b/src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.cpp
@@ -336,7 +336,9 @@
         , bias12_13(src.bias12_13)
         , bias14_15(src.bias14_15)
         , thresholds1_7(src.thresholds1_7)
-        , thresholds9_13(src.thresholds9_13) {}
+        , thresholds9_13(src.thresholds9_13) {
+    this->cloneAndRegisterAllChildProcessors(src);
+}
 std::unique_ptr<GrFragmentProcessor> GrUnrolledBinaryGradientColorizer::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrUnrolledBinaryGradientColorizer(*this));
 }
diff --git a/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp b/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp
index 48e5d47..d20a1d3 100644
--- a/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp
+++ b/src/gpu/ops/GrStencilAndCoverPathRenderer.cpp
@@ -36,7 +36,7 @@
         return true;
     }
     for (int i = fp.numChildProcessors() - 1; i >= 0; --i) {
-        if (has_matrix(fp.childProcessor(i))) {
+        if (fp.childProcessor(i) && has_matrix(*fp.childProcessor(i))) {
             return true;
         }
     }
diff --git a/src/sksl/SkSLCPPCodeGenerator.cpp b/src/sksl/SkSLCPPCodeGenerator.cpp
index 4a0cad9..561ff87 100644
--- a/src/sksl/SkSLCPPCodeGenerator.cpp
+++ b/src/sksl/SkSLCPPCodeGenerator.cpp
@@ -93,19 +93,20 @@
         SkASSERT(var->fType.kind() == Type::kNullable_Kind &&
                  var->fType.componentType() == *fContext.fFragmentProcessor_Type);
         this->write("%s");
-        const char* op;
+        const char* op = "";
         switch (b.fOperator) {
             case Token::Kind::TK_EQEQ:
-                op = "<";
+                op = "!";
                 break;
             case Token::Kind::TK_NEQ:
-                op = ">=";
+                op = "";
                 break;
             default:
                 SkASSERT(false);
         }
-        fFormatArgs.push_back("_outer." + String(var->fName) + "_index " + op + " 0 ? \"true\" "
-                              ": \"false\"");
+        int childIndex = this->getChildFPIndex(*var);
+        fFormatArgs.push_back(String(op) + "_outer.childProcessor(" + to_string(childIndex) +
+                              ") ? \"true\" : \"false\"");
     } else {
         INHERITED::writeBinaryExpression(b, parentPrecedence);
     }
@@ -357,8 +358,8 @@
 
         const Type::Field& field = fContext.fFragmentProcessor_Type->fields()[access.fFieldIndex];
         const Variable& var = ((const VariableReference&) *access.fBase).fVariable;
-        String cppAccess = String::printf("_outer.childProcessor(_outer.%s_index).%s()",
-                                          String(var.fName).c_str(),
+        String cppAccess = String::printf("_outer.childProcessor(%d)->%s()",
+                                          this->getChildFPIndex(var),
                                           String(field.fName).c_str());
 
         if (fCPPMode) {
@@ -416,12 +417,11 @@
         // sksl variables defined in earlier sksl code.
         this->newExtraEmitCodeBlock();
 
-        String inputColorName; // the sksl variable/expression, referenced later for null child FPs
         String inputColor;
         if (c.fArguments.size() > 1 && c.fArguments[1]->fType.name() == "half4") {
             // Use the invokeChild() variant that accepts an input color, so convert the 2nd
             // argument's expression into C++ code that produces sksl stored in an SkString.
-            inputColorName = "_input" + to_string(c.fOffset);
+            String inputColorName = "_input" + to_string(c.fOffset);
             addExtraEmitCodeLine(convertSKSLExpressionToCPP(*c.fArguments[1], inputColorName));
 
             // invokeChild() needs a char* and a pre-pended comma
@@ -454,32 +454,9 @@
 
         // Write the output handling after the possible input handling
         String childName = "_sample" + to_string(c.fOffset);
-        addExtraEmitCodeLine("SkString " + childName + ";");
-
-        if (c.fArguments[0]->fType.kind() == Type::kNullable_Kind) {
-            addExtraEmitCodeLine("if (_outer." + String(child.fName) + "_index >= 0) {\n    ");
-        }
-        addExtraEmitCodeLine(childName + " = this->" + invokeFunction + "(_outer." +
-                             String(child.fName) + "_index" + inputColor + ", args" +
-                             inputCoord + ");");
-
-        if (c.fArguments[0]->fType.kind() == Type::kNullable_Kind) {
-            // Null FPs are not emitted, but their output can still be referenced in dependent
-            // expressions - thus we always fill the variable with something.
-            // Sampling from a null fragment processor will provide in the input color as-is. This
-            // defaults to half4(1) if no color is specified.
-            if (!inputColorName.empty()) {
-                addExtraEmitCodeLine(
-                    "} else {"
-                    "    " + childName + ".swap(" + inputColorName + ");"
-                    "}");
-            } else {
-                addExtraEmitCodeLine(
-                    "} else {"
-                    "    " + childName + " = \"half4(1)\";"
-                    "}");
-            }
-        }
+        String childIndexStr = to_string(this->getChildFPIndex(child));
+        addExtraEmitCodeLine("SkString " + childName + " = this->" + invokeFunction + "(" +
+                             childIndexStr + inputColor + ", args" + inputCoord + ");");
 
         this->write("%s");
         fFormatArgs.push_back(childName + ".c_str()");
@@ -1109,21 +1086,11 @@
             }
         }
         this->writef(" {\n");
+        this->writef("        this->cloneAndRegisterAllChildProcessors(src);\n");
         int samplerCount = 0;
         for (const auto& param : fSectionAndParameterHelper.getParameters()) {
             if (param->fType.kind() == Type::kSampler_Kind) {
                 ++samplerCount;
-            } else if (param->fType.nonnullable() == *fContext.fFragmentProcessor_Type) {
-                String fieldName = HCodeGenerator::FieldName(String(param->fName).c_str());
-                if (param->fType.kind() == Type::kNullable_Kind) {
-                    this->writef("    if (src.%s_index >= 0) {\n", fieldName.c_str());
-                } else {
-                    this->write("    {\n");
-                }
-                this->writef("        %s_index = this->cloneAndRegisterChildProcessor("
-                                                     "src.childProcessor(src.%s_index));\n"
-                             "    }\n",
-                             fieldName.c_str(), fieldName.c_str());
             }
         }
         if (samplerCount) {
diff --git a/src/sksl/SkSLHCodeGenerator.cpp b/src/sksl/SkSLHCodeGenerator.cpp
index 3d46c1d..e9ab69d 100644
--- a/src/sksl/SkSLHCodeGenerator.cpp
+++ b/src/sksl/SkSLHCodeGenerator.cpp
@@ -288,8 +288,7 @@
             }
             std::string usageArg = usage.constructor(std::move(perspExpression));
 
-            this->writef("        %s_index = this->registerChild(std::move(%s), %s);",
-                         FieldName(String(param->fName).c_str()).c_str(),
+            this->writef("        this->registerChild(std::move(%s), %s);",
                          String(param->fName).c_str(),
                          usageArg.c_str());
         }
@@ -305,7 +304,7 @@
     for (const auto& param : fSectionAndParameterHelper.getParameters()) {
         String name = FieldName(String(param->fName).c_str());
         if (param->fType.nonnullable() == *fContext.fFragmentProcessor_Type) {
-            this->writef("    int %s_index = -1;\n", name.c_str());
+            // Don't need to write any fields, FPs are held as children
         } else {
             this->writef("    %s %s;\n", FieldType(fContext, param->fType,
                                                    param->fModifiers.fLayout).c_str(),
diff --git a/tests/ProcessorTest.cpp b/tests/ProcessorTest.cpp
index 192c9c6..4142e56 100644
--- a/tests/ProcessorTest.cpp
+++ b/tests/ProcessorTest.cpp
@@ -710,9 +710,11 @@
                                  std::string indent,
                                  SkString* text) {
     for (int index = 0; index < fp.numChildProcessors(); ++index) {
-        const GrFragmentProcessor& childFP = fp.childProcessor(index);
-        text->appendf("\n%s(#%d) -> %s", indent.c_str(), index, childFP.name());
-        describe_fp_children(childFP, indent + "\t", text);
+        const GrFragmentProcessor* childFP = fp.childProcessor(index);
+        text->appendf("\n%s(#%d) -> %s", indent.c_str(), index, childFP ? childFP->name() : "null");
+        if (childFP) {
+            describe_fp_children(*childFP, indent + "\t", text);
+        }
     }
 }
 
diff --git a/tests/ProgramsTest.cpp b/tests/ProgramsTest.cpp
index 9b71ddf..98e5645 100644
--- a/tests/ProgramsTest.cpp
+++ b/tests/ProgramsTest.cpp
@@ -110,7 +110,7 @@
     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLFP; }
 
     std::unique_ptr<GrFragmentProcessor> clone() const override {
-        return Make(this->childProcessor(0).clone());
+        return Make(this->childProcessor(0)->clone());
     }
 
 private:
@@ -187,7 +187,7 @@
                 if (!fp) {
                     return nullptr;
                 }
-                if (0 == fp->numChildProcessors()) {
+                if (0 == fp->numNonNullChildProcessors()) {
                     break;
                 }
             }
diff --git a/tests/SkSLFPTest.cpp b/tests/SkSLFPTest.cpp
index 6bf42d8..e8516dc 100644
--- a/tests/SkSLFPTest.cpp
+++ b/tests/SkSLFPTest.cpp
@@ -170,6 +170,7 @@
 }
 GrTest::GrTest(const GrTest& src)
 : INHERITED(kGrTest_ClassID, src.optimizationFlags()) {
+        this->cloneAndRegisterAllChildProcessors(src);
 }
 std::unique_ptr<GrFragmentProcessor> GrTest::clone() const {
     return std::unique_ptr<GrFragmentProcessor>(new GrTest(*this));
@@ -543,20 +544,17 @@
              }
          )__SkSL__",
          /*expectedH=*/{
-            "child1_index = this->registerChild(std::move(child1), SkSL::SampleUsage::PassThrough());",
-            "child2_index = this->registerChild(std::move(child2), SkSL::SampleUsage::PassThrough());"
+            "this->registerChild(std::move(child1), SkSL::SampleUsage::PassThrough());",
+            "this->registerChild(std::move(child2), SkSL::SampleUsage::PassThrough());"
          },
          /*expectedCPP=*/{
-            "SkString _sample149;\n",
-            "_sample149 = this->invokeChild(_outer.child1_index, args);\n",
-            "SkString _sample166;\n",
-            "_sample166 = this->invokeChild(_outer.child2_index, args);\n",
+            "SkString _sample149 = this->invokeChild(0, args);\n",
+            "SkString _sample166 = this->invokeChild(1, args);\n",
             "fragBuilder->codeAppendf(\n"
             "R\"SkSL(%s = %s * %s;\n"
             ")SkSL\"\n"
             ", args.fOutputColor, _sample149.c_str(), _sample166.c_str());",
-            "child1_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child1_index));",
-            "child2_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child2_index));",
+            "this->cloneAndRegisterAllChildProcessors(src);",
          });
 }
 
@@ -574,22 +572,19 @@
              }
          )__SkSL__",
          /*expectedH=*/{
-            "child1_index = this->registerChild(std::move(child1), SkSL::SampleUsage::PassThrough());",
-            "child2_index = this->registerChild(std::move(child2), SkSL::SampleUsage::PassThrough());"
+            "this->registerChild(std::move(child1), SkSL::SampleUsage::PassThrough());",
+            "this->registerChild(std::move(child2), SkSL::SampleUsage::PassThrough());"
          },
          /*expectedCPP=*/{
             "SkString _input198(\"childIn\");",
-            "SkString _sample198;",
-            "_sample198 = this->invokeChild(_outer.child1_index, _input198.c_str(), args);",
+            "SkString _sample198 = this->invokeChild(0, _input198.c_str(), args);",
             "fragBuilder->codeAppendf(\n"
             "R\"SkSL(\n"
             "half4 childOut1 = %s;)SkSL\"\n"
             ", _sample198.c_str());",
             "SkString _input258(\"childOut1\");",
-            "SkString _sample258;",
-            "_sample258 = this->invokeChild(_outer.child2_index, _input258.c_str(), args);",
-            "child1_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child1_index));",
-            "child2_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child2_index));",
+            "SkString _sample258 = this->invokeChild(1, _input258.c_str(), args);",
+            "this->cloneAndRegisterAllChildProcessors(src);",
          });
 }
 
@@ -603,17 +598,16 @@
              }
          )__SkSL__",
          /*expectedH=*/{
-            "child_index = this->registerChild(std::move(child), SkSL::SampleUsage::PassThrough());",
+            "this->registerChild(std::move(child), SkSL::SampleUsage::PassThrough());",
          },
          /*expectedCPP=*/{
             "SkString _input106 = SkStringPrintf(\"%s * half4(0.5)\", args.fInputColor);",
-            "SkString _sample106;",
-            "_sample106 = this->invokeChild(_outer.child_index, _input106.c_str(), args);",
+            "SkString _sample106 = this->invokeChild(0, _input106.c_str(), args);",
             "fragBuilder->codeAppendf(\n"
             "R\"SkSL(%s = %s;\n"
             ")SkSL\"\n"
             ", args.fOutputColor, _sample106.c_str());",
-            "child_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child_index));",
+            "this->cloneAndRegisterAllChildProcessors(src);",
          });
 }
 
@@ -628,22 +622,19 @@
              }
          )__SkSL__",
          /*expectedH=*/{
-            "child1_index = this->registerChild(std::move(child1), SkSL::SampleUsage::PassThrough());",
-            "child2_index = this->registerChild(std::move(child2), SkSL::SampleUsage::PassThrough());"
+            "this->registerChild(std::move(child1), SkSL::SampleUsage::PassThrough());",
+            "this->registerChild(std::move(child2), SkSL::SampleUsage::PassThrough());"
          },
          /*expectedCPP=*/{
             "SkString _input177 = SkStringPrintf(\"%s * half4(0.5)\", args.fInputColor);",
-            "SkString _sample177;",
-            "_sample177 = this->invokeChild(_outer.child1_index, _input177.c_str(), args);",
+            "SkString _sample177 = this->invokeChild(0, _input177.c_str(), args);",
             "SkString _input149 = SkStringPrintf(\"%s * %s\", args.fInputColor, _sample177.c_str());",
-            "SkString _sample149;",
-            "_sample149 = this->invokeChild(_outer.child2_index, _input149.c_str(), args);",
+            "SkString _sample149 = this->invokeChild(1, _input149.c_str(), args);",
             "fragBuilder->codeAppendf(\n"
             "R\"SkSL(%s = %s;\n"
             ")SkSL\"\n"
             ", args.fOutputColor, _sample149.c_str());",
-            "child1_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child1_index));",
-            "child2_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child2_index));",
+            "this->cloneAndRegisterAllChildProcessors(src);",
             });
 }
 
@@ -662,7 +653,7 @@
              }
          )__SkSL__",
          /*expectedH=*/{
-            "child_index = this->registerChild(std::move(child), SkSL::SampleUsage::PassThrough());"
+            "this->registerChild(std::move(child), SkSL::SampleUsage::PassThrough());"
          },
          /*expectedCPP=*/{
             "hasCap = sk_Caps.externalTextureSupport;",
@@ -672,8 +663,7 @@
             "if (hasCap) {)SkSL\"\n"
             ", (hasCap ? \"true\" : \"false\"));",
             "SkString _input200(args.fInputColor);",
-            "SkString _sample200;",
-            "_sample200 = this->invokeChild(_outer.child_index, _input200.c_str(), args);",
+            "SkString _sample200 = this->invokeChild(0, _input200.c_str(), args);",
             "fragBuilder->codeAppendf(\n"
             "R\"SkSL(\n"
             "    %s = %s;\n"
@@ -682,7 +672,7 @@
             "}\n"
             ")SkSL\"\n"
             ", args.fOutputColor, _sample200.c_str(), args.fOutputColor);",
-            "child_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child_index));",
+            "this->cloneAndRegisterAllChildProcessors(src);",
          });
 }
 
@@ -700,15 +690,14 @@
              }
          )__SkSL__",
          /*expectedH=*/{
-            "child_index = this->registerChild(std::move(child), SkSL::SampleUsage::PassThrough());"
+            "this->registerChild(std::move(child), SkSL::SampleUsage::PassThrough());"
          },
          /*expectedCPP=*/{
             "fragBuilder->codeAppendf(\n"
             "R\"SkSL(if (%s) {)SkSL\"\n"
-            ", (_outer.childProcessor(_outer.child_index).preservesOpaqueInput() ? \"true\" : \"false\"));",
+            ", (_outer.childProcessor(0)->preservesOpaqueInput() ? \"true\" : \"false\"));",
             "SkString _input161(args.fInputColor);",
-            "SkString _sample161;",
-            "_sample161 = this->invokeChild(_outer.child_index, _input161.c_str(), args);",
+            "SkString _sample161 = this->invokeChild(0, _input161.c_str(), args);",
             "fragBuilder->codeAppendf(\n"
             "R\"SkSL(\n"
             "    %s = %s;\n"
@@ -717,7 +706,7 @@
             "}\n"
             ")SkSL\"\n"
             ", args.fOutputColor, _sample161.c_str(), args.fOutputColor);",
-            "child_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child_index));",
+            "this->cloneAndRegisterAllChildProcessors(src);",
          });
 }
 
@@ -736,16 +725,15 @@
          }
          )__SkSL__",
          /*expectedH=*/{
-            "child_index = this->registerChild(std::move(child), SkSL::SampleUsage::PassThrough());"
+            "this->registerChild(std::move(child), SkSL::SampleUsage::PassThrough());"
          },
          /*expectedCPP=*/{
-            "opaque = _outer.childProcessor(_outer.child_index).preservesOpaqueInput();",
+            "opaque = _outer.childProcessor(0)->preservesOpaqueInput();",
             "fragBuilder->codeAppendf(\n"
             "R\"SkSL(bool opaque = %s;\n"
             "if (opaque) {)SkSL\"\n"
             ", (opaque ? \"true\" : \"false\"));",
-            "SkString _sample196;",
-            "_sample196 = this->invokeChild(_outer.child_index, args);",
+            "SkString _sample196 = this->invokeChild(0, args);",
             "fragBuilder->codeAppendf(\n"
             "R\"SkSL(\n"
             "    %s = %s;\n"
@@ -754,7 +742,7 @@
             "}\n"
             ")SkSL\"\n"
             ", args.fOutputColor, _sample196.c_str(), args.fOutputColor);",
-            "child_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child_index));",
+            "this->cloneAndRegisterAllChildProcessors(src);",
          });
 }
 
@@ -775,10 +763,8 @@
          /*expectedCPP=*/{
             "fragBuilder->codeAppendf(\n"
             "R\"SkSL(if (%s) {)SkSL\"\n"
-            ", _outer.child_index >= 0 ? \"true\" : \"false\");",
-            "SkString _sample149;",
-            "if (_outer.child_index >= 0) {",
-            "_sample149 = this->invokeChild(_outer.child_index, args);",
+            ", _outer.childProcessor(0) ? \"true\" : \"false\");",
+            "SkString _sample149 = this->invokeChild(0, args);",
             "fragBuilder->codeAppendf(\n"
             "R\"SkSL(\n"
             "    %s = %s;\n"
@@ -812,15 +798,13 @@
              }
          )__SkSL__",
          /*expectedH=*/{
-             "child_index = this->registerChild(std::move(child), SkSL::SampleUsage(SkSL::SampleUsage::Kind::kNone, \"\", false, true, true));",
+             "this->registerChild(std::move(child), SkSL::SampleUsage(SkSL::SampleUsage::Kind::kNone, \"\", false, true, true));",
              "this->setUsesSampleCoordsDirectly();"
          },
          /*expectedCPP=*/{
-            "SkString _sample118;\n",
-            "_sample118 = this->invokeChild(_outer.child_index, args);\n",
-            "SkString _sample118;\n",
+            "SkString _sample118 = this->invokeChild(0, args);\n",
             "SkString _coords134 = SkStringPrintf(\"%s / 2.0\", args.fSampleCoord);\n",
-            "_sample134 = this->invokeChild(_outer.child_index, args, _coords134.c_str());\n",
+            "SkString _sample134 = this->invokeChild(0, args, _coords134.c_str());\n",
             "fragBuilder->codeAppendf(\n"
             "R\"SkSL(%s = %s + %s;\n"
             ")SkSL\"\n"
@@ -872,7 +856,7 @@
                     "SkSL::SampleUsage::UniformMatrix(\"float3x3(2.0)\", true));"
          },
          /*expectedCPP=*/{
-             "this->invokeChildWithMatrix(_outer.child_index, args)"
+             "this->invokeChildWithMatrix(0, args)"
          });
 }
 
@@ -892,7 +876,7 @@
                     "SkSL::SampleUsage::UniformMatrix(\"matrix\", true));"
          },
          /*expectedCPP=*/{
-             "this->invokeChildWithMatrix(_outer.child_index, args)"
+             "this->invokeChildWithMatrix(0, args)"
          });
 }
 
@@ -912,7 +896,7 @@
                     "SkSL::SampleUsage::UniformMatrix(\"matrix\", matrix.hasPerspective()));"
          },
          /*expectedCPP=*/{
-             "this->invokeChildWithMatrix(_outer.child_index, args)"
+             "this->invokeChildWithMatrix(0, args)"
          });
 }
 
@@ -936,9 +920,9 @@
          },
          /*expectedCPP=*/{
              "SkString _matrix191(args.fUniformHandler->getUniformCStr(matrixAVar));",
-             "this->invokeChildWithMatrix(_outer.child_index, args, _matrix191.c_str());",
+             "this->invokeChildWithMatrix(0, args, _matrix191.c_str());",
              "SkString _matrix247(args.fUniformHandler->getUniformCStr(matrixBVar));",
-             "this->invokeChildWithMatrix(_outer.child_index, args, _matrix247.c_str());"
+             "this->invokeChildWithMatrix(0, args, _matrix247.c_str());"
          });
 }
 
@@ -961,7 +945,7 @@
          /*expectedCPP=*/{
             "SkString _matrix145 = SkStringPrintf(\"0.5 * %s\", "
                     "args.fUniformHandler->getUniformCStr(matrixVar));",
-             "this->invokeChildWithMatrix(_outer.child_index, args, _matrix145.c_str());"
+             "this->invokeChildWithMatrix(0, args, _matrix145.c_str());"
          });
 }
 
@@ -980,9 +964,9 @@
                     "SkSL::SampleUsage(SkSL::SampleUsage::Kind::kUniform, \"float3x3(0.5)\", true, true, false));"
          },
          /*expectedCPP=*/{
-             "this->invokeChildWithMatrix(_outer.child_index, args)",
+             "this->invokeChildWithMatrix(0, args)",
              "SkString _coords180 = SkStringPrintf(\"%s / 2.0\", args.fSampleCoord);",
-             "this->invokeChild(_outer.child_index, args, _coords180.c_str())",
+             "this->invokeChild(0, args, _coords180.c_str())",
          });
 }
 
@@ -1003,8 +987,8 @@
          },
          /*expectedCPP=*/{
              "SkString _matrix178(\"matrix\");",
-             "this->invokeChildWithMatrix(_outer.child_index, args, _matrix178.c_str())",
+             "this->invokeChildWithMatrix(0, args, _matrix178.c_str())",
              "SkString _coords232 = SkStringPrintf(\"%s / 2.0\", args.fSampleCoord);",
-             "this->invokeChild(_outer.child_index, args, _coords232.c_str()",
+             "this->invokeChild(0, args, _coords232.c_str()",
          });
 }