blob: 3e95d9975f6adf1a66addf5c55dd5a623cad2104 [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,
64 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -040065 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -040066 "}",
67 *SkSL::ShaderCapsFactory::Default(),
68 {
69 "/*\n"
70 " * Copyright 2017 Google Inc.\n"
71 " *\n"
72 " * Use of this source code is governed by a BSD-style license that can be\n"
73 " * found in the LICENSE file.\n"
74 " */\n"
75 "\n"
76 "/*\n"
77 " * This file was autogenerated from GrTest.fp; do not modify.\n"
78 " */\n"
79 "#ifndef GrTest_DEFINED\n"
80 "#define GrTest_DEFINED\n"
Ethan Nicholasceb4d482017-07-10 15:40:20 -040081 "#include \"SkTypes.h\"\n"
82 "#if SK_SUPPORT_GPU\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -040083 "#include \"GrFragmentProcessor.h\"\n"
84 "#include \"GrCoordTransform.h\"\n"
Ethan Nicholas68990be2017-07-13 09:36:52 -040085 "#include \"GrColorSpaceXform.h\"\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -040086 "class GrTest : public GrFragmentProcessor {\n"
87 "public:\n"
Brian Salomonaff329b2017-08-11 09:40:37 -040088 " static std::unique_ptr<GrFragmentProcessor> Make() {\n"
89 " return std::unique_ptr<GrFragmentProcessor>(new GrTest());\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -040090 " }\n"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -040091 " GrTest(const GrTest& src);\n"
Brian Salomonaff329b2017-08-11 09:40:37 -040092 " std::unique_ptr<GrFragmentProcessor> clone() const override;\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -040093 " const char* name() const override { return \"Test\"; }\n"
94 "private:\n"
95 " GrTest()\n"
Ethan Nicholasabff9562017-10-09 10:54:08 -040096 " : INHERITED(kGrTest_ClassID, kNone_OptimizationFlags) {\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -040097 " }\n"
98 " GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;\n"
99 " void onGetGLSLProcessorKey(const GrShaderCaps&,GrProcessorKeyBuilder*) "
100 "const override;\n"
101 " bool onIsEqual(const GrFragmentProcessor&) const override;\n"
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400102 " GR_DECLARE_FRAGMENT_PROCESSOR_TEST\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400103 " typedef GrFragmentProcessor INHERITED;\n"
104 "};\n"
105 "#endif\n"
Ethan Nicholasceb4d482017-07-10 15:40:20 -0400106 "#endif\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400107 },
108 {
109 "/*\n"
110 " * Copyright 2017 Google Inc.\n"
111 " *\n"
112 " * Use of this source code is governed by a BSD-style license that can be\n"
113 " * found in the LICENSE file.\n"
114 " */\n"
115 "\n"
116 "/*\n"
117 " * This file was autogenerated from GrTest.fp; do not modify.\n"
118 " */\n"
119 "#include \"GrTest.h\"\n"
Ethan Nicholasceb4d482017-07-10 15:40:20 -0400120 "#if SK_SUPPORT_GPU\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400121 "#include \"glsl/GrGLSLColorSpaceXformHelper.h\"\n"
122 "#include \"glsl/GrGLSLFragmentProcessor.h\"\n"
123 "#include \"glsl/GrGLSLFragmentShaderBuilder.h\"\n"
124 "#include \"glsl/GrGLSLProgramBuilder.h\"\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400125 "#include \"SkSLCPP.h\"\n"
126 "#include \"SkSLUtil.h\"\n"
127 "class GrGLSLTest : public GrGLSLFragmentProcessor {\n"
128 "public:\n"
129 " GrGLSLTest() {}\n"
130 " void emitCode(EmitArgs& args) override {\n"
131 " GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;\n"
132 " const GrTest& _outer = args.fFp.cast<GrTest>();\n"
133 " (void) _outer;\n"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400134 " fragBuilder->codeAppendf(\"%s = half4(1.0);\\n\", args.fOutputColor);\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400135 " }\n"
136 "private:\n"
137 " void onSetData(const GrGLSLProgramDataManager& pdman, "
138 "const GrFragmentProcessor& _proc) override {\n"
139 " }\n"
140 "};\n"
141 "GrGLSLFragmentProcessor* GrTest::onCreateGLSLInstance() const {\n"
142 " return new GrGLSLTest();\n"
143 "}\n"
144 "void GrTest::onGetGLSLProcessorKey(const GrShaderCaps& caps, "
145 "GrProcessorKeyBuilder* b) const {\n"
146 "}\n"
147 "bool GrTest::onIsEqual(const GrFragmentProcessor& other) const {\n"
148 " const GrTest& that = other.cast<GrTest>();\n"
149 " (void) that;\n"
150 " return true;\n"
151 "}\n"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400152 "GrTest::GrTest(const GrTest& src)\n"
Ethan Nicholasabff9562017-10-09 10:54:08 -0400153 ": INHERITED(kGrTest_ClassID, src.optimizationFlags()) {\n"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400154 "}\n"
Brian Salomonaff329b2017-08-11 09:40:37 -0400155 "std::unique_ptr<GrFragmentProcessor> GrTest::clone() const {\n"
156 " return std::unique_ptr<GrFragmentProcessor>(new GrTest(*this));\n"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400157 "}\n"
Ethan Nicholasceb4d482017-07-10 15:40:20 -0400158 "#endif\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400159 });
160}
161
162DEF_TEST(SkSLFPInput, r) {
163 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400164 "in half2 point;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400165 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400166 "sk_OutColor = half4(point, point);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400167 "}",
168 *SkSL::ShaderCapsFactory::Default(),
169 {
170 "SkPoint point() const { return fPoint; }",
Brian Salomonaff329b2017-08-11 09:40:37 -0400171 "static std::unique_ptr<GrFragmentProcessor> Make(SkPoint point) {",
172 "return std::unique_ptr<GrFragmentProcessor>(new GrTest(point));",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400173 "GrTest(SkPoint point)",
174 ", fPoint(point)"
175 },
176 {
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400177 "fragBuilder->codeAppendf(\"%s = half4(half2(%f, %f), half2(%f, %f));\\n\", "
Ethan Nicholas762466e2017-06-29 10:03:38 -0400178 "args.fOutputColor, _outer.point().fX, _outer.point().fY, "
179 "_outer.point().fX, _outer.point().fY);",
180 "if (fPoint != that.fPoint) return false;"
181 });
182}
183
184DEF_TEST(SkSLFPUniform, r) {
185 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400186 "uniform half4 color;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400187 "void main() {"
188 "sk_OutColor = color;"
189 "}",
190 *SkSL::ShaderCapsFactory::Default(),
191 {
Brian Salomonaff329b2017-08-11 09:40:37 -0400192 "static std::unique_ptr<GrFragmentProcessor> Make()"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400193 },
194 {
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400195 "fColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
Ethan Nicholas762466e2017-06-29 10:03:38 -0400196 "kDefault_GrSLPrecision, \"color\");",
197 });
198}
199
200DEF_TEST(SkSLFPInUniform, r) {
201 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400202 "in uniform half4 color;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400203 "void main() {"
204 "sk_OutColor = color;"
205 "}",
206 *SkSL::ShaderCapsFactory::Default(),
207 {
Brian Salomonaff329b2017-08-11 09:40:37 -0400208 "static std::unique_ptr<GrFragmentProcessor> Make(SkRect color) {",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400209 },
210 {
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400211 "fColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "
Ethan Nicholas762466e2017-06-29 10:03:38 -0400212 "kDefault_GrSLPrecision, \"color\");",
213 "const SkRect colorValue = _outer.color();",
Ethan Nicholasee338732017-07-17 15:13:45 -0400214 "pdman.set4fv(fColorVar, 1, (float*) &colorValue);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400215 });
216}
217
218DEF_TEST(SkSLFPSections, r) {
219 test(r,
220 "@header { header 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 {
Ethan Nicholasceb4d482017-07-10 15:40:20 -0400226 "#if SK_SUPPORT_GPU\n header section"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400227 },
228 {});
229 test(r,
230 "@class { class section }"
231 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400232 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400233 "}",
234 *SkSL::ShaderCapsFactory::Default(),
235 {
236 "class GrTest : public GrFragmentProcessor {\n"
237 "public:\n"
238 " class section"
239 },
240 {});
241 test(r,
242 "@cpp { cpp section }"
243 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400244 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400245 "}",
246 *SkSL::ShaderCapsFactory::Default(),
247 {},
248 {"cpp section"});
249 test(r,
250 "@constructorParams { int x, float y, std::vector<float> z }"
Ethan Nicholas8aa45692017-09-20 11:24:15 -0400251 "in float w;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400252 "void main() {"
Ethan Nicholas8aa45692017-09-20 11:24:15 -0400253 "sk_OutColor = float4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400254 "}",
255 *SkSL::ShaderCapsFactory::Default(),
256 {
257 "Make(float w, int x, float y, std::vector<float> z )",
Brian Salomonaff329b2017-08-11 09:40:37 -0400258 "return std::unique_ptr<GrFragmentProcessor>(new GrTest(w, x, y, z));",
Ethan Nicholas762466e2017-06-29 10:03:38 -0400259 "GrTest(float w, int x, float y, std::vector<float> z )",
260 ", fW(w) {"
261 },
262 {});
263 test(r,
264 "@constructor { constructor 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 {
270 "private:\n constructor section"
271 },
272 {});
273 test(r,
274 "@initializers { initializers section }"
275 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400276 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400277 "}",
278 *SkSL::ShaderCapsFactory::Default(),
279 {
Ethan Nicholasabff9562017-10-09 10:54:08 -0400280 ": INHERITED(kGrTest_ClassID, kNone_OptimizationFlags)\n , initializers section"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400281 },
282 {});
283 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400284 "half x = 10;"
285 "@emitCode { fragBuilder->codeAppendf(\"half y = %d\\n\", x * 2); }"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400286 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400287 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400288 "}",
289 *SkSL::ShaderCapsFactory::Default(),
290 {},
291 {
292 "x = 10.0;\n"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400293 " fragBuilder->codeAppendf(\"half y = %d\\n\", x * 2);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400294 });
295 test(r,
296 "@fields { fields section }"
Ethan Nicholasf57c0d62017-07-31 11:18:22 -0400297 "@clone { }"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400298 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400299 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400300 "}",
301 *SkSL::ShaderCapsFactory::Default(),
302 {
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400303 "GR_DECLARE_FRAGMENT_PROCESSOR_TEST\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400304 " fields section typedef GrFragmentProcessor INHERITED;"
305 },
306 {});
307 test(r,
308 "@make { make section }"
309 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400310 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400311 "}",
312 *SkSL::ShaderCapsFactory::Default(),
313 {
314 "public:\n"
315 " make section"
316 },
317 {});
318 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400319 "uniform half calculated;"
320 "in half provided;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400321 "@setData(varName) { varName.set1f(calculated, provided * 2); }"
322 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400323 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400324 "}",
325 *SkSL::ShaderCapsFactory::Default(),
326 {},
327 {
328 "void onSetData(const GrGLSLProgramDataManager& varName, "
329 "const GrFragmentProcessor& _proc) override {\n",
330 "UniformHandle& calculated = fCalculatedVar;",
331 "auto provided = _outer.provided();",
332 "varName.set1f(calculated, provided * 2);"
333 });
334 test(r,
335 "@test(testDataName) { testDataName section }"
336 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400337 "sk_OutColor = half4(1);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400338 "}",
339 *SkSL::ShaderCapsFactory::Default(),
340 {},
341 {
342 "#if GR_TEST_UTILS\n"
Brian Salomonaff329b2017-08-11 09:40:37 -0400343 "std::unique_ptr<GrFragmentProcessor> GrTest::TestCreate(GrProcessorTestData* testDataName) {\n"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400344 " testDataName section }\n"
345 "#endif"
346 });
347}
348
349DEF_TEST(SkSLFPColorSpaceXform, r) {
350 test(r,
351 "in uniform sampler2D image;"
352 "in uniform colorSpaceXform colorXform;"
353 "void main() {"
Ethan Nicholas8aa45692017-09-20 11:24:15 -0400354 "sk_OutColor = sk_InColor * texture(image, float2(0, 0), colorXform);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400355 "}",
356 *SkSL::ShaderCapsFactory::Default(),
357 {
Ethan Nicholasceb4d482017-07-10 15:40:20 -0400358 "sk_sp<GrColorSpaceXform> colorXform() const { return fColorXform; }",
359 "GrTest(sk_sp<GrTextureProxy> image, sk_sp<GrColorSpaceXform> colorXform)",
360 "this->addTextureSampler(&fImage);",
361 "sk_sp<GrColorSpaceXform> fColorXform;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400362 },
363 {
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400364 "fragBuilder->codeAppendf(\"half4 _tmpVar1;%s = %s * %stexture(%s, "
Ethan Nicholas8aa45692017-09-20 11:24:15 -0400365 "float2(0.0, 0.0)).%s%s;\\n\", args.fOutputColor, args.fInputColor ? args.fInputColor : "
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400366 "\"half4(1)\", fColorSpaceHelper.isValid() ? \"(_tmpVar1 = \" : \"\", "
Ethan Nicholas68990be2017-07-13 09:36:52 -0400367 "fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(), "
Ethan Nicholasceb4d482017-07-10 15:40:20 -0400368 "fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str(), "
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400369 "fColorSpaceHelper.isValid() ? SkStringPrintf(\", half4(clamp((%s * half4(_tmpVar1.rgb, "
Ethan Nicholas68990be2017-07-13 09:36:52 -0400370 "1.0)).rgb, 0.0, _tmpVar1.a), _tmpVar1.a))\", args.fUniformHandler->getUniformCStr("
371 "fColorSpaceHelper.gamutXformUniform())).c_str() : \"\");"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400372 });
373}
374
375DEF_TEST(SkSLFPTransformedCoords, r) {
376 test(r,
377 "void main() {"
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400378 "sk_OutColor = half4(sk_TransformedCoords2D[0], sk_TransformedCoords2D[0]);"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400379 "}",
380 *SkSL::ShaderCapsFactory::Default(),
381 {},
382 {
Brian Osman72a37be2017-08-15 09:19:53 -0400383 "SkString sk_TransformedCoords2D_0 = "
Ethan Nicholas762466e2017-06-29 10:03:38 -0400384 "fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);",
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400385 "fragBuilder->codeAppendf(\"%s = half4(%s, %s);\\n\", args.fOutputColor, "
Ethan Nicholas762466e2017-06-29 10:03:38 -0400386 "sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str());"
387 });
388
389}
390
391DEF_TEST(SkSLFPLayoutWhen, r) {
392 test(r,
Ethan Nicholasf7b88202017-09-18 14:10:39 -0400393 "layout(when=someExpression(someOtherExpression())) uniform half sometimes;"
Ethan Nicholas762466e2017-06-29 10:03:38 -0400394 "void main() {"
395 "}",
396 *SkSL::ShaderCapsFactory::Default(),
397 {},
398 {
399 "if (someExpression(someOtherExpression())) {\n"
400 " fSometimesVar = args.fUniformHandler->addUniform"
401 });
402
403}
404
405#endif