fixed sample(..., matrix) with runtime effects

Change-Id: Id5b7f1b5e992c587be000e112706bedfe00c90fd
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/294697
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/src/core/SkRuntimeEffect.cpp b/src/core/SkRuntimeEffect.cpp
index 858baed..68768b5 100644
--- a/src/core/SkRuntimeEffect.cpp
+++ b/src/core/SkRuntimeEffect.cpp
@@ -27,7 +27,6 @@
 #if SK_SUPPORT_GPU
 #include "include/private/GrRecordingContext.h"
 #include "src/gpu/GrColorInfo.h"
-#include "src/gpu/GrFPArgs.h"
 #include "src/gpu/effects/GrMatrixEffect.h"
 #include "src/gpu/effects/GrSkSLFP.h"
 #endif
diff --git a/src/gpu/effects/GrSkSLFP.cpp b/src/gpu/effects/GrSkSLFP.cpp
index a2e9b46..6cab5a8 100644
--- a/src/gpu/effects/GrSkSLFP.cpp
+++ b/src/gpu/effects/GrSkSLFP.cpp
@@ -19,7 +19,7 @@
 
 class GrGLSLSkSLFP : public GrGLSLFragmentProcessor {
 public:
-    GrGLSLSkSLFP(SkSL::PipelineStageArgs&& args) : fArgs(std::move(args)) {}
+    GrGLSLSkSLFP(const SkSL::PipelineStageArgs& args) : fArgs(std::move(args)) {}
 
     SkSL::String expandFormatArgs(const SkSL::String& raw,
                                   EmitArgs& args,
@@ -57,6 +57,13 @@
                                 result += this->invokeChild(arg.fIndex, args, coords).c_str();
                                 break;
                             }
+                            case SkSL::Compiler::FormatArg::Kind::kChildProcessorWithMatrix: {
+                                SkSL::String coords = this->expandFormatArgs(arg.fCoords, args,
+                                                                             fmtArg, coordsName);
+                                result += this->invokeChildWithMatrix(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();
@@ -95,7 +102,8 @@
         // 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) {
-            (void)this->invokeChild(i, args, SkSL::String("_coords"));
+            bool isExplicit = args.fFp.childProcessor(i).isSampledWithExplicitCoords();
+            (void)this->invokeChild(i, args, isExplicit ? SkSL::String("_coords") : "");
         }
         for (const auto& f : fArgs.fFunctions) {
             fFunctionNames.emplace_back();
@@ -181,6 +189,7 @@
         , fName(name)
         , fInputs(std::move(inputs)) {
     this->addCoordTransform(&fCoordTransform);
+    fEffect->toPipelineStage(fInputs->data(), fShaderCaps.get(), fShaderErrorHandler, &fArgs);
 }
 
 GrSkSLFP::GrSkSLFP(const GrSkSLFP& other)
@@ -189,7 +198,8 @@
         , fShaderErrorHandler(other.fShaderErrorHandler)
         , fEffect(other.fEffect)
         , fName(other.fName)
-        , fInputs(other.fInputs) {
+        , fInputs(other.fInputs)
+        , fArgs(other.fArgs) {
     this->addCoordTransform(&fCoordTransform);
 }
 
@@ -198,15 +208,18 @@
 }
 
 void GrSkSLFP::addChild(std::unique_ptr<GrFragmentProcessor> child) {
-    child->setSampledWithExplicitCoords();
+    int newIndex = this->numChildProcessors();
+    if ((int) fArgs.fSampleMatrices.size() > newIndex &&
+        fArgs.fSampleMatrices[newIndex].fKind != SkSL::SampleMatrix::Kind::kNone) {
+        child->setSampleMatrix(fArgs.fSampleMatrices[newIndex]);
+    } else {
+        child->setSampledWithExplicitCoords();
+    }
     this->registerChildProcessor(std::move(child));
 }
 
 GrGLSLFragmentProcessor* GrSkSLFP::onCreateGLSLInstance() const {
-    // Note: This is actually SkSL (again) but with inline format specifiers.
-    SkSL::PipelineStageArgs args;
-    fEffect->toPipelineStage(fInputs->data(), fShaderCaps.get(), fShaderErrorHandler, &args);
-    return new GrGLSLSkSLFP(std::move(args));
+    return new GrGLSLSkSLFP(fArgs);
 }
 
 void GrSkSLFP::onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
diff --git a/src/gpu/effects/GrSkSLFP.h b/src/gpu/effects/GrSkSLFP.h
index 8dc9e30..5b94acd 100644
--- a/src/gpu/effects/GrSkSLFP.h
+++ b/src/gpu/effects/GrSkSLFP.h
@@ -94,9 +94,10 @@
     sk_sp<const GrShaderCaps> fShaderCaps;
     ShaderErrorHandler*       fShaderErrorHandler;
 
-    sk_sp<SkRuntimeEffect> fEffect;
-    const char*            fName;
-    sk_sp<SkData>          fInputs;
+    sk_sp<SkRuntimeEffect>  fEffect;
+    const char*             fName;
+    sk_sp<SkData>           fInputs;
+    SkSL::PipelineStageArgs fArgs;
 
     GrCoordTransform fCoordTransform;
 
diff --git a/src/gpu/glsl/GrGLSLFragmentProcessor.cpp b/src/gpu/glsl/GrGLSLFragmentProcessor.cpp
index 90f50c2..6450907 100644
--- a/src/gpu/glsl/GrGLSLFragmentProcessor.cpp
+++ b/src/gpu/glsl/GrGLSLFragmentProcessor.cpp
@@ -81,6 +81,7 @@
 SkString GrGLSLFragmentProcessor::invokeChildWithMatrix(int childIndex, const char* inputColor,
                                                         EmitArgs& args,
                                                         SkSL::String skslMatrix) {
+    SkASSERT(!args.fFp.isSampledWithExplicitCoords());
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
     while (childIndex >= (int) fFunctionNames.size()) {
         fFunctionNames.emplace_back();
diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h
index 3193197..ee0edb5 100644
--- a/src/sksl/SkSLCompiler.h
+++ b/src/sksl/SkSLCompiler.h
@@ -17,6 +17,7 @@
 #include "src/sksl/SkSLContext.h"
 #include "src/sksl/SkSLErrorReporter.h"
 #include "src/sksl/SkSLLexer.h"
+#include "src/sksl/SkSLSampleMatrix.h"
 #include "src/sksl/ir/SkSLProgram.h"
 #include "src/sksl/ir/SkSLSymbolTable.h"
 
@@ -79,6 +80,7 @@
             kCoords,
             kUniform,
             kChildProcessor,
+            kChildProcessorWithMatrix,
             kFunctionName
         };
 
@@ -245,6 +247,7 @@
     String fCode;
     std::vector<Compiler::FormatArg>    fFormatArgs;
     std::vector<Compiler::GLSLFunction> fFunctions;
+    std::vector<SkSL::SampleMatrix>     fSampleMatrices;
 };
 #endif
 
diff --git a/src/sksl/SkSLPipelineStageCodeGenerator.cpp b/src/sksl/SkSLPipelineStageCodeGenerator.cpp
index a98ad9d..4fa902c 100644
--- a/src/sksl/SkSLPipelineStageCodeGenerator.cpp
+++ b/src/sksl/SkSLPipelineStageCodeGenerator.cpp
@@ -81,8 +81,18 @@
         SkASSERT(found);
         this->write("%s");
         size_t childCallIndex = fArgs->fFormatArgs.size();
+        bool matrixCall = c.fArguments.size() == 2 &&
+                          c.fArguments[1]->fType.kind() == Type::kMatrix_Kind;
         fArgs->fFormatArgs.push_back(
-                Compiler::FormatArg(Compiler::FormatArg::Kind::kChildProcessor, index));
+               Compiler::FormatArg(matrixCall ? Compiler::FormatArg::Kind::kChildProcessorWithMatrix
+                                              : Compiler::FormatArg::Kind::kChildProcessor,
+                                   index));
+        while ((int) fArgs->fSampleMatrices.size() <= index) {
+            fArgs->fSampleMatrices.push_back(SampleMatrix(SampleMatrix::Kind::kNone));
+        }
+        if (matrixCall) {
+            fArgs->fSampleMatrices[index] = SampleMatrix(SampleMatrix::Kind::kVariable);
+        }
         OutputStream* oldOut = fOut;
         StringStream buffer;
         fOut = &buffer;