blob: 510b51fc16e5a438879f8810d1fb814a1d9de59b [file] [log] [blame]
Ethan Nicholas762466e2017-06-29 10:03:38 -04001/*
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
Ethan Nicholas762466e2017-06-29 10:03:38 -040012static void test(skiatest::Reporter* r, const char* src, const GrShaderCaps& caps,
13 std::vector<const char*> expectedH, std::vector<const char*> expectedCPP) {
14 SkSL::Program::Settings settings;
15 settings.fCaps = &caps;
16 SkSL::Compiler compiler;
17 SkSL::StringStream output;
18 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
19 SkSL::Program::kFragmentProcessor_Kind,
Brian Osman93ba0a42017-08-14 14:48:10 -040020 SkSL::String(src),
Ethan Nicholas762466e2017-06-29 10:03:38 -040021 settings);
22 if (!program) {
23 SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
24 return;
25 }
26 REPORTER_ASSERT(r, program);
27 bool success = compiler.toH(*program, "Test", output);
28 if (!success) {
29 SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
30 }
31 REPORTER_ASSERT(r, success);
32 if (success) {
33 for (const char* expected : expectedH) {
34 bool found = strstr(output.str().c_str(), expected);
35 if (!found) {
36 SkDebugf("HEADER MISMATCH:\nsource:\n%s\n\nexpected:\n'%s'\n\nreceived:\n'%s'", src,
37 expected, output.str().c_str());
38 }
39 REPORTER_ASSERT(r, found);
40 }
41 }
42 output.reset();
43 success = compiler.toCPP(*program, "Test", output);
44 if (!success) {
45 SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
46 }
47 REPORTER_ASSERT(r, success);
48 if (success) {
49 for (const char* expected : expectedCPP) {
50 bool found = strstr(output.str().c_str(), expected);
51 if (!found) {
52 SkDebugf("CPP MISMATCH:\nsource:\n%s\n\nexpected:\n'%s'\n\nreceived:\n'%s'", src,
53 expected, output.str().c_str());
54 }
55 REPORTER_ASSERT(r, found);
56 }
57 }
58}
59
60DEF_TEST(SkSLFPHelloWorld, r) {
61 test(r,
Ethan Nicholas130fb3f2018-02-01 12:14:34 -050062 "/* HEADER */"
Ethan Nicholas762466e2017-06-29 10:03:38 -040063 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -040064 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -040065 "}",
66 *SkSL::ShaderCapsFactory::Default(),
67 {
Ethan Nicholas130fb3f2018-02-01 12:14:34 -050068 "/* HEADER */\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -040069 "\n"
Ethan Nicholas130fb3f2018-02-01 12:14:34 -050070 "/**************************************************************************************************\n"
71 " *** This file was autogenerated from GrTest.fp; do not modify.\n"
72 " **************************************************************************************************/\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -040073 "#ifndef GrTest_DEFINED\n"
74 "#define GrTest_DEFINED\n"
Ethan Nicholasceb4d482017-07-10 15:40:20 -040075 "#include \"SkTypes.h\"\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -040076 "#include \"GrFragmentProcessor.h\"\n"
77 "#include \"GrCoordTransform.h\"\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -040078 "class GrTest : public GrFragmentProcessor {\n"
79 "public:\n"
Brian Salomonaff329b2017-08-11 09:40:37 -040080 " static std::unique_ptr<GrFragmentProcessor> Make() {\n"
81 " return std::unique_ptr<GrFragmentProcessor>(new GrTest());\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -040082 " }\n"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -040083 " GrTest(const GrTest& src);\n"
Brian Salomonaff329b2017-08-11 09:40:37 -040084 " std::unique_ptr<GrFragmentProcessor> clone() const override;\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -040085 " const char* name() const override { return \"Test\"; }\n"
86 "private:\n"
87 " GrTest()\n"
Ethan Nicholasabff9562017-10-09 10:54:08 -040088 " : INHERITED(kGrTest_ClassID, kNone_OptimizationFlags) {\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -040089 " }\n"
90 " GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;\n"
91 " void onGetGLSLProcessorKey(const GrShaderCaps&,GrProcessorKeyBuilder*) "
92 "const override;\n"
93 " bool onIsEqual(const GrFragmentProcessor&) const override;\n"
Brian Salomon0c26a9d2017-07-06 10:09:38 -040094 " GR_DECLARE_FRAGMENT_PROCESSOR_TEST\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -040095 " typedef GrFragmentProcessor INHERITED;\n"
96 "};\n"
97 "#endif\n"
98 },
99 {
Ethan Nicholas130fb3f2018-02-01 12:14:34 -0500100 "/* HEADER */\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400101 "\n"
Ethan Nicholas130fb3f2018-02-01 12:14:34 -0500102 "/**************************************************************************************************\n"
103 " *** This file was autogenerated from GrTest.fp; do not modify.\n"
104 " **************************************************************************************************/\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400105 "#include \"GrTest.h\"\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400106 "#include \"glsl/GrGLSLFragmentProcessor.h\"\n"
107 "#include \"glsl/GrGLSLFragmentShaderBuilder.h\"\n"
108 "#include \"glsl/GrGLSLProgramBuilder.h\"\n"
Ethan Nicholas2d5f9b32017-12-13 14:36:14 -0500109 "#include \"GrTexture.h\"\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400110 "#include \"SkSLCPP.h\"\n"
111 "#include \"SkSLUtil.h\"\n"
112 "class GrGLSLTest : public GrGLSLFragmentProcessor {\n"
113 "public:\n"
114 " GrGLSLTest() {}\n"
115 " void emitCode(EmitArgs& args) override {\n"
116 " GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;\n"
117 " const GrTest& _outer = args.fFp.cast<GrTest>();\n"
118 " (void) _outer;\n"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400119 " fragBuilder->codeAppendf(\"%s = half4(1.0);\\n\", args.fOutputColor);\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400120 " }\n"
121 "private:\n"
122 " void onSetData(const GrGLSLProgramDataManager& pdman, "
123 "const GrFragmentProcessor& _proc) override {\n"
124 " }\n"
125 "};\n"
126 "GrGLSLFragmentProcessor* GrTest::onCreateGLSLInstance() const {\n"
127 " return new GrGLSLTest();\n"
128 "}\n"
129 "void GrTest::onGetGLSLProcessorKey(const GrShaderCaps& caps, "
130 "GrProcessorKeyBuilder* b) const {\n"
131 "}\n"
132 "bool GrTest::onIsEqual(const GrFragmentProcessor& other) const {\n"
133 " const GrTest& that = other.cast<GrTest>();\n"
134 " (void) that;\n"
135 " return true;\n"
136 "}\n"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400137 "GrTest::GrTest(const GrTest& src)\n"
Ethan Nicholasabff9562017-10-09 10:54:08 -0400138 ": INHERITED(kGrTest_ClassID, src.optimizationFlags()) {\n"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400139 "}\n"
Brian Salomonaff329b2017-08-11 09:40:37 -0400140 "std::unique_ptr<GrFragmentProcessor> GrTest::clone() const {\n"
141 " return std::unique_ptr<GrFragmentProcessor>(new GrTest(*this));\n"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400142 "}\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400143 });
144}
145
146DEF_TEST(SkSLFPInput, r) {
147 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400148 "in half2 point;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400149 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400150 "sk_OutColor = half4(point, point);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400151 "}",
152 *SkSL::ShaderCapsFactory::Default(),
153 {
Michael Ludwiga4275592018-08-31 10:52:47 -0400154 "const SkPoint& point() const { return fPoint; }",
Brian Salomonaff329b2017-08-11 09:40:37 -0400155 "static std::unique_ptr<GrFragmentProcessor> Make(SkPoint point) {",
156 "return std::unique_ptr<GrFragmentProcessor>(new GrTest(point));",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400157 "GrTest(SkPoint point)",
158 ", fPoint(point)"
159 },
160 {
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400161 "fragBuilder->codeAppendf(\"%s = half4(half2(%f, %f), half2(%f, %f));\\n\", "
Ethan Nicholas762466e2017-06-29 10:03:38 -0400162 "args.fOutputColor, _outer.point().fX, _outer.point().fY, "
163 "_outer.point().fX, _outer.point().fY);",
164 "if (fPoint != that.fPoint) return false;"
165 });
166}
167
168DEF_TEST(SkSLFPUniform, r) {
169 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400170 "uniform half4 color;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400171 "void main() {"
172 "sk_OutColor = color;"
173 "}",
174 *SkSL::ShaderCapsFactory::Default(),
175 {
Brian Salomonaff329b2017-08-11 09:40:37 -0400176 "static std::unique_ptr<GrFragmentProcessor> Make()"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400177 },
178 {
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400179 "fColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
Ethan Nicholas762466e2017-06-29 10:03:38 -0400180 "kDefault_GrSLPrecision, \"color\");",
181 });
182}
183
Michael Ludwiga4275592018-08-31 10:52:47 -0400184// SkSLFPInUniform tests the simplest plumbing case, default type, no tracking
185// with a setUniform template that supports inlining the value call with no
186// local variable.
Ethan Nicholas762466e2017-06-29 10:03:38 -0400187DEF_TEST(SkSLFPInUniform, r) {
188 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400189 "in uniform half4 color;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400190 "void main() {"
191 "sk_OutColor = color;"
192 "}",
193 *SkSL::ShaderCapsFactory::Default(),
194 {
Brian Salomonaff329b2017-08-11 09:40:37 -0400195 "static std::unique_ptr<GrFragmentProcessor> Make(SkRect color) {",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400196 },
197 {
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400198 "fColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
Ethan Nicholas762466e2017-06-29 10:03:38 -0400199 "kDefault_GrSLPrecision, \"color\");",
Michael Ludwiga4275592018-08-31 10:52:47 -0400200 "pdman.set4fv(fColorVar, 1, reinterpret_cast<const float*>(&(_outer.color())));"
201 });
202}
203
204// As above, but tests in uniform's ability to override the default ctype.
205DEF_TEST(SkSLFPInUniformCType, r) {
206 test(r,
207 "layout(ctype=GrColor4f) in uniform half4 color;"
208 "void main() {"
209 "sk_OutColor = color;"
210 "}",
211 *SkSL::ShaderCapsFactory::Default(),
212 {
213 "static std::unique_ptr<GrFragmentProcessor> Make(GrColor4f color) {",
214 },
215 {
216 "fColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
217 "kDefault_GrSLPrecision, \"color\");",
218 "pdman.set4fv(fColorVar, 1, (_outer.color()).fRGBA);"
219 });
220}
221
222// Add state tracking to the default typed SkRect <-> half4 uniform. But since
223// it now has to track state, the value inlining previously done for the
224// setUniform call is removed in favor of a local variable.
225DEF_TEST(SkSLFPTrackedInUniform, r) {
226 test(r,
227 "layout(tracked) in uniform half4 color;"
228 "void main() {"
229 "sk_OutColor = color;"
230 "}",
231 *SkSL::ShaderCapsFactory::Default(),
232 {
233 "static std::unique_ptr<GrFragmentProcessor> Make(SkRect color) {",
234 },
235 {
236 "SkRect fColorPrev = SkRect::MakeEmpty();",
237 "fColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
238 "kDefault_GrSLPrecision, \"color\");",
239 "const SkRect& colorValue = _outer.color();",
240 "if (fColorPrev.isEmpty() || fColorPrev != colorValue) {",
241 "fColorPrev = colorValue;",
242 "pdman.set4fv(fColorVar, 1, reinterpret_cast<const float*>(&colorValue));"
243 });
244}
245
246// Test the case where the template does not support variable inlining in
247// setUniform (i.e. it references the value multiple times).
248DEF_TEST(SkSLFPNonInlinedInUniform, r) {
249 test(r,
250 "in uniform half2 point;"
251 "void main() {"
252 "sk_OutColor = half4(point, point);"
253 "}",
254 *SkSL::ShaderCapsFactory::Default(),
255 {
256 "static std::unique_ptr<GrFragmentProcessor> Make(SkPoint point) {",
257 },
258 {
259 "fPointVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType, "
260 "kDefault_GrSLPrecision, \"point\");",
261 "const SkPoint& pointValue = _outer.point();",
262 "pdman.set2f(fPointVar, pointValue.fX, pointValue.fY);"
263 });
264}
265
266// Test handling conditional uniforms (that use when= in layout), combined with
267// state tracking and custom ctypes to really put the code generation through its paces.
268DEF_TEST(SkSLFPConditionalInUniform, r) {
269 test(r,
270 "in bool test;"
271 "layout(ctype=GrColor4f, tracked, when=test) in uniform half4 color;"
272 "void main() {"
273 " if (test) {"
274 " sk_OutColor = color;"
275 " } else {"
276 " sk_OutColor = half4(1);"
277 " }"
278 "}",
279 *SkSL::ShaderCapsFactory::Default(),
280 {
281 "static std::unique_ptr<GrFragmentProcessor> Make(bool test, GrColor4f color) {",
282 },
283 {
284 "GrColor4f fColorPrev = GrColor4f::kIllegalConstructor",
285 "auto test = _outer.test();",
286 "if (test) {",
287 "fColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
288 "kDefault_GrSLPrecision, \"color\");",
289 "if (fColorVar.isValid()) {",
290 "const GrColor4f& colorValue = _outer.color();",
291 "if (fColorPrev != colorValue) {",
292 "fColorPrev = colorValue;",
293 "pdman.set4fv(fColorVar, 1, colorValue.fRGBA);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400294 });
295}
296
297DEF_TEST(SkSLFPSections, r) {
298 test(r,
299 "@header { header section }"
300 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400301 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400302 "}",
303 *SkSL::ShaderCapsFactory::Default(),
304 {
Greg Daniel3e8c3452018-04-06 10:37:55 -0400305 "header section"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400306 },
307 {});
308 test(r,
309 "@class { class section }"
310 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400311 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400312 "}",
313 *SkSL::ShaderCapsFactory::Default(),
314 {
315 "class GrTest : public GrFragmentProcessor {\n"
316 "public:\n"
317 " class section"
318 },
319 {});
320 test(r,
321 "@cpp { cpp section }"
322 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400323 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400324 "}",
325 *SkSL::ShaderCapsFactory::Default(),
326 {},
327 {"cpp section"});
328 test(r,
329 "@constructorParams { int x, float y, std::vector<float> z }"
Ethan Nicholas8aa45692017-09-20 11:24:15 -0400330 "in float w;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400331 "void main() {"
Ethan Nicholas8aa45692017-09-20 11:24:15 -0400332 "sk_OutColor = float4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400333 "}",
334 *SkSL::ShaderCapsFactory::Default(),
335 {
336 "Make(float w, int x, float y, std::vector<float> z )",
Brian Salomonaff329b2017-08-11 09:40:37 -0400337 "return std::unique_ptr<GrFragmentProcessor>(new GrTest(w, x, y, z));",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400338 "GrTest(float w, int x, float y, std::vector<float> z )",
339 ", fW(w) {"
340 },
341 {});
342 test(r,
343 "@constructor { constructor section }"
344 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400345 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400346 "}",
347 *SkSL::ShaderCapsFactory::Default(),
348 {
349 "private:\n constructor section"
350 },
351 {});
352 test(r,
353 "@initializers { initializers section }"
354 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400355 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400356 "}",
357 *SkSL::ShaderCapsFactory::Default(),
358 {
Ethan Nicholasabff9562017-10-09 10:54:08 -0400359 ": INHERITED(kGrTest_ClassID, kNone_OptimizationFlags)\n , initializers section"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400360 },
361 {});
362 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400363 "half x = 10;"
364 "@emitCode { fragBuilder->codeAppendf(\"half y = %d\\n\", x * 2); }"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400365 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400366 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400367 "}",
368 *SkSL::ShaderCapsFactory::Default(),
369 {},
370 {
371 "x = 10.0;\n"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400372 " fragBuilder->codeAppendf(\"half y = %d\\n\", x * 2);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400373 });
374 test(r,
375 "@fields { fields section }"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400376 "@clone { }"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400377 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400378 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400379 "}",
380 *SkSL::ShaderCapsFactory::Default(),
381 {
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400382 "GR_DECLARE_FRAGMENT_PROCESSOR_TEST\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400383 " fields section typedef GrFragmentProcessor INHERITED;"
384 },
385 {});
386 test(r,
387 "@make { make section }"
388 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400389 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400390 "}",
391 *SkSL::ShaderCapsFactory::Default(),
392 {
393 "public:\n"
394 " make section"
395 },
396 {});
397 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400398 "uniform half calculated;"
399 "in half provided;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400400 "@setData(varName) { varName.set1f(calculated, provided * 2); }"
401 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400402 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400403 "}",
404 *SkSL::ShaderCapsFactory::Default(),
405 {},
406 {
407 "void onSetData(const GrGLSLProgramDataManager& varName, "
408 "const GrFragmentProcessor& _proc) override {\n",
409 "UniformHandle& calculated = fCalculatedVar;",
410 "auto provided = _outer.provided();",
411 "varName.set1f(calculated, provided * 2);"
412 });
413 test(r,
414 "@test(testDataName) { testDataName section }"
415 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400416 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400417 "}",
418 *SkSL::ShaderCapsFactory::Default(),
419 {},
420 {
421 "#if GR_TEST_UTILS\n"
Brian Salomonaff329b2017-08-11 09:40:37 -0400422 "std::unique_ptr<GrFragmentProcessor> GrTest::TestCreate(GrProcessorTestData* testDataName) {\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400423 " testDataName section }\n"
424 "#endif"
425 });
426}
427
Ethan Nicholas762466e2017-06-29 10:03:38 -0400428DEF_TEST(SkSLFPTransformedCoords, r) {
429 test(r,
430 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400431 "sk_OutColor = half4(sk_TransformedCoords2D[0], sk_TransformedCoords2D[0]);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400432 "}",
433 *SkSL::ShaderCapsFactory::Default(),
434 {},
435 {
Brian Osman72a37be2017-08-15 09:19:53 -0400436 "SkString sk_TransformedCoords2D_0 = "
Ethan Nicholas762466e2017-06-29 10:03:38 -0400437 "fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);",
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400438 "fragBuilder->codeAppendf(\"%s = half4(%s, %s);\\n\", args.fOutputColor, "
Ethan Nicholas762466e2017-06-29 10:03:38 -0400439 "sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str());"
440 });
441
442}
443
444DEF_TEST(SkSLFPLayoutWhen, r) {
445 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400446 "layout(when=someExpression(someOtherExpression())) uniform half sometimes;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400447 "void main() {"
448 "}",
449 *SkSL::ShaderCapsFactory::Default(),
450 {},
451 {
452 "if (someExpression(someOtherExpression())) {\n"
453 " fSometimesVar = args.fUniformHandler->addUniform"
454 });
455
456}
457
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400458DEF_TEST(SkSLFPChildProcessors, r) {
459 test(r,
460 "in fragmentProcessor child1;"
461 "in fragmentProcessor child2;"
462 "void main() {"
463 " sk_OutColor = process(child1) * process(child2);"
464 "}",
465 *SkSL::ShaderCapsFactory::Default(),
466 {
467 "this->registerChildProcessor(std::move(child1));",
468 "this->registerChildProcessor(std::move(child2));"
469 },
470 {
471 "SkString _child0(\"_child0\");",
472 "this->emitChild(0, &_child0, args);",
473 "SkString _child1(\"_child1\");",
474 "this->emitChild(1, &_child1, args);",
475 "this->registerChildProcessor(src.childProcessor(0).clone());",
476 "this->registerChildProcessor(src.childProcessor(1).clone());"
477 });
478}
Michael Ludwig92e4c7f2018-08-30 16:08:18 -0400479
480DEF_TEST(SkSLFPChildProcessorsWithInput, r) {
481 test(r,
482 "in fragmentProcessor child1;"
483 "in fragmentProcessor child2;"
484 "void main() {"
485 " half4 childIn = sk_InColor;"
486 " half4 childOut1 = process(child1, childIn);"
487 " half4 childOut2 = process(child2, childOut1);"
488 " sk_OutColor = childOut2;"
489 "}",
490 *SkSL::ShaderCapsFactory::Default(),
491 {
492 "this->registerChildProcessor(std::move(child1));",
493 "this->registerChildProcessor(std::move(child2));"
494 },
495 {
496 "SkString _input0(\"childIn\");",
497 "SkString _child0(\"_child0\");",
498 "this->emitChild(0, _input0.c_str(), &_child0, args);",
499 "SkString _input1(\"childOut1\");",
500 "SkString _child1(\"_child1\");",
501 "this->emitChild(1, _input1.c_str(), &_child1, args);",
502 "this->registerChildProcessor(src.childProcessor(0).clone());",
503 "this->registerChildProcessor(src.childProcessor(1).clone());"
504 });
505}
506
507DEF_TEST(SkSLFPChildProcessorWithInputExpression, r) {
508 test(r,
509 "in fragmentProcessor child;"
510 "void main() {"
511 " sk_OutColor = process(child, sk_InColor * half4(0.5));"
512 "}",
513 *SkSL::ShaderCapsFactory::Default(),
514 {
515 "this->registerChildProcessor(std::move(child));",
516 },
517 {
518 "SkString _input0 = SkStringPrintf(\"%s * half4(0.5)\", args.fInputColor);",
519 "SkString _child0(\"_child0\");",
520 "this->emitChild(0, _input0.c_str(), &_child0, args);",
521 "this->registerChildProcessor(src.childProcessor(0).clone());",
522 });
523}
524
525DEF_TEST(SkSLFPNestedChildProcessors, r) {
526 test(r,
527 "in fragmentProcessor child1;"
528 "in fragmentProcessor child2;"
529 "void main() {"
530 " sk_OutColor = process(child2, sk_InColor * process(child1, sk_InColor * half4(0.5)));"
531 "}",
532 *SkSL::ShaderCapsFactory::Default(),
533 {
534 "this->registerChildProcessor(std::move(child1));",
535 "this->registerChildProcessor(std::move(child2));"
536 },
537 {
538 "SkString _input0 = SkStringPrintf(\"%s * half4(0.5)\", args.fInputColor);",
539 "SkString _child0(\"_child0\");",
540 "this->emitChild(0, _input0.c_str(), &_child0, args);",
541 "SkString _input1 = SkStringPrintf(\"%s * %s\", args.fInputColor, _child0.c_str());",
542 "SkString _child1(\"_child1\");",
543 "this->emitChild(1, _input1.c_str(), &_child1, args);",
544 "this->registerChildProcessor(src.childProcessor(0).clone());",
545 "this->registerChildProcessor(src.childProcessor(1).clone());"
546 });
547}