blob: f1a65fcfdb9d3967f08f75db702cb0752121bdae [file] [log] [blame]
Ethan Nicholas762466e2017-06-29 10:03:38 -04001/*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkSLCompiler.h"
9
10#include "Test.h"
11
12#if SK_SUPPORT_GPU
13
14static void test(skiatest::Reporter* r, const char* src, const GrShaderCaps& caps,
15 std::vector<const char*> expectedH, std::vector<const char*> expectedCPP) {
16 SkSL::Program::Settings settings;
17 settings.fCaps = &caps;
18 SkSL::Compiler compiler;
19 SkSL::StringStream output;
20 std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
21 SkSL::Program::kFragmentProcessor_Kind,
Brian Osman93ba0a42017-08-14 14:48:10 -040022 SkSL::String(src),
Ethan Nicholas762466e2017-06-29 10:03:38 -040023 settings);
24 if (!program) {
25 SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
26 return;
27 }
28 REPORTER_ASSERT(r, program);
29 bool success = compiler.toH(*program, "Test", output);
30 if (!success) {
31 SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
32 }
33 REPORTER_ASSERT(r, success);
34 if (success) {
35 for (const char* expected : expectedH) {
36 bool found = strstr(output.str().c_str(), expected);
37 if (!found) {
38 SkDebugf("HEADER MISMATCH:\nsource:\n%s\n\nexpected:\n'%s'\n\nreceived:\n'%s'", src,
39 expected, output.str().c_str());
40 }
41 REPORTER_ASSERT(r, found);
42 }
43 }
44 output.reset();
45 success = compiler.toCPP(*program, "Test", output);
46 if (!success) {
47 SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
48 }
49 REPORTER_ASSERT(r, success);
50 if (success) {
51 for (const char* expected : expectedCPP) {
52 bool found = strstr(output.str().c_str(), expected);
53 if (!found) {
54 SkDebugf("CPP MISMATCH:\nsource:\n%s\n\nexpected:\n'%s'\n\nreceived:\n'%s'", src,
55 expected, output.str().c_str());
56 }
57 REPORTER_ASSERT(r, found);
58 }
59 }
60}
61
62DEF_TEST(SkSLFPHelloWorld, r) {
63 test(r,
Ethan Nicholas130fb3f2018-02-01 12:14:34 -050064 "/* HEADER */"
Ethan Nicholas762466e2017-06-29 10:03:38 -040065 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -040066 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -040067 "}",
68 *SkSL::ShaderCapsFactory::Default(),
69 {
Ethan Nicholas130fb3f2018-02-01 12:14:34 -050070 "/* HEADER */\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -040071 "\n"
Ethan Nicholas130fb3f2018-02-01 12:14:34 -050072 "/**************************************************************************************************\n"
73 " *** This file was autogenerated from GrTest.fp; do not modify.\n"
74 " **************************************************************************************************/\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -040075 "#ifndef GrTest_DEFINED\n"
76 "#define GrTest_DEFINED\n"
Ethan Nicholasceb4d482017-07-10 15:40:20 -040077 "#include \"SkTypes.h\"\n"
78 "#if SK_SUPPORT_GPU\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -040079 "#include \"GrFragmentProcessor.h\"\n"
80 "#include \"GrCoordTransform.h\"\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -040081 "class GrTest : public GrFragmentProcessor {\n"
82 "public:\n"
Brian Salomonaff329b2017-08-11 09:40:37 -040083 " static std::unique_ptr<GrFragmentProcessor> Make() {\n"
84 " return std::unique_ptr<GrFragmentProcessor>(new GrTest());\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -040085 " }\n"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -040086 " GrTest(const GrTest& src);\n"
Brian Salomonaff329b2017-08-11 09:40:37 -040087 " std::unique_ptr<GrFragmentProcessor> clone() const override;\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -040088 " const char* name() const override { return \"Test\"; }\n"
89 "private:\n"
90 " GrTest()\n"
Ethan Nicholasabff9562017-10-09 10:54:08 -040091 " : INHERITED(kGrTest_ClassID, kNone_OptimizationFlags) {\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -040092 " }\n"
93 " GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;\n"
94 " void onGetGLSLProcessorKey(const GrShaderCaps&,GrProcessorKeyBuilder*) "
95 "const override;\n"
96 " bool onIsEqual(const GrFragmentProcessor&) const override;\n"
Brian Salomon0c26a9d2017-07-06 10:09:38 -040097 " GR_DECLARE_FRAGMENT_PROCESSOR_TEST\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -040098 " typedef GrFragmentProcessor INHERITED;\n"
99 "};\n"
100 "#endif\n"
Ethan Nicholasceb4d482017-07-10 15:40:20 -0400101 "#endif\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400102 },
103 {
Ethan Nicholas130fb3f2018-02-01 12:14:34 -0500104 "/* HEADER */\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400105 "\n"
Ethan Nicholas130fb3f2018-02-01 12:14:34 -0500106 "/**************************************************************************************************\n"
107 " *** This file was autogenerated from GrTest.fp; do not modify.\n"
108 " **************************************************************************************************/\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400109 "#include \"GrTest.h\"\n"
Ethan Nicholasceb4d482017-07-10 15:40:20 -0400110 "#if SK_SUPPORT_GPU\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400111 "#include \"glsl/GrGLSLFragmentProcessor.h\"\n"
112 "#include \"glsl/GrGLSLFragmentShaderBuilder.h\"\n"
113 "#include \"glsl/GrGLSLProgramBuilder.h\"\n"
Ethan Nicholas2d5f9b32017-12-13 14:36:14 -0500114 "#include \"GrTexture.h\"\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400115 "#include \"SkSLCPP.h\"\n"
116 "#include \"SkSLUtil.h\"\n"
117 "class GrGLSLTest : public GrGLSLFragmentProcessor {\n"
118 "public:\n"
119 " GrGLSLTest() {}\n"
120 " void emitCode(EmitArgs& args) override {\n"
121 " GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;\n"
122 " const GrTest& _outer = args.fFp.cast<GrTest>();\n"
123 " (void) _outer;\n"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400124 " fragBuilder->codeAppendf(\"%s = half4(1.0);\\n\", args.fOutputColor);\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400125 " }\n"
126 "private:\n"
127 " void onSetData(const GrGLSLProgramDataManager& pdman, "
128 "const GrFragmentProcessor& _proc) override {\n"
129 " }\n"
130 "};\n"
131 "GrGLSLFragmentProcessor* GrTest::onCreateGLSLInstance() const {\n"
132 " return new GrGLSLTest();\n"
133 "}\n"
134 "void GrTest::onGetGLSLProcessorKey(const GrShaderCaps& caps, "
135 "GrProcessorKeyBuilder* b) const {\n"
136 "}\n"
137 "bool GrTest::onIsEqual(const GrFragmentProcessor& other) const {\n"
138 " const GrTest& that = other.cast<GrTest>();\n"
139 " (void) that;\n"
140 " return true;\n"
141 "}\n"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400142 "GrTest::GrTest(const GrTest& src)\n"
Ethan Nicholasabff9562017-10-09 10:54:08 -0400143 ": INHERITED(kGrTest_ClassID, src.optimizationFlags()) {\n"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400144 "}\n"
Brian Salomonaff329b2017-08-11 09:40:37 -0400145 "std::unique_ptr<GrFragmentProcessor> GrTest::clone() const {\n"
146 " return std::unique_ptr<GrFragmentProcessor>(new GrTest(*this));\n"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400147 "}\n"
Ethan Nicholasceb4d482017-07-10 15:40:20 -0400148 "#endif\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400149 });
150}
151
152DEF_TEST(SkSLFPInput, r) {
153 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400154 "in half2 point;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400155 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400156 "sk_OutColor = half4(point, point);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400157 "}",
158 *SkSL::ShaderCapsFactory::Default(),
159 {
160 "SkPoint point() const { return fPoint; }",
Brian Salomonaff329b2017-08-11 09:40:37 -0400161 "static std::unique_ptr<GrFragmentProcessor> Make(SkPoint point) {",
162 "return std::unique_ptr<GrFragmentProcessor>(new GrTest(point));",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400163 "GrTest(SkPoint point)",
164 ", fPoint(point)"
165 },
166 {
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400167 "fragBuilder->codeAppendf(\"%s = half4(half2(%f, %f), half2(%f, %f));\\n\", "
Ethan Nicholas762466e2017-06-29 10:03:38 -0400168 "args.fOutputColor, _outer.point().fX, _outer.point().fY, "
169 "_outer.point().fX, _outer.point().fY);",
170 "if (fPoint != that.fPoint) return false;"
171 });
172}
173
174DEF_TEST(SkSLFPUniform, r) {
175 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400176 "uniform half4 color;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400177 "void main() {"
178 "sk_OutColor = color;"
179 "}",
180 *SkSL::ShaderCapsFactory::Default(),
181 {
Brian Salomonaff329b2017-08-11 09:40:37 -0400182 "static std::unique_ptr<GrFragmentProcessor> Make()"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400183 },
184 {
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400185 "fColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
Ethan Nicholas762466e2017-06-29 10:03:38 -0400186 "kDefault_GrSLPrecision, \"color\");",
187 });
188}
189
190DEF_TEST(SkSLFPInUniform, r) {
191 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400192 "in uniform half4 color;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400193 "void main() {"
194 "sk_OutColor = color;"
195 "}",
196 *SkSL::ShaderCapsFactory::Default(),
197 {
Brian Salomonaff329b2017-08-11 09:40:37 -0400198 "static std::unique_ptr<GrFragmentProcessor> Make(SkRect color) {",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400199 },
200 {
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400201 "fColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
Ethan Nicholas762466e2017-06-29 10:03:38 -0400202 "kDefault_GrSLPrecision, \"color\");",
203 "const SkRect colorValue = _outer.color();",
Ethan Nicholasee338732017-07-17 15:13:45 -0400204 "pdman.set4fv(fColorVar, 1, (float*) &colorValue);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400205 });
206}
207
208DEF_TEST(SkSLFPSections, r) {
209 test(r,
210 "@header { header section }"
211 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400212 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400213 "}",
214 *SkSL::ShaderCapsFactory::Default(),
215 {
Ethan Nicholasceb4d482017-07-10 15:40:20 -0400216 "#if SK_SUPPORT_GPU\n header section"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400217 },
218 {});
219 test(r,
220 "@class { class section }"
221 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400222 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400223 "}",
224 *SkSL::ShaderCapsFactory::Default(),
225 {
226 "class GrTest : public GrFragmentProcessor {\n"
227 "public:\n"
228 " class section"
229 },
230 {});
231 test(r,
232 "@cpp { cpp section }"
233 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400234 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400235 "}",
236 *SkSL::ShaderCapsFactory::Default(),
237 {},
238 {"cpp section"});
239 test(r,
240 "@constructorParams { int x, float y, std::vector<float> z }"
Ethan Nicholas8aa45692017-09-20 11:24:15 -0400241 "in float w;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400242 "void main() {"
Ethan Nicholas8aa45692017-09-20 11:24:15 -0400243 "sk_OutColor = float4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400244 "}",
245 *SkSL::ShaderCapsFactory::Default(),
246 {
247 "Make(float w, int x, float y, std::vector<float> z )",
Brian Salomonaff329b2017-08-11 09:40:37 -0400248 "return std::unique_ptr<GrFragmentProcessor>(new GrTest(w, x, y, z));",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400249 "GrTest(float w, int x, float y, std::vector<float> z )",
250 ", fW(w) {"
251 },
252 {});
253 test(r,
254 "@constructor { constructor section }"
255 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400256 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400257 "}",
258 *SkSL::ShaderCapsFactory::Default(),
259 {
260 "private:\n constructor section"
261 },
262 {});
263 test(r,
264 "@initializers { initializers section }"
265 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400266 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400267 "}",
268 *SkSL::ShaderCapsFactory::Default(),
269 {
Ethan Nicholasabff9562017-10-09 10:54:08 -0400270 ": INHERITED(kGrTest_ClassID, kNone_OptimizationFlags)\n , initializers section"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400271 },
272 {});
273 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400274 "half x = 10;"
275 "@emitCode { fragBuilder->codeAppendf(\"half y = %d\\n\", x * 2); }"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400276 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400277 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400278 "}",
279 *SkSL::ShaderCapsFactory::Default(),
280 {},
281 {
282 "x = 10.0;\n"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400283 " fragBuilder->codeAppendf(\"half y = %d\\n\", x * 2);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400284 });
285 test(r,
286 "@fields { fields section }"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400287 "@clone { }"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400288 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400289 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400290 "}",
291 *SkSL::ShaderCapsFactory::Default(),
292 {
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400293 "GR_DECLARE_FRAGMENT_PROCESSOR_TEST\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400294 " fields section typedef GrFragmentProcessor INHERITED;"
295 },
296 {});
297 test(r,
298 "@make { make section }"
299 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400300 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400301 "}",
302 *SkSL::ShaderCapsFactory::Default(),
303 {
304 "public:\n"
305 " make section"
306 },
307 {});
308 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400309 "uniform half calculated;"
310 "in half provided;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400311 "@setData(varName) { varName.set1f(calculated, provided * 2); }"
312 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400313 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400314 "}",
315 *SkSL::ShaderCapsFactory::Default(),
316 {},
317 {
318 "void onSetData(const GrGLSLProgramDataManager& varName, "
319 "const GrFragmentProcessor& _proc) override {\n",
320 "UniformHandle& calculated = fCalculatedVar;",
321 "auto provided = _outer.provided();",
322 "varName.set1f(calculated, provided * 2);"
323 });
324 test(r,
325 "@test(testDataName) { testDataName section }"
326 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400327 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400328 "}",
329 *SkSL::ShaderCapsFactory::Default(),
330 {},
331 {
332 "#if GR_TEST_UTILS\n"
Brian Salomonaff329b2017-08-11 09:40:37 -0400333 "std::unique_ptr<GrFragmentProcessor> GrTest::TestCreate(GrProcessorTestData* testDataName) {\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400334 " testDataName section }\n"
335 "#endif"
336 });
337}
338
Ethan Nicholas762466e2017-06-29 10:03:38 -0400339DEF_TEST(SkSLFPTransformedCoords, r) {
340 test(r,
341 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400342 "sk_OutColor = half4(sk_TransformedCoords2D[0], sk_TransformedCoords2D[0]);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400343 "}",
344 *SkSL::ShaderCapsFactory::Default(),
345 {},
346 {
Brian Osman72a37be2017-08-15 09:19:53 -0400347 "SkString sk_TransformedCoords2D_0 = "
Ethan Nicholas762466e2017-06-29 10:03:38 -0400348 "fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);",
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400349 "fragBuilder->codeAppendf(\"%s = half4(%s, %s);\\n\", args.fOutputColor, "
Ethan Nicholas762466e2017-06-29 10:03:38 -0400350 "sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str());"
351 });
352
353}
354
355DEF_TEST(SkSLFPLayoutWhen, r) {
356 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400357 "layout(when=someExpression(someOtherExpression())) uniform half sometimes;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400358 "void main() {"
359 "}",
360 *SkSL::ShaderCapsFactory::Default(),
361 {},
362 {
363 "if (someExpression(someOtherExpression())) {\n"
364 " fSometimesVar = args.fUniformHandler->addUniform"
365 });
366
367}
368
Ethan Nicholasc9472af2017-10-10 16:30:21 -0400369DEF_TEST(SkSLFPChildProcessors, r) {
370 test(r,
371 "in fragmentProcessor child1;"
372 "in fragmentProcessor child2;"
373 "void main() {"
374 " sk_OutColor = process(child1) * process(child2);"
375 "}",
376 *SkSL::ShaderCapsFactory::Default(),
377 {
378 "this->registerChildProcessor(std::move(child1));",
379 "this->registerChildProcessor(std::move(child2));"
380 },
381 {
382 "SkString _child0(\"_child0\");",
383 "this->emitChild(0, &_child0, args);",
384 "SkString _child1(\"_child1\");",
385 "this->emitChild(1, &_child1, args);",
386 "this->registerChildProcessor(src.childProcessor(0).clone());",
387 "this->registerChildProcessor(src.childProcessor(1).clone());"
388 });
389}
390
Ethan Nicholas762466e2017-06-29 10:03:38 -0400391#endif