1 /*
2  * Copyright 2017 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkSLCompiler.h"
9 
10 #include "Test.h"
11 
12 #if SK_SUPPORT_GPU
13 
14 static void test(skiatest::Reporter* r, const char* src, const GrShaderCaps& caps,
15                  std::vector<const char*> expectedH, std::vector<const char*> expectedCPP) {
16     SkSL::Program::Settings settings;
17     settings.fCaps = &caps;
18     SkSL::Compiler compiler;
19     SkSL::StringStream output;
20     std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
21                                                              SkSL::Program::kFragmentProcessor_Kind,
22                                                              SkSL::String(src),
23                                                              settings);
24     if (!program) {
25         SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
26         return;
27     }
28     REPORTER_ASSERT(r, program);
29     bool success = compiler.toH(*program, "Test", output);
30     if (!success) {
31         SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
32     }
33     REPORTER_ASSERT(r, success);
34     if (success) {
35         for (const char* expected : expectedH) {
36             bool found = strstr(output.str().c_str(), expected);
37             if (!found) {
38                 SkDebugf("HEADER MISMATCH:\nsource:\n%s\n\nexpected:\n'%s'\n\nreceived:\n'%s'", src,
39                          expected, output.str().c_str());
40             }
41             REPORTER_ASSERT(r, found);
42         }
43     }
44     output.reset();
45     success = compiler.toCPP(*program, "Test", output);
46     if (!success) {
47         SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
48     }
49     REPORTER_ASSERT(r, success);
50     if (success) {
51         for (const char* expected : expectedCPP) {
52             bool found = strstr(output.str().c_str(), expected);
53             if (!found) {
54                 SkDebugf("CPP MISMATCH:\nsource:\n%s\n\nexpected:\n'%s'\n\nreceived:\n'%s'", src,
55                          expected, output.str().c_str());
56             }
57             REPORTER_ASSERT(r, found);
58         }
59     }
60 }
61 
62 DEF_TEST(SkSLFPHelloWorld, r) {
63     test(r,
64          "/* HEADER */"
65          "void main() {"
66          "sk_OutColor = half4(1);"
67          "}",
68          *SkSL::ShaderCapsFactory::Default(),
69          {
70              "/* HEADER */\n"
71              "\n"
72              "/**************************************************************************************************\n"
73              " *** This file was autogenerated from GrTest.fp; do not modify.\n"
74              " **************************************************************************************************/\n"
75              "#ifndef GrTest_DEFINED\n"
76              "#define GrTest_DEFINED\n"
77              "#include \"SkTypes.h\"\n"
78              "#if SK_SUPPORT_GPU\n"
79              "#include \"GrFragmentProcessor.h\"\n"
80              "#include \"GrCoordTransform.h\"\n"
81              "class GrTest : public GrFragmentProcessor {\n"
82              "public:\n"
83              "    static std::unique_ptr<GrFragmentProcessor> Make() {\n"
84              "        return std::unique_ptr<GrFragmentProcessor>(new GrTest());\n"
85              "    }\n"
86              "    GrTest(const GrTest& src);\n"
87              "    std::unique_ptr<GrFragmentProcessor> clone() const override;\n"
88              "    const char* name() const override { return \"Test\"; }\n"
89              "private:\n"
90              "    GrTest()\n"
91              "    : INHERITED(kGrTest_ClassID, kNone_OptimizationFlags) {\n"
92              "    }\n"
93              "    GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;\n"
94              "    void onGetGLSLProcessorKey(const GrShaderCaps&,GrProcessorKeyBuilder*) "
95                     "const override;\n"
96              "    bool onIsEqual(const GrFragmentProcessor&) const override;\n"
97              "    GR_DECLARE_FRAGMENT_PROCESSOR_TEST\n"
98              "    typedef GrFragmentProcessor INHERITED;\n"
99              "};\n"
100              "#endif\n"
101              "#endif\n"
102          },
103          {
104              "/* HEADER */\n"
105              "\n"
106              "/**************************************************************************************************\n"
107              " *** This file was autogenerated from GrTest.fp; do not modify.\n"
108              " **************************************************************************************************/\n"
109              "#include \"GrTest.h\"\n"
110              "#if SK_SUPPORT_GPU\n"
111              "#include \"glsl/GrGLSLFragmentProcessor.h\"\n"
112              "#include \"glsl/GrGLSLFragmentShaderBuilder.h\"\n"
113              "#include \"glsl/GrGLSLProgramBuilder.h\"\n"
114              "#include \"GrTexture.h\"\n"
115              "#include \"SkSLCPP.h\"\n"
116              "#include \"SkSLUtil.h\"\n"
117              "class GrGLSLTest : public GrGLSLFragmentProcessor {\n"
118              "public:\n"
119              "    GrGLSLTest() {}\n"
120              "    void emitCode(EmitArgs& args) override {\n"
121              "        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;\n"
122              "        const GrTest& _outer = args.fFp.cast<GrTest>();\n"
123              "        (void) _outer;\n"
124              "        fragBuilder->codeAppendf(\"%s = half4(1.0);\\n\", args.fOutputColor);\n"
125              "    }\n"
126              "private:\n"
127              "    void onSetData(const GrGLSLProgramDataManager& pdman, "
128                                 "const GrFragmentProcessor& _proc) override {\n"
129              "    }\n"
130              "};\n"
131              "GrGLSLFragmentProcessor* GrTest::onCreateGLSLInstance() const {\n"
132              "    return new GrGLSLTest();\n"
133              "}\n"
134              "void GrTest::onGetGLSLProcessorKey(const GrShaderCaps& caps, "
135                                                 "GrProcessorKeyBuilder* b) const {\n"
136              "}\n"
137              "bool GrTest::onIsEqual(const GrFragmentProcessor& other) const {\n"
138              "    const GrTest& that = other.cast<GrTest>();\n"
139              "    (void) that;\n"
140              "    return true;\n"
141              "}\n"
142              "GrTest::GrTest(const GrTest& src)\n"
143              ": INHERITED(kGrTest_ClassID, src.optimizationFlags()) {\n"
144              "}\n"
145              "std::unique_ptr<GrFragmentProcessor> GrTest::clone() const {\n"
146              "    return std::unique_ptr<GrFragmentProcessor>(new GrTest(*this));\n"
147              "}\n"
148              "#endif\n"
149          });
150 }
151 
152 DEF_TEST(SkSLFPInput, r) {
153     test(r,
154          "in half2 point;"
155          "void main() {"
156          "sk_OutColor = half4(point, point);"
157          "}",
158          *SkSL::ShaderCapsFactory::Default(),
159          {
160              "SkPoint point() const { return fPoint; }",
161              "static std::unique_ptr<GrFragmentProcessor> Make(SkPoint point) {",
162              "return std::unique_ptr<GrFragmentProcessor>(new GrTest(point));",
163              "GrTest(SkPoint point)",
164              ", fPoint(point)"
165          },
166          {
167              "fragBuilder->codeAppendf(\"%s = half4(half2(%f, %f), half2(%f, %f));\\n\", "
168                                       "args.fOutputColor, _outer.point().fX, _outer.point().fY, "
169                                       "_outer.point().fX, _outer.point().fY);",
170              "if (fPoint != that.fPoint) return false;"
171          });
172 }
173 
174 DEF_TEST(SkSLFPUniform, r) {
175     test(r,
176          "uniform half4 color;"
177          "void main() {"
178          "sk_OutColor = color;"
179          "}",
180          *SkSL::ShaderCapsFactory::Default(),
181          {
182              "static std::unique_ptr<GrFragmentProcessor> Make()"
183          },
184          {
185             "fColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
186                                                          "kDefault_GrSLPrecision, \"color\");",
187          });
188 }
189 
190 DEF_TEST(SkSLFPInUniform, r) {
191     test(r,
192          "in uniform half4 color;"
193          "void main() {"
194          "sk_OutColor = color;"
195          "}",
196          *SkSL::ShaderCapsFactory::Default(),
197          {
198              "static std::unique_ptr<GrFragmentProcessor> Make(SkRect color) {",
199          },
200          {
201             "fColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
202                                                          "kDefault_GrSLPrecision, \"color\");",
203             "const SkRect colorValue = _outer.color();",
204             "pdman.set4fv(fColorVar, 1, (float*) &colorValue);"
205          });
206 }
207 
208 DEF_TEST(SkSLFPSections, r) {
209     test(r,
210          "@header { header section }"
211          "void main() {"
212          "sk_OutColor = half4(1);"
213          "}",
214          *SkSL::ShaderCapsFactory::Default(),
215          {
216              "#if SK_SUPPORT_GPU\n header section"
217          },
218          {});
219     test(r,
220          "@class { class section }"
221          "void main() {"
222          "sk_OutColor = half4(1);"
223          "}",
224          *SkSL::ShaderCapsFactory::Default(),
225          {
226              "class GrTest : public GrFragmentProcessor {\n"
227              "public:\n"
228              " class section"
229          },
230          {});
231     test(r,
232          "@cpp { cpp section }"
233          "void main() {"
234          "sk_OutColor = half4(1);"
235          "}",
236          *SkSL::ShaderCapsFactory::Default(),
237          {},
238          {"cpp section"});
239     test(r,
240          "@constructorParams { int x, float y, std::vector<float> z }"
241          "in float w;"
242          "void main() {"
243          "sk_OutColor = float4(1);"
244          "}",
245          *SkSL::ShaderCapsFactory::Default(),
246          {
247              "Make(float w,  int x, float y, std::vector<float> z )",
248              "return std::unique_ptr<GrFragmentProcessor>(new GrTest(w, x, y, z));",
249              "GrTest(float w,  int x, float y, std::vector<float> z )",
250              ", fW(w) {"
251          },
252          {});
253     test(r,
254          "@constructor { constructor section }"
255          "void main() {"
256          "sk_OutColor = half4(1);"
257          "}",
258          *SkSL::ShaderCapsFactory::Default(),
259          {
260              "private:\n constructor section"
261          },
262          {});
263     test(r,
264          "@initializers { initializers section }"
265          "void main() {"
266          "sk_OutColor = half4(1);"
267          "}",
268          *SkSL::ShaderCapsFactory::Default(),
269          {
270              ": INHERITED(kGrTest_ClassID, kNone_OptimizationFlags)\n    ,  initializers section"
271          },
272          {});
273     test(r,
274          "half x = 10;"
275          "@emitCode { fragBuilder->codeAppendf(\"half y = %d\\n\", x * 2); }"
276          "void main() {"
277          "sk_OutColor = half4(1);"
278          "}",
279          *SkSL::ShaderCapsFactory::Default(),
280          {},
281          {
282             "x = 10.0;\n"
283             " fragBuilder->codeAppendf(\"half y = %d\\n\", x * 2);"
284          });
285     test(r,
286          "@fields { fields section }"
287          "@clone { }"
288          "void main() {"
289          "sk_OutColor = half4(1);"
290          "}",
291          *SkSL::ShaderCapsFactory::Default(),
292          {
293             "GR_DECLARE_FRAGMENT_PROCESSOR_TEST\n"
294             " fields section     typedef GrFragmentProcessor INHERITED;"
295          },
296          {});
297     test(r,
298          "@make { make section }"
299          "void main() {"
300          "sk_OutColor = half4(1);"
301          "}",
302          *SkSL::ShaderCapsFactory::Default(),
303          {
304             "public:\n"
305             " make section"
306          },
307          {});
308     test(r,
309          "uniform half calculated;"
310          "in half provided;"
311          "@setData(varName) { varName.set1f(calculated, provided * 2); }"
312          "void main() {"
313          "sk_OutColor = half4(1);"
314          "}",
315          *SkSL::ShaderCapsFactory::Default(),
316          {},
317          {
318              "void onSetData(const GrGLSLProgramDataManager& varName, "
319                             "const GrFragmentProcessor& _proc) override {\n",
320              "UniformHandle& calculated = fCalculatedVar;",
321              "auto provided = _outer.provided();",
322              "varName.set1f(calculated, provided * 2);"
323          });
324     test(r,
325          "@test(testDataName) { testDataName section }"
326          "void main() {"
327          "sk_OutColor = half4(1);"
328          "}",
329          *SkSL::ShaderCapsFactory::Default(),
330          {},
331          {
332              "#if GR_TEST_UTILS\n"
333              "std::unique_ptr<GrFragmentProcessor> GrTest::TestCreate(GrProcessorTestData* testDataName) {\n"
334              " testDataName section }\n"
335              "#endif"
336          });
337 }
338 
339 DEF_TEST(SkSLFPTransformedCoords, r) {
340     test(r,
341          "void main() {"
342          "sk_OutColor = half4(sk_TransformedCoords2D[0], sk_TransformedCoords2D[0]);"
343          "}",
344          *SkSL::ShaderCapsFactory::Default(),
345          {},
346          {
347             "SkString sk_TransformedCoords2D_0 = "
348                                          "fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);",
349             "fragBuilder->codeAppendf(\"%s = half4(%s, %s);\\n\", args.fOutputColor, "
350                               "sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str());"
351          });
352 
353 }
354 
355 DEF_TEST(SkSLFPLayoutWhen, r) {
356     test(r,
357          "layout(when=someExpression(someOtherExpression())) uniform half sometimes;"
358          "void main() {"
359          "}",
360          *SkSL::ShaderCapsFactory::Default(),
361          {},
362          {
363             "if (someExpression(someOtherExpression())) {\n"
364             "            fSometimesVar = args.fUniformHandler->addUniform"
365          });
366 
367 }
368 
369 DEF_TEST(SkSLFPChildProcessors, r) {
370     test(r,
371          "in fragmentProcessor child1;"
372          "in fragmentProcessor child2;"
373          "void main() {"
374          "    sk_OutColor = process(child1) * process(child2);"
375          "}",
376          *SkSL::ShaderCapsFactory::Default(),
377          {
378             "this->registerChildProcessor(std::move(child1));",
379             "this->registerChildProcessor(std::move(child2));"
380          },
381          {
382             "SkString _child0(\"_child0\");",
383             "this->emitChild(0, &_child0, args);",
384             "SkString _child1(\"_child1\");",
385             "this->emitChild(1, &_child1, args);",
386             "this->registerChildProcessor(src.childProcessor(0).clone());",
387             "this->registerChildProcessor(src.childProcessor(1).clone());"
388          });
389 }
390 
391 #endif
392