From ccf59917d3fe7aaf59de714acfbd0596503f324f Mon Sep 17 00:00:00 2001 From: Ethan Nicholas Date: Tue, 27 Jun 2017 09:56:09 -0400 Subject: sksl fragment processor support Bug: skia: Change-Id: Ia3b0305c2b0c78074303831f628fb01852b90d34 Reviewed-on: https://skia-review.googlesource.com/17843 Commit-Queue: Ethan Nicholas Reviewed-by: Ben Wagner Reviewed-by: Mike Klein --- tests/SkSLFPTest.cpp | 381 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 381 insertions(+) create mode 100644 tests/SkSLFPTest.cpp (limited to 'tests/SkSLFPTest.cpp') diff --git a/tests/SkSLFPTest.cpp b/tests/SkSLFPTest.cpp new file mode 100644 index 0000000000..6f1326d6f7 --- /dev/null +++ b/tests/SkSLFPTest.cpp @@ -0,0 +1,381 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkSLCompiler.h" + +#include "Test.h" + +#if SK_SUPPORT_GPU + +static void test(skiatest::Reporter* r, const char* src, const GrShaderCaps& caps, + std::vector expectedH, std::vector expectedCPP) { + SkSL::Program::Settings settings; + settings.fCaps = ∩︀ + SkSL::Compiler compiler; + SkSL::StringStream output; + std::unique_ptr program = compiler.convertProgram( + SkSL::Program::kFragmentProcessor_Kind, + SkString(src), + settings); + if (!program) { + SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str()); + return; + } + REPORTER_ASSERT(r, program); + bool success = compiler.toH(*program, "Test", output); + if (!success) { + SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str()); + } + REPORTER_ASSERT(r, success); + if (success) { + for (const char* expected : expectedH) { + bool found = strstr(output.str().c_str(), expected); + if (!found) { + SkDebugf("HEADER MISMATCH:\nsource:\n%s\n\nexpected:\n'%s'\n\nreceived:\n'%s'", src, + expected, output.str().c_str()); + } + REPORTER_ASSERT(r, found); + } + } + output.reset(); + success = compiler.toCPP(*program, "Test", output); + if (!success) { + SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str()); + } + REPORTER_ASSERT(r, success); + if (success) { + for (const char* expected : expectedCPP) { + bool found = strstr(output.str().c_str(), expected); + if (!found) { + SkDebugf("CPP MISMATCH:\nsource:\n%s\n\nexpected:\n'%s'\n\nreceived:\n'%s'", src, + expected, output.str().c_str()); + } + REPORTER_ASSERT(r, found); + } + } +} + +DEF_TEST(SkSLFPHelloWorld, r) { + test(r, + "void main() {" + "sk_OutColor = vec4(1);" + "}", + *SkSL::ShaderCapsFactory::Default(), + { + "/*\n" + " * This file was autogenerated from GrTest.fp.\n" + " */\n" + "#ifndef GrTest_DEFINED\n" + "#define GrTest_DEFINED\n" + "#include \"GrFragmentProcessor.h\"\n" + "#include \"GrCoordTransform.h\"\n" + "#include \"effects/GrProxyMove.h\"\n" + "class GrTest : public GrFragmentProcessor {\n" + "public:\n" + " static sk_sp Make() {\n" + " return sk_sp(new GrTest());\n" + " }\n" + " const char* name() const override { return \"Test\"; }\n" + "private:\n" + " GrTest()\n" + " : INHERITED(kNone_OptimizationFlags) {\n" + " this->initClassID();\n" + " }\n" + " GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;\n" + " void onGetGLSLProcessorKey(const GrShaderCaps&,GrProcessorKeyBuilder*) " + "const override;\n" + " bool onIsEqual(const GrFragmentProcessor&) const override;\n" + " GR_DECLARE_FRAGMENT_PROCESSOR_TEST;\n" + " typedef GrFragmentProcessor INHERITED;\n" + "};\n" + "#endif\n" + }, + { + "/*\n" + " * This file was autogenerated from GrTest.fp.\n" + " */\n" + "#include \"GrTest.h\"\n" + "#include \"glsl/GrGLSLColorSpaceXformHelper.h\"\n" + "#include \"glsl/GrGLSLFragmentProcessor.h\"\n" + "#include \"glsl/GrGLSLFragmentShaderBuilder.h\"\n" + "#include \"glsl/GrGLSLProgramBuilder.h\"\n" + "#include \"GrResourceProvider.h\"\n" + "#include \"SkSLCPP.h\"\n" + "#include \"SkSLUtil.h\"\n" + "class GrGLSLTest : public GrGLSLFragmentProcessor {\n" + "public:\n" + " GrGLSLTest() {}\n" + " void emitCode(EmitArgs& args) override {\n" + " GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;\n" + " const GrTest& _outer = args.fFp.cast();\n" + " (void) _outer;\n" + " fragBuilder->codeAppendf(\"%s = vec4(1.0);\\n\", args.fOutputColor);\n" + " }\n" + "private:\n" + " void onSetData(const GrGLSLProgramDataManager& pdman, " + "const GrFragmentProcessor& _proc) override {\n" + " }\n" + "};\n" + "GrGLSLFragmentProcessor* GrTest::onCreateGLSLInstance() const {\n" + " return new GrGLSLTest();\n" + "}\n" + "void GrTest::onGetGLSLProcessorKey(const GrShaderCaps& caps, " + "GrProcessorKeyBuilder* b) const {\n" + "}\n" + "bool GrTest::onIsEqual(const GrFragmentProcessor& other) const {\n" + " const GrTest& that = other.cast();\n" + " (void) that;\n" + " return true;\n" + "}\n" + }); +} + +DEF_TEST(SkSLFPInput, r) { + test(r, + "in vec2 point;" + "void main() {" + "sk_OutColor = vec4(point, point);" + "}", + *SkSL::ShaderCapsFactory::Default(), + { + "SkPoint point() const { return fPoint; }", + "static sk_sp Make(SkPoint point) {", + "return sk_sp(new GrTest(point));", + "GrTest(SkPoint point)", + ", fPoint(point)" + }, + { + "fragBuilder->codeAppendf(\"%s = vec4(vec2(%f, %f), vec2(%f, %f));\\n\", " + "args.fOutputColor, _outer.point().fX, _outer.point().fY, " + "_outer.point().fX, _outer.point().fY);", + "if (fPoint != that.fPoint) return false;" + }); +} + +DEF_TEST(SkSLFPUniform, r) { + test(r, + "uniform vec4 color;" + "void main() {" + "sk_OutColor = color;" + "}", + *SkSL::ShaderCapsFactory::Default(), + { + "static sk_sp Make()" + }, + { + "fColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType, " + "kDefault_GrSLPrecision, \"color\");", + }); +} + +DEF_TEST(SkSLFPInUniform, r) { + test(r, + "in uniform vec4 color;" + "void main() {" + "sk_OutColor = color;" + "}", + *SkSL::ShaderCapsFactory::Default(), + { + "static sk_sp Make(SkRect color) {", + }, + { + "fColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType, " + "kDefault_GrSLPrecision, \"color\");", + "const SkRect colorValue = _outer.color();", + "pdman.set4fv(fColorVar, 4, (float*) &colorValue);" + }); +} + +DEF_TEST(SkSLFPSections, r) { + test(r, + "@header { header section }" + "void main() {" + "sk_OutColor = vec4(1);" + "}", + *SkSL::ShaderCapsFactory::Default(), + { + "header section class GrTest", + }, + {}); + test(r, + "@class { class section }" + "void main() {" + "sk_OutColor = vec4(1);" + "}", + *SkSL::ShaderCapsFactory::Default(), + { + "class GrTest : public GrFragmentProcessor {\n" + "public:\n" + " class section" + }, + {}); + test(r, + "@cpp { cpp section }" + "void main() {" + "sk_OutColor = vec4(1);" + "}", + *SkSL::ShaderCapsFactory::Default(), + {}, + {"cpp section"}); + test(r, + "@constructorParams { int x, float y, std::vector z }" + "in float w;" + "void main() {" + "sk_OutColor = vec4(1);" + "}", + *SkSL::ShaderCapsFactory::Default(), + { + "Make(float w, int x, float y, std::vector z )", + "return sk_sp(new GrTest(w, x, y, z));", + "GrTest(float w, int x, float y, std::vector z )", + ", fW(w) {" + }, + {}); + test(r, + "@constructor { constructor section }" + "void main() {" + "sk_OutColor = vec4(1);" + "}", + *SkSL::ShaderCapsFactory::Default(), + { + "private:\n constructor section" + }, + {}); + test(r, + "@initializers { initializers section }" + "void main() {" + "sk_OutColor = vec4(1);" + "}", + *SkSL::ShaderCapsFactory::Default(), + { + ": INHERITED(kNone_OptimizationFlags)\n , initializers section" + }, + {}); + test(r, + "float x = 10;" + "@emitCode { fragBuilder->codeAppendf(\"float y = %d\\n\", x * 2); }" + "void main() {" + "sk_OutColor = vec4(1);" + "}", + *SkSL::ShaderCapsFactory::Default(), + {}, + { + "x = 10.0;\n" + " fragBuilder->codeAppendf(\"float y = %d\\n\", x * 2);" + }); + test(r, + "@fields { fields section }" + "void main() {" + "sk_OutColor = vec4(1);" + "}", + *SkSL::ShaderCapsFactory::Default(), + { + "GR_DECLARE_FRAGMENT_PROCESSOR_TEST;\n" + " fields section typedef GrFragmentProcessor INHERITED;" + }, + {}); + test(r, + "@make { make section }" + "void main() {" + "sk_OutColor = vec4(1);" + "}", + *SkSL::ShaderCapsFactory::Default(), + { + "public:\n" + " make section" + }, + {}); + test(r, + "uniform float calculated;" + "in float provided;" + "@setData(varName) { varName.set1f(calculated, provided * 2); }" + "void main() {" + "sk_OutColor = vec4(1);" + "}", + *SkSL::ShaderCapsFactory::Default(), + {}, + { + "void onSetData(const GrGLSLProgramDataManager& varName, " + "const GrFragmentProcessor& _proc) override {\n", + "UniformHandle& calculated = fCalculatedVar;", + "auto provided = _outer.provided();", + "varName.set1f(calculated, provided * 2);" + }); + test(r, + "@test(testDataName) { testDataName section }" + "void main() {" + "sk_OutColor = vec4(1);" + "}", + *SkSL::ShaderCapsFactory::Default(), + {}, + { + "#if GR_TEST_UTILS\n" + "sk_sp GrTest::TestCreate(GrProcessorTestData* testDataName) {\n" + " testDataName section }\n" + "#endif" + }); +} + +DEF_TEST(SkSLFPColorSpaceXform, r) { + test(r, + "in uniform sampler2D image;" + "in uniform colorSpaceXform colorXform;" + "void main() {" + "sk_OutColor = sk_InColor * texture(image, vec2(0, 0), colorXform);" + "}", + *SkSL::ShaderCapsFactory::Default(), + { + "sk_sp colorXform() const { return fColorXform; }", + "GrTest(sk_sp image, sk_sp colorXform)", + "this->addTextureSampler(&fImage);", + "sk_sp fColorXform;" + }, + { + "fragBuilder->codeAppendf(\"vec4 _tmp0;\\n%s = %s * " + "(_tmp0 = texture(%s, vec2(0.0, 0.0)) , %s != mat4(1.0) ? " + "vec4(clamp((%s * vec4(_tmp0.xyz, 1.0)).xyz, 0.0, _tmp0.w), _tmp0.w) : " + "_tmp0);\\n\", args.fOutputColor, args.fInputColor ? args.fInputColor : " + "\"vec4(1)\", fragBuilder->getProgramBuilder()->samplerVariable(" + "args.fTexSamplers[0]).c_str(), fColorSpaceHelper.isValid() ? " + "args.fUniformHandler->getUniformCStr(fColorSpaceHelper.gamutXformUniform()) : " + "\"mat4(1.0)\", fColorSpaceHelper.isValid() ? " + "args.fUniformHandler->getUniformCStr(fColorSpaceHelper.gamutXformUniform()) : " + "\"mat4(1.0)\");" + }); +} + +DEF_TEST(SkSLFPTransformedCoords, r) { + test(r, + "void main() {" + "sk_OutColor = vec4(sk_TransformedCoords2D[0], sk_TransformedCoords2D[0]);" + "}", + *SkSL::ShaderCapsFactory::Default(), + {}, + { + "SkSL::String sk_TransformedCoords2D_0 = " + "fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);", + "fragBuilder->codeAppendf(\"%s = vec4(%s, %s);\\n\", args.fOutputColor, " + "sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str());" + }); + +} + +DEF_TEST(SkSLFPLayoutWhen, r) { + test(r, + "layout(when=someExpression(someOtherExpression())) uniform float sometimes;" + "void main() {" + "}", + *SkSL::ShaderCapsFactory::Default(), + {}, + { + "if (someExpression(someOtherExpression())) {\n" + " fSometimesVar = args.fUniformHandler->addUniform" + }); + +} + +#endif -- cgit v1.2.3