1 /* 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 14 static 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 = ∩︀ 18 SkSL::Compiler compiler; 19 SkSL::StringStream output; 20 std::unique_ptr<SkSL::Program> program = compiler.convertProgram( 21 SkSL::Program::kFragmentProcessor_Kind, 22 SkSL::String(src), 23 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 62 DEF_TEST(SkSLFPHelloWorld, r) { 63 test(r, 64 "/* HEADER */" 65 "void main() {" 66 "sk_OutColor = half4(1);" 67 "}", 68 *SkSL::ShaderCapsFactory::Default(), 69 { 70 "/* HEADER */\n" 71 "\n" 72 "/**************************************************************************************************\n" 73 " *** This file was autogenerated from GrTest.fp; do not modify.\n" 74 " **************************************************************************************************/\n" 75 "#ifndef GrTest_DEFINED\n" 76 "#define GrTest_DEFINED\n" 77 "#include \"SkTypes.h\"\n" 78 "#if SK_SUPPORT_GPU\n" 79 "#include \"GrFragmentProcessor.h\"\n" 80 "#include \"GrCoordTransform.h\"\n" 81 "class GrTest : public GrFragmentProcessor {\n" 82 "public:\n" 83 " static std::unique_ptr<GrFragmentProcessor> Make() {\n" 84 " return std::unique_ptr<GrFragmentProcessor>(new GrTest());\n" 85 " }\n" 86 " GrTest(const GrTest& src);\n" 87 " std::unique_ptr<GrFragmentProcessor> clone() const override;\n" 88 " const char* name() const override { return \"Test\"; }\n" 89 "private:\n" 90 " GrTest()\n" 91 " : INHERITED(kGrTest_ClassID, kNone_OptimizationFlags) {\n" 92 " }\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" 97 " GR_DECLARE_FRAGMENT_PROCESSOR_TEST\n" 98 " typedef GrFragmentProcessor INHERITED;\n" 99 "};\n" 100 "#endif\n" 101 "#endif\n" 102 }, 103 { 104 "/* HEADER */\n" 105 "\n" 106 "/**************************************************************************************************\n" 107 " *** This file was autogenerated from GrTest.fp; do not modify.\n" 108 " **************************************************************************************************/\n" 109 "#include \"GrTest.h\"\n" 110 "#if SK_SUPPORT_GPU\n" 111 "#include \"glsl/GrGLSLFragmentProcessor.h\"\n" 112 "#include \"glsl/GrGLSLFragmentShaderBuilder.h\"\n" 113 "#include \"glsl/GrGLSLProgramBuilder.h\"\n" 114 "#include \"GrTexture.h\"\n" 115 "#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" 124 " fragBuilder->codeAppendf(\"%s = half4(1.0);\\n\", args.fOutputColor);\n" 125 " }\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" 142 "GrTest::GrTest(const GrTest& src)\n" 143 ": INHERITED(kGrTest_ClassID, src.optimizationFlags()) {\n" 144 "}\n" 145 "std::unique_ptr<GrFragmentProcessor> GrTest::clone() const {\n" 146 " return std::unique_ptr<GrFragmentProcessor>(new GrTest(*this));\n" 147 "}\n" 148 "#endif\n" 149 }); 150 } 151 152 DEF_TEST(SkSLFPInput, r) { 153 test(r, 154 "in half2 point;" 155 "void main() {" 156 "sk_OutColor = half4(point, point);" 157 "}", 158 *SkSL::ShaderCapsFactory::Default(), 159 { 160 "SkPoint point() const { return fPoint; }", 161 "static std::unique_ptr<GrFragmentProcessor> Make(SkPoint point) {", 162 "return std::unique_ptr<GrFragmentProcessor>(new GrTest(point));", 163 "GrTest(SkPoint point)", 164 ", fPoint(point)" 165 }, 166 { 167 "fragBuilder->codeAppendf(\"%s = half4(half2(%f, %f), half2(%f, %f));\\n\", " 168 "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 174 DEF_TEST(SkSLFPUniform, r) { 175 test(r, 176 "uniform half4 color;" 177 "void main() {" 178 "sk_OutColor = color;" 179 "}", 180 *SkSL::ShaderCapsFactory::Default(), 181 { 182 "static std::unique_ptr<GrFragmentProcessor> Make()" 183 }, 184 { 185 "fColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, " 186 "kDefault_GrSLPrecision, \"color\");", 187 }); 188 } 189 190 DEF_TEST(SkSLFPInUniform, r) { 191 test(r, 192 "in uniform half4 color;" 193 "void main() {" 194 "sk_OutColor = color;" 195 "}", 196 *SkSL::ShaderCapsFactory::Default(), 197 { 198 "static std::unique_ptr<GrFragmentProcessor> Make(SkRect color) {", 199 }, 200 { 201 "fColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, " 202 "kDefault_GrSLPrecision, \"color\");", 203 "const SkRect colorValue = _outer.color();", 204 "pdman.set4fv(fColorVar, 1, (float*) &colorValue);" 205 }); 206 } 207 208 DEF_TEST(SkSLFPSections, r) { 209 test(r, 210 "@header { header section }" 211 "void main() {" 212 "sk_OutColor = half4(1);" 213 "}", 214 *SkSL::ShaderCapsFactory::Default(), 215 { 216 "#if SK_SUPPORT_GPU\n header section" 217 }, 218 {}); 219 test(r, 220 "@class { class section }" 221 "void main() {" 222 "sk_OutColor = half4(1);" 223 "}", 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() {" 234 "sk_OutColor = half4(1);" 235 "}", 236 *SkSL::ShaderCapsFactory::Default(), 237 {}, 238 {"cpp section"}); 239 test(r, 240 "@constructorParams { int x, float y, std::vector<float> z }" 241 "in float w;" 242 "void main() {" 243 "sk_OutColor = float4(1);" 244 "}", 245 *SkSL::ShaderCapsFactory::Default(), 246 { 247 "Make(float w, int x, float y, std::vector<float> z )", 248 "return std::unique_ptr<GrFragmentProcessor>(new GrTest(w, x, y, z));", 249 "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() {" 256 "sk_OutColor = half4(1);" 257 "}", 258 *SkSL::ShaderCapsFactory::Default(), 259 { 260 "private:\n constructor section" 261 }, 262 {}); 263 test(r, 264 "@initializers { initializers section }" 265 "void main() {" 266 "sk_OutColor = half4(1);" 267 "}", 268 *SkSL::ShaderCapsFactory::Default(), 269 { 270 ": INHERITED(kGrTest_ClassID, kNone_OptimizationFlags)\n , initializers section" 271 }, 272 {}); 273 test(r, 274 "half x = 10;" 275 "@emitCode { fragBuilder->codeAppendf(\"half y = %d\\n\", x * 2); }" 276 "void main() {" 277 "sk_OutColor = half4(1);" 278 "}", 279 *SkSL::ShaderCapsFactory::Default(), 280 {}, 281 { 282 "x = 10.0;\n" 283 " fragBuilder->codeAppendf(\"half y = %d\\n\", x * 2);" 284 }); 285 test(r, 286 "@fields { fields section }" 287 "@clone { }" 288 "void main() {" 289 "sk_OutColor = half4(1);" 290 "}", 291 *SkSL::ShaderCapsFactory::Default(), 292 { 293 "GR_DECLARE_FRAGMENT_PROCESSOR_TEST\n" 294 " fields section typedef GrFragmentProcessor INHERITED;" 295 }, 296 {}); 297 test(r, 298 "@make { make section }" 299 "void main() {" 300 "sk_OutColor = half4(1);" 301 "}", 302 *SkSL::ShaderCapsFactory::Default(), 303 { 304 "public:\n" 305 " make section" 306 }, 307 {}); 308 test(r, 309 "uniform half calculated;" 310 "in half provided;" 311 "@setData(varName) { varName.set1f(calculated, provided * 2); }" 312 "void main() {" 313 "sk_OutColor = half4(1);" 314 "}", 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() {" 327 "sk_OutColor = half4(1);" 328 "}", 329 *SkSL::ShaderCapsFactory::Default(), 330 {}, 331 { 332 "#if GR_TEST_UTILS\n" 333 "std::unique_ptr<GrFragmentProcessor> GrTest::TestCreate(GrProcessorTestData* testDataName) {\n" 334 " testDataName section }\n" 335 "#endif" 336 }); 337 } 338 339 DEF_TEST(SkSLFPTransformedCoords, r) { 340 test(r, 341 "void main() {" 342 "sk_OutColor = half4(sk_TransformedCoords2D[0], sk_TransformedCoords2D[0]);" 343 "}", 344 *SkSL::ShaderCapsFactory::Default(), 345 {}, 346 { 347 "SkString sk_TransformedCoords2D_0 = " 348 "fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);", 349 "fragBuilder->codeAppendf(\"%s = half4(%s, %s);\\n\", args.fOutputColor, " 350 "sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str());" 351 }); 352 353 } 354 355 DEF_TEST(SkSLFPLayoutWhen, r) { 356 test(r, 357 "layout(when=someExpression(someOtherExpression())) uniform half sometimes;" 358 "void main() {" 359 "}", 360 *SkSL::ShaderCapsFactory::Default(), 361 {}, 362 { 363 "if (someExpression(someOtherExpression())) {\n" 364 " fSometimesVar = args.fUniformHandler->addUniform" 365 }); 366 367 } 368 369 DEF_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 391 #endif 392