Revert "GPU support for SkMixers"

This reverts commit 3f2d05e7af2f0774f987f8fdf10c7c0c05079f5b.

Reason for revert: breaking the bots

Original change's description:
> GPU support for SkMixers
> 
> Bug: skia:
> Change-Id: Ic92f0b3c4613b3d599d59924d93cd4da8d161e89
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/204445
> Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
> Reviewed-by: Mike Reed <reed@google.com>
> Reviewed-by: Brian Salomon <bsalomon@google.com>

TBR=bsalomon@google.com,ethannicholas@google.com,reed@google.com

Change-Id: Ice7c470a57a3ae55215288718aa6390592bd85e5
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/204724
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
diff --git a/gm/runtimecolorfilter.cpp b/gm/runtimecolorfilter.cpp
index 2d2bede..efee4a8 100644
--- a/gm/runtimecolorfilter.cpp
+++ b/gm/runtimecolorfilter.cpp
@@ -34,9 +34,7 @@
 
     float b = 0.75;
     sk_sp<SkData> data = SkData::MakeWithCopy(&b, sizeof(b));
-    static SkRuntimeColorFilterFactory fact = SkRuntimeColorFilterFactory(SkString(SKSL_TEST_SRC),
-                                                                          runtimeCpuFunc);
-    auto cf1 = fact.make(data);
+    auto cf1 = SkRuntimeColorFilterFactory(SkString(SKSL_TEST_SRC), runtimeCpuFunc).make(data);
     SkPaint p;
     p.setColorFilter(cf1);
     canvas->drawImage(img, 256, 0, &p);
@@ -59,9 +57,7 @@
 
     float b = 0.75;
     sk_sp<SkData> data = SkData::MakeWithCopy(&b, sizeof(b));
-    static SkRuntimeColorFilterFactory fact = SkRuntimeColorFilterFactory(SkString(SKSL_TEST_SRC),
-                                                                          nullptr);
-    auto cf1 = fact.make(data);
+    auto cf1 = SkRuntimeColorFilterFactory(SkString(SKSL_TEST_SRC), nullptr).make(data);
     SkPaint p;
     p.setColorFilter(cf1);
     canvas->drawImage(img, 256, 0, &p);
diff --git a/src/core/SkMixer.cpp b/src/core/SkMixer.cpp
index 51c3a10..72c5a75 100644
--- a/src/core/SkMixer.cpp
+++ b/src/core/SkMixer.cpp
@@ -8,36 +8,13 @@
 #include "SkBlendModePriv.h"
 #include "SkEffectPriv.h"
 #include "SkMixerBase.h"
-#include "SkMixerShader.h"
 #include "SkReadBuffer.h"
 #include "SkRasterPipeline.h"
 #include "SkWriteBuffer.h"
 
 #if SK_SUPPORT_GPU
-#include "GrRecordingContext.h"
 #include "effects/GrConstColorProcessor.h"
-#include "effects/GrSkSLFP.h"
 #include "effects/GrXfermodeFragmentProcessor.h"
-
-static std::unique_ptr<GrFragmentProcessor> sksl_mixer_fp(
-                                               const GrFPArgs& args,
-                                               int index,
-                                               const char* sksl,
-                                               sk_sp<SkData> inputs,
-                                               std::unique_ptr<GrFragmentProcessor> fp1,
-                                               std::unique_ptr<GrFragmentProcessor> fp2,
-                                               std::unique_ptr<GrFragmentProcessor> fp3 = nullptr) {
-    std::unique_ptr<GrSkSLFP> result = GrSkSLFP::Make(args.fContext, index, "Runtime Mixer", sksl,
-                                                      inputs ? inputs->data() : nullptr,
-                                                      inputs ? inputs->size() : 0,
-                                                      SkSL::Program::kMixer_Kind);
-    result->addChild(std::move(fp1));
-    result->addChild(std::move(fp2));
-    if (fp3) {
-        result->addChild(std::move(fp3));
-    }
-    return std::move(result);
-}
 #endif
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -60,9 +37,9 @@
 
 #if SK_SUPPORT_GPU
     std::unique_ptr<GrFragmentProcessor>
-    asFragmentProcessor(const GrFPArgs& args, const sk_sp<SkShader> shader1,
-                        const sk_sp<SkShader> shader2) const override {
-        return GrConstColorProcessor::Make(fPM, GrConstColorProcessor::InputMode::kIgnore);
+    asFragmentProcessor(GrRecordingContext*, const GrColorSpaceInfo& dstColorSpaceInfo) const override {
+        //    return GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(fpB), std::move(fpA), fMode);
+        return nullptr;
     }
 #endif
 };
@@ -105,9 +82,9 @@
 
 #if SK_SUPPORT_GPU
     std::unique_ptr<GrFragmentProcessor>
-    asFragmentProcessor(const GrFPArgs& args, const sk_sp<SkShader> shader1,
-                        const sk_sp<SkShader> shader2) const override {
-        return as_MB(fProxy)->asFragmentProcessor(args, shader2, shader1);
+    asFragmentProcessor(GrRecordingContext*, const GrColorSpaceInfo& dstColorSpaceInfo) const override {
+        //    return GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(fpB), std::move(fpA), fMode);
+        return nullptr;
     }
 #endif
 };
@@ -137,12 +114,9 @@
 
 #if SK_SUPPORT_GPU
     std::unique_ptr<GrFragmentProcessor>
-    asFragmentProcessor(const GrFPArgs& args, const sk_sp<SkShader> shader1,
-                        const sk_sp<SkShader> shader2) const override {
-        return GrXfermodeFragmentProcessor::MakeFromTwoProcessors(
-                                                          as_SB(shader2)->asFragmentProcessor(args),
-                                                          as_SB(shader1)->asFragmentProcessor(args),
-                                                          fMode);
+    asFragmentProcessor(GrRecordingContext*, const GrColorSpaceInfo& dstColorSpaceInfo) const override {
+        //    return GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(fpB), std::move(fpA), fMode);
+        return nullptr;
     }
 #endif
 };
@@ -177,18 +151,9 @@
 
 #if SK_SUPPORT_GPU
     std::unique_ptr<GrFragmentProcessor>
-    asFragmentProcessor(const GrFPArgs& args, const sk_sp<SkShader> shader1,
-                        const sk_sp<SkShader> shader2) const override {
-        static int index = GrSkSLFP::NewIndex();
-        return sksl_mixer_fp(args,
-                             index,
-                             "in uniform float weight;"
-                             "half4 main(half4 input1, half4 input2) {"
-                             "    return mix(input1, input2, half(weight));"
-                             "}",
-                             SkData::MakeWithCopy(&fWeight, sizeof(fWeight)),
-                             as_SB(shader1)->asFragmentProcessor(args),
-                             as_SB(shader2)->asFragmentProcessor(args));
+    asFragmentProcessor(GrRecordingContext*, const GrColorSpaceInfo& dstColorSpaceInfo) const override {
+        //    return GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(fpB), std::move(fpA), fMode);
+        return nullptr;
     }
 #endif
 };
@@ -241,19 +206,8 @@
 
 #if SK_SUPPORT_GPU
     std::unique_ptr<GrFragmentProcessor>
-    asFragmentProcessor(const GrFPArgs& args, const sk_sp<SkShader> shader1,
-                        const sk_sp<SkShader> shader2) const override {
-        static int index = GrSkSLFP::NewIndex();
-        return sksl_mixer_fp(args,
-                             index,
-                             "in fragmentProcessor lerpControl;"
-                             "half4 main(half4 input1, half4 input2) {"
-                             "    return mix(input1, input2, process(lerpControl).r);"
-                             "}",
-                             nullptr,
-                             as_SB(shader1)->asFragmentProcessor(args),
-                             as_SB(shader2)->asFragmentProcessor(args),
-                             as_SB(fShader)->asFragmentProcessor(args));
+    asFragmentProcessor(GrRecordingContext*, const GrColorSpaceInfo& dstColorSpaceInfo) const override {
+        return nullptr;
     }
 #endif
 };
@@ -322,11 +276,9 @@
 
 #if SK_SUPPORT_GPU
     std::unique_ptr<GrFragmentProcessor>
-    asFragmentProcessor(const GrFPArgs& args, const sk_sp<SkShader> shader1,
-                        const sk_sp<SkShader> shader2) const override {
-        return SkShader_Mixer(sk_sp<SkShader>(new SkShader_Mixer(shader1, shader2, fM0)),
-                              sk_sp<SkShader>(new SkShader_Mixer(shader1, shader2, fM1)),
-                              fCombine).asFragmentProcessor(args);
+    asFragmentProcessor(GrRecordingContext*, const GrColorSpaceInfo& dstColorSpaceInfo) const override {
+        //    return GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(fpB), std::move(fpA), fMode);
+        return nullptr;
     }
 #endif
 };
diff --git a/src/core/SkMixerBase.h b/src/core/SkMixerBase.h
index bfa5283..31b17b8 100644
--- a/src/core/SkMixerBase.h
+++ b/src/core/SkMixerBase.h
@@ -5,14 +5,13 @@
  * found in the LICENSE file.
  */
 
-#ifndef SkMixerBase_DEFINED
-#define SkMixerBase_DEFINED
+#ifndef SkMixerPriv_DEFINED
+#define SkMixerPriv_DEFINED
 
 #include "SkMixer.h"
 #include "SkColorData.h"
 
 class GrColorSpaceInfo;
-struct GrFPArgs;
 class GrFragmentProcessor;
 class GrRecordingContext;
 struct SkStageRec;
@@ -32,9 +31,8 @@
      *
      *  A null return indicates that the color filter isn't implemented for the GPU backend.
      */
-    virtual std::unique_ptr<GrFragmentProcessor>
-    asFragmentProcessor(const GrFPArgs& args, const sk_sp<SkShader> shader1,
-                        const sk_sp<SkShader> shader2) const = 0;
+    virtual std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
+            GrRecordingContext*, const GrColorSpaceInfo& dstColorSpaceInfo) const = 0;
 #endif
 
     static void RegisterFlattenables();
diff --git a/src/gpu/effects/GrSkSLFP.cpp b/src/gpu/effects/GrSkSLFP.cpp
index 5a13646..31da647 100644
--- a/src/gpu/effects/GrSkSLFP.cpp
+++ b/src/gpu/effects/GrSkSLFP.cpp
@@ -16,13 +16,13 @@
 #include "glsl/GrGLSLFragmentShaderBuilder.h"
 #include "glsl/GrGLSLProgramBuilder.h"
 
-GrSkSLFPFactory::GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCaps, const char* sksl,
-                                 SkSL::Program::Kind kind)
-        : fKind(kind)
-        , fName(name) {
+GrSkSLFPFactory::GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCaps, const char* sksl)
+        : fName(name) {
     SkSL::Program::Settings settings;
     settings.fCaps = shaderCaps;
-    fBaseProgram = fCompiler.convertProgram(fKind, SkSL::String(sksl), settings);
+    fBaseProgram = fCompiler.convertProgram(SkSL::Program::kPipelineStage_Kind,
+                                            SkSL::String(sksl),
+                                            settings);
     if (fCompiler.errorCount()) {
         SkDebugf("%s\n", fCompiler.errorText().c_str());
     }
@@ -81,11 +81,7 @@
     }
 
     std::unique_ptr<SkSL::Program> specialized = fCompiler.specialize(*fBaseProgram, inputMap);
-    bool optimized = fCompiler.optimize(*specialized);
-    if (!optimized) {
-        SkDebugf("%s\n", fCompiler.errorText().c_str());
-        SkASSERT(false);
-    }
+    SkAssertResult(fCompiler.optimize(*specialized));
     const SkSL::Program* result = specialized.get();
     fSpecializations.insert(std::make_pair(key, std::move(specialized)));
     return result;
@@ -249,38 +245,34 @@
 
 std::unique_ptr<GrSkSLFP> GrSkSLFP::Make(GrContext_Base* context, int index, const char* name,
                                          const char* sksl, const void* inputs,
-                                         size_t inputSize, SkSL::Program::Kind kind) {
+                                         size_t inputSize) {
     return std::unique_ptr<GrSkSLFP>(new GrSkSLFP(context->priv().fpFactoryCache(),
                                                   context->priv().caps()->shaderCaps(),
-                                                  kind, index, name, sksl, SkString(),
-                                                  inputs, inputSize));
+                                                  index, name, sksl, SkString(), inputs,
+                                                  inputSize));
 }
 
 std::unique_ptr<GrSkSLFP> GrSkSLFP::Make(GrContext_Base* context, int index, const char* name,
-                                         SkString sksl, const void* inputs, size_t inputSize,
-                                         SkSL::Program::Kind kind) {
+                                         SkString sksl, const void* inputs, size_t inputSize) {
     return std::unique_ptr<GrSkSLFP>(new GrSkSLFP(context->priv().fpFactoryCache(),
                                                   context->priv().caps()->shaderCaps(),
-                                                  kind, index, name, nullptr, std::move(sksl),
-                                                  inputs, inputSize));
+                                                  index, name, nullptr, std::move(sksl), inputs,
+                                                  inputSize));
 }
 
 GrSkSLFP::GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache, const GrShaderCaps* shaderCaps,
-                   SkSL::Program::Kind kind, int index, const char* name, const char* sksl,
-                   SkString skslString, const void* inputs, size_t inputSize)
+                   int index, const char* name, const char* sksl, SkString skslString,
+                   const void* inputs, size_t inputSize)
         : INHERITED(kGrSkSLFP_ClassID, kNone_OptimizationFlags)
         , fFactoryCache(factoryCache)
         , fShaderCaps(sk_ref_sp(shaderCaps))
-        , fKind(kind)
         , fIndex(index)
         , fName(name)
         , fSkSLString(skslString)
         , fSkSL(sksl ? sksl : fSkSLString.c_str())
         , fInputs(new int8_t[inputSize])
         , fInputSize(inputSize) {
-    if (fInputSize) {
-        memcpy(fInputs.get(), inputs, inputSize);
-    }
+    memcpy(fInputs.get(), inputs, inputSize);
 }
 
 GrSkSLFP::GrSkSLFP(const GrSkSLFP& other)
@@ -288,16 +280,13 @@
         , fFactoryCache(other.fFactoryCache)
         , fShaderCaps(other.fShaderCaps)
         , fFactory(other.fFactory)
-        , fKind(other.fKind)
         , fIndex(other.fIndex)
         , fName(other.fName)
         , fSkSLString(other.fSkSLString)
         , fSkSL(other.fSkSL)
         , fInputs(new int8_t[other.fInputSize])
         , fInputSize(other.fInputSize) {
-    if (fInputSize) {
-        memcpy(fInputs.get(), other.fInputs.get(), fInputSize);
-    }
+    memcpy(fInputs.get(), other.fInputs.get(), fInputSize);
 }
 
 const char* GrSkSLFP::name() const {
@@ -308,8 +297,7 @@
     if (!fFactory) {
         fFactory = fFactoryCache->get(fIndex);
         if (!fFactory) {
-            fFactory = sk_sp<GrSkSLFPFactory>(new GrSkSLFPFactory(fName, fShaderCaps.get(), fSkSL,
-                                                                  fKind));
+            fFactory = sk_sp<GrSkSLFPFactory>(new GrSkSLFPFactory(fName, fShaderCaps.get(), fSkSL));
             fFactoryCache->set(fIndex, fFactory);
         }
     }
@@ -334,7 +322,6 @@
 void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps,
                                      GrProcessorKeyBuilder* b) const {
     this->createFactory();
-    b->add32(fIndex);
     size_t offset = 0;
     char* inputs = (char*) fInputs.get();
     const SkSL::Context& context = fFactory->fCompiler.context();
diff --git a/src/gpu/effects/GrSkSLFP.h b/src/gpu/effects/GrSkSLFP.h
index fb7369f..83a7537 100644
--- a/src/gpu/effects/GrSkSLFP.h
+++ b/src/gpu/effects/GrSkSLFP.h
@@ -73,8 +73,7 @@
                    const char* name,
                    const char* sksl,
                    const void* inputs,
-                   size_t inputSize,
-                   SkSL::Program::Kind kind = SkSL::Program::kPipelineStage_Kind);
+                   size_t inputSize);
 
     static std::unique_ptr<GrSkSLFP> Make(
                    GrContext_Base* context,
@@ -82,8 +81,7 @@
                    const char* name,
                    SkString sksl,
                    const void* inputs,
-                   size_t inputSize,
-                   SkSL::Program::Kind kind = SkSL::Program::kPipelineStage_Kind);
+                   size_t inputSize);
 
     const char* name() const override;
 
@@ -92,9 +90,9 @@
     std::unique_ptr<GrFragmentProcessor> clone() const override;
 
 private:
-    GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache, const GrShaderCaps* shaderCaps,
-             SkSL::Program::Kind kind, int fIndex, const char* name, const char* sksl,
-             SkString skslString, const void* inputs, size_t inputSize);
+    GrSkSLFP(sk_sp<GrSkSLFPFactoryCache> factoryCache, const GrShaderCaps* shaderCaps, int fIndex,
+             const char* name, const char* sksl, SkString skslString, const void* inputs,
+             size_t inputSize);
 
     GrSkSLFP(const GrSkSLFP& other);
 
@@ -112,8 +110,6 @@
 
     mutable sk_sp<GrSkSLFPFactory> fFactory;
 
-    SkSL::Program::Kind fKind;
-
     int fIndex;
 
     const char* fName;
@@ -156,14 +152,11 @@
      * the produced shaders to differ), so it is important to reuse the same factory instance for
      * the same shader in order to avoid repeatedly re-parsing the SkSL.
      */
-    GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCaps, const char* sksl,
-                    SkSL::Program::Kind kind = SkSL::Program::kPipelineStage_Kind);
+    GrSkSLFPFactory(const char* name, const GrShaderCaps* shaderCaps, const char* sksl);
 
     const SkSL::Program* getSpecialization(const SkSL::String& key, const void* inputs,
                                            size_t inputSize);
 
-    SkSL::Program::Kind fKind;
-
     const char* fName;
 
     SkSL::Compiler fCompiler;
diff --git a/src/shaders/SkMixerShader.cpp b/src/shaders/SkMixerShader.cpp
index e10325d..c34a07e 100644
--- a/src/shaders/SkMixerShader.cpp
+++ b/src/shaders/SkMixerShader.cpp
@@ -73,6 +73,17 @@
 
 std::unique_ptr<GrFragmentProcessor>
 SkShader_Mixer::asFragmentProcessor(const GrFPArgs& args) const {
-    return as_MB(fMixer)->asFragmentProcessor(args, fShader0, fShader1);
+    std::unique_ptr<GrFragmentProcessor> fpA(as_SB(fShader0)->asFragmentProcessor(args));
+    if (!fpA) {
+        return nullptr;
+    }
+    std::unique_ptr<GrFragmentProcessor> fpB(as_SB(fShader1)->asFragmentProcessor(args));
+    if (!fpB) {
+        return nullptr;
+    }
+
+    // TODO: need to make a mixer-processor...
+    return nullptr;
+    //return GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(fpB), std::move(fpA), fMode);
 }
 #endif
diff --git a/src/sksl/SkSLCFGGenerator.cpp b/src/sksl/SkSLCFGGenerator.cpp
index d86892e..9d6fb06 100644
--- a/src/sksl/SkSLCFGGenerator.cpp
+++ b/src/sksl/SkSLCFGGenerator.cpp
@@ -451,10 +451,6 @@
     }
 }
 
-static bool is_true(Expression& expr) {
-    return expr.fKind == Expression::kBoolLiteral_Kind && ((BoolLiteral&) expr).fValue;
-}
-
 void CFGGenerator::addStatement(CFG& cfg, std::unique_ptr<Statement>* s) {
     switch ((*s)->fKind) {
         case Statement::kBlock_Kind:
@@ -540,9 +536,7 @@
             fLoopExits.push(loopExit);
             this->addExpression(cfg, &w.fTest, true);
             BlockId test = cfg.fCurrent;
-            if (!is_true(*w.fTest)) {
-                cfg.addExit(test, loopExit);
-            }
+            cfg.addExit(test, loopExit);
             cfg.newBlock();
             this->addStatement(cfg, &w.fStatement);
             cfg.addExit(cfg.fCurrent, loopStart);
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index 22a7e65..720fcb6 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -61,10 +61,6 @@
 #include "sksl_pipeline.inc"
 ;
 
-static const char* SKSL_MIXER_INCLUDE =
-#include "sksl_mixer.inc"
-;
-
 namespace SkSL {
 
 Compiler::Compiler(Flags flags)
@@ -1272,13 +1268,6 @@
                                          strlen(SKSL_PIPELINE_STAGE_INCLUDE), *fTypes, &elements);
             fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
             break;
-        case Program::kMixer_Kind:
-            inherited = nullptr;
-            fIRGenerator->start(&settings, nullptr);
-            fIRGenerator->convertProgram(kind, SKSL_MIXER_INCLUDE, strlen(SKSL_MIXER_INCLUDE),
-                                         *fTypes, &elements);
-            fIRGenerator->fSymbolTable->markAllFunctionsBuiltin();
-            break;
     }
     for (auto& element : elements) {
         if (element->fKind == ProgramElement::kEnum_Kind) {
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index c37e86c..3cfea0b 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -669,10 +669,6 @@
     return std::unique_ptr<Statement>(new ExpressionStatement(std::move(result)));
 }
 
-// returns true if the modifiers are (explicitly or implicitly) nothing but 'in'
-static bool is_in(const Modifiers& modifiers) {
-    return (modifiers.fFlags & ~Modifiers::kIn_Flag) == 0;
-}
 
 void IRGenerator::convertFunction(const ASTFunction& f) {
     const Type* returnType = this->convertType(*f.fReturnType);
@@ -700,51 +696,33 @@
     }
 
     if (f.fName == "main") {
-        switch (fKind) {
-            case Program::kPipelineStage_Kind: {
-                bool valid;
-                switch (parameters.size()) {
-                    case 3:
-                        valid = parameters[0]->fType == *fContext.fInt_Type &&
-                                parameters[0]->fModifiers.fFlags == 0 &&
-                                parameters[1]->fType == *fContext.fInt_Type &&
-                                parameters[1]->fModifiers.fFlags == 0 &&
-                                parameters[2]->fType == *fContext.fHalf4_Type &&
-                                parameters[2]->fModifiers.fFlags == (Modifiers::kIn_Flag |
-                                                                     Modifiers::kOut_Flag);
-                        break;
-                    case 1:
-                        valid = parameters[0]->fType == *fContext.fHalf4_Type &&
-                                parameters[0]->fModifiers.fFlags == (Modifiers::kIn_Flag |
-                                                                     Modifiers::kOut_Flag);
-                        break;
-                    default:
-                        valid = false;
-                }
-                if (!valid) {
-                    fErrors.error(f.fOffset, "pipeline stage 'main' must be declared main(int, "
-                                             "int, inout half4) or main(inout half4)");
-                    return;
-                }
-                break;
+        if (fKind == Program::kPipelineStage_Kind) {
+            bool valid;
+            switch (parameters.size()) {
+                case 3:
+                    valid = parameters[0]->fType == *fContext.fInt_Type &&
+                            parameters[0]->fModifiers.fFlags == 0 &&
+                            parameters[1]->fType == *fContext.fInt_Type &&
+                            parameters[1]->fModifiers.fFlags == 0 &&
+                            parameters[2]->fType == *fContext.fHalf4_Type &&
+                            parameters[2]->fModifiers.fFlags == (Modifiers::kIn_Flag |
+                                                                 Modifiers::kOut_Flag);
+                    break;
+                case 1:
+                    valid = parameters[0]->fType == *fContext.fHalf4_Type &&
+                            parameters[0]->fModifiers.fFlags == (Modifiers::kIn_Flag |
+                                                                 Modifiers::kOut_Flag);
+                    break;
+                default:
+                    valid = false;
             }
-            case Program::kMixer_Kind: {
-                if (*returnType != *fContext.fHalf4_Type ||
-                    parameters.size() != 2 ||
-                    parameters[0]->fType != *fContext.fHalf4_Type ||
-                    !is_in(parameters[0]->fModifiers) ||
-                    parameters[1]->fType != *fContext.fHalf4_Type ||
-                    !is_in(parameters[1]->fModifiers)) {
-                    fErrors.error(f.fOffset, "mixer stage 'main' must be declared half4 main("
-                                             "half4, half4)");
-                    return;
-                }
-                break;
+            if (!valid) {
+                fErrors.error(f.fOffset, "pipeline stage 'main' must be declared main(int, "
+                                         "int, inout half4) or main(inout half4)");
+                return;
             }
-            default:
-                if (parameters.size()) {
-                    fErrors.error(f.fOffset, "shader 'main' must have zero parameters");
-                }
+        } else if (parameters.size()) {
+            fErrors.error(f.fOffset, "shader 'main' must have zero parameters");
         }
     }
 
diff --git a/src/sksl/SkSLPipelineStageCodeGenerator.cpp b/src/sksl/SkSLPipelineStageCodeGenerator.cpp
index cafa0e0..5121b67 100644
--- a/src/sksl/SkSLPipelineStageCodeGenerator.cpp
+++ b/src/sksl/SkSLPipelineStageCodeGenerator.cpp
@@ -59,7 +59,7 @@
 }
 
 void PipelineStageCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
-                                                       Precedence parentPrecedence) {
+                                             Precedence parentPrecedence) {
     if (b.fOperator == Token::PERCENT) {
         // need to use "%%" instead of "%" b/c the code will be inside of a printf
         Precedence precedence = GetBinaryPrecedence(b.fOperator);
@@ -147,7 +147,8 @@
                                 found = true;
                                 break;
                             }
-                            if (var.fModifiers.fFlags & Modifiers::kUniform_Flag) {
+                            if (var.fModifiers.fFlags & (Modifiers::kIn_Flag |
+                                                         Modifiers::kUniform_Flag)) {
                                 ++index;
                             }
                         }
@@ -156,20 +157,8 @@
                 SkASSERT(found);
                 fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kUniform,
                                                            index));
-            } else if (fProgramKind == Program::kMixer_Kind &&
-                     ref.fVariable.fStorage == Variable::kParameter_Storage &&
-                     fCurrentFunction->fName == "main") {
-                this->write("%s");
-                for (size_t i = 0; i < fCurrentFunction->fParameters.size(); ++i) {
-                    if (fCurrentFunction->fParameters[i] == &ref.fVariable) {
-                        fFormatArgs->push_back(Compiler::FormatArg(
-                                                         Compiler::FormatArg::Kind::kChildProcessor,
-                                                         i));
-                        return;
-                    }
-                }
-                SkASSERT(false);
-            } else {
+            }
+            else {
                 this->write(ref.fVariable.fName);
             }
     }
@@ -182,18 +171,6 @@
     INHERITED::writeIfStatement(s);
 }
 
-void PipelineStageCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
-    if (fProgramKind == Program::Kind::kMixer_Kind) {
-        SkASSERT(r.fExpression);
-        this->write("%s = ");
-        fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kOutput));
-        this->writeExpression(*r.fExpression, kTopLevel_Precedence);
-        this->write(";\nbreak;\n");
-    } else {
-        INHERITED::writeReturnStatement(r);
-    }
-}
-
 void PipelineStageCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
     if (s.fIsStatic) {
         this->write("@");
@@ -202,13 +179,7 @@
 }
 
 void PipelineStageCodeGenerator::writeFunction(const FunctionDefinition& f) {
-    fCurrentFunction = &f.fDeclaration;
     if (f.fDeclaration.fName == "main") {
-        if (fProgramKind == Program::kMixer_Kind) {
-            // Mixers use return statements. To make this work, we wrap the Mixer's body in a loop
-            // and replace the return with a break.
-            this->writef("while (true) {");
-        }
         fFunctionHeader = "";
         OutputStream* oldOut = fOut;
         StringStream buffer;
@@ -220,9 +191,6 @@
             this->writeStatement(*s);
             this->writeLine();
         }
-        if (fProgramKind == Program::kMixer_Kind) {
-            this->write("};\n");
-        }
 
         fOut = oldOut;
         this->write(fFunctionHeader);
diff --git a/src/sksl/SkSLPipelineStageCodeGenerator.h b/src/sksl/SkSLPipelineStageCodeGenerator.h
index df2ca01..9de7a4a 100644
--- a/src/sksl/SkSLPipelineStageCodeGenerator.h
+++ b/src/sksl/SkSLPipelineStageCodeGenerator.h
@@ -44,8 +44,6 @@
 
     void writeIfStatement(const IfStatement& s) override;
 
-    void writeReturnStatement(const ReturnStatement& r) override;
-
     void writeSwitchStatement(const SwitchStatement& s) override;
 
     void writeFunction(const FunctionDefinition& f) override;
@@ -60,7 +58,6 @@
     String fExtraEmitCodeCode;
     std::set<int> fWrittenTransformedCoords;
     std::vector<Compiler::FormatArg>* fFormatArgs;
-    const FunctionDeclaration* fCurrentFunction;
 
     typedef GLSLCodeGenerator INHERITED;
 };
diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp
index c688594..e05327a 100644
--- a/src/sksl/SkSLSPIRVCodeGenerator.cpp
+++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp
@@ -2954,16 +2954,23 @@
 }
 
 void SPIRVCodeGenerator::writeWhileStatement(const WhileStatement& w, OutputStream& out) {
+    // We believe the while loop code below will work, but Skia doesn't actually use them and
+    // adequately testing this code in the absence of Skia exercising it isn't straightforward. For
+    // the time being, we just fail with an error due to the lack of testing. If you encounter this
+    // message, simply remove the error call below to see whether our while loop support actually
+    // works.
+    fErrors.error(w.fOffset, "internal error: while loop support has been disabled in SPIR-V, "
+                  "see SkSLSPIRVCodeGenerator.cpp for details");
+
     SpvId header = this->nextId();
     SpvId start = this->nextId();
     SpvId body = this->nextId();
-    SpvId continueTarget = this->nextId();
-    fContinueTarget.push(continueTarget);
+    fContinueTarget.push(start);
     SpvId end = this->nextId();
     fBreakTarget.push(end);
     this->writeInstruction(SpvOpBranch, header, out);
     this->writeLabel(header, out);
-    this->writeInstruction(SpvOpLoopMerge, end, continueTarget, SpvLoopControlMaskNone, out);
+    this->writeInstruction(SpvOpLoopMerge, end, start, SpvLoopControlMaskNone, out);
     this->writeInstruction(SpvOpBranch, start, out);
     this->writeLabel(start, out);
     SpvId test = this->writeExpression(*w.fTest, out);
@@ -2971,10 +2978,8 @@
     this->writeLabel(body, out);
     this->writeStatement(*w.fStatement, out);
     if (fCurrentBlock) {
-        this->writeInstruction(SpvOpBranch, continueTarget, out);
+        this->writeInstruction(SpvOpBranch, start, out);
     }
-    this->writeLabel(continueTarget, out);
-    this->writeInstruction(SpvOpBranch, header, out);
     this->writeLabel(end, out);
     fBreakTarget.pop();
     fContinueTarget.pop();
@@ -2992,13 +2997,12 @@
     SpvId header = this->nextId();
     SpvId start = this->nextId();
     SpvId next = this->nextId();
-    SpvId continueTarget = this->nextId();
-    fContinueTarget.push(continueTarget);
+    fContinueTarget.push(next);
     SpvId end = this->nextId();
     fBreakTarget.push(end);
     this->writeInstruction(SpvOpBranch, header, out);
     this->writeLabel(header, out);
-    this->writeInstruction(SpvOpLoopMerge, end, continueTarget, SpvLoopControlMaskNone, out);
+    this->writeInstruction(SpvOpLoopMerge, end, start, SpvLoopControlMaskNone, out);
     this->writeInstruction(SpvOpBranch, start, out);
     this->writeLabel(start, out);
     this->writeStatement(*d.fStatement, out);
@@ -3007,9 +3011,7 @@
     }
     this->writeLabel(next, out);
     SpvId test = this->writeExpression(*d.fTest, out);
-    this->writeInstruction(SpvOpBranchConditional, test, continueTarget, end, out);
-    this->writeLabel(continueTarget, out);
-    this->writeInstruction(SpvOpBranch, header, out);
+    this->writeInstruction(SpvOpBranchConditional, test, start, end, out);
     this->writeLabel(end, out);
     fBreakTarget.pop();
     fContinueTarget.pop();
diff --git a/src/sksl/ir/SkSLProgram.h b/src/sksl/ir/SkSLProgram.h
index 8871455..a3c4093 100644
--- a/src/sksl/ir/SkSLProgram.h
+++ b/src/sksl/ir/SkSLProgram.h
@@ -213,8 +213,7 @@
         kVertex_Kind,
         kGeometry_Kind,
         kFragmentProcessor_Kind,
-        kPipelineStage_Kind,
-        kMixer_Kind
+        kPipelineStage_Kind
     };
 
     Program(Kind kind,
diff --git a/src/sksl/sksl_mixer.inc b/src/sksl/sksl_mixer.inc
deleted file mode 100644
index 88143d4..0000000
--- a/src/sksl/sksl_mixer.inc
+++ /dev/null
@@ -1,8 +0,0 @@
-STRINGIFY(
-in fragmentProcessor _child1;
-in fragmentProcessor _child2;
-
-layout(builtin=10004) out half4 sk_OutColor;
-
-half4 process(fragmentProcessor fp);
-)