use same signature for shader/colorfilters in sksl

'void main(float x, float y, inout half4 color)'

For colorfilters, x,y are uninitialized
For shaders, color is paint-color

Change-Id: I21c2f570702f117d33646bd8fba0ab4def20a118
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/227439
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Mike Reed <reed@google.com>
diff --git a/gm/runtimecolorfilter.cpp b/gm/runtimecolorfilter.cpp
index 3d8c9e5..6f6dc91 100644
--- a/gm/runtimecolorfilter.cpp
+++ b/gm/runtimecolorfilter.cpp
@@ -28,7 +28,7 @@
 const char* SKSL_TEST_SRC = R"(
     layout(ctype=float) in uniform half b;
 
-    void main(inout half4 color) {
+    void main(float x, float y, inout half4 color) {
         color.a = color.r*0.3 + color.g*0.6 + color.b*0.1;
         color.r = 0;
         color.g = 0;
diff --git a/gm/runtimeshader.cpp b/gm/runtimeshader.cpp
index fa944cb..4e783ec 100644
--- a/gm/runtimeshader.cpp
+++ b/gm/runtimeshader.cpp
@@ -25,13 +25,15 @@
                                             const SkMatrix* localMatrix, bool isOpaque);
 
 const char* gProg = R"(
-    layout(ctype=float) in uniform half4 gColor;
+    layout(ctype=SkRect) in uniform half4 gColor;
 
-    half4 main(in float x, in float y) {
-        return half4(half(x)*(1.0/255), half(y)*(1.0/255), gColor.b, 1);
+    void main(float x, float y, inout half4 color) {
+        color = half4(half(x)*(1.0/255), half(y)*(1.0/255), gColor.b, 1);
     }
 )";
 
+static sk_sp<SkShader> gShader;
+
 class RuntimeShader : public skiagm::GM {
 public:
     RuntimeShader() {
@@ -50,24 +52,26 @@
     }
 
     void onOnceBeforeDraw() override {
-        SkMatrix localM;
-        localM.setRotate(90, 128, 128);
+        // use global to pass gl persistent cache test in dm
+        if (!gShader) {
+            SkMatrix localM;
+            localM.setRotate(90, 128, 128);
 
-        fData = SkData::MakeUninitialized(sizeof(SkColor4f));
-        SkColor4f* c = (SkColor4f*)fData->writable_data();
-        *c = {1, 1, 0, 1};
-        fShader = SkRuntimeShaderMaker(SkString(gProg), fData, &localM, true);
+            fData = SkData::MakeUninitialized(sizeof(SkColor4f));
+            SkColor4f* c = (SkColor4f*)fData->writable_data();
+            *c = {1, 0, 0, 1};
+            gShader = SkRuntimeShaderMaker(SkString(gProg), fData, &localM, true);
+        }
     }
 
     void onDraw(SkCanvas* canvas) override {
         SkPaint p;
-        p.setShader(fShader);
+        p.setShader(gShader);
         canvas->drawRect({0, 0, 256, 256}, p);
     }
 private:
     SkString fName;
     sk_sp<SkData> fData;
-    sk_sp<SkShader> fShader;
 
     typedef skiagm::GM INHERITED;
 };
diff --git a/src/core/SkColorFilter.cpp b/src/core/SkColorFilter.cpp
index a713f3e..f6df121 100644
--- a/src/core/SkColorFilter.cpp
+++ b/src/core/SkColorFilter.cpp
@@ -405,9 +405,10 @@
             rec.fPipeline->append(SkRasterPipeline::callback, ctx);
         } else {
             auto ctx = rec.fAlloc->make<SkRasterPipeline_InterpreterCtx>();
+            // don't need to set ctx->paintColor
             ctx->inputs = fInputs->data();
             ctx->ninputs = fInputs->size() / 4;
-            ctx->shader_convention = false;
+            ctx->shaderConvention = false;
 
             SkAutoMutexExclusive ama(fByteCodeMutex);
             if (!fByteCode) {
diff --git a/src/core/SkRasterPipeline.h b/src/core/SkRasterPipeline.h
index 55df06c..0339819 100644
--- a/src/core/SkRasterPipeline.h
+++ b/src/core/SkRasterPipeline.h
@@ -159,9 +159,10 @@
     SkSL::ByteCode*         byteCode;
     SkSL::ByteCodeFunction* fn;
 
+    SkColor4f   paintColor;
     const void* inputs;
     int         ninputs;
-    bool        shader_convention;  // if false, we're a colorfilter
+    bool        shaderConvention;  // if false, we're a colorfilter
 };
 
 struct SkRasterPipeline_GradientCtx {
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 0cffd76..d633b9b 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -47,7 +47,7 @@
 // This controls the range of values added to color channels
 layout(key) in int rangeType;
 
-void main(int x, int y, inout half4 color) {
+void main(float x, float y, inout half4 color) {
     half value;
     half range;
     @switch (rangeType) {
@@ -73,7 +73,7 @@
     } else {
         // Simulate the integer effect used above using step/mod. For speed, simulates a 4x4
         // dither pattern rather than an 8x8 one.
-        half4 modValues = mod(half4(x, y, x, y), half4(2.0, 2.0, 4.0, 4.0));
+        half4 modValues = mod(half4(half(x), half(y), half(x), half(y)), half4(2.0, 2.0, 4.0, 4.0));
         half4 stepValues = step(modValues, half4(1.0, 1.0, 2.0, 2.0));
         value = dot(stepValues, half4(8.0 / 16.0, 4.0 / 16.0, 2.0 / 16.0, 1.0 / 16.0)) - 15.0 / 32.0;
     }
diff --git a/src/opts/SkRasterPipeline_opts.h b/src/opts/SkRasterPipeline_opts.h
index b090618..fe275a1 100644
--- a/src/opts/SkRasterPipeline_opts.h
+++ b/src/opts/SkRasterPipeline_opts.h
@@ -2555,31 +2555,33 @@
     load4(c->read_from,0, &r,&g,&b,&a);
 }
 
+// void main(int x, int h, inout half4 color)
 STAGE(interpreter, SkRasterPipeline_InterpreterCtx* c) {
     // If N is less than the interpreter's VecWidth, then we are doing more work than necessary in
     // the interpreter. This is a known issue, and will be addressed at some point.
-    float rr[N];
-    float gg[N];
-    float bb[N];
-    float aa[N];
-    size_t in_count, out_count;
+    float xx[N], yy[N],
+          rr[N], gg[N], bb[N], aa[N];
 
-    float* args[] = { rr, gg, bb, aa };
+    float* args[]  = { xx, yy, rr, gg, bb, aa };
 
-    sk_unaligned_store(rr, r);  // x if we're a shader
-    sk_unaligned_store(gg, g);  // y if we're a shader
-    if (c->shader_convention) {
-        in_count = 2;   // x, y
-        out_count = 4;  // r, g, b, a
+    if (c->shaderConvention) {
+        // our caller must have called seed_shader to set these
+        sk_unaligned_store(xx, r);
+        sk_unaligned_store(yy, g);
+        sk_unaligned_store(rr, F(c->paintColor.fR));
+        sk_unaligned_store(gg, F(c->paintColor.fG));
+        sk_unaligned_store(bb, F(c->paintColor.fB));
+        sk_unaligned_store(aa, F(c->paintColor.fA));
     } else {
-        in_count = 4;   // r, g, b, a (in/out)
+        // leave xx,yy uninitialized for colorfilters
+        sk_unaligned_store(rr, r);
+        sk_unaligned_store(gg, g);
         sk_unaligned_store(bb, b);
         sk_unaligned_store(aa, a);
-        out_count = 0;
     }
 
-    c->byteCode->runStriped(c->fn, args, in_count, tail ? tail : N,
-                            (const float*)c->inputs, c->ninputs, args, out_count);
+    c->byteCode->runStriped(c->fn, args, 6, tail ? tail : N,
+                            (const float*)c->inputs, c->ninputs, nullptr, 0);
 
     r = sk_unaligned_load<F>(rr);
     g = sk_unaligned_load<F>(gg);
diff --git a/src/shaders/SkRTShader.cpp b/src/shaders/SkRTShader.cpp
index bd5586e..565d7bc 100644
--- a/src/shaders/SkRTShader.cpp
+++ b/src/shaders/SkRTShader.cpp
@@ -12,33 +12,44 @@
 #include "src/core/SkReadBuffer.h"
 #include "src/core/SkWriteBuffer.h"
 
+#include "src/sksl/SkSLByteCode.h"
+#include "src/sksl/SkSLCompiler.h"
+
 #if SK_SUPPORT_GPU
+#include "include/private/GrRecordingContext.h"
+#include "src/gpu/GrCaps.h"
+#include "src/gpu/GrColorSpaceInfo.h"
+#include "src/gpu/GrRecordingContextPriv.h"
+#include "src/gpu/SkGr.h"
+
 #include "src/gpu/GrFragmentProcessor.h"
 #include "src/gpu/effects/generated/GrMixerEffect.h"
 #include "src/gpu/effects/GrSkSLFP.h"
-#endif
 
-#include "src/sksl/SkSLByteCode.h"
-#include "src/sksl/SkSLCompiler.h"
+static inline uint32_t new_sksl_unique_id() {
+    return GrSkSLFP::NewIndex();
+}
+#else
+static inline uint32_t new_sksl_unique_id() {
+    return 0;   // not used w/o GPU
+}
+#endif
 
 SkRTShader::SkRTShader(SkString sksl, sk_sp<SkData> inputs, const SkMatrix* localMatrix,
                        bool isOpaque)
     : SkShaderBase(localMatrix)
     , fSkSL(std::move(sksl))
     , fInputs(std::move(inputs))
+    , fUniqueID(new_sksl_unique_id())
     , fIsOpaque(isOpaque)
 {}
 
 bool SkRTShader::onAppendStages(const SkStageRec& rec) const {
-    SkMatrix inverse;
-    if (!this->computeTotalInverse(rec.fCTM, rec.fLocalM, &inverse)) {
-        return false;
-    }
-
     auto ctx = rec.fAlloc->make<SkRasterPipeline_InterpreterCtx>();
+    ctx->paintColor = rec.fPaint.getColor4f();
     ctx->inputs = fInputs->data();
     ctx->ninputs = fInputs->size() / 4;
-    ctx->shader_convention = true;
+    ctx->shaderConvention = true;
 
     SkAutoMutexExclusive ama(fByteCodeMutex);
     if (!fByteCode) {
@@ -61,7 +72,6 @@
     ctx->fn = ctx->byteCode->fFunctions[0].get();
 
     rec.fPipeline->append(SkRasterPipeline::seed_shader);
-    rec.fPipeline->append_matrix(rec.fAlloc, inverse);
     rec.fPipeline->append(SkRasterPipeline::interpreter, ctx);
     return true;
 }
@@ -114,3 +124,11 @@
     return sk_sp<SkShader>(new SkRTShader(std::move(sksl), std::move(inputs),
                                           localMatrix, isOpaque));
 }
+
+#if SK_SUPPORT_GPU
+std::unique_ptr<GrFragmentProcessor> SkRTShader::asFragmentProcessor(const GrFPArgs& args) const {
+    return GrSkSLFP::Make(args.fContext, fUniqueID, "runtime-shader", fSkSL,
+                          fInputs->data(), fInputs->size());
+}
+#endif
+
diff --git a/src/shaders/SkRTShader.h b/src/shaders/SkRTShader.h
index 6bd4447..a25e930 100644
--- a/src/shaders/SkRTShader.h
+++ b/src/shaders/SkRTShader.h
@@ -24,15 +24,12 @@
 public:
     SkRTShader(SkString sksl, sk_sp<SkData> inputs, const SkMatrix* localMatrix, bool isOpaque);
 
-#if SK_SUPPORT_GPU
-    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(const GrFPArgs&) const override {
-        // TODO
-        return nullptr;
-    }
-#endif
-
     bool isOpaque() const override { return fIsOpaque; }
 
+#if SK_SUPPORT_GPU
+    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(const GrFPArgs&) const override;
+#endif
+
 protected:
     void flatten(SkWriteBuffer&) const override;
     bool onAppendStages(const SkStageRec& rec) const override;
@@ -42,6 +39,7 @@
 
     SkString fSkSL;
     sk_sp<SkData> fInputs;
+    const uint32_t fUniqueID;
     const bool fIsOpaque;
 
     mutable SkMutex fByteCodeMutex;
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index c5f3c1d..ea573ad 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -756,9 +756,9 @@
                 bool valid;
                 switch (parameters.size()) {
                     case 3:
-                        valid = parameters[0]->fType == *fContext.fInt_Type &&
+                        valid = parameters[0]->fType == *fContext.fFloat_Type &&
                                 parameters[0]->fModifiers.fFlags == 0 &&
-                                parameters[1]->fType == *fContext.fInt_Type &&
+                                parameters[1]->fType == *fContext.fFloat_Type &&
                                 parameters[1]->fModifiers.fFlags == 0 &&
                                 parameters[2]->fType == *fContext.fHalf4_Type &&
                                 parameters[2]->fModifiers.fFlags == (Modifiers::kIn_Flag |
@@ -773,8 +773,8 @@
                         valid = false;
                 }
                 if (!valid) {
-                    fErrors.error(f.fOffset, "pipeline stage 'main' must be declared main(int, "
-                                             "int, inout half4) or main(inout half4)");
+                    fErrors.error(f.fOffset, "pipeline stage 'main' must be declared main(float, "
+                                             "float, inout half4) or main(inout half4)");
                     return;
                 }
                 break;