blob: 00b39f08fe6005b40a317ad55eb950d0a7aaa3ba [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 Reed46f5c5f2020-02-20 15:42:29 -050097 "#include \"include/core/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"
Greg Daniel456f9b52020-03-05 19:14:18 +0000126 "#include \"src/gpu/GrTexture.h\"\n"
Mike Kleinc0bd9f92019-04-23 12:05:21 -0500127 "#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 Nicholas16464c32020-04-06 13:53:05 -0400198 "colorVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, "
199 "kHalf4_GrSLType, \"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 Nicholas16464c32020-04-06 13:53:05 -0400217 "colorVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, "
218 "kHalf4_GrSLType, \"color\");",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400219 "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 Nicholas16464c32020-04-06 13:53:05 -0400235 "colorVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, "
236 "kHalf4_GrSLType, \"color\");",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400237 "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();",
Ethan Nicholas16464c32020-04-06 13:53:05 -0400256 "colorVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, "
257 "kHalf4_GrSLType, \"color\");",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400258 "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 Nicholas16464c32020-04-06 13:53:05 -0400278 "pointVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, "
279 "kHalf2_GrSLType, \"point\");",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400280 "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 Nicholas16464c32020-04-06 13:53:05 -0400306 "colorVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, "
307 "kHalf4_GrSLType, \"color\");",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400308 "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",
Brian Salomonb243b432020-02-20 14:41:47 -0500496 "{",
497 " auto clone = src.childProcessor(child1_index).clone();",
498 " clone->setSampledWithExplicitCoords(",
499 " src.childProcessor(child1_index).isSampledWithExplicitCoords());",
500 " this->registerChildProcessor(std::move(clone));",
501 "}",
502 "{",
503 " auto clone = src.childProcessor(child2_index).clone();",
504 " clone->setSampledWithExplicitCoords(",
505 " src.childProcessor(child2_index).isSampledWithExplicitCoords());",
506 " this->registerChildProcessor(std::move(clone));",
507 "}",
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400508 });
509}
Michael Ludwig92e4c7f2018-08-30 16:08:18 -0400510
511DEF_TEST(SkSLFPChildProcessorsWithInput, r) {
512 test(r,
513 "in fragmentProcessor child1;"
514 "in fragmentProcessor child2;"
515 "void main() {"
516 " half4 childIn = sk_InColor;"
Ethan Nicholas13863662019-07-29 13:05:15 -0400517 " half4 childOut1 = sample(child1, childIn);"
518 " half4 childOut2 = sample(child2, childOut1);"
Michael Ludwig92e4c7f2018-08-30 16:08:18 -0400519 " sk_OutColor = childOut2;"
520 "}",
521 *SkSL::ShaderCapsFactory::Default(),
522 {
523 "this->registerChildProcessor(std::move(child1));",
524 "this->registerChildProcessor(std::move(child2));"
525 },
526 {
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400527 "SkString _input128(\"childIn\");",
Brian Osman978693c2020-01-24 14:52:10 -0500528 "SkString _sample128;",
529 "_sample128 = this->invokeChild(_outer.child1_index, _input128.c_str(), args);",
Ethan Nicholas13863662019-07-29 13:05:15 -0400530 "fragBuilder->codeAppendf(\"\\nhalf4 childOut1 = %s;\", _sample128.c_str());",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400531 "SkString _input174(\"childOut1\");",
Brian Osman978693c2020-01-24 14:52:10 -0500532 "SkString _sample174;",
533 "_sample174 = this->invokeChild(_outer.child2_index, _input174.c_str(), args);",
Brian Salomonb243b432020-02-20 14:41:47 -0500534 "{",
535 " auto clone = src.childProcessor(child1_index).clone();",
536 " clone->setSampledWithExplicitCoords(",
537 " src.childProcessor(child1_index).isSampledWithExplicitCoords());",
538 " this->registerChildProcessor(std::move(clone));",
539 "}",
540 "{",
541 " auto clone = src.childProcessor(child2_index).clone();",
542 " clone->setSampledWithExplicitCoords(",
543 " src.childProcessor(child2_index).isSampledWithExplicitCoords());",
544 " this->registerChildProcessor(std::move(clone));",
545 "}"
Michael Ludwig92e4c7f2018-08-30 16:08:18 -0400546 });
547}
548
549DEF_TEST(SkSLFPChildProcessorWithInputExpression, r) {
550 test(r,
551 "in fragmentProcessor child;"
552 "void main() {"
Ethan Nicholas13863662019-07-29 13:05:15 -0400553 " sk_OutColor = sample(child, sk_InColor * half4(0.5));"
Michael Ludwig92e4c7f2018-08-30 16:08:18 -0400554 "}",
555 *SkSL::ShaderCapsFactory::Default(),
556 {
557 "this->registerChildProcessor(std::move(child));",
558 },
559 {
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400560 "SkString _input64 = SkStringPrintf(\"%s * half4(0.5)\", args.fInputColor);",
Brian Osman978693c2020-01-24 14:52:10 -0500561 "SkString _sample64;",
562 "_sample64 = this->invokeChild(_outer.child_index, _input64.c_str(), args);",
Ethan Nicholas13863662019-07-29 13:05:15 -0400563 "fragBuilder->codeAppendf(\"%s = %s;\\n\", args.fOutputColor, _sample64.c_str());",
Brian Salomonb243b432020-02-20 14:41:47 -0500564 "{",
565 " auto clone = src.childProcessor(child_index).clone();",
566 " clone->setSampledWithExplicitCoords(",
567 " src.childProcessor(child_index).isSampledWithExplicitCoords());",
568 " this->registerChildProcessor(std::move(clone));",
569 "}",
Michael Ludwig92e4c7f2018-08-30 16:08:18 -0400570 });
571}
572
573DEF_TEST(SkSLFPNestedChildProcessors, r) {
574 test(r,
575 "in fragmentProcessor child1;"
576 "in fragmentProcessor child2;"
577 "void main() {"
Ethan Nicholas13863662019-07-29 13:05:15 -0400578 " sk_OutColor = sample(child2, sk_InColor * sample(child1, sk_InColor * half4(0.5)));"
Michael Ludwig92e4c7f2018-08-30 16:08:18 -0400579 "}",
580 *SkSL::ShaderCapsFactory::Default(),
581 {
582 "this->registerChildProcessor(std::move(child1));",
583 "this->registerChildProcessor(std::move(child2));"
584 },
585 {
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400586 "SkString _input121 = SkStringPrintf(\"%s * half4(0.5)\", args.fInputColor);",
Brian Osman978693c2020-01-24 14:52:10 -0500587 "SkString _sample121;",
588 "_sample121 = this->invokeChild(_outer.child1_index, _input121.c_str(), args);",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400589 "SkString _input93 = SkStringPrintf(\"%s * %s\", args.fInputColor, _sample121.c_str());",
Brian Osman978693c2020-01-24 14:52:10 -0500590 "SkString _sample93;",
591 "_sample93 = this->invokeChild(_outer.child2_index, _input93.c_str(), args);",
Ethan Nicholas13863662019-07-29 13:05:15 -0400592 "fragBuilder->codeAppendf(\"%s = %s;\\n\", args.fOutputColor, _sample93.c_str());",
Brian Salomonb243b432020-02-20 14:41:47 -0500593 "{",
594 " auto clone = src.childProcessor(child1_index).clone();",
595 " clone->setSampledWithExplicitCoords(",
596 " src.childProcessor(child1_index).isSampledWithExplicitCoords());",
597 " this->registerChildProcessor(std::move(clone));",
598 "}",
599 "{",
600 " auto clone = src.childProcessor(child2_index).clone();",
601 " clone->setSampledWithExplicitCoords(",
602 " src.childProcessor(child2_index).isSampledWithExplicitCoords());",
603 " this->registerChildProcessor(std::move(clone));",
604 "}",
605 });
Michael Ludwig92e4c7f2018-08-30 16:08:18 -0400606}
Michael Ludwig1fc5fbd2018-09-07 13:13:06 -0400607
608DEF_TEST(SkSLFPChildFPAndGlobal, r) {
609 test(r,
610 "in fragmentProcessor child;"
611 "bool hasCap = sk_Caps.externalTextureSupport;"
612 "void main() {"
613 " if (hasCap) {"
Ethan Nicholas13863662019-07-29 13:05:15 -0400614 " sk_OutColor = sample(child, sk_InColor);"
Michael Ludwig1fc5fbd2018-09-07 13:13:06 -0400615 " } else {"
616 " sk_OutColor = half4(1);"
617 " }"
618 "}",
619 *SkSL::ShaderCapsFactory::Default(),
620 {
621 "this->registerChildProcessor(std::move(child));"
622 },
623 {
624 "hasCap = sk_Caps.externalTextureSupport;",
Ethan Nicholas13863662019-07-29 13:05:15 -0400625 "fragBuilder->codeAppendf(\"bool hasCap = %s;\\nif (hasCap) {\", (hasCap ? \"true\" : "
626 "\"false\"));",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400627 "SkString _input130 = SkStringPrintf(\"%s\", args.fInputColor);",
Brian Osman978693c2020-01-24 14:52:10 -0500628 "SkString _sample130;",
629 "_sample130 = this->invokeChild(_outer.child_index, _input130.c_str(), args);",
Ethan Nicholas13863662019-07-29 13:05:15 -0400630 "fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(1.0);\\n}\\n\","
631 " args.fOutputColor, _sample130.c_str(), args.fOutputColor);",
Brian Salomonb243b432020-02-20 14:41:47 -0500632 "{",
633 " auto clone = src.childProcessor(child_index).clone();",
634 " clone->setSampledWithExplicitCoords(",
635 " src.childProcessor(child_index).isSampledWithExplicitCoords());",
636 " this->registerChildProcessor(std::move(clone));",
637 "}",
638 });
Michael Ludwig1fc5fbd2018-09-07 13:13:06 -0400639}
Michael Ludwig9094f2c2018-09-07 13:44:21 -0400640
641DEF_TEST(SkSLFPChildProcessorInlineFieldAccess, r) {
642 test(r,
643 "in fragmentProcessor child;"
644 "void main() {"
645 " if (child.preservesOpaqueInput) {"
Ethan Nicholas13863662019-07-29 13:05:15 -0400646 " sk_OutColor = sample(child, sk_InColor);"
Michael Ludwig9094f2c2018-09-07 13:44:21 -0400647 " } else {"
648 " sk_OutColor = half4(1);"
649 " }"
650 "}",
651 *SkSL::ShaderCapsFactory::Default(),
652 {
653 "this->registerChildProcessor(std::move(child));"
654 },
655 {
656 "fragBuilder->codeAppendf(\"if (%s) {\", "
Ethan Nicholas13863662019-07-29 13:05:15 -0400657 "(_outer.childProcessor(_outer.child_index).preservesOpaqueInput() ? ",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400658 "SkString _input105 = SkStringPrintf(\"%s\", args.fInputColor);",
Brian Osman978693c2020-01-24 14:52:10 -0500659 "SkString _sample105;",
660 "_sample105 = this->invokeChild(_outer.child_index, _input105.c_str(), args);",
Ethan Nicholas13863662019-07-29 13:05:15 -0400661 "fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(1.0);\\n}\\n\","
662 " args.fOutputColor, _sample105.c_str(), args.fOutputColor);",
Brian Salomonb243b432020-02-20 14:41:47 -0500663 "{",
664 " auto clone = src.childProcessor(child_index).clone();",
665 " clone->setSampledWithExplicitCoords(",
666 " src.childProcessor(child_index).isSampledWithExplicitCoords());",
667 " this->registerChildProcessor(std::move(clone));",
668 "}",
Michael Ludwig9094f2c2018-09-07 13:44:21 -0400669 });
670}
671
672DEF_TEST(SkSLFPChildProcessorFieldAccess, r) {
673 test(r,
674 "in fragmentProcessor child;"
675 "bool opaque = child.preservesOpaqueInput;"
676 "void main() {"
677 " if (opaque) {"
Ethan Nicholas13863662019-07-29 13:05:15 -0400678 " sk_OutColor = sample(child);"
Michael Ludwig9094f2c2018-09-07 13:44:21 -0400679 " } else {"
680 " sk_OutColor = half4(0.5);"
681 " }"
682 "}",
683 *SkSL::ShaderCapsFactory::Default(),
684 {
685 "this->registerChildProcessor(std::move(child));"
686 },
687 {
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400688 "opaque = _outer.childProcessor(_outer.child_index).preservesOpaqueInput();",
Ethan Nicholas13863662019-07-29 13:05:15 -0400689 "fragBuilder->codeAppendf(\"bool opaque = %s;\\nif (opaque) {\", (opaque ? \"true\" : "
690 "\"false\"));",
Brian Osman978693c2020-01-24 14:52:10 -0500691 "SkString _sample126;",
692 "_sample126 = this->invokeChild(_outer.child_index, args);",
Ethan Nicholas13863662019-07-29 13:05:15 -0400693 "fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(0.5);\\n}\\n\","
694 " args.fOutputColor, _sample126.c_str(), args.fOutputColor);",
Brian Salomonb243b432020-02-20 14:41:47 -0500695 "{",
696 " auto clone = src.childProcessor(child_index).clone();",
697 " clone->setSampledWithExplicitCoords(",
698 " src.childProcessor(child_index).isSampledWithExplicitCoords());",
699 " this->registerChildProcessor(std::move(clone));",
700 "}",
Michael Ludwig9094f2c2018-09-07 13:44:21 -0400701 });
702}
Florin Malita390f9bd2019-03-04 12:25:57 -0500703
704DEF_TEST(SkSLFPNullableChildProcessor, r) {
705 test(r,
706 "in fragmentProcessor? child;"
707 "void main() {"
708 " if (child != null) {"
Ethan Nicholas13863662019-07-29 13:05:15 -0400709 " sk_OutColor = sample(child);"
Florin Malita390f9bd2019-03-04 12:25:57 -0500710 " } else {"
711 " sk_OutColor = half4(0.5);"
712 " }"
713 "}",
714 *SkSL::ShaderCapsFactory::Default(),
715 {},
716 {
Ethan Nicholas13863662019-07-29 13:05:15 -0400717 "fragBuilder->codeAppendf(\"if (%s) {\", _outer.child_index >= 0 ? \"true\" : "
718 "\"false\");",
Brian Osman978693c2020-01-24 14:52:10 -0500719 "SkString _sample93;",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400720 "if (_outer.child_index >= 0) {",
Brian Osman978693c2020-01-24 14:52:10 -0500721 "_sample93 = this->invokeChild(_outer.child_index, args);",
Florin Malita390f9bd2019-03-04 12:25:57 -0500722 "}",
Ethan Nicholas13863662019-07-29 13:05:15 -0400723 "fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(0.5);\\n}\\n\","
724 " args.fOutputColor, _sample93.c_str(), args.fOutputColor);"
725
Florin Malita390f9bd2019-03-04 12:25:57 -0500726 });
727}
Ethan Nicholas33c59ed2019-08-13 10:21:38 -0400728
729DEF_TEST(SkSLFPBadIn, r) {
730 test_failure(r,
731 "in half4 c;"
732 "void main() {"
733 " sk_OutColor = c;"
734 "}",
735 "error: 1: 'in' variable must be either 'uniform' or 'layout(key)', or there must be a "
736 "custom @setData function\n1 error\n");
737}
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400738
739DEF_TEST(SkSLFPSampleCoords, r) {
740 test(r,
741 "in fragmentProcessor child;"
742 "@coordTransform { SkMatrix() }"
743 "void main() {"
744 " sk_OutColor = sample(child) + sample(child, sk_TransformedCoords2D[0] / 2);"
745 "}",
746 *SkSL::ShaderCapsFactory::Default(),
747 {},
748 {
Brian Osman978693c2020-01-24 14:52:10 -0500749 "SkString _sample94;\n",
750 "_sample94 = this->invokeChild(_outer.child_index, args);\n",
751 "SkString _sample110;\n",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400752 "SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D("
753 "args.fTransformedCoords[0].fVaryingPoint);\n",
754 "SkString _coords110 = SkStringPrintf(\"%s / 2.0\", "
Brian Salomonbf5c0c02019-11-11 14:55:28 -0500755 "sk_TransformedCoords2D_0.c_str());\n",
Brian Osman978693c2020-01-24 14:52:10 -0500756 "_sample110 = this->invokeChild(_outer.child_index, args, _coords110.c_str());\n",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400757 "fragBuilder->codeAppendf(\"%s = %s + %s;\\n\", args.fOutputColor, _sample94.c_str(), "
758 "_sample110.c_str());\n"
759 });
760}
Ethan Nicholas095f5b42019-08-30 11:51:41 -0400761
762DEF_TEST(SkSLFPFunction, r) {
763 test(r,
764 "in fragmentProcessor? child;"
765 "half4 flip(half4 c) { return c.abgr; }"
766 "void main() {"
767 " sk_OutColor = flip(sk_InColor);"
768 "}",
769 *SkSL::ShaderCapsFactory::Default(),
770 {},
771 {
772 "SkString flip_name;",
773 "const GrShaderVar flip_args[] = { GrShaderVar(\"c\", kHalf4_GrSLType)};",
774 "fragBuilder->emitFunction(kHalf4_GrSLType, \"flip\", 1, flip_args, "
775 "\"return c.wzyx;\\n\", &flip_name);",
776 "fragBuilder->codeAppendf(\"%s = %s(%s);\\n\", args.fOutputColor, flip_name.c_str(), "
777 "args.fInputColor);"
778 });
779}