blob: 753aaf8d7722d494ca3d1f4f9d917a3946b2ecc0 [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/sksl/SkSLCompiler.h"
Ethan Nicholasfc994162019-06-06 10:04:27 -04009#include "src/sksl/SkSLStringStream.h"
Ethan Nicholas762466e2017-06-29 10:03:38 -040010
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "tests/Test.h"
Ethan Nicholas762466e2017-06-29 10:03:38 -040012
Ethan Nicholas762466e2017-06-29 10:03:38 -040013static void test(skiatest::Reporter* r, const char* src, const GrShaderCaps& caps,
14 std::vector<const char*> expectedH, std::vector<const char*> expectedCPP) {
15 SkSL::Program::Settings settings;
16 settings.fCaps = &caps;
17 SkSL::Compiler compiler;
18 SkSL::StringStream output;
19 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
20 SkSL::Program::kFragmentProcessor_Kind,
Brian Osman93ba0a42017-08-14 14:48:10 -040021 SkSL::String(src),
Ethan Nicholas762466e2017-06-29 10:03:38 -040022 settings);
23 if (!program) {
24 SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
25 return;
26 }
27 REPORTER_ASSERT(r, program);
28 bool success = compiler.toH(*program, "Test", output);
29 if (!success) {
30 SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
31 }
32 REPORTER_ASSERT(r, success);
33 if (success) {
34 for (const char* expected : expectedH) {
35 bool found = strstr(output.str().c_str(), expected);
36 if (!found) {
37 SkDebugf("HEADER MISMATCH:\nsource:\n%s\n\nexpected:\n'%s'\n\nreceived:\n'%s'", src,
38 expected, output.str().c_str());
39 }
40 REPORTER_ASSERT(r, found);
41 }
42 }
43 output.reset();
44 success = compiler.toCPP(*program, "Test", output);
45 if (!success) {
46 SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
47 }
48 REPORTER_ASSERT(r, success);
49 if (success) {
50 for (const char* expected : expectedCPP) {
51 bool found = strstr(output.str().c_str(), expected);
52 if (!found) {
53 SkDebugf("CPP MISMATCH:\nsource:\n%s\n\nexpected:\n'%s'\n\nreceived:\n'%s'", src,
54 expected, output.str().c_str());
55 }
56 REPORTER_ASSERT(r, found);
57 }
58 }
59}
60
Ethan Nicholas33c59ed2019-08-13 10:21:38 -040061static void test_failure(skiatest::Reporter* r, const char* src, const char* error) {
62 SkSL::Compiler compiler;
63 SkSL::Program::Settings settings;
64 sk_sp<GrShaderCaps> caps = SkSL::ShaderCapsFactory::Default();
65 settings.fCaps = caps.get();
66 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
67 SkSL::Program::kFragmentProcessor_Kind,
68 SkSL::String(src),
69 settings);
70 if (!compiler.errorCount()) {
71 compiler.optimize(*program);
72 }
73 SkSL::String skError(error);
74 if (compiler.errorText() != skError) {
75 SkDebugf("SKSL ERROR:\n source: %s\n expected: %s received: %s", src, error,
76 compiler.errorText().c_str());
77 }
78 REPORTER_ASSERT(r, compiler.errorText() == skError);
79}
80
Ethan Nicholas762466e2017-06-29 10:03:38 -040081DEF_TEST(SkSLFPHelloWorld, r) {
82 test(r,
Ethan Nicholas130fb3f2018-02-01 12:14:34 -050083 "/* HEADER */"
Ethan Nicholas762466e2017-06-29 10:03:38 -040084 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -040085 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -040086 "}",
87 *SkSL::ShaderCapsFactory::Default(),
88 {
Ethan Nicholas130fb3f2018-02-01 12:14:34 -050089 "/* HEADER */\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -040090 "\n"
Ethan Nicholas130fb3f2018-02-01 12:14:34 -050091 "/**************************************************************************************************\n"
92 " *** This file was autogenerated from GrTest.fp; do not modify.\n"
93 " **************************************************************************************************/\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -040094 "#ifndef GrTest_DEFINED\n"
95 "#define GrTest_DEFINED\n"
Mike Reed55f6fc32020-01-21 12:23:51 -050096 "#include \"include/core/SkTypes.h\"\n"
Mike Reedb26b4e72020-01-22 14:31:21 -050097 "#include \"include/private/SkM44.h\"\n\n"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050098 "#include \"src/gpu/GrCoordTransform.h\"\n"
99 "#include \"src/gpu/GrFragmentProcessor.h\"\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400100 "class GrTest : public GrFragmentProcessor {\n"
101 "public:\n"
Brian Salomonaff329b2017-08-11 09:40:37 -0400102 " static std::unique_ptr<GrFragmentProcessor> Make() {\n"
103 " return std::unique_ptr<GrFragmentProcessor>(new GrTest());\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400104 " }\n"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400105 " GrTest(const GrTest& src);\n"
Brian Salomonaff329b2017-08-11 09:40:37 -0400106 " std::unique_ptr<GrFragmentProcessor> clone() const override;\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400107 " const char* name() const override { return \"Test\"; }\n"
108 "private:\n"
109 " GrTest()\n"
Ethan Nicholasabff9562017-10-09 10:54:08 -0400110 " : INHERITED(kGrTest_ClassID, kNone_OptimizationFlags) {\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400111 " }\n"
112 " GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;\n"
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400113 " void onGetGLSLProcessorKey(const GrShaderCaps&,GrProcessorKeyBuilder*) const "
114 "override;\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400115 " bool onIsEqual(const GrFragmentProcessor&) const override;\n"
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400116 " GR_DECLARE_FRAGMENT_PROCESSOR_TEST\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400117 " typedef GrFragmentProcessor INHERITED;\n"
118 "};\n"
119 "#endif\n"
120 },
121 {
Ethan Nicholas130fb3f2018-02-01 12:14:34 -0500122 "/**************************************************************************************************\n"
123 " *** This file was autogenerated from GrTest.fp; do not modify.\n"
124 " **************************************************************************************************/\n"
Mike Kleinc0bd9f92019-04-23 12:05:21 -0500125 "#include \"GrTest.h\"\n\n"
126 "#include \"include/gpu/GrTexture.h\"\n"
127 "#include \"src/gpu/glsl/GrGLSLFragmentProcessor.h\"\n"
128 "#include \"src/gpu/glsl/GrGLSLFragmentShaderBuilder.h\"\n"
129 "#include \"src/gpu/glsl/GrGLSLProgramBuilder.h\"\n"
130 "#include \"src/sksl/SkSLCPP.h\"\n"
131 "#include \"src/sksl/SkSLUtil.h\"\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400132 "class GrGLSLTest : public GrGLSLFragmentProcessor {\n"
133 "public:\n"
134 " GrGLSLTest() {}\n"
135 " void emitCode(EmitArgs& args) override {\n"
136 " GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;\n"
137 " const GrTest& _outer = args.fFp.cast<GrTest>();\n"
138 " (void) _outer;\n"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400139 " fragBuilder->codeAppendf(\"%s = half4(1.0);\\n\", args.fOutputColor);\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400140 " }\n"
141 "private:\n"
142 " void onSetData(const GrGLSLProgramDataManager& pdman, "
143 "const GrFragmentProcessor& _proc) override {\n"
144 " }\n"
145 "};\n"
146 "GrGLSLFragmentProcessor* GrTest::onCreateGLSLInstance() const {\n"
147 " return new GrGLSLTest();\n"
148 "}\n"
149 "void GrTest::onGetGLSLProcessorKey(const GrShaderCaps& caps, "
150 "GrProcessorKeyBuilder* b) const {\n"
151 "}\n"
152 "bool GrTest::onIsEqual(const GrFragmentProcessor& other) const {\n"
153 " const GrTest& that = other.cast<GrTest>();\n"
154 " (void) that;\n"
155 " return true;\n"
156 "}\n"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400157 "GrTest::GrTest(const GrTest& src)\n"
Ethan Nicholasabff9562017-10-09 10:54:08 -0400158 ": INHERITED(kGrTest_ClassID, src.optimizationFlags()) {\n"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400159 "}\n"
Brian Salomonaff329b2017-08-11 09:40:37 -0400160 "std::unique_ptr<GrFragmentProcessor> GrTest::clone() const {\n"
161 " return std::unique_ptr<GrFragmentProcessor>(new GrTest(*this));\n"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400162 "}\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400163 });
164}
165
166DEF_TEST(SkSLFPInput, r) {
167 test(r,
Ethan Nicholas33c59ed2019-08-13 10:21:38 -0400168 "layout(key) in half2 point;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400169 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400170 "sk_OutColor = half4(point, point);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400171 "}",
172 *SkSL::ShaderCapsFactory::Default(),
173 {
Brian Salomonaff329b2017-08-11 09:40:37 -0400174 "static std::unique_ptr<GrFragmentProcessor> Make(SkPoint point) {",
175 "return std::unique_ptr<GrFragmentProcessor>(new GrTest(point));",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400176 "GrTest(SkPoint point)",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400177 ", point(point)"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400178 },
179 {
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400180 "fragBuilder->codeAppendf(\"%s = half4(half2(%f, %f), half2(%f, %f));\\n\", "
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400181 "args.fOutputColor, _outer.point.fX, _outer.point.fY, "
182 "_outer.point.fX, _outer.point.fY);",
183 "if (point != that.point) return false;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400184 });
185}
186
187DEF_TEST(SkSLFPUniform, r) {
188 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400189 "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()"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400196 },
197 {
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400198 "colorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
199 "\"color\");",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400200 });
201}
202
Michael Ludwiga4275592018-08-31 10:52:47 -0400203// SkSLFPInUniform tests the simplest plumbing case, default type, no tracking
204// with a setUniform template that supports inlining the value call with no
205// local variable.
Ethan Nicholas762466e2017-06-29 10:03:38 -0400206DEF_TEST(SkSLFPInUniform, r) {
207 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400208 "in uniform half4 color;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400209 "void main() {"
210 "sk_OutColor = color;"
211 "}",
212 *SkSL::ShaderCapsFactory::Default(),
213 {
Brian Salomonaff329b2017-08-11 09:40:37 -0400214 "static std::unique_ptr<GrFragmentProcessor> Make(SkRect color) {",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400215 },
216 {
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400217 "colorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
218 "\"color\");",
219 "pdman.set4fv(colorVar, 1, reinterpret_cast<const float*>(&(_outer.color)));"
Michael Ludwiga4275592018-08-31 10:52:47 -0400220 });
221}
222
223// As above, but tests in uniform's ability to override the default ctype.
224DEF_TEST(SkSLFPInUniformCType, r) {
225 test(r,
Brian Osman495993a2018-10-16 15:45:55 -0400226 "layout(ctype=SkPMColor4f) in uniform half4 color;"
Michael Ludwiga4275592018-08-31 10:52:47 -0400227 "void main() {"
228 "sk_OutColor = color;"
229 "}",
230 *SkSL::ShaderCapsFactory::Default(),
231 {
Brian Osman495993a2018-10-16 15:45:55 -0400232 "static std::unique_ptr<GrFragmentProcessor> Make(SkPMColor4f color) {",
Michael Ludwiga4275592018-08-31 10:52:47 -0400233 },
234 {
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400235 "colorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
236 "\"color\");",
237 "pdman.set4fv(colorVar, 1, (_outer.color).vec());"
Michael Ludwiga4275592018-08-31 10:52:47 -0400238 });
239}
240
241// Add state tracking to the default typed SkRect <-> half4 uniform. But since
242// it now has to track state, the value inlining previously done for the
243// setUniform call is removed in favor of a local variable.
244DEF_TEST(SkSLFPTrackedInUniform, r) {
245 test(r,
246 "layout(tracked) in uniform half4 color;"
247 "void main() {"
248 "sk_OutColor = color;"
249 "}",
250 *SkSL::ShaderCapsFactory::Default(),
251 {
252 "static std::unique_ptr<GrFragmentProcessor> Make(SkRect color) {",
253 },
254 {
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400255 "SkRect colorPrev = SkRect::MakeEmpty();",
256 "colorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
257 "\"color\");",
258 "const SkRect& colorValue = _outer.color;",
259 "if (colorPrev.isEmpty() || colorPrev != colorValue) {",
260 "colorPrev = colorValue;",
261 "pdman.set4fv(colorVar, 1, reinterpret_cast<const float*>(&colorValue));"
Michael Ludwiga4275592018-08-31 10:52:47 -0400262 });
263}
264
265// Test the case where the template does not support variable inlining in
266// setUniform (i.e. it references the value multiple times).
267DEF_TEST(SkSLFPNonInlinedInUniform, r) {
268 test(r,
269 "in uniform half2 point;"
270 "void main() {"
271 "sk_OutColor = half4(point, point);"
272 "}",
273 *SkSL::ShaderCapsFactory::Default(),
274 {
275 "static std::unique_ptr<GrFragmentProcessor> Make(SkPoint point) {",
276 },
277 {
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400278 "pointVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType, "
279 "\"point\");",
280 "const SkPoint& pointValue = _outer.point;",
281 "pdman.set2f(pointVar, pointValue.fX, pointValue.fY);"
Michael Ludwiga4275592018-08-31 10:52:47 -0400282 });
283}
284
285// Test handling conditional uniforms (that use when= in layout), combined with
286// state tracking and custom ctypes to really put the code generation through its paces.
287DEF_TEST(SkSLFPConditionalInUniform, r) {
288 test(r,
Ethan Nicholas33c59ed2019-08-13 10:21:38 -0400289 "layout(key) in bool test;"
Brian Osman495993a2018-10-16 15:45:55 -0400290 "layout(ctype=SkPMColor4f, tracked, when=test) in uniform half4 color;"
Michael Ludwiga4275592018-08-31 10:52:47 -0400291 "void main() {"
292 " if (test) {"
293 " sk_OutColor = color;"
294 " } else {"
295 " sk_OutColor = half4(1);"
296 " }"
297 "}",
298 *SkSL::ShaderCapsFactory::Default(),
299 {
Brian Osman495993a2018-10-16 15:45:55 -0400300 "static std::unique_ptr<GrFragmentProcessor> Make(bool test, SkPMColor4f color) {",
Michael Ludwiga4275592018-08-31 10:52:47 -0400301 },
302 {
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400303 "SkPMColor4f colorPrev = {SK_FloatNaN, SK_FloatNaN, SK_FloatNaN, SK_FloatNaN}",
304 "auto test = _outer.test;",
Michael Ludwiga4275592018-08-31 10:52:47 -0400305 "if (test) {",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400306 "colorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
307 "\"color\");",
308 "if (colorVar.isValid()) {",
309 "const SkPMColor4f& colorValue = _outer.color;",
310 "if (colorPrev != colorValue) {",
311 "colorPrev = colorValue;",
312 "pdman.set4fv(colorVar, 1, colorValue.vec());"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400313 });
314}
315
316DEF_TEST(SkSLFPSections, r) {
317 test(r,
318 "@header { header section }"
319 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400320 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400321 "}",
322 *SkSL::ShaderCapsFactory::Default(),
323 {
Greg Daniel3e8c3452018-04-06 10:37:55 -0400324 "header section"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400325 },
326 {});
327 test(r,
328 "@class { class section }"
329 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400330 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400331 "}",
332 *SkSL::ShaderCapsFactory::Default(),
333 {
334 "class GrTest : public GrFragmentProcessor {\n"
335 "public:\n"
336 " class section"
337 },
338 {});
339 test(r,
340 "@cpp { cpp section }"
341 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400342 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400343 "}",
344 *SkSL::ShaderCapsFactory::Default(),
345 {},
346 {"cpp section"});
347 test(r,
348 "@constructorParams { int x, float y, std::vector<float> z }"
Ethan Nicholas8aa45692017-09-20 11:24:15 -0400349 "in float w;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400350 "void main() {"
Ethan Nicholase1f55022019-02-05 17:17:40 -0500351 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400352 "}",
353 *SkSL::ShaderCapsFactory::Default(),
354 {
355 "Make(float w, int x, float y, std::vector<float> z )",
Brian Salomonaff329b2017-08-11 09:40:37 -0400356 "return std::unique_ptr<GrFragmentProcessor>(new GrTest(w, x, y, z));",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400357 "GrTest(float w, int x, float y, std::vector<float> z )",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400358 ", w(w) {"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400359 },
360 {});
361 test(r,
362 "@constructor { constructor section }"
363 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400364 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400365 "}",
366 *SkSL::ShaderCapsFactory::Default(),
367 {
368 "private:\n constructor section"
369 },
370 {});
371 test(r,
372 "@initializers { initializers section }"
373 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400374 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400375 "}",
376 *SkSL::ShaderCapsFactory::Default(),
377 {
Ethan Nicholasabff9562017-10-09 10:54:08 -0400378 ": INHERITED(kGrTest_ClassID, kNone_OptimizationFlags)\n , initializers section"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400379 },
380 {});
381 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400382 "half x = 10;"
383 "@emitCode { fragBuilder->codeAppendf(\"half y = %d\\n\", x * 2); }"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400384 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400385 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400386 "}",
387 *SkSL::ShaderCapsFactory::Default(),
388 {},
389 {
390 "x = 10.0;\n"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400391 " fragBuilder->codeAppendf(\"half y = %d\\n\", x * 2);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400392 });
393 test(r,
394 "@fields { fields section }"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400395 "@clone { }"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400396 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400397 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400398 "}",
399 *SkSL::ShaderCapsFactory::Default(),
400 {
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400401 "const char* name() const override { return \"Test\"; }\n"
402 " fields section private:"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400403 },
404 {});
405 test(r,
406 "@make { make section }"
407 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400408 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400409 "}",
410 *SkSL::ShaderCapsFactory::Default(),
411 {
412 "public:\n"
413 " make section"
414 },
415 {});
416 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400417 "uniform half calculated;"
Ethan Nicholas33c59ed2019-08-13 10:21:38 -0400418 "layout(key) in half provided;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400419 "@setData(varName) { varName.set1f(calculated, provided * 2); }"
420 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400421 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400422 "}",
423 *SkSL::ShaderCapsFactory::Default(),
424 {},
425 {
426 "void onSetData(const GrGLSLProgramDataManager& varName, "
427 "const GrFragmentProcessor& _proc) override {\n",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400428 "UniformHandle& calculated = calculatedVar;",
429 "auto provided = _outer.provided;",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400430 "varName.set1f(calculated, provided * 2);"
431 });
432 test(r,
433 "@test(testDataName) { testDataName section }"
434 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400435 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400436 "}",
437 *SkSL::ShaderCapsFactory::Default(),
438 {},
439 {
440 "#if GR_TEST_UTILS\n"
Brian Salomonaff329b2017-08-11 09:40:37 -0400441 "std::unique_ptr<GrFragmentProcessor> GrTest::TestCreate(GrProcessorTestData* testDataName) {\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400442 " testDataName section }\n"
443 "#endif"
444 });
445}
446
Ethan Nicholas762466e2017-06-29 10:03:38 -0400447DEF_TEST(SkSLFPTransformedCoords, r) {
448 test(r,
449 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400450 "sk_OutColor = half4(sk_TransformedCoords2D[0], sk_TransformedCoords2D[0]);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400451 "}",
452 *SkSL::ShaderCapsFactory::Default(),
453 {},
454 {
Brian Osman72a37be2017-08-15 09:19:53 -0400455 "SkString sk_TransformedCoords2D_0 = "
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400456 "fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);",
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400457 "fragBuilder->codeAppendf(\"%s = half4(%s, %s);\\n\", args.fOutputColor, "
Brian Salomonbf5c0c02019-11-11 14:55:28 -0500458 "sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str());"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400459 });
460
461}
462
463DEF_TEST(SkSLFPLayoutWhen, r) {
464 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400465 "layout(when=someExpression(someOtherExpression())) uniform half sometimes;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400466 "void main() {"
467 "}",
468 *SkSL::ShaderCapsFactory::Default(),
469 {},
470 {
471 "if (someExpression(someOtherExpression())) {\n"
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400472 " sometimesVar = args.fUniformHandler->addUniform"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400473 });
474
475}
476
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400477DEF_TEST(SkSLFPChildProcessors, r) {
478 test(r,
479 "in fragmentProcessor child1;"
480 "in fragmentProcessor child2;"
481 "void main() {"
Ethan Nicholas13863662019-07-29 13:05:15 -0400482 " sk_OutColor = sample(child1) * sample(child2);"
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400483 "}",
484 *SkSL::ShaderCapsFactory::Default(),
485 {
486 "this->registerChildProcessor(std::move(child1));",
487 "this->registerChildProcessor(std::move(child2));"
488 },
489 {
Brian Osman978693c2020-01-24 14:52:10 -0500490 "SkString _sample93;\n",
491 "_sample93 = this->invokeChild(_outer.child1_index, args);\n",
492 "SkString _sample110;\n",
493 "_sample110 = this->invokeChild(_outer.child2_index, args);\n",
Ethan Nicholas13863662019-07-29 13:05:15 -0400494 "fragBuilder->codeAppendf(\"%s = %s * %s;\\n\", args.fOutputColor, _sample93.c_str(), "
495 "_sample110.c_str());\n",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400496 "this->registerChildProcessor(src.childProcessor(child1_index).clone());",
497 "this->registerChildProcessor(src.childProcessor(child2_index).clone());"
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400498 });
499}
Michael Ludwig92e4c7f2018-08-30 16:08:18 -0400500
501DEF_TEST(SkSLFPChildProcessorsWithInput, r) {
502 test(r,
503 "in fragmentProcessor child1;"
504 "in fragmentProcessor child2;"
505 "void main() {"
506 " half4 childIn = sk_InColor;"
Ethan Nicholas13863662019-07-29 13:05:15 -0400507 " half4 childOut1 = sample(child1, childIn);"
508 " half4 childOut2 = sample(child2, childOut1);"
Michael Ludwig92e4c7f2018-08-30 16:08:18 -0400509 " sk_OutColor = childOut2;"
510 "}",
511 *SkSL::ShaderCapsFactory::Default(),
512 {
513 "this->registerChildProcessor(std::move(child1));",
514 "this->registerChildProcessor(std::move(child2));"
515 },
516 {
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400517 "SkString _input128(\"childIn\");",
Brian Osman978693c2020-01-24 14:52:10 -0500518 "SkString _sample128;",
519 "_sample128 = this->invokeChild(_outer.child1_index, _input128.c_str(), args);",
Ethan Nicholas13863662019-07-29 13:05:15 -0400520 "fragBuilder->codeAppendf(\"\\nhalf4 childOut1 = %s;\", _sample128.c_str());",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400521 "SkString _input174(\"childOut1\");",
Brian Osman978693c2020-01-24 14:52:10 -0500522 "SkString _sample174;",
523 "_sample174 = this->invokeChild(_outer.child2_index, _input174.c_str(), args);",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400524 "this->registerChildProcessor(src.childProcessor(child1_index).clone());",
525 "this->registerChildProcessor(src.childProcessor(child2_index).clone());"
Michael Ludwig92e4c7f2018-08-30 16:08:18 -0400526 });
527}
528
529DEF_TEST(SkSLFPChildProcessorWithInputExpression, r) {
530 test(r,
531 "in fragmentProcessor child;"
532 "void main() {"
Ethan Nicholas13863662019-07-29 13:05:15 -0400533 " sk_OutColor = sample(child, sk_InColor * half4(0.5));"
Michael Ludwig92e4c7f2018-08-30 16:08:18 -0400534 "}",
535 *SkSL::ShaderCapsFactory::Default(),
536 {
537 "this->registerChildProcessor(std::move(child));",
538 },
539 {
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400540 "SkString _input64 = SkStringPrintf(\"%s * half4(0.5)\", args.fInputColor);",
Brian Osman978693c2020-01-24 14:52:10 -0500541 "SkString _sample64;",
542 "_sample64 = this->invokeChild(_outer.child_index, _input64.c_str(), args);",
Ethan Nicholas13863662019-07-29 13:05:15 -0400543 "fragBuilder->codeAppendf(\"%s = %s;\\n\", args.fOutputColor, _sample64.c_str());",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400544 "this->registerChildProcessor(src.childProcessor(child_index).clone());",
Michael Ludwig92e4c7f2018-08-30 16:08:18 -0400545 });
546}
547
548DEF_TEST(SkSLFPNestedChildProcessors, r) {
549 test(r,
550 "in fragmentProcessor child1;"
551 "in fragmentProcessor child2;"
552 "void main() {"
Ethan Nicholas13863662019-07-29 13:05:15 -0400553 " sk_OutColor = sample(child2, sk_InColor * sample(child1, sk_InColor * half4(0.5)));"
Michael Ludwig92e4c7f2018-08-30 16:08:18 -0400554 "}",
555 *SkSL::ShaderCapsFactory::Default(),
556 {
557 "this->registerChildProcessor(std::move(child1));",
558 "this->registerChildProcessor(std::move(child2));"
559 },
560 {
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400561 "SkString _input121 = SkStringPrintf(\"%s * half4(0.5)\", args.fInputColor);",
Brian Osman978693c2020-01-24 14:52:10 -0500562 "SkString _sample121;",
563 "_sample121 = this->invokeChild(_outer.child1_index, _input121.c_str(), args);",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400564 "SkString _input93 = SkStringPrintf(\"%s * %s\", args.fInputColor, _sample121.c_str());",
Brian Osman978693c2020-01-24 14:52:10 -0500565 "SkString _sample93;",
566 "_sample93 = this->invokeChild(_outer.child2_index, _input93.c_str(), args);",
Ethan Nicholas13863662019-07-29 13:05:15 -0400567 "fragBuilder->codeAppendf(\"%s = %s;\\n\", args.fOutputColor, _sample93.c_str());",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400568 "this->registerChildProcessor(src.childProcessor(child1_index).clone());",
569 "this->registerChildProcessor(src.childProcessor(child2_index).clone());"
Michael Ludwig92e4c7f2018-08-30 16:08:18 -0400570 });
571}
Michael Ludwig1fc5fbd2018-09-07 13:13:06 -0400572
573DEF_TEST(SkSLFPChildFPAndGlobal, r) {
574 test(r,
575 "in fragmentProcessor child;"
576 "bool hasCap = sk_Caps.externalTextureSupport;"
577 "void main() {"
578 " if (hasCap) {"
Ethan Nicholas13863662019-07-29 13:05:15 -0400579 " sk_OutColor = sample(child, sk_InColor);"
Michael Ludwig1fc5fbd2018-09-07 13:13:06 -0400580 " } else {"
581 " sk_OutColor = half4(1);"
582 " }"
583 "}",
584 *SkSL::ShaderCapsFactory::Default(),
585 {
586 "this->registerChildProcessor(std::move(child));"
587 },
588 {
589 "hasCap = sk_Caps.externalTextureSupport;",
Ethan Nicholas13863662019-07-29 13:05:15 -0400590 "fragBuilder->codeAppendf(\"bool hasCap = %s;\\nif (hasCap) {\", (hasCap ? \"true\" : "
591 "\"false\"));",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400592 "SkString _input130 = SkStringPrintf(\"%s\", args.fInputColor);",
Brian Osman978693c2020-01-24 14:52:10 -0500593 "SkString _sample130;",
594 "_sample130 = this->invokeChild(_outer.child_index, _input130.c_str(), args);",
Ethan Nicholas13863662019-07-29 13:05:15 -0400595 "fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(1.0);\\n}\\n\","
596 " args.fOutputColor, _sample130.c_str(), args.fOutputColor);",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400597 "this->registerChildProcessor(src.childProcessor(child_index).clone());"
Michael Ludwig1fc5fbd2018-09-07 13:13:06 -0400598 });
599}
Michael Ludwig9094f2c2018-09-07 13:44:21 -0400600
601DEF_TEST(SkSLFPChildProcessorInlineFieldAccess, r) {
602 test(r,
603 "in fragmentProcessor child;"
604 "void main() {"
605 " if (child.preservesOpaqueInput) {"
Ethan Nicholas13863662019-07-29 13:05:15 -0400606 " sk_OutColor = sample(child, sk_InColor);"
Michael Ludwig9094f2c2018-09-07 13:44:21 -0400607 " } else {"
608 " sk_OutColor = half4(1);"
609 " }"
610 "}",
611 *SkSL::ShaderCapsFactory::Default(),
612 {
613 "this->registerChildProcessor(std::move(child));"
614 },
615 {
616 "fragBuilder->codeAppendf(\"if (%s) {\", "
Ethan Nicholas13863662019-07-29 13:05:15 -0400617 "(_outer.childProcessor(_outer.child_index).preservesOpaqueInput() ? ",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400618 "SkString _input105 = SkStringPrintf(\"%s\", args.fInputColor);",
Brian Osman978693c2020-01-24 14:52:10 -0500619 "SkString _sample105;",
620 "_sample105 = this->invokeChild(_outer.child_index, _input105.c_str(), args);",
Ethan Nicholas13863662019-07-29 13:05:15 -0400621 "fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(1.0);\\n}\\n\","
622 " args.fOutputColor, _sample105.c_str(), args.fOutputColor);",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400623 "this->registerChildProcessor(src.childProcessor(child_index).clone());"
Michael Ludwig9094f2c2018-09-07 13:44:21 -0400624 });
625}
626
627DEF_TEST(SkSLFPChildProcessorFieldAccess, r) {
628 test(r,
629 "in fragmentProcessor child;"
630 "bool opaque = child.preservesOpaqueInput;"
631 "void main() {"
632 " if (opaque) {"
Ethan Nicholas13863662019-07-29 13:05:15 -0400633 " sk_OutColor = sample(child);"
Michael Ludwig9094f2c2018-09-07 13:44:21 -0400634 " } else {"
635 " sk_OutColor = half4(0.5);"
636 " }"
637 "}",
638 *SkSL::ShaderCapsFactory::Default(),
639 {
640 "this->registerChildProcessor(std::move(child));"
641 },
642 {
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400643 "opaque = _outer.childProcessor(_outer.child_index).preservesOpaqueInput();",
Ethan Nicholas13863662019-07-29 13:05:15 -0400644 "fragBuilder->codeAppendf(\"bool opaque = %s;\\nif (opaque) {\", (opaque ? \"true\" : "
645 "\"false\"));",
Brian Osman978693c2020-01-24 14:52:10 -0500646 "SkString _sample126;",
647 "_sample126 = this->invokeChild(_outer.child_index, args);",
Ethan Nicholas13863662019-07-29 13:05:15 -0400648 "fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(0.5);\\n}\\n\","
649 " args.fOutputColor, _sample126.c_str(), args.fOutputColor);",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400650 "this->registerChildProcessor(src.childProcessor(child_index).clone());"
Michael Ludwig9094f2c2018-09-07 13:44:21 -0400651 });
652}
Florin Malita390f9bd2019-03-04 12:25:57 -0500653
654DEF_TEST(SkSLFPNullableChildProcessor, r) {
655 test(r,
656 "in fragmentProcessor? child;"
657 "void main() {"
658 " if (child != null) {"
Ethan Nicholas13863662019-07-29 13:05:15 -0400659 " sk_OutColor = sample(child);"
Florin Malita390f9bd2019-03-04 12:25:57 -0500660 " } else {"
661 " sk_OutColor = half4(0.5);"
662 " }"
663 "}",
664 *SkSL::ShaderCapsFactory::Default(),
665 {},
666 {
Ethan Nicholas13863662019-07-29 13:05:15 -0400667 "fragBuilder->codeAppendf(\"if (%s) {\", _outer.child_index >= 0 ? \"true\" : "
668 "\"false\");",
Brian Osman978693c2020-01-24 14:52:10 -0500669 "SkString _sample93;",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400670 "if (_outer.child_index >= 0) {",
Brian Osman978693c2020-01-24 14:52:10 -0500671 "_sample93 = this->invokeChild(_outer.child_index, args);",
Florin Malita390f9bd2019-03-04 12:25:57 -0500672 "}",
Ethan Nicholas13863662019-07-29 13:05:15 -0400673 "fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(0.5);\\n}\\n\","
674 " args.fOutputColor, _sample93.c_str(), args.fOutputColor);"
675
Florin Malita390f9bd2019-03-04 12:25:57 -0500676 });
677}
Ethan Nicholas33c59ed2019-08-13 10:21:38 -0400678
679DEF_TEST(SkSLFPBadIn, r) {
680 test_failure(r,
681 "in half4 c;"
682 "void main() {"
683 " sk_OutColor = c;"
684 "}",
685 "error: 1: 'in' variable must be either 'uniform' or 'layout(key)', or there must be a "
686 "custom @setData function\n1 error\n");
687}
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400688
689DEF_TEST(SkSLFPSampleCoords, r) {
690 test(r,
691 "in fragmentProcessor child;"
692 "@coordTransform { SkMatrix() }"
693 "void main() {"
694 " sk_OutColor = sample(child) + sample(child, sk_TransformedCoords2D[0] / 2);"
695 "}",
696 *SkSL::ShaderCapsFactory::Default(),
697 {},
698 {
Brian Osman978693c2020-01-24 14:52:10 -0500699 "SkString _sample94;\n",
700 "_sample94 = this->invokeChild(_outer.child_index, args);\n",
701 "SkString _sample110;\n",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400702 "SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D("
703 "args.fTransformedCoords[0].fVaryingPoint);\n",
704 "SkString _coords110 = SkStringPrintf(\"%s / 2.0\", "
Brian Salomonbf5c0c02019-11-11 14:55:28 -0500705 "sk_TransformedCoords2D_0.c_str());\n",
Brian Osman978693c2020-01-24 14:52:10 -0500706 "_sample110 = this->invokeChild(_outer.child_index, args, _coords110.c_str());\n",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400707 "fragBuilder->codeAppendf(\"%s = %s + %s;\\n\", args.fOutputColor, _sample94.c_str(), "
708 "_sample110.c_str());\n"
709 });
710}
Ethan Nicholas095f5b42019-08-30 11:51:41 -0400711
712DEF_TEST(SkSLFPFunction, r) {
713 test(r,
714 "in fragmentProcessor? child;"
715 "half4 flip(half4 c) { return c.abgr; }"
716 "void main() {"
717 " sk_OutColor = flip(sk_InColor);"
718 "}",
719 *SkSL::ShaderCapsFactory::Default(),
720 {},
721 {
722 "SkString flip_name;",
723 "const GrShaderVar flip_args[] = { GrShaderVar(\"c\", kHalf4_GrSLType)};",
724 "fragBuilder->emitFunction(kHalf4_GrSLType, \"flip\", 1, flip_args, "
725 "\"return c.wzyx;\\n\", &flip_name);",
726 "fragBuilder->codeAppendf(\"%s = %s(%s);\\n\", args.fOutputColor, flip_name.c_str(), "
727 "args.fInputColor);"
728 });
729}