blob: 793366854e0fd0ce323c1a26011832ee145ffdaf [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 Kleinc0bd9f92019-04-23 12:05:21 -050096 "#include \"include/core/SkTypes.h\"\n\n"
97 "#include \"src/gpu/GrCoordTransform.h\"\n"
98 "#include \"src/gpu/GrFragmentProcessor.h\"\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -040099 "class GrTest : public GrFragmentProcessor {\n"
100 "public:\n"
Brian Salomonaff329b2017-08-11 09:40:37 -0400101 " static std::unique_ptr<GrFragmentProcessor> Make() {\n"
102 " return std::unique_ptr<GrFragmentProcessor>(new GrTest());\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400103 " }\n"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400104 " GrTest(const GrTest& src);\n"
Brian Salomonaff329b2017-08-11 09:40:37 -0400105 " std::unique_ptr<GrFragmentProcessor> clone() const override;\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400106 " const char* name() const override { return \"Test\"; }\n"
107 "private:\n"
108 " GrTest()\n"
Ethan Nicholasabff9562017-10-09 10:54:08 -0400109 " : INHERITED(kGrTest_ClassID, kNone_OptimizationFlags) {\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400110 " }\n"
111 " GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;\n"
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400112 " void onGetGLSLProcessorKey(const GrShaderCaps&,GrProcessorKeyBuilder*) const "
113 "override;\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400114 " bool onIsEqual(const GrFragmentProcessor&) const override;\n"
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400115 " GR_DECLARE_FRAGMENT_PROCESSOR_TEST\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400116 " typedef GrFragmentProcessor INHERITED;\n"
117 "};\n"
118 "#endif\n"
119 },
120 {
Ethan Nicholas130fb3f2018-02-01 12:14:34 -0500121 "/**************************************************************************************************\n"
122 " *** This file was autogenerated from GrTest.fp; do not modify.\n"
123 " **************************************************************************************************/\n"
Mike Kleinc0bd9f92019-04-23 12:05:21 -0500124 "#include \"GrTest.h\"\n\n"
125 "#include \"include/gpu/GrTexture.h\"\n"
126 "#include \"src/gpu/glsl/GrGLSLFragmentProcessor.h\"\n"
127 "#include \"src/gpu/glsl/GrGLSLFragmentShaderBuilder.h\"\n"
128 "#include \"src/gpu/glsl/GrGLSLProgramBuilder.h\"\n"
129 "#include \"src/sksl/SkSLCPP.h\"\n"
130 "#include \"src/sksl/SkSLUtil.h\"\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400131 "class GrGLSLTest : public GrGLSLFragmentProcessor {\n"
132 "public:\n"
133 " GrGLSLTest() {}\n"
134 " void emitCode(EmitArgs& args) override {\n"
135 " GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;\n"
136 " const GrTest& _outer = args.fFp.cast<GrTest>();\n"
137 " (void) _outer;\n"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400138 " fragBuilder->codeAppendf(\"%s = half4(1.0);\\n\", args.fOutputColor);\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400139 " }\n"
140 "private:\n"
141 " void onSetData(const GrGLSLProgramDataManager& pdman, "
142 "const GrFragmentProcessor& _proc) override {\n"
143 " }\n"
144 "};\n"
145 "GrGLSLFragmentProcessor* GrTest::onCreateGLSLInstance() const {\n"
146 " return new GrGLSLTest();\n"
147 "}\n"
148 "void GrTest::onGetGLSLProcessorKey(const GrShaderCaps& caps, "
149 "GrProcessorKeyBuilder* b) const {\n"
150 "}\n"
151 "bool GrTest::onIsEqual(const GrFragmentProcessor& other) const {\n"
152 " const GrTest& that = other.cast<GrTest>();\n"
153 " (void) that;\n"
154 " return true;\n"
155 "}\n"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400156 "GrTest::GrTest(const GrTest& src)\n"
Ethan Nicholasabff9562017-10-09 10:54:08 -0400157 ": INHERITED(kGrTest_ClassID, src.optimizationFlags()) {\n"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400158 "}\n"
Brian Salomonaff329b2017-08-11 09:40:37 -0400159 "std::unique_ptr<GrFragmentProcessor> GrTest::clone() const {\n"
160 " return std::unique_ptr<GrFragmentProcessor>(new GrTest(*this));\n"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400161 "}\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400162 });
163}
164
165DEF_TEST(SkSLFPInput, r) {
166 test(r,
Ethan Nicholas33c59ed2019-08-13 10:21:38 -0400167 "layout(key) in half2 point;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400168 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400169 "sk_OutColor = half4(point, point);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400170 "}",
171 *SkSL::ShaderCapsFactory::Default(),
172 {
Brian Salomonaff329b2017-08-11 09:40:37 -0400173 "static std::unique_ptr<GrFragmentProcessor> Make(SkPoint point) {",
174 "return std::unique_ptr<GrFragmentProcessor>(new GrTest(point));",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400175 "GrTest(SkPoint point)",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400176 ", point(point)"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400177 },
178 {
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400179 "fragBuilder->codeAppendf(\"%s = half4(half2(%f, %f), half2(%f, %f));\\n\", "
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400180 "args.fOutputColor, _outer.point.fX, _outer.point.fY, "
181 "_outer.point.fX, _outer.point.fY);",
182 "if (point != that.point) return false;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400183 });
184}
185
186DEF_TEST(SkSLFPUniform, r) {
187 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400188 "uniform half4 color;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400189 "void main() {"
190 "sk_OutColor = color;"
191 "}",
192 *SkSL::ShaderCapsFactory::Default(),
193 {
Brian Salomonaff329b2017-08-11 09:40:37 -0400194 "static std::unique_ptr<GrFragmentProcessor> Make()"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400195 },
196 {
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400197 "colorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
198 "\"color\");",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400199 });
200}
201
Michael Ludwiga4275592018-08-31 10:52:47 -0400202// SkSLFPInUniform tests the simplest plumbing case, default type, no tracking
203// with a setUniform template that supports inlining the value call with no
204// local variable.
Ethan Nicholas762466e2017-06-29 10:03:38 -0400205DEF_TEST(SkSLFPInUniform, r) {
206 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400207 "in uniform half4 color;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400208 "void main() {"
209 "sk_OutColor = color;"
210 "}",
211 *SkSL::ShaderCapsFactory::Default(),
212 {
Brian Salomonaff329b2017-08-11 09:40:37 -0400213 "static std::unique_ptr<GrFragmentProcessor> Make(SkRect color) {",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400214 },
215 {
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400216 "colorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
217 "\"color\");",
218 "pdman.set4fv(colorVar, 1, reinterpret_cast<const float*>(&(_outer.color)));"
Michael Ludwiga4275592018-08-31 10:52:47 -0400219 });
220}
221
222// As above, but tests in uniform's ability to override the default ctype.
223DEF_TEST(SkSLFPInUniformCType, r) {
224 test(r,
Brian Osman495993a2018-10-16 15:45:55 -0400225 "layout(ctype=SkPMColor4f) in uniform half4 color;"
Michael Ludwiga4275592018-08-31 10:52:47 -0400226 "void main() {"
227 "sk_OutColor = color;"
228 "}",
229 *SkSL::ShaderCapsFactory::Default(),
230 {
Brian Osman495993a2018-10-16 15:45:55 -0400231 "static std::unique_ptr<GrFragmentProcessor> Make(SkPMColor4f color) {",
Michael Ludwiga4275592018-08-31 10:52:47 -0400232 },
233 {
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400234 "colorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
235 "\"color\");",
236 "pdman.set4fv(colorVar, 1, (_outer.color).vec());"
Michael Ludwiga4275592018-08-31 10:52:47 -0400237 });
238}
239
240// Add state tracking to the default typed SkRect <-> half4 uniform. But since
241// it now has to track state, the value inlining previously done for the
242// setUniform call is removed in favor of a local variable.
243DEF_TEST(SkSLFPTrackedInUniform, r) {
244 test(r,
245 "layout(tracked) in uniform half4 color;"
246 "void main() {"
247 "sk_OutColor = color;"
248 "}",
249 *SkSL::ShaderCapsFactory::Default(),
250 {
251 "static std::unique_ptr<GrFragmentProcessor> Make(SkRect color) {",
252 },
253 {
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400254 "SkRect colorPrev = SkRect::MakeEmpty();",
255 "colorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
256 "\"color\");",
257 "const SkRect& colorValue = _outer.color;",
258 "if (colorPrev.isEmpty() || colorPrev != colorValue) {",
259 "colorPrev = colorValue;",
260 "pdman.set4fv(colorVar, 1, reinterpret_cast<const float*>(&colorValue));"
Michael Ludwiga4275592018-08-31 10:52:47 -0400261 });
262}
263
264// Test the case where the template does not support variable inlining in
265// setUniform (i.e. it references the value multiple times).
266DEF_TEST(SkSLFPNonInlinedInUniform, r) {
267 test(r,
268 "in uniform half2 point;"
269 "void main() {"
270 "sk_OutColor = half4(point, point);"
271 "}",
272 *SkSL::ShaderCapsFactory::Default(),
273 {
274 "static std::unique_ptr<GrFragmentProcessor> Make(SkPoint point) {",
275 },
276 {
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400277 "pointVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType, "
278 "\"point\");",
279 "const SkPoint& pointValue = _outer.point;",
280 "pdman.set2f(pointVar, pointValue.fX, pointValue.fY);"
Michael Ludwiga4275592018-08-31 10:52:47 -0400281 });
282}
283
284// Test handling conditional uniforms (that use when= in layout), combined with
285// state tracking and custom ctypes to really put the code generation through its paces.
286DEF_TEST(SkSLFPConditionalInUniform, r) {
287 test(r,
Ethan Nicholas33c59ed2019-08-13 10:21:38 -0400288 "layout(key) in bool test;"
Brian Osman495993a2018-10-16 15:45:55 -0400289 "layout(ctype=SkPMColor4f, tracked, when=test) in uniform half4 color;"
Michael Ludwiga4275592018-08-31 10:52:47 -0400290 "void main() {"
291 " if (test) {"
292 " sk_OutColor = color;"
293 " } else {"
294 " sk_OutColor = half4(1);"
295 " }"
296 "}",
297 *SkSL::ShaderCapsFactory::Default(),
298 {
Brian Osman495993a2018-10-16 15:45:55 -0400299 "static std::unique_ptr<GrFragmentProcessor> Make(bool test, SkPMColor4f color) {",
Michael Ludwiga4275592018-08-31 10:52:47 -0400300 },
301 {
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400302 "SkPMColor4f colorPrev = {SK_FloatNaN, SK_FloatNaN, SK_FloatNaN, SK_FloatNaN}",
303 "auto test = _outer.test;",
Michael Ludwiga4275592018-08-31 10:52:47 -0400304 "if (test) {",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400305 "colorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
306 "\"color\");",
307 "if (colorVar.isValid()) {",
308 "const SkPMColor4f& colorValue = _outer.color;",
309 "if (colorPrev != colorValue) {",
310 "colorPrev = colorValue;",
311 "pdman.set4fv(colorVar, 1, colorValue.vec());"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400312 });
313}
314
315DEF_TEST(SkSLFPSections, r) {
316 test(r,
317 "@header { header section }"
318 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400319 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400320 "}",
321 *SkSL::ShaderCapsFactory::Default(),
322 {
Greg Daniel3e8c3452018-04-06 10:37:55 -0400323 "header section"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400324 },
325 {});
326 test(r,
327 "@class { class section }"
328 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400329 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400330 "}",
331 *SkSL::ShaderCapsFactory::Default(),
332 {
333 "class GrTest : public GrFragmentProcessor {\n"
334 "public:\n"
335 " class section"
336 },
337 {});
338 test(r,
339 "@cpp { cpp section }"
340 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400341 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400342 "}",
343 *SkSL::ShaderCapsFactory::Default(),
344 {},
345 {"cpp section"});
346 test(r,
347 "@constructorParams { int x, float y, std::vector<float> z }"
Ethan Nicholas8aa45692017-09-20 11:24:15 -0400348 "in float w;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400349 "void main() {"
Ethan Nicholase1f55022019-02-05 17:17:40 -0500350 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400351 "}",
352 *SkSL::ShaderCapsFactory::Default(),
353 {
354 "Make(float w, int x, float y, std::vector<float> z )",
Brian Salomonaff329b2017-08-11 09:40:37 -0400355 "return std::unique_ptr<GrFragmentProcessor>(new GrTest(w, x, y, z));",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400356 "GrTest(float w, int x, float y, std::vector<float> z )",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400357 ", w(w) {"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400358 },
359 {});
360 test(r,
361 "@constructor { constructor section }"
362 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400363 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400364 "}",
365 *SkSL::ShaderCapsFactory::Default(),
366 {
367 "private:\n constructor section"
368 },
369 {});
370 test(r,
371 "@initializers { initializers section }"
372 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400373 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400374 "}",
375 *SkSL::ShaderCapsFactory::Default(),
376 {
Ethan Nicholasabff9562017-10-09 10:54:08 -0400377 ": INHERITED(kGrTest_ClassID, kNone_OptimizationFlags)\n , initializers section"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400378 },
379 {});
380 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400381 "half x = 10;"
382 "@emitCode { fragBuilder->codeAppendf(\"half y = %d\\n\", x * 2); }"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400383 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400384 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400385 "}",
386 *SkSL::ShaderCapsFactory::Default(),
387 {},
388 {
389 "x = 10.0;\n"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400390 " fragBuilder->codeAppendf(\"half y = %d\\n\", x * 2);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400391 });
392 test(r,
393 "@fields { fields section }"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400394 "@clone { }"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400395 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400396 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400397 "}",
398 *SkSL::ShaderCapsFactory::Default(),
399 {
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400400 "const char* name() const override { return \"Test\"; }\n"
401 " fields section private:"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400402 },
403 {});
404 test(r,
405 "@make { make section }"
406 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400407 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400408 "}",
409 *SkSL::ShaderCapsFactory::Default(),
410 {
411 "public:\n"
412 " make section"
413 },
414 {});
415 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400416 "uniform half calculated;"
Ethan Nicholas33c59ed2019-08-13 10:21:38 -0400417 "layout(key) in half provided;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400418 "@setData(varName) { varName.set1f(calculated, provided * 2); }"
419 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400420 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400421 "}",
422 *SkSL::ShaderCapsFactory::Default(),
423 {},
424 {
425 "void onSetData(const GrGLSLProgramDataManager& varName, "
426 "const GrFragmentProcessor& _proc) override {\n",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400427 "UniformHandle& calculated = calculatedVar;",
428 "auto provided = _outer.provided;",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400429 "varName.set1f(calculated, provided * 2);"
430 });
431 test(r,
432 "@test(testDataName) { testDataName section }"
433 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400434 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400435 "}",
436 *SkSL::ShaderCapsFactory::Default(),
437 {},
438 {
439 "#if GR_TEST_UTILS\n"
Brian Salomonaff329b2017-08-11 09:40:37 -0400440 "std::unique_ptr<GrFragmentProcessor> GrTest::TestCreate(GrProcessorTestData* testDataName) {\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400441 " testDataName section }\n"
442 "#endif"
443 });
444}
445
Ethan Nicholas762466e2017-06-29 10:03:38 -0400446DEF_TEST(SkSLFPTransformedCoords, r) {
447 test(r,
448 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400449 "sk_OutColor = half4(sk_TransformedCoords2D[0], sk_TransformedCoords2D[0]);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400450 "}",
451 *SkSL::ShaderCapsFactory::Default(),
452 {},
453 {
Brian Osman72a37be2017-08-15 09:19:53 -0400454 "SkString sk_TransformedCoords2D_0 = "
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400455 "fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint);",
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400456 "fragBuilder->codeAppendf(\"%s = half4(%s, %s);\\n\", args.fOutputColor, "
Brian Salomonbf5c0c02019-11-11 14:55:28 -0500457 "sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str());"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400458 });
459
460}
461
462DEF_TEST(SkSLFPLayoutWhen, r) {
463 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400464 "layout(when=someExpression(someOtherExpression())) uniform half sometimes;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400465 "void main() {"
466 "}",
467 *SkSL::ShaderCapsFactory::Default(),
468 {},
469 {
470 "if (someExpression(someOtherExpression())) {\n"
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400471 " sometimesVar = args.fUniformHandler->addUniform"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400472 });
473
474}
475
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400476DEF_TEST(SkSLFPChildProcessors, r) {
477 test(r,
478 "in fragmentProcessor child1;"
479 "in fragmentProcessor child2;"
480 "void main() {"
Ethan Nicholas13863662019-07-29 13:05:15 -0400481 " sk_OutColor = sample(child1) * sample(child2);"
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400482 "}",
483 *SkSL::ShaderCapsFactory::Default(),
484 {
485 "this->registerChildProcessor(std::move(child1));",
486 "this->registerChildProcessor(std::move(child2));"
487 },
488 {
Ethan Nicholas13863662019-07-29 13:05:15 -0400489 "SkString _sample93(\"_sample93\");\n",
490 "this->invokeChild(_outer.child1_index, &_sample93, args);\n",
491 "SkString _sample110(\"_sample110\");\n",
492 "this->invokeChild(_outer.child2_index, &_sample110, args);\n",
493 "fragBuilder->codeAppendf(\"%s = %s * %s;\\n\", args.fOutputColor, _sample93.c_str(), "
494 "_sample110.c_str());\n",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400495 "this->registerChildProcessor(src.childProcessor(child1_index).clone());",
496 "this->registerChildProcessor(src.childProcessor(child2_index).clone());"
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400497 });
498}
Michael Ludwig92e4c7f2018-08-30 16:08:18 -0400499
500DEF_TEST(SkSLFPChildProcessorsWithInput, r) {
501 test(r,
502 "in fragmentProcessor child1;"
503 "in fragmentProcessor child2;"
504 "void main() {"
505 " half4 childIn = sk_InColor;"
Ethan Nicholas13863662019-07-29 13:05:15 -0400506 " half4 childOut1 = sample(child1, childIn);"
507 " half4 childOut2 = sample(child2, childOut1);"
Michael Ludwig92e4c7f2018-08-30 16:08:18 -0400508 " sk_OutColor = childOut2;"
509 "}",
510 *SkSL::ShaderCapsFactory::Default(),
511 {
512 "this->registerChildProcessor(std::move(child1));",
513 "this->registerChildProcessor(std::move(child2));"
514 },
515 {
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400516 "SkString _input128(\"childIn\");",
Ethan Nicholas13863662019-07-29 13:05:15 -0400517 "SkString _sample128(\"_sample128\");",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400518 "this->invokeChild(_outer.child1_index, _input128.c_str(), &_sample128, args);",
Ethan Nicholas13863662019-07-29 13:05:15 -0400519 "fragBuilder->codeAppendf(\"\\nhalf4 childOut1 = %s;\", _sample128.c_str());",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400520 "SkString _input174(\"childOut1\");",
Ethan Nicholas13863662019-07-29 13:05:15 -0400521 "SkString _sample174(\"_sample174\");",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400522 "this->invokeChild(_outer.child2_index, _input174.c_str(), &_sample174, args);",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400523 "this->registerChildProcessor(src.childProcessor(child1_index).clone());",
524 "this->registerChildProcessor(src.childProcessor(child2_index).clone());"
Michael Ludwig92e4c7f2018-08-30 16:08:18 -0400525 });
526}
527
528DEF_TEST(SkSLFPChildProcessorWithInputExpression, r) {
529 test(r,
530 "in fragmentProcessor child;"
531 "void main() {"
Ethan Nicholas13863662019-07-29 13:05:15 -0400532 " sk_OutColor = sample(child, sk_InColor * half4(0.5));"
Michael Ludwig92e4c7f2018-08-30 16:08:18 -0400533 "}",
534 *SkSL::ShaderCapsFactory::Default(),
535 {
536 "this->registerChildProcessor(std::move(child));",
537 },
538 {
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400539 "SkString _input64 = SkStringPrintf(\"%s * half4(0.5)\", args.fInputColor);",
Ethan Nicholas13863662019-07-29 13:05:15 -0400540 "SkString _sample64(\"_sample64\");",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400541 "this->invokeChild(_outer.child_index, _input64.c_str(), &_sample64, args);",
Ethan Nicholas13863662019-07-29 13:05:15 -0400542 "fragBuilder->codeAppendf(\"%s = %s;\\n\", args.fOutputColor, _sample64.c_str());",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400543 "this->registerChildProcessor(src.childProcessor(child_index).clone());",
Michael Ludwig92e4c7f2018-08-30 16:08:18 -0400544 });
545}
546
547DEF_TEST(SkSLFPNestedChildProcessors, r) {
548 test(r,
549 "in fragmentProcessor child1;"
550 "in fragmentProcessor child2;"
551 "void main() {"
Ethan Nicholas13863662019-07-29 13:05:15 -0400552 " sk_OutColor = sample(child2, sk_InColor * sample(child1, sk_InColor * half4(0.5)));"
Michael Ludwig92e4c7f2018-08-30 16:08:18 -0400553 "}",
554 *SkSL::ShaderCapsFactory::Default(),
555 {
556 "this->registerChildProcessor(std::move(child1));",
557 "this->registerChildProcessor(std::move(child2));"
558 },
559 {
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400560 "SkString _input121 = SkStringPrintf(\"%s * half4(0.5)\", args.fInputColor);",
Ethan Nicholas13863662019-07-29 13:05:15 -0400561 "SkString _sample121(\"_sample121\");",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400562 "this->invokeChild(_outer.child1_index, _input121.c_str(), &_sample121, args);",
563 "SkString _input93 = SkStringPrintf(\"%s * %s\", args.fInputColor, _sample121.c_str());",
Ethan Nicholas13863662019-07-29 13:05:15 -0400564 "SkString _sample93(\"_sample93\");",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400565 "this->invokeChild(_outer.child2_index, _input93.c_str(), &_sample93, args);",
Ethan Nicholas13863662019-07-29 13:05:15 -0400566 "fragBuilder->codeAppendf(\"%s = %s;\\n\", args.fOutputColor, _sample93.c_str());",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400567 "this->registerChildProcessor(src.childProcessor(child1_index).clone());",
568 "this->registerChildProcessor(src.childProcessor(child2_index).clone());"
Michael Ludwig92e4c7f2018-08-30 16:08:18 -0400569 });
570}
Michael Ludwig1fc5fbd2018-09-07 13:13:06 -0400571
572DEF_TEST(SkSLFPChildFPAndGlobal, r) {
573 test(r,
574 "in fragmentProcessor child;"
575 "bool hasCap = sk_Caps.externalTextureSupport;"
576 "void main() {"
577 " if (hasCap) {"
Ethan Nicholas13863662019-07-29 13:05:15 -0400578 " sk_OutColor = sample(child, sk_InColor);"
Michael Ludwig1fc5fbd2018-09-07 13:13:06 -0400579 " } else {"
580 " sk_OutColor = half4(1);"
581 " }"
582 "}",
583 *SkSL::ShaderCapsFactory::Default(),
584 {
585 "this->registerChildProcessor(std::move(child));"
586 },
587 {
588 "hasCap = sk_Caps.externalTextureSupport;",
Ethan Nicholas13863662019-07-29 13:05:15 -0400589 "fragBuilder->codeAppendf(\"bool hasCap = %s;\\nif (hasCap) {\", (hasCap ? \"true\" : "
590 "\"false\"));",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400591 "SkString _input130 = SkStringPrintf(\"%s\", args.fInputColor);",
Ethan Nicholas13863662019-07-29 13:05:15 -0400592 "SkString _sample130(\"_sample130\");",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400593 "this->invokeChild(_outer.child_index, _input130.c_str(), &_sample130, args);",
Ethan Nicholas13863662019-07-29 13:05:15 -0400594 "fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(1.0);\\n}\\n\","
595 " args.fOutputColor, _sample130.c_str(), args.fOutputColor);",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400596 "this->registerChildProcessor(src.childProcessor(child_index).clone());"
Michael Ludwig1fc5fbd2018-09-07 13:13:06 -0400597 });
598}
Michael Ludwig9094f2c2018-09-07 13:44:21 -0400599
600DEF_TEST(SkSLFPChildProcessorInlineFieldAccess, r) {
601 test(r,
602 "in fragmentProcessor child;"
603 "void main() {"
604 " if (child.preservesOpaqueInput) {"
Ethan Nicholas13863662019-07-29 13:05:15 -0400605 " sk_OutColor = sample(child, sk_InColor);"
Michael Ludwig9094f2c2018-09-07 13:44:21 -0400606 " } else {"
607 " sk_OutColor = half4(1);"
608 " }"
609 "}",
610 *SkSL::ShaderCapsFactory::Default(),
611 {
612 "this->registerChildProcessor(std::move(child));"
613 },
614 {
615 "fragBuilder->codeAppendf(\"if (%s) {\", "
Ethan Nicholas13863662019-07-29 13:05:15 -0400616 "(_outer.childProcessor(_outer.child_index).preservesOpaqueInput() ? ",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400617 "SkString _input105 = SkStringPrintf(\"%s\", args.fInputColor);",
Ethan Nicholas13863662019-07-29 13:05:15 -0400618 "SkString _sample105(\"_sample105\");",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400619 "this->invokeChild(_outer.child_index, _input105.c_str(), &_sample105, args);",
Ethan Nicholas13863662019-07-29 13:05:15 -0400620 "fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(1.0);\\n}\\n\","
621 " args.fOutputColor, _sample105.c_str(), args.fOutputColor);",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400622 "this->registerChildProcessor(src.childProcessor(child_index).clone());"
Michael Ludwig9094f2c2018-09-07 13:44:21 -0400623 });
624}
625
626DEF_TEST(SkSLFPChildProcessorFieldAccess, r) {
627 test(r,
628 "in fragmentProcessor child;"
629 "bool opaque = child.preservesOpaqueInput;"
630 "void main() {"
631 " if (opaque) {"
Ethan Nicholas13863662019-07-29 13:05:15 -0400632 " sk_OutColor = sample(child);"
Michael Ludwig9094f2c2018-09-07 13:44:21 -0400633 " } else {"
634 " sk_OutColor = half4(0.5);"
635 " }"
636 "}",
637 *SkSL::ShaderCapsFactory::Default(),
638 {
639 "this->registerChildProcessor(std::move(child));"
640 },
641 {
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400642 "opaque = _outer.childProcessor(_outer.child_index).preservesOpaqueInput();",
Ethan Nicholas13863662019-07-29 13:05:15 -0400643 "fragBuilder->codeAppendf(\"bool opaque = %s;\\nif (opaque) {\", (opaque ? \"true\" : "
644 "\"false\"));",
645 "SkString _sample126(\"_sample126\");",
646 "this->invokeChild(_outer.child_index, &_sample126, args);",
647 "fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(0.5);\\n}\\n\","
648 " args.fOutputColor, _sample126.c_str(), args.fOutputColor);",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400649 "this->registerChildProcessor(src.childProcessor(child_index).clone());"
Michael Ludwig9094f2c2018-09-07 13:44:21 -0400650 });
651}
Florin Malita390f9bd2019-03-04 12:25:57 -0500652
653DEF_TEST(SkSLFPNullableChildProcessor, r) {
654 test(r,
655 "in fragmentProcessor? child;"
656 "void main() {"
657 " if (child != null) {"
Ethan Nicholas13863662019-07-29 13:05:15 -0400658 " sk_OutColor = sample(child);"
Florin Malita390f9bd2019-03-04 12:25:57 -0500659 " } else {"
660 " sk_OutColor = half4(0.5);"
661 " }"
662 "}",
663 *SkSL::ShaderCapsFactory::Default(),
664 {},
665 {
Ethan Nicholas13863662019-07-29 13:05:15 -0400666 "fragBuilder->codeAppendf(\"if (%s) {\", _outer.child_index >= 0 ? \"true\" : "
667 "\"false\");",
668 "SkString _sample93(\"_sample93\");",
Ethan Nicholasbcd51e82019-04-09 10:40:41 -0400669 "if (_outer.child_index >= 0) {",
Ethan Nicholas13863662019-07-29 13:05:15 -0400670 "this->invokeChild(_outer.child_index, &_sample93, args);",
Florin Malita390f9bd2019-03-04 12:25:57 -0500671 "}",
Ethan Nicholas13863662019-07-29 13:05:15 -0400672 "fragBuilder->codeAppendf(\"\\n %s = %s;\\n} else {\\n %s = half4(0.5);\\n}\\n\","
673 " args.fOutputColor, _sample93.c_str(), args.fOutputColor);"
674
Florin Malita390f9bd2019-03-04 12:25:57 -0500675 });
676}
Ethan Nicholas33c59ed2019-08-13 10:21:38 -0400677
678DEF_TEST(SkSLFPBadIn, r) {
679 test_failure(r,
680 "in half4 c;"
681 "void main() {"
682 " sk_OutColor = c;"
683 "}",
684 "error: 1: 'in' variable must be either 'uniform' or 'layout(key)', or there must be a "
685 "custom @setData function\n1 error\n");
686}
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400687
688DEF_TEST(SkSLFPSampleCoords, r) {
689 test(r,
690 "in fragmentProcessor child;"
691 "@coordTransform { SkMatrix() }"
692 "void main() {"
693 " sk_OutColor = sample(child) + sample(child, sk_TransformedCoords2D[0] / 2);"
694 "}",
695 *SkSL::ShaderCapsFactory::Default(),
696 {},
697 {
698 "SkString _sample94(\"_sample94\");\n",
699 "this->invokeChild(_outer.child_index, &_sample94, args);\n",
700 "SkString _sample110(\"_sample110\");\n",
701 "SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D("
702 "args.fTransformedCoords[0].fVaryingPoint);\n",
703 "SkString _coords110 = SkStringPrintf(\"%s / 2.0\", "
Brian Salomonbf5c0c02019-11-11 14:55:28 -0500704 "sk_TransformedCoords2D_0.c_str());\n",
Ethan Nicholasd4efe682019-08-29 16:10:13 -0400705 "this->invokeChild(_outer.child_index, &_sample110, args, _coords110.c_str());\n",
706 "fragBuilder->codeAppendf(\"%s = %s + %s;\\n\", args.fOutputColor, _sample94.c_str(), "
707 "_sample110.c_str());\n"
708 });
709}
Ethan Nicholas095f5b42019-08-30 11:51:41 -0400710
711DEF_TEST(SkSLFPFunction, r) {
712 test(r,
713 "in fragmentProcessor? child;"
714 "half4 flip(half4 c) { return c.abgr; }"
715 "void main() {"
716 " sk_OutColor = flip(sk_InColor);"
717 "}",
718 *SkSL::ShaderCapsFactory::Default(),
719 {},
720 {
721 "SkString flip_name;",
722 "const GrShaderVar flip_args[] = { GrShaderVar(\"c\", kHalf4_GrSLType)};",
723 "fragBuilder->emitFunction(kHalf4_GrSLType, \"flip\", 1, flip_args, "
724 "\"return c.wzyx;\\n\", &flip_name);",
725 "fragBuilder->codeAppendf(\"%s = %s(%s);\\n\", args.fOutputColor, flip_name.c_str(), "
726 "args.fInputColor);"
727 });
728}