Reland "Switch runtime SkSL to always sample at explicit coords"

This reverts commit d4bf54eac6243b2b5c2125f6e696d880bbe3ec33.

Change-Id: I65bfea4d880de29394e25d44d781fd18508fe337
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/266942
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/src/effects/imagefilters/SkArithmeticImageFilter.cpp b/src/effects/imagefilters/SkArithmeticImageFilter.cpp
index 5f2a20e..1e91985 100644
--- a/src/effects/imagefilters/SkArithmeticImageFilter.cpp
+++ b/src/effects/imagefilters/SkArithmeticImageFilter.cpp
@@ -36,8 +36,8 @@
 in bool enforcePMColor;
 in fragmentProcessor child;
 
-void main(inout half4 color) {
-    half4 dst = sample(child);
+void main(float x, float y, inout half4 color) {
+    half4 dst = sample(child, float2(x, y));
     color = saturate(half(k.x) * color * dst + half(k.y) * color + half(k.z) * dst + half(k.w));
     @if (enforcePMColor) {
         color.rgb = min(color.rgb, color.a);
diff --git a/src/gpu/effects/GrSkSLFP.cpp b/src/gpu/effects/GrSkSLFP.cpp
index c10bac4..48d3b79 100644
--- a/src/gpu/effects/GrSkSLFP.cpp
+++ b/src/gpu/effects/GrSkSLFP.cpp
@@ -22,13 +22,11 @@
     GrGLSLSkSLFP(SkSL::PipelineStageArgs&& args) : fArgs(std::move(args)) {}
 
     SkSL::String expandFormatArgs(const SkSL::String& raw,
-                                  const EmitArgs& args,
-                                  const std::vector<SkSL::Compiler::FormatArg> formatArgs,
-                                  const char* coordsName,
-                                  const std::vector<SkString>& childNames) {
+                                  EmitArgs& args,
+                                  std::vector<SkSL::Compiler::FormatArg>::const_iterator& fmtArg,
+                                  const char* coordsName) {
         SkSL::String result;
         int substringStartIndex = 0;
-        int formatArgIndex = 0;
         for (size_t i = 0; i < raw.length(); ++i) {
             char c = raw[i];
             if (c == '%') {
@@ -38,7 +36,7 @@
                 c = raw[i];
                 switch (c) {
                     case 's': {
-                        const SkSL::Compiler::FormatArg& arg = formatArgs[formatArgIndex++];
+                        const SkSL::Compiler::FormatArg& arg = *fmtArg++;
                         switch (arg.fKind) {
                             case SkSL::Compiler::FormatArg::Kind::kInput:
                                 result += args.fInputColor;
@@ -58,9 +56,12 @@
                                 result += args.fUniformHandler->getUniformCStr(
                                                                        fUniformHandles[arg.fIndex]);
                                 break;
-                            case SkSL::Compiler::FormatArg::Kind::kChildProcessor:
-                                result += childNames[arg.fIndex].c_str();
+                            case SkSL::Compiler::FormatArg::Kind::kChildProcessor: {
+                                SkSL::String coords = this->expandFormatArgs(arg.fCoords, args,
+                                                                             fmtArg, coordsName);
+                                result += this->invokeChild(arg.fIndex, args, coords).c_str();
                                 break;
+                            }
                             case SkSL::Compiler::FormatArg::Kind::kFunctionName:
                                 SkASSERT((int) fFunctionNames.size() > arg.fIndex);
                                 result += fFunctionNames[arg.fIndex].c_str();
@@ -94,13 +95,17 @@
         SkASSERT(args.fTransformedCoords.count() == 1);
         SkString coords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);
         std::vector<SkString> childNames;
+        // We need to ensure that we call invokeChild on each child FP at least once.
+        // Any child FP that isn't sampled won't trigger a call otherwise, leading to asserts later.
         for (int i = 0; i < this->numChildProcessors(); ++i) {
-            childNames.push_back(this->invokeChild(i, args));
+            (void)this->invokeChild(i, args, SkSL::String("_coords"));
         }
         for (const auto& f : fArgs.fFunctions) {
             fFunctionNames.emplace_back();
-            SkSL::String body = this->expandFormatArgs(f.fBody.c_str(), args, f.fFormatArgs,
-                                                       coords.c_str(), childNames);
+            auto fmtArgIter = f.fFormatArgs.cbegin();
+            SkSL::String body =
+                    this->expandFormatArgs(f.fBody.c_str(), args, fmtArgIter, coords.c_str());
+            SkASSERT(fmtArgIter == f.fFormatArgs.cend());
             fragBuilder->emitFunction(f.fReturnType,
                                       f.fName.c_str(),
                                       f.fParameters.size(),
@@ -108,8 +113,10 @@
                                       body.c_str(),
                                       &fFunctionNames.back());
         }
-        fragBuilder->codeAppend(this->expandFormatArgs(fArgs.fCode.c_str(), args, fArgs.fFormatArgs,
-                                                       coords.c_str(), childNames).c_str());
+        auto fmtArgIter = fArgs.fFormatArgs.cbegin();
+        fragBuilder->codeAppend(this->expandFormatArgs(fArgs.fCode.c_str(), args, fmtArgIter,
+                                                       coords.c_str()).c_str());
+        SkASSERT(fmtArgIter == fArgs.fFormatArgs.cend());
     }
 
     void onSetData(const GrGLSLProgramDataManager& pdman,
@@ -198,6 +205,7 @@
 }
 
 void GrSkSLFP::addChild(std::unique_ptr<GrFragmentProcessor> child) {
+    child->setSampledWithExplicitCoords(true);
     this->registerChildProcessor(std::move(child));
 }
 
@@ -244,7 +252,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->registerChildProcessor(this->childProcessor(i).clone());
+        result->addChild(this->childProcessor(i).clone());
     }
     return std::unique_ptr<GrFragmentProcessor>(result.release());
 }
diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h
index 25762e8..cf657e5 100644
--- a/src/sksl/SkSLCompiler.h
+++ b/src/sksl/SkSLCompiler.h
@@ -92,8 +92,8 @@
                 , fIndex(index) {}
 
         Kind fKind;
-
         int fIndex;
+        String fCoords;
     };
 
 #if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
diff --git a/src/sksl/SkSLPipelineStageCodeGenerator.cpp b/src/sksl/SkSLPipelineStageCodeGenerator.cpp
index 08cedbf..907009d 100644
--- a/src/sksl/SkSLPipelineStageCodeGenerator.cpp
+++ b/src/sksl/SkSLPipelineStageCodeGenerator.cpp
@@ -56,9 +56,10 @@
 void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) {
     if (c.fFunction.fBuiltin && c.fFunction.fName == "sample" &&
         c.fArguments[0]->fType.kind() != Type::Kind::kSampler_Kind) {
-        SkASSERT(c.fArguments.size() == 1);
+        SkASSERT(c.fArguments.size() == 2);
         SkASSERT("fragmentProcessor"  == c.fArguments[0]->fType.name() ||
                  "fragmentProcessor?" == c.fArguments[0]->fType.name());
+        SkASSERT("float2" == c.fArguments[1]->fType.name());
         SkASSERT(Expression::kVariableReference_Kind == c.fArguments[0]->fKind);
         int index = 0;
         bool found = false;
@@ -80,8 +81,15 @@
         }
         SkASSERT(found);
         this->write("%s");
+        size_t childCallIndex = fArgs->fFormatArgs.size();
         fArgs->fFormatArgs.push_back(
                 Compiler::FormatArg(Compiler::FormatArg::Kind::kChildProcessor, index));
+        OutputStream* oldOut = fOut;
+        StringStream buffer;
+        fOut = &buffer;
+        this->writeExpression(*c.fArguments[1], kSequence_Precedence);
+        fOut = oldOut;
+        fArgs->fFormatArgs[childCallIndex].fCoords = buffer.str();
         return;
     }
     if (c.fFunction.fBuiltin) {
diff --git a/src/sksl/sksl_pipeline.inc b/src/sksl/sksl_pipeline.inc
index 56f189e..ff7068b 100644
--- a/src/sksl/sksl_pipeline.inc
+++ b/src/sksl/sksl_pipeline.inc
@@ -1,3 +1,3 @@
 STRINGIFY(
-    half4 sample(fragmentProcessor fp);
+    half4 sample(fragmentProcessor fp, float2 coords);
 )
diff --git a/tools/viewer/SkSLSlide.cpp b/tools/viewer/SkSLSlide.cpp
index c2ca079..01619f8 100644
--- a/tools/viewer/SkSLSlide.cpp
+++ b/tools/viewer/SkSLSlide.cpp
@@ -8,6 +8,7 @@
 #include "tools/viewer/SkSLSlide.h"
 
 #include "include/effects/SkGradientShader.h"
+#include "include/effects/SkPerlinNoiseShader.h"
 #include "src/core/SkEnumerate.h"
 #include "tools/Resources.h"
 #include "tools/viewer/ImGuiLayer.h"
@@ -36,10 +37,10 @@
 
     fSkSL =
 
-        "uniform half4 gColor;\n"
+        "in fragmentProcessor fp;\n"
         "\n"
         "void main(float x, float y, inout half4 color) {\n"
-        "    color = half4(half(x)*(1.0/255), half(y)*(1.0/255), gColor.b, 1);\n"
+        "    color = sample(fp, float2(x, y));\n"
         "}\n";
 }
 
@@ -62,6 +63,9 @@
     shader = GetResourceAsImage("images/mandrill_256.png")->makeShader();
     fShaders.push_back(std::make_pair("Mandrill", shader));
 
+    shader = SkPerlinNoiseShader::MakeImprovedNoise(0.025f, 0.025f, 3, 0.0f);
+    fShaders.push_back(std::make_pair("Perlin Noise", shader));
+
     this->rebuild();
 }