skia2/tests/SkSLFPTest.cpp
Brian Osman 93ba0a4fc8 Switch SkSL to std::string
On desktop, this saves just over 5% of the time in the SkSL compiler.

As written, the code will now build either way, so it's much easier to
switch back (or even have some platforms use SkString, if that's ever
required).

Bug: skia:
Change-Id: I634f26a4f6fcb404e59bda6a5c6a21a9c6d73c0b
Reviewed-on: https://skia-review.googlesource.com/34381
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-08-14 21:24:55 +00:00

408 lines
15 KiB
C++

/*
* 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<const char*> expectedH, std::vector<const char*> expectedCPP) {
SkSL::Program::Settings settings;
settings.fCaps = &caps;
SkSL::Compiler compiler;
SkSL::StringStream output;
std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
SkSL::Program::kFragmentProcessor_Kind,
SkSL::String(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 = float4(1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{
"/*\n"
" * Copyright 2017 Google Inc.\n"
" *\n"
" * Use of this source code is governed by a BSD-style license that can be\n"
" * found in the LICENSE file.\n"
" */\n"
"\n"
"/*\n"
" * This file was autogenerated from GrTest.fp; do not modify.\n"
" */\n"
"#ifndef GrTest_DEFINED\n"
"#define GrTest_DEFINED\n"
"#include \"SkTypes.h\"\n"
"#if SK_SUPPORT_GPU\n"
"#include \"GrFragmentProcessor.h\"\n"
"#include \"GrCoordTransform.h\"\n"
"#include \"GrColorSpaceXform.h\"\n"
"class GrTest : public GrFragmentProcessor {\n"
"public:\n"
" static std::unique_ptr<GrFragmentProcessor> Make() {\n"
" return std::unique_ptr<GrFragmentProcessor>(new GrTest());\n"
" }\n"
" GrTest(const GrTest& src);\n"
" std::unique_ptr<GrFragmentProcessor> clone() const override;\n"
" const char* name() const override { return \"Test\"; }\n"
"private:\n"
" GrTest()\n"
" : INHERITED(kNone_OptimizationFlags) {\n"
" this->initClassID<GrTest>();\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"
"#endif\n"
},
{
"/*\n"
" * Copyright 2017 Google Inc.\n"
" *\n"
" * Use of this source code is governed by a BSD-style license that can be\n"
" * found in the LICENSE file.\n"
" */\n"
"\n"
"/*\n"
" * This file was autogenerated from GrTest.fp; do not modify.\n"
" */\n"
"#include \"GrTest.h\"\n"
"#if SK_SUPPORT_GPU\n"
"#include \"glsl/GrGLSLColorSpaceXformHelper.h\"\n"
"#include \"glsl/GrGLSLFragmentProcessor.h\"\n"
"#include \"glsl/GrGLSLFragmentShaderBuilder.h\"\n"
"#include \"glsl/GrGLSLProgramBuilder.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<GrTest>();\n"
" (void) _outer;\n"
" fragBuilder->codeAppendf(\"%s = float4(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<GrTest>();\n"
" (void) that;\n"
" return true;\n"
"}\n"
"GrTest::GrTest(const GrTest& src)\n"
": INHERITED(src.optimizationFlags()) {\n"
" this->initClassID<GrTest>();\n"
"}\n"
"std::unique_ptr<GrFragmentProcessor> GrTest::clone() const {\n"
" return std::unique_ptr<GrFragmentProcessor>(new GrTest(*this));\n"
"}\n"
"#endif\n"
});
}
DEF_TEST(SkSLFPInput, r) {
test(r,
"in float2 point;"
"void main() {"
"sk_OutColor = float4(point, point);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{
"SkPoint point() const { return fPoint; }",
"static std::unique_ptr<GrFragmentProcessor> Make(SkPoint point) {",
"return std::unique_ptr<GrFragmentProcessor>(new GrTest(point));",
"GrTest(SkPoint point)",
", fPoint(point)"
},
{
"fragBuilder->codeAppendf(\"%s = float4(float2(%f, %f), float2(%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 float4 color;"
"void main() {"
"sk_OutColor = color;"
"}",
*SkSL::ShaderCapsFactory::Default(),
{
"static std::unique_ptr<GrFragmentProcessor> Make()"
},
{
"fColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType, "
"kDefault_GrSLPrecision, \"color\");",
});
}
DEF_TEST(SkSLFPInUniform, r) {
test(r,
"in uniform float4 color;"
"void main() {"
"sk_OutColor = color;"
"}",
*SkSL::ShaderCapsFactory::Default(),
{
"static std::unique_ptr<GrFragmentProcessor> Make(SkRect color) {",
},
{
"fColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType, "
"kDefault_GrSLPrecision, \"color\");",
"const SkRect colorValue = _outer.color();",
"pdman.set4fv(fColorVar, 1, (float*) &colorValue);"
});
}
DEF_TEST(SkSLFPSections, r) {
test(r,
"@header { header section }"
"void main() {"
"sk_OutColor = float4(1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{
"#if SK_SUPPORT_GPU\n header section"
},
{});
test(r,
"@class { class section }"
"void main() {"
"sk_OutColor = float4(1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{
"class GrTest : public GrFragmentProcessor {\n"
"public:\n"
" class section"
},
{});
test(r,
"@cpp { cpp section }"
"void main() {"
"sk_OutColor = float4(1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{},
{"cpp section"});
test(r,
"@constructorParams { int x, float y, std::vector<float> z }"
"in float w;"
"void main() {"
"sk_OutColor = float4(1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{
"Make(float w, int x, float y, std::vector<float> z )",
"return std::unique_ptr<GrFragmentProcessor>(new GrTest(w, x, y, z));",
"GrTest(float w, int x, float y, std::vector<float> z )",
", fW(w) {"
},
{});
test(r,
"@constructor { constructor section }"
"void main() {"
"sk_OutColor = float4(1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{
"private:\n constructor section"
},
{});
test(r,
"@initializers { initializers section }"
"void main() {"
"sk_OutColor = float4(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 = float4(1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{},
{
"x = 10.0;\n"
" fragBuilder->codeAppendf(\"float y = %d\\n\", x * 2);"
});
test(r,
"@fields { fields section }"
"@clone { }"
"void main() {"
"sk_OutColor = float4(1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{
"GR_DECLARE_FRAGMENT_PROCESSOR_TEST\n"
" fields section typedef GrFragmentProcessor INHERITED;"
},
{});
test(r,
"@make { make section }"
"void main() {"
"sk_OutColor = float4(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 = float4(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 = float4(1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{},
{
"#if GR_TEST_UTILS\n"
"std::unique_ptr<GrFragmentProcessor> 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, float2(0, 0), colorXform);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{
"sk_sp<GrColorSpaceXform> colorXform() const { return fColorXform; }",
"GrTest(sk_sp<GrTextureProxy> image, sk_sp<GrColorSpaceXform> colorXform)",
"this->addTextureSampler(&fImage);",
"sk_sp<GrColorSpaceXform> fColorXform;"
},
{
"fragBuilder->codeAppendf(\"float4 _tmpVar1;%s = %s * %stexture(%s, "
"float2(0.0, 0.0)).%s%s;\\n\", args.fOutputColor, args.fInputColor ? args.fInputColor : "
"\"float4(1)\", fColorSpaceHelper.isValid() ? \"(_tmpVar1 = \" : \"\", "
"fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(), "
"fragBuilder->getProgramBuilder()->samplerSwizzle(args.fTexSamplers[0]).c_str(), "
"fColorSpaceHelper.isValid() ? SkStringPrintf(\", float4(clamp((%s * float4(_tmpVar1.rgb, "
"1.0)).rgb, 0.0, _tmpVar1.a), _tmpVar1.a))\", args.fUniformHandler->getUniformCStr("
"fColorSpaceHelper.gamutXformUniform())).c_str() : \"\");"
});
}
DEF_TEST(SkSLFPTransformedCoords, r) {
test(r,
"void main() {"
"sk_OutColor = float4(sk_TransformedCoords2D[0], sk_TransformedCoords2D[0]);"
"}",
*SkSL::ShaderCapsFactory::Default(),
{},
{
"SkSL::String sk_TransformedCoords2D_0 = "
"fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);",
"fragBuilder->codeAppendf(\"%s = float4(%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