2017-06-29 14:03:38 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2017 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "src/sksl/SkSLCompiler.h"
|
2019-06-06 14:04:27 +00:00
|
|
|
#include "src/sksl/SkSLStringStream.h"
|
2017-06-29 14:03:38 +00:00
|
|
|
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "tests/Test.h"
|
2017-06-29 14:03:38 +00:00
|
|
|
|
2020-06-10 20:40:38 +00:00
|
|
|
static void test(skiatest::Reporter* r, const GrShaderCaps& caps, const char* src,
|
2017-06-29 14:03:38 +00:00
|
|
|
std::vector<const char*> expectedH, std::vector<const char*> expectedCPP) {
|
|
|
|
SkSL::Program::Settings settings;
|
|
|
|
settings.fCaps = ∩︀
|
2020-06-03 20:58:20 +00:00
|
|
|
settings.fRemoveDeadFunctions = false;
|
2017-06-29 14:03:38 +00:00
|
|
|
SkSL::Compiler compiler;
|
|
|
|
SkSL::StringStream output;
|
|
|
|
std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
|
|
|
|
SkSL::Program::kFragmentProcessor_Kind,
|
2017-08-14 18:48:10 +00:00
|
|
|
SkSL::String(src),
|
2017-06-29 14:03:38 +00:00
|
|
|
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) {
|
2020-06-18 17:00:38 +00:00
|
|
|
SkDebugf("HEADER MISMATCH:\nsource:\n%s\n\n"
|
|
|
|
"header expected:\n'%s'\n\n"
|
|
|
|
"header received:\n'%s'",
|
2020-06-10 20:40:38 +00:00
|
|
|
src, expected, output.str().c_str());
|
2017-06-29 14:03:38 +00:00
|
|
|
}
|
|
|
|
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) {
|
2020-06-18 17:00:38 +00:00
|
|
|
SkDebugf("CPP MISMATCH:\nsource:\n%s\n\n"
|
|
|
|
"cpp expected:\n'%s'\n\n"
|
|
|
|
"cpp received:\n'%s'",
|
2020-06-10 20:40:38 +00:00
|
|
|
src, expected, output.str().c_str());
|
2017-06-29 14:03:38 +00:00
|
|
|
}
|
|
|
|
REPORTER_ASSERT(r, found);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-13 14:21:38 +00:00
|
|
|
static void test_failure(skiatest::Reporter* r, const char* src, const char* error) {
|
|
|
|
SkSL::Compiler compiler;
|
|
|
|
SkSL::Program::Settings settings;
|
|
|
|
sk_sp<GrShaderCaps> caps = SkSL::ShaderCapsFactory::Default();
|
|
|
|
settings.fCaps = caps.get();
|
|
|
|
std::unique_ptr<SkSL::Program> program = compiler.convertProgram(
|
|
|
|
SkSL::Program::kFragmentProcessor_Kind,
|
|
|
|
SkSL::String(src),
|
|
|
|
settings);
|
|
|
|
if (!compiler.errorCount()) {
|
|
|
|
compiler.optimize(*program);
|
|
|
|
}
|
|
|
|
SkSL::String skError(error);
|
|
|
|
if (compiler.errorText() != skError) {
|
2020-06-10 20:40:38 +00:00
|
|
|
SkDebugf("SKSL ERROR:\n source: %s\n expected: %s received: %s",
|
|
|
|
src, error, compiler.errorText().c_str());
|
2019-08-13 14:21:38 +00:00
|
|
|
}
|
|
|
|
REPORTER_ASSERT(r, compiler.errorText() == skError);
|
|
|
|
}
|
|
|
|
|
2017-06-29 14:03:38 +00:00
|
|
|
DEF_TEST(SkSLFPHelloWorld, r) {
|
|
|
|
test(r,
|
2020-06-10 20:40:38 +00:00
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
|
|
|
R"__SkSL__(
|
2020-06-18 17:00:38 +00:00
|
|
|
/* HELLO WORLD */
|
2020-06-10 20:40:38 +00:00
|
|
|
void main() {
|
|
|
|
sk_OutColor = half4(1);
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{
|
2020-06-18 17:00:38 +00:00
|
|
|
R"__Header__(/* HELLO WORLD */
|
2020-06-10 20:40:38 +00:00
|
|
|
|
|
|
|
/**************************************************************************************************
|
|
|
|
*** This file was autogenerated from GrTest.fp; do not modify.
|
|
|
|
**************************************************************************************************/
|
|
|
|
#ifndef GrTest_DEFINED
|
|
|
|
#define GrTest_DEFINED
|
|
|
|
|
|
|
|
#include "include/core/SkM44.h"
|
|
|
|
#include "include/core/SkTypes.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "src/gpu/GrCoordTransform.h"
|
|
|
|
#include "src/gpu/GrFragmentProcessor.h"
|
|
|
|
|
|
|
|
class GrTest : public GrFragmentProcessor {
|
|
|
|
public:
|
|
|
|
static std::unique_ptr<GrFragmentProcessor> Make() {
|
|
|
|
return std::unique_ptr<GrFragmentProcessor>(new GrTest());
|
|
|
|
}
|
|
|
|
GrTest(const GrTest& src);
|
|
|
|
std::unique_ptr<GrFragmentProcessor> clone() const override;
|
|
|
|
const char* name() const override { return "Test"; }
|
|
|
|
private:
|
|
|
|
GrTest()
|
|
|
|
: INHERITED(kGrTest_ClassID, kNone_OptimizationFlags) {
|
|
|
|
}
|
|
|
|
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
|
|
|
|
void onGetGLSLProcessorKey(const GrShaderCaps&,GrProcessorKeyBuilder*) const override;
|
|
|
|
bool onIsEqual(const GrFragmentProcessor&) const override;
|
|
|
|
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
|
|
|
|
typedef GrFragmentProcessor INHERITED;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
)__Header__"
|
2017-06-29 14:03:38 +00:00
|
|
|
},
|
2020-06-10 20:40:38 +00:00
|
|
|
/*expectedCPP=*/{
|
2020-06-18 17:00:38 +00:00
|
|
|
R"__Cpp__(/* HELLO WORLD */
|
|
|
|
|
|
|
|
/**************************************************************************************************
|
2020-06-10 20:40:38 +00:00
|
|
|
*** This file was autogenerated from GrTest.fp; do not modify.
|
|
|
|
**************************************************************************************************/
|
|
|
|
#include "GrTest.h"
|
|
|
|
|
|
|
|
#include "src/gpu/GrTexture.h"
|
|
|
|
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
|
|
|
|
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
|
|
|
|
#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
|
|
|
|
#include "src/sksl/SkSLCPP.h"
|
|
|
|
#include "src/sksl/SkSLUtil.h"
|
|
|
|
class GrGLSLTest : public GrGLSLFragmentProcessor {
|
|
|
|
public:
|
|
|
|
GrGLSLTest() {}
|
|
|
|
void emitCode(EmitArgs& args) override {
|
|
|
|
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
|
|
|
const GrTest& _outer = args.fFp.cast<GrTest>();
|
|
|
|
(void) _outer;
|
2020-06-18 17:00:38 +00:00
|
|
|
fragBuilder->codeAppendf(
|
|
|
|
R"SkSL(%s = half4(1.0);
|
|
|
|
)SkSL"
|
|
|
|
, args.fOutputColor);
|
2020-06-10 20:40:38 +00:00
|
|
|
}
|
|
|
|
private:
|
|
|
|
void onSetData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& _proc) override {
|
|
|
|
}
|
|
|
|
};
|
|
|
|
GrGLSLFragmentProcessor* GrTest::onCreateGLSLInstance() const {
|
|
|
|
return new GrGLSLTest();
|
|
|
|
}
|
|
|
|
void GrTest::onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
|
|
|
|
}
|
|
|
|
bool GrTest::onIsEqual(const GrFragmentProcessor& other) const {
|
|
|
|
const GrTest& that = other.cast<GrTest>();
|
|
|
|
(void) that;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
GrTest::GrTest(const GrTest& src)
|
|
|
|
: INHERITED(kGrTest_ClassID, src.optimizationFlags()) {
|
|
|
|
}
|
|
|
|
std::unique_ptr<GrFragmentProcessor> GrTest::clone() const {
|
|
|
|
return std::unique_ptr<GrFragmentProcessor>(new GrTest(*this));
|
|
|
|
}
|
|
|
|
)__Cpp__"
|
2017-06-29 14:03:38 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
DEF_TEST(SkSLFPInput, r) {
|
|
|
|
test(r,
|
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
2020-06-10 20:40:38 +00:00
|
|
|
R"__SkSL__(
|
|
|
|
layout(key) in half2 point;
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = half4(point, point);
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{
|
2017-08-11 13:40:37 +00:00
|
|
|
"static std::unique_ptr<GrFragmentProcessor> Make(SkPoint point) {",
|
|
|
|
"return std::unique_ptr<GrFragmentProcessor>(new GrTest(point));",
|
2017-06-29 14:03:38 +00:00
|
|
|
"GrTest(SkPoint point)",
|
2019-04-09 14:40:41 +00:00
|
|
|
", point(point)"
|
2017-06-29 14:03:38 +00:00
|
|
|
},
|
2020-06-10 20:40:38 +00:00
|
|
|
/*expectedCPP=*/{
|
2020-06-18 17:00:38 +00:00
|
|
|
"fragBuilder->codeAppendf(\n"
|
|
|
|
"R\"SkSL(%s = half4(half2(%f, %f), half2(%f, %f));\n"
|
|
|
|
")SkSL\"\n"
|
|
|
|
", args.fOutputColor, _outer.point.fX, _outer.point.fY, _outer.point.fX, _outer.point.fY);",
|
2019-04-09 14:40:41 +00:00
|
|
|
"if (point != that.point) return false;"
|
2017-06-29 14:03:38 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
DEF_TEST(SkSLFPUniform, r) {
|
|
|
|
test(r,
|
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
2020-06-10 20:40:38 +00:00
|
|
|
R"__SkSL__(
|
|
|
|
uniform half4 color;
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = color;
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{
|
2017-08-11 13:40:37 +00:00
|
|
|
"static std::unique_ptr<GrFragmentProcessor> Make()"
|
2017-06-29 14:03:38 +00:00
|
|
|
},
|
2020-06-10 20:40:38 +00:00
|
|
|
/*expectedCPP=*/{
|
|
|
|
"colorVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, "
|
2020-04-06 17:53:05 +00:00
|
|
|
"kHalf4_GrSLType, \"color\");",
|
2017-06-29 14:03:38 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-08-31 14:52:47 +00:00
|
|
|
// SkSLFPInUniform tests the simplest plumbing case, default type, no tracking
|
|
|
|
// with a setUniform template that supports inlining the value call with no
|
|
|
|
// local variable.
|
2017-06-29 14:03:38 +00:00
|
|
|
DEF_TEST(SkSLFPInUniform, r) {
|
|
|
|
test(r,
|
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
2020-06-10 20:40:38 +00:00
|
|
|
R"__SkSL__(
|
|
|
|
in uniform half4 color;
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = color;
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{
|
2017-08-11 13:40:37 +00:00
|
|
|
"static std::unique_ptr<GrFragmentProcessor> Make(SkRect color) {",
|
2017-06-29 14:03:38 +00:00
|
|
|
},
|
2020-06-10 20:40:38 +00:00
|
|
|
/*expectedCPP=*/{
|
2020-04-06 17:53:05 +00:00
|
|
|
"colorVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, "
|
|
|
|
"kHalf4_GrSLType, \"color\");",
|
2019-04-09 14:40:41 +00:00
|
|
|
"pdman.set4fv(colorVar, 1, reinterpret_cast<const float*>(&(_outer.color)));"
|
2018-08-31 14:52:47 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// As above, but tests in uniform's ability to override the default ctype.
|
|
|
|
DEF_TEST(SkSLFPInUniformCType, r) {
|
|
|
|
test(r,
|
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
2020-06-10 20:40:38 +00:00
|
|
|
R"__SkSL__(
|
|
|
|
layout(ctype=SkPMColor4f) in uniform half4 color;
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = color;
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{
|
2018-10-16 19:45:55 +00:00
|
|
|
"static std::unique_ptr<GrFragmentProcessor> Make(SkPMColor4f color) {",
|
2018-08-31 14:52:47 +00:00
|
|
|
},
|
2020-06-10 20:40:38 +00:00
|
|
|
/*expectedCPP=*/{
|
2020-04-06 17:53:05 +00:00
|
|
|
"colorVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, "
|
|
|
|
"kHalf4_GrSLType, \"color\");",
|
2019-04-09 14:40:41 +00:00
|
|
|
"pdman.set4fv(colorVar, 1, (_outer.color).vec());"
|
2018-08-31 14:52:47 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add state tracking to the default typed SkRect <-> half4 uniform. But since
|
|
|
|
// it now has to track state, the value inlining previously done for the
|
|
|
|
// setUniform call is removed in favor of a local variable.
|
|
|
|
DEF_TEST(SkSLFPTrackedInUniform, r) {
|
|
|
|
test(r,
|
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
2020-06-10 20:40:38 +00:00
|
|
|
R"__SkSL__(
|
|
|
|
layout(tracked) in uniform half4 color;
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = color;
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{
|
2018-08-31 14:52:47 +00:00
|
|
|
"static std::unique_ptr<GrFragmentProcessor> Make(SkRect color) {",
|
|
|
|
},
|
2020-06-10 20:40:38 +00:00
|
|
|
/*expectedCPP=*/{
|
2019-04-09 14:40:41 +00:00
|
|
|
"SkRect colorPrev = SkRect::MakeEmpty();",
|
2020-04-06 17:53:05 +00:00
|
|
|
"colorVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, "
|
|
|
|
"kHalf4_GrSLType, \"color\");",
|
2019-04-09 14:40:41 +00:00
|
|
|
"const SkRect& colorValue = _outer.color;",
|
|
|
|
"if (colorPrev.isEmpty() || colorPrev != colorValue) {",
|
|
|
|
"colorPrev = colorValue;",
|
|
|
|
"pdman.set4fv(colorVar, 1, reinterpret_cast<const float*>(&colorValue));"
|
2018-08-31 14:52:47 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test the case where the template does not support variable inlining in
|
|
|
|
// setUniform (i.e. it references the value multiple times).
|
|
|
|
DEF_TEST(SkSLFPNonInlinedInUniform, r) {
|
|
|
|
test(r,
|
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
2020-06-10 20:40:38 +00:00
|
|
|
R"__SkSL__(
|
|
|
|
in uniform half2 point;
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = half4(point, point);
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{
|
2018-08-31 14:52:47 +00:00
|
|
|
"static std::unique_ptr<GrFragmentProcessor> Make(SkPoint point) {",
|
|
|
|
},
|
2020-06-10 20:40:38 +00:00
|
|
|
/*expectedCPP=*/{
|
2020-04-06 17:53:05 +00:00
|
|
|
"pointVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, "
|
|
|
|
"kHalf2_GrSLType, \"point\");",
|
2019-04-09 14:40:41 +00:00
|
|
|
"const SkPoint& pointValue = _outer.point;",
|
|
|
|
"pdman.set2f(pointVar, pointValue.fX, pointValue.fY);"
|
2018-08-31 14:52:47 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test handling conditional uniforms (that use when= in layout), combined with
|
|
|
|
// state tracking and custom ctypes to really put the code generation through its paces.
|
|
|
|
DEF_TEST(SkSLFPConditionalInUniform, r) {
|
|
|
|
test(r,
|
2020-06-10 20:40:38 +00:00
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
|
|
|
R"__SkSL__(
|
|
|
|
layout(key) in bool test;
|
|
|
|
layout(ctype=SkPMColor4f, tracked, when=test) in uniform half4 color;
|
|
|
|
void main() {
|
|
|
|
if (test) {
|
|
|
|
sk_OutColor = color;
|
|
|
|
} else {
|
|
|
|
sk_OutColor = half4(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{
|
2018-10-16 19:45:55 +00:00
|
|
|
"static std::unique_ptr<GrFragmentProcessor> Make(bool test, SkPMColor4f color) {",
|
2018-08-31 14:52:47 +00:00
|
|
|
},
|
2020-06-10 20:40:38 +00:00
|
|
|
/*expectedCPP=*/{
|
2019-04-09 14:40:41 +00:00
|
|
|
"SkPMColor4f colorPrev = {SK_FloatNaN, SK_FloatNaN, SK_FloatNaN, SK_FloatNaN}",
|
|
|
|
"auto test = _outer.test;",
|
2018-08-31 14:52:47 +00:00
|
|
|
"if (test) {",
|
2020-04-06 17:53:05 +00:00
|
|
|
"colorVar = args.fUniformHandler->addUniform(&_outer, kFragment_GrShaderFlag, "
|
|
|
|
"kHalf4_GrSLType, \"color\");",
|
2019-04-09 14:40:41 +00:00
|
|
|
"if (colorVar.isValid()) {",
|
|
|
|
"const SkPMColor4f& colorValue = _outer.color;",
|
|
|
|
"if (colorPrev != colorValue) {",
|
|
|
|
"colorPrev = colorValue;",
|
|
|
|
"pdman.set4fv(colorVar, 1, colorValue.vec());"
|
2017-06-29 14:03:38 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
DEF_TEST(SkSLFPSections, r) {
|
|
|
|
test(r,
|
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
2020-06-10 20:40:38 +00:00
|
|
|
R"__SkSL__(
|
|
|
|
@header { header section }
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = half4(1);
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{
|
2018-04-06 14:37:55 +00:00
|
|
|
"header section"
|
2017-06-29 14:03:38 +00:00
|
|
|
},
|
2020-06-10 20:40:38 +00:00
|
|
|
/*expectedCPP=*/{});
|
2017-06-29 14:03:38 +00:00
|
|
|
test(r,
|
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
2020-06-10 20:40:38 +00:00
|
|
|
R"__SkSL__(
|
|
|
|
@class { class section }
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = half4(1);
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{
|
2017-06-29 14:03:38 +00:00
|
|
|
"class GrTest : public GrFragmentProcessor {\n"
|
|
|
|
"public:\n"
|
|
|
|
" class section"
|
|
|
|
},
|
2020-06-10 20:40:38 +00:00
|
|
|
/*expectedCPP=*/{});
|
|
|
|
test(r,
|
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
|
|
|
R"__SkSL__(
|
|
|
|
@cpp { cpp section }
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = half4(1);
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{},
|
|
|
|
/*expectedCPP=*/{
|
|
|
|
"cpp section"
|
|
|
|
});
|
2017-06-29 14:03:38 +00:00
|
|
|
test(r,
|
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
2020-06-10 20:40:38 +00:00
|
|
|
R"__SkSL__(
|
|
|
|
@constructorParams { int x, float y, std::vector<float> z }
|
|
|
|
in float w;
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = half4(1);
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{
|
2017-06-29 14:03:38 +00:00
|
|
|
"Make(float w, int x, float y, std::vector<float> z )",
|
2017-08-11 13:40:37 +00:00
|
|
|
"return std::unique_ptr<GrFragmentProcessor>(new GrTest(w, x, y, z));",
|
2017-06-29 14:03:38 +00:00
|
|
|
"GrTest(float w, int x, float y, std::vector<float> z )",
|
2019-04-09 14:40:41 +00:00
|
|
|
", w(w) {"
|
2017-06-29 14:03:38 +00:00
|
|
|
},
|
2020-06-10 20:40:38 +00:00
|
|
|
/*expectedCPP=*/{});
|
2017-06-29 14:03:38 +00:00
|
|
|
test(r,
|
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
2020-06-10 20:40:38 +00:00
|
|
|
R"__SkSL__(
|
|
|
|
@constructor { constructor section }
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = half4(1);
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{
|
2017-06-29 14:03:38 +00:00
|
|
|
"private:\n constructor section"
|
|
|
|
},
|
2020-06-10 20:40:38 +00:00
|
|
|
/*expectedCPP=*/{});
|
2017-06-29 14:03:38 +00:00
|
|
|
test(r,
|
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
2020-06-10 20:40:38 +00:00
|
|
|
R"__SkSL__(
|
|
|
|
@initializers { initializers section }
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = half4(1);
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{
|
2017-10-09 14:54:08 +00:00
|
|
|
": INHERITED(kGrTest_ClassID, kNone_OptimizationFlags)\n , initializers section"
|
2017-06-29 14:03:38 +00:00
|
|
|
},
|
2020-06-10 20:40:38 +00:00
|
|
|
/*expectedCPP=*/{});
|
|
|
|
test(r,
|
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
|
|
|
R"__SkSL__(
|
|
|
|
half x = 10;
|
|
|
|
@emitCode { fragBuilder->codeAppendf("half y = %d\n", x * 2); }
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = half4(1);
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{},
|
|
|
|
/*expectedCPP=*/{
|
2017-06-29 14:03:38 +00:00
|
|
|
"x = 10.0;\n"
|
2017-09-18 18:10:39 +00:00
|
|
|
" fragBuilder->codeAppendf(\"half y = %d\\n\", x * 2);"
|
2017-06-29 14:03:38 +00:00
|
|
|
});
|
|
|
|
test(r,
|
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
2020-06-10 20:40:38 +00:00
|
|
|
R"__SkSL__(
|
|
|
|
@fields { fields section }
|
|
|
|
@clone { }
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = half4(1);
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{
|
2019-04-09 14:40:41 +00:00
|
|
|
"const char* name() const override { return \"Test\"; }\n"
|
|
|
|
" fields section private:"
|
2017-06-29 14:03:38 +00:00
|
|
|
},
|
2020-06-10 20:40:38 +00:00
|
|
|
/*expectedCPP=*/{});
|
2017-06-29 14:03:38 +00:00
|
|
|
test(r,
|
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
2020-06-10 20:40:38 +00:00
|
|
|
R"__SkSL__(
|
|
|
|
@make { make section }
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = half4(1);
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{
|
2017-06-29 14:03:38 +00:00
|
|
|
"public:\n"
|
|
|
|
" make section"
|
|
|
|
},
|
2020-06-10 20:40:38 +00:00
|
|
|
/*expectedCPP=*/{});
|
|
|
|
test(r,
|
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
|
|
|
R"__SkSL__(
|
|
|
|
uniform half calculated;
|
|
|
|
layout(key) in half provided;
|
|
|
|
@setData(varName) { varName.set1f(calculated, provided * 2); }
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = half4(1);
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{},
|
|
|
|
/*expectedCPP=*/{
|
2017-06-29 14:03:38 +00:00
|
|
|
"void onSetData(const GrGLSLProgramDataManager& varName, "
|
|
|
|
"const GrFragmentProcessor& _proc) override {\n",
|
2019-04-09 14:40:41 +00:00
|
|
|
"UniformHandle& calculated = calculatedVar;",
|
|
|
|
"auto provided = _outer.provided;",
|
2017-06-29 14:03:38 +00:00
|
|
|
"varName.set1f(calculated, provided * 2);"
|
|
|
|
});
|
|
|
|
test(r,
|
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
2020-06-10 20:40:38 +00:00
|
|
|
R"__SkSL__(
|
|
|
|
@test(testDataName) { testDataName section }
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = half4(1);
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{},
|
|
|
|
/*expectedCPP=*/{
|
2017-06-29 14:03:38 +00:00
|
|
|
"#if GR_TEST_UTILS\n"
|
2017-08-11 13:40:37 +00:00
|
|
|
"std::unique_ptr<GrFragmentProcessor> GrTest::TestCreate(GrProcessorTestData* testDataName) {\n"
|
2017-06-29 14:03:38 +00:00
|
|
|
" testDataName section }\n"
|
|
|
|
"#endif"
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
DEF_TEST(SkSLFPTransformedCoords, r) {
|
|
|
|
test(r,
|
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
2020-06-10 20:40:38 +00:00
|
|
|
R"__SkSL__(
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = half4(sk_TransformedCoords2D[0], sk_TransformedCoords2D[0]);
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{},
|
|
|
|
/*expectedCPP=*/{
|
2017-08-15 13:19:53 +00:00
|
|
|
"SkString sk_TransformedCoords2D_0 = "
|
2020-04-14 13:54:02 +00:00
|
|
|
"fragBuilder->ensureCoords2D(args.fTransformedCoords[0].fVaryingPoint, "
|
|
|
|
"_outer.sampleMatrix());",
|
2020-06-18 17:00:38 +00:00
|
|
|
"fragBuilder->codeAppendf(\n"
|
|
|
|
"R\"SkSL(%s = half4(%s, %s);\n"
|
|
|
|
")SkSL\"\n"
|
|
|
|
", args.fOutputColor, sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str());"
|
2017-06-29 14:03:38 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
DEF_TEST(SkSLFPLayoutWhen, r) {
|
|
|
|
test(r,
|
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
2020-06-10 20:40:38 +00:00
|
|
|
R"__SkSL__(
|
|
|
|
layout(when=someExpression(someOtherExpression())) uniform half sometimes;
|
|
|
|
void main() {
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{},
|
|
|
|
/*expectedCPP=*/{
|
2017-06-29 14:03:38 +00:00
|
|
|
"if (someExpression(someOtherExpression())) {\n"
|
2019-04-09 14:40:41 +00:00
|
|
|
" sometimesVar = args.fUniformHandler->addUniform"
|
2017-06-29 14:03:38 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-10-10 20:30:21 +00:00
|
|
|
DEF_TEST(SkSLFPChildProcessors, r) {
|
|
|
|
test(r,
|
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
2020-06-10 20:40:38 +00:00
|
|
|
R"__SkSL__(
|
|
|
|
in fragmentProcessor child1;
|
|
|
|
in fragmentProcessor child2;
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = sample(child1) * sample(child2);
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{
|
2020-06-22 18:46:36 +00:00
|
|
|
"child1_index = this->registerChild(std::move(child1));",
|
|
|
|
"child2_index = this->registerChild(std::move(child2));"
|
2017-10-10 20:30:21 +00:00
|
|
|
},
|
2020-06-10 20:40:38 +00:00
|
|
|
/*expectedCPP=*/{
|
|
|
|
"SkString _sample149;\n",
|
|
|
|
"_sample149 = this->invokeChild(_outer.child1_index, args);\n",
|
|
|
|
"SkString _sample166;\n",
|
|
|
|
"_sample166 = this->invokeChild(_outer.child2_index, args);\n",
|
2020-06-18 17:00:38 +00:00
|
|
|
"fragBuilder->codeAppendf(\n"
|
|
|
|
"R\"SkSL(%s = %s * %s;\n"
|
|
|
|
")SkSL\"\n"
|
|
|
|
", args.fOutputColor, _sample149.c_str(), _sample166.c_str());",
|
|
|
|
"child1_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child1_index));",
|
|
|
|
"child2_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child2_index));",
|
2017-10-10 20:30:21 +00:00
|
|
|
});
|
|
|
|
}
|
2018-08-30 20:08:18 +00:00
|
|
|
|
|
|
|
DEF_TEST(SkSLFPChildProcessorsWithInput, r) {
|
|
|
|
test(r,
|
2020-06-10 20:40:38 +00:00
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
|
|
|
R"__SkSL__(
|
|
|
|
in fragmentProcessor child1;
|
|
|
|
in fragmentProcessor child2;
|
|
|
|
void main() {
|
|
|
|
half4 childIn = sk_InColor;
|
|
|
|
half4 childOut1 = sample(child1, childIn);
|
|
|
|
half4 childOut2 = sample(child2, childOut1);
|
|
|
|
sk_OutColor = childOut2;
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{
|
2020-06-22 18:46:36 +00:00
|
|
|
"child1_index = this->registerChild(std::move(child1));",
|
|
|
|
"child2_index = this->registerChild(std::move(child2));"
|
2018-08-30 20:08:18 +00:00
|
|
|
},
|
2020-06-10 20:40:38 +00:00
|
|
|
/*expectedCPP=*/{
|
|
|
|
"SkString _input198(\"childIn\");",
|
|
|
|
"SkString _sample198;",
|
|
|
|
"_sample198 = this->invokeChild(_outer.child1_index, _input198.c_str(), args);",
|
2020-06-18 17:00:38 +00:00
|
|
|
"fragBuilder->codeAppendf(\n"
|
|
|
|
"R\"SkSL(\n"
|
|
|
|
"half4 childOut1 = %s;)SkSL\"\n"
|
|
|
|
", _sample198.c_str());",
|
2020-06-10 20:40:38 +00:00
|
|
|
"SkString _input258(\"childOut1\");",
|
|
|
|
"SkString _sample258;",
|
|
|
|
"_sample258 = this->invokeChild(_outer.child2_index, _input258.c_str(), args);",
|
2020-06-18 17:00:38 +00:00
|
|
|
"child1_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child1_index));",
|
|
|
|
"child2_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child2_index));",
|
2018-08-30 20:08:18 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
DEF_TEST(SkSLFPChildProcessorWithInputExpression, r) {
|
|
|
|
test(r,
|
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
2020-06-10 20:40:38 +00:00
|
|
|
R"__SkSL__(
|
|
|
|
in fragmentProcessor child;
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = sample(child, sk_InColor * half4(0.5));
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{
|
2020-06-22 18:46:36 +00:00
|
|
|
"child_index = this->registerChild(std::move(child));",
|
2018-08-30 20:08:18 +00:00
|
|
|
},
|
2020-06-10 20:40:38 +00:00
|
|
|
/*expectedCPP=*/{
|
|
|
|
"SkString _input106 = SkStringPrintf(\"%s * half4(0.5)\", args.fInputColor);",
|
|
|
|
"SkString _sample106;",
|
|
|
|
"_sample106 = this->invokeChild(_outer.child_index, _input106.c_str(), args);",
|
2020-06-18 17:00:38 +00:00
|
|
|
"fragBuilder->codeAppendf(\n"
|
|
|
|
"R\"SkSL(%s = %s;\n"
|
|
|
|
")SkSL\"\n"
|
|
|
|
", args.fOutputColor, _sample106.c_str());",
|
|
|
|
"child_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child_index));",
|
2018-08-30 20:08:18 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
DEF_TEST(SkSLFPNestedChildProcessors, r) {
|
|
|
|
test(r,
|
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
2020-06-10 20:40:38 +00:00
|
|
|
R"__SkSL__(
|
|
|
|
in fragmentProcessor child1;
|
|
|
|
in fragmentProcessor child2;
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = sample(child2, sk_InColor * sample(child1, sk_InColor * half4(0.5)));
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{
|
2020-06-22 18:46:36 +00:00
|
|
|
"child1_index = this->registerChild(std::move(child1));",
|
|
|
|
"child2_index = this->registerChild(std::move(child2));"
|
2018-08-30 20:08:18 +00:00
|
|
|
},
|
2020-06-10 20:40:38 +00:00
|
|
|
/*expectedCPP=*/{
|
|
|
|
"SkString _input177 = SkStringPrintf(\"%s * half4(0.5)\", args.fInputColor);",
|
|
|
|
"SkString _sample177;",
|
|
|
|
"_sample177 = this->invokeChild(_outer.child1_index, _input177.c_str(), args);",
|
|
|
|
"SkString _input149 = SkStringPrintf(\"%s * %s\", args.fInputColor, _sample177.c_str());",
|
|
|
|
"SkString _sample149;",
|
|
|
|
"_sample149 = this->invokeChild(_outer.child2_index, _input149.c_str(), args);",
|
2020-06-18 17:00:38 +00:00
|
|
|
"fragBuilder->codeAppendf(\n"
|
|
|
|
"R\"SkSL(%s = %s;\n"
|
|
|
|
")SkSL\"\n"
|
|
|
|
", args.fOutputColor, _sample149.c_str());",
|
|
|
|
"child1_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child1_index));",
|
|
|
|
"child2_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child2_index));",
|
2020-02-20 19:41:47 +00:00
|
|
|
});
|
2018-08-30 20:08:18 +00:00
|
|
|
}
|
Reland "Redo how extra emit code flushing operates" with type fix.
This reverts commit d0440195d5cc049062238d02b8a962ae49c7f4ff.
Reason for revert: Fixes size_t -> int that was triggering ASAN failures.
Original change's description:
> Revert "Redo how extra emit code flushing operates"
>
> This reverts commit 9b8181b05a84e7dd24234c46c87d0bb2c73a7c08.
>
> Reason for revert: <INSERT REASONING HERE>
>
> Original change's description:
> > Redo how extra emit code flushing operates
> >
> > The previous implementation of flushEmittedCode(), that flushed on
> > demand when a process() was encountered, was brittle and susceptible to
> > mangling the expected sksl when fOut was modified outside of its
> > control. Given that writeFunction() and generateCode() in the parent
> > class all do this, it's possible to generate a simple SkSL snippet that
> > would generate a CPP file that builds invalid final SkSL:
> >
> > ```
> > in fragmentProcessor child;
> > bool someGlobalVar = ...;
> > void main() {
> > if (someGlobalVar) {
> > sk_OutColor = process(child, sk_InColor);
> > } else {
> > sk_OutColor = half4(1);
> > }
> > }
> > ```
> >
> > The CPP generated code *should* insert 'bool someGlobalVar' at the start
> > but because of the early flush from the child process and because of
> > how fOut was overwritten, someGlobalVar's declaration is put into a
> > stream that is not visible to the flush and ends up being inserted into
> > the output sksl in an incorrect location (namely after the if condition
> > that depends on it).
> >
> > This CL updates the extra emitted code logic to support multiple blocks
> > of extra CPP code. When a flush point occurs in SkSL writing, a special
> > token is inserted into the SkSL and a new CPP code buffer is associated
> > with that token. Then once all of the SkSL is accumulated into the root
> > output stream, it is processed into sections for each extra CPP block.
> > Special logic is done so that the SkSL that is emitted before the next
> > CPP block terminates at the end of the last valid statement before the
> > special token.
> >
> > A unit test demonstrating this failure condition is added to SkSLFPTest
> > and the CL properly passes. Since this bug did not trigger on existing
> > .fp files, the updated generator does not modify the generated FPs.
> >
> > Bug: skia:
> > Change-Id: Ib74911942080f1b964159807a06805bc52898789
> > Reviewed-on: https://skia-review.googlesource.com/152321
> > Commit-Queue: Michael Ludwig <michaelludwig@google.com>
> > Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
>
> TBR=ethannicholas@google.com,michaelludwig@google.com
>
> Change-Id: Id0f908453b596873f43b86a1c14eed48b2474a76
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: skia:
> Reviewed-on: https://skia-review.googlesource.com/152660
> Reviewed-by: Michael Ludwig <michaelludwig@google.com>
> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
TBR=ethannicholas@google.com,michaelludwig@google.com
Change-Id: I3ccf2fee6ef96c6102dbe1c2c2ef6c14a701b8fd
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:
Reviewed-on: https://skia-review.googlesource.com/152663
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
2018-09-07 17:13:06 +00:00
|
|
|
|
|
|
|
DEF_TEST(SkSLFPChildFPAndGlobal, r) {
|
|
|
|
test(r,
|
2020-06-10 20:40:38 +00:00
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
|
|
|
R"__SkSL__(
|
|
|
|
in fragmentProcessor child;
|
|
|
|
bool hasCap = sk_Caps.externalTextureSupport;
|
|
|
|
void main() {
|
|
|
|
if (hasCap) {
|
|
|
|
sk_OutColor = sample(child, sk_InColor);
|
|
|
|
} else {
|
|
|
|
sk_OutColor = half4(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{
|
2020-06-22 18:46:36 +00:00
|
|
|
"child_index = this->registerChild(std::move(child));"
|
Reland "Redo how extra emit code flushing operates" with type fix.
This reverts commit d0440195d5cc049062238d02b8a962ae49c7f4ff.
Reason for revert: Fixes size_t -> int that was triggering ASAN failures.
Original change's description:
> Revert "Redo how extra emit code flushing operates"
>
> This reverts commit 9b8181b05a84e7dd24234c46c87d0bb2c73a7c08.
>
> Reason for revert: <INSERT REASONING HERE>
>
> Original change's description:
> > Redo how extra emit code flushing operates
> >
> > The previous implementation of flushEmittedCode(), that flushed on
> > demand when a process() was encountered, was brittle and susceptible to
> > mangling the expected sksl when fOut was modified outside of its
> > control. Given that writeFunction() and generateCode() in the parent
> > class all do this, it's possible to generate a simple SkSL snippet that
> > would generate a CPP file that builds invalid final SkSL:
> >
> > ```
> > in fragmentProcessor child;
> > bool someGlobalVar = ...;
> > void main() {
> > if (someGlobalVar) {
> > sk_OutColor = process(child, sk_InColor);
> > } else {
> > sk_OutColor = half4(1);
> > }
> > }
> > ```
> >
> > The CPP generated code *should* insert 'bool someGlobalVar' at the start
> > but because of the early flush from the child process and because of
> > how fOut was overwritten, someGlobalVar's declaration is put into a
> > stream that is not visible to the flush and ends up being inserted into
> > the output sksl in an incorrect location (namely after the if condition
> > that depends on it).
> >
> > This CL updates the extra emitted code logic to support multiple blocks
> > of extra CPP code. When a flush point occurs in SkSL writing, a special
> > token is inserted into the SkSL and a new CPP code buffer is associated
> > with that token. Then once all of the SkSL is accumulated into the root
> > output stream, it is processed into sections for each extra CPP block.
> > Special logic is done so that the SkSL that is emitted before the next
> > CPP block terminates at the end of the last valid statement before the
> > special token.
> >
> > A unit test demonstrating this failure condition is added to SkSLFPTest
> > and the CL properly passes. Since this bug did not trigger on existing
> > .fp files, the updated generator does not modify the generated FPs.
> >
> > Bug: skia:
> > Change-Id: Ib74911942080f1b964159807a06805bc52898789
> > Reviewed-on: https://skia-review.googlesource.com/152321
> > Commit-Queue: Michael Ludwig <michaelludwig@google.com>
> > Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
>
> TBR=ethannicholas@google.com,michaelludwig@google.com
>
> Change-Id: Id0f908453b596873f43b86a1c14eed48b2474a76
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: skia:
> Reviewed-on: https://skia-review.googlesource.com/152660
> Reviewed-by: Michael Ludwig <michaelludwig@google.com>
> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
TBR=ethannicholas@google.com,michaelludwig@google.com
Change-Id: I3ccf2fee6ef96c6102dbe1c2c2ef6c14a701b8fd
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:
Reviewed-on: https://skia-review.googlesource.com/152663
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
2018-09-07 17:13:06 +00:00
|
|
|
},
|
2020-06-10 20:40:38 +00:00
|
|
|
/*expectedCPP=*/{
|
Reland "Redo how extra emit code flushing operates" with type fix.
This reverts commit d0440195d5cc049062238d02b8a962ae49c7f4ff.
Reason for revert: Fixes size_t -> int that was triggering ASAN failures.
Original change's description:
> Revert "Redo how extra emit code flushing operates"
>
> This reverts commit 9b8181b05a84e7dd24234c46c87d0bb2c73a7c08.
>
> Reason for revert: <INSERT REASONING HERE>
>
> Original change's description:
> > Redo how extra emit code flushing operates
> >
> > The previous implementation of flushEmittedCode(), that flushed on
> > demand when a process() was encountered, was brittle and susceptible to
> > mangling the expected sksl when fOut was modified outside of its
> > control. Given that writeFunction() and generateCode() in the parent
> > class all do this, it's possible to generate a simple SkSL snippet that
> > would generate a CPP file that builds invalid final SkSL:
> >
> > ```
> > in fragmentProcessor child;
> > bool someGlobalVar = ...;
> > void main() {
> > if (someGlobalVar) {
> > sk_OutColor = process(child, sk_InColor);
> > } else {
> > sk_OutColor = half4(1);
> > }
> > }
> > ```
> >
> > The CPP generated code *should* insert 'bool someGlobalVar' at the start
> > but because of the early flush from the child process and because of
> > how fOut was overwritten, someGlobalVar's declaration is put into a
> > stream that is not visible to the flush and ends up being inserted into
> > the output sksl in an incorrect location (namely after the if condition
> > that depends on it).
> >
> > This CL updates the extra emitted code logic to support multiple blocks
> > of extra CPP code. When a flush point occurs in SkSL writing, a special
> > token is inserted into the SkSL and a new CPP code buffer is associated
> > with that token. Then once all of the SkSL is accumulated into the root
> > output stream, it is processed into sections for each extra CPP block.
> > Special logic is done so that the SkSL that is emitted before the next
> > CPP block terminates at the end of the last valid statement before the
> > special token.
> >
> > A unit test demonstrating this failure condition is added to SkSLFPTest
> > and the CL properly passes. Since this bug did not trigger on existing
> > .fp files, the updated generator does not modify the generated FPs.
> >
> > Bug: skia:
> > Change-Id: Ib74911942080f1b964159807a06805bc52898789
> > Reviewed-on: https://skia-review.googlesource.com/152321
> > Commit-Queue: Michael Ludwig <michaelludwig@google.com>
> > Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
>
> TBR=ethannicholas@google.com,michaelludwig@google.com
>
> Change-Id: Id0f908453b596873f43b86a1c14eed48b2474a76
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: skia:
> Reviewed-on: https://skia-review.googlesource.com/152660
> Reviewed-by: Michael Ludwig <michaelludwig@google.com>
> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
TBR=ethannicholas@google.com,michaelludwig@google.com
Change-Id: I3ccf2fee6ef96c6102dbe1c2c2ef6c14a701b8fd
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:
Reviewed-on: https://skia-review.googlesource.com/152663
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
2018-09-07 17:13:06 +00:00
|
|
|
"hasCap = sk_Caps.externalTextureSupport;",
|
2020-06-18 17:00:38 +00:00
|
|
|
|
|
|
|
"fragBuilder->codeAppendf(\n"
|
|
|
|
"R\"SkSL(bool hasCap = %s;\n"
|
|
|
|
"if (hasCap) {)SkSL\"\n"
|
|
|
|
", (hasCap ? \"true\" : \"false\"));",
|
|
|
|
"SkString _input200(args.fInputColor);",
|
2020-06-10 20:40:38 +00:00
|
|
|
"SkString _sample200;",
|
|
|
|
"_sample200 = this->invokeChild(_outer.child_index, _input200.c_str(), args);",
|
2020-06-18 17:00:38 +00:00
|
|
|
"fragBuilder->codeAppendf(\n"
|
|
|
|
"R\"SkSL(\n"
|
|
|
|
" %s = %s;\n"
|
|
|
|
"} else {\n"
|
|
|
|
" %s = half4(1.0);\n"
|
|
|
|
"}\n"
|
|
|
|
")SkSL\"\n"
|
|
|
|
", args.fOutputColor, _sample200.c_str(), args.fOutputColor);",
|
|
|
|
"child_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child_index));",
|
2020-06-10 20:40:38 +00:00
|
|
|
});
|
Reland "Redo how extra emit code flushing operates" with type fix.
This reverts commit d0440195d5cc049062238d02b8a962ae49c7f4ff.
Reason for revert: Fixes size_t -> int that was triggering ASAN failures.
Original change's description:
> Revert "Redo how extra emit code flushing operates"
>
> This reverts commit 9b8181b05a84e7dd24234c46c87d0bb2c73a7c08.
>
> Reason for revert: <INSERT REASONING HERE>
>
> Original change's description:
> > Redo how extra emit code flushing operates
> >
> > The previous implementation of flushEmittedCode(), that flushed on
> > demand when a process() was encountered, was brittle and susceptible to
> > mangling the expected sksl when fOut was modified outside of its
> > control. Given that writeFunction() and generateCode() in the parent
> > class all do this, it's possible to generate a simple SkSL snippet that
> > would generate a CPP file that builds invalid final SkSL:
> >
> > ```
> > in fragmentProcessor child;
> > bool someGlobalVar = ...;
> > void main() {
> > if (someGlobalVar) {
> > sk_OutColor = process(child, sk_InColor);
> > } else {
> > sk_OutColor = half4(1);
> > }
> > }
> > ```
> >
> > The CPP generated code *should* insert 'bool someGlobalVar' at the start
> > but because of the early flush from the child process and because of
> > how fOut was overwritten, someGlobalVar's declaration is put into a
> > stream that is not visible to the flush and ends up being inserted into
> > the output sksl in an incorrect location (namely after the if condition
> > that depends on it).
> >
> > This CL updates the extra emitted code logic to support multiple blocks
> > of extra CPP code. When a flush point occurs in SkSL writing, a special
> > token is inserted into the SkSL and a new CPP code buffer is associated
> > with that token. Then once all of the SkSL is accumulated into the root
> > output stream, it is processed into sections for each extra CPP block.
> > Special logic is done so that the SkSL that is emitted before the next
> > CPP block terminates at the end of the last valid statement before the
> > special token.
> >
> > A unit test demonstrating this failure condition is added to SkSLFPTest
> > and the CL properly passes. Since this bug did not trigger on existing
> > .fp files, the updated generator does not modify the generated FPs.
> >
> > Bug: skia:
> > Change-Id: Ib74911942080f1b964159807a06805bc52898789
> > Reviewed-on: https://skia-review.googlesource.com/152321
> > Commit-Queue: Michael Ludwig <michaelludwig@google.com>
> > Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
>
> TBR=ethannicholas@google.com,michaelludwig@google.com
>
> Change-Id: Id0f908453b596873f43b86a1c14eed48b2474a76
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: skia:
> Reviewed-on: https://skia-review.googlesource.com/152660
> Reviewed-by: Michael Ludwig <michaelludwig@google.com>
> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
TBR=ethannicholas@google.com,michaelludwig@google.com
Change-Id: I3ccf2fee6ef96c6102dbe1c2c2ef6c14a701b8fd
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:
Reviewed-on: https://skia-review.googlesource.com/152663
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
2018-09-07 17:13:06 +00:00
|
|
|
}
|
2018-09-07 17:44:21 +00:00
|
|
|
|
|
|
|
DEF_TEST(SkSLFPChildProcessorInlineFieldAccess, r) {
|
|
|
|
test(r,
|
2020-06-10 20:40:38 +00:00
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
|
|
|
R"__SkSL__(
|
|
|
|
in fragmentProcessor child;
|
|
|
|
void main() {
|
|
|
|
if (child.preservesOpaqueInput) {
|
|
|
|
sk_OutColor = sample(child, sk_InColor);
|
|
|
|
} else {
|
|
|
|
sk_OutColor = half4(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{
|
2020-06-22 18:46:36 +00:00
|
|
|
"child_index = this->registerChild(std::move(child));"
|
2018-09-07 17:44:21 +00:00
|
|
|
},
|
2020-06-10 20:40:38 +00:00
|
|
|
/*expectedCPP=*/{
|
2020-06-18 17:00:38 +00:00
|
|
|
"fragBuilder->codeAppendf(\n"
|
|
|
|
"R\"SkSL(if (%s) {)SkSL\"\n"
|
|
|
|
", (_outer.childProcessor(_outer.child_index).preservesOpaqueInput() ? \"true\" : \"false\"));",
|
|
|
|
"SkString _input161(args.fInputColor);",
|
2020-06-10 20:40:38 +00:00
|
|
|
"SkString _sample161;",
|
|
|
|
"_sample161 = this->invokeChild(_outer.child_index, _input161.c_str(), args);",
|
2020-06-18 17:00:38 +00:00
|
|
|
"fragBuilder->codeAppendf(\n"
|
|
|
|
"R\"SkSL(\n"
|
|
|
|
" %s = %s;\n"
|
|
|
|
"} else {\n"
|
|
|
|
" %s = half4(1.0);\n"
|
|
|
|
"}\n"
|
|
|
|
")SkSL\"\n"
|
|
|
|
", args.fOutputColor, _sample161.c_str(), args.fOutputColor);",
|
|
|
|
"child_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child_index));",
|
2018-09-07 17:44:21 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
DEF_TEST(SkSLFPChildProcessorFieldAccess, r) {
|
|
|
|
test(r,
|
2020-06-10 20:40:38 +00:00
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
|
|
|
R"__SkSL__(
|
|
|
|
in fragmentProcessor child;
|
|
|
|
bool opaque = child.preservesOpaqueInput;
|
|
|
|
void main() {
|
|
|
|
if (opaque) {
|
|
|
|
sk_OutColor = sample(child);
|
|
|
|
} else {
|
|
|
|
sk_OutColor = half4(0.5);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{
|
2020-06-22 18:46:36 +00:00
|
|
|
"child_index = this->registerChild(std::move(child));"
|
2018-09-07 17:44:21 +00:00
|
|
|
},
|
2020-06-10 20:40:38 +00:00
|
|
|
/*expectedCPP=*/{
|
2019-04-09 14:40:41 +00:00
|
|
|
"opaque = _outer.childProcessor(_outer.child_index).preservesOpaqueInput();",
|
2020-06-18 17:00:38 +00:00
|
|
|
"fragBuilder->codeAppendf(\n"
|
|
|
|
"R\"SkSL(bool opaque = %s;\n"
|
|
|
|
"if (opaque) {)SkSL\"\n"
|
|
|
|
", (opaque ? \"true\" : \"false\"));",
|
2020-06-10 20:40:38 +00:00
|
|
|
"SkString _sample196;",
|
|
|
|
"_sample196 = this->invokeChild(_outer.child_index, args);",
|
2020-06-18 17:00:38 +00:00
|
|
|
"fragBuilder->codeAppendf(\n"
|
|
|
|
"R\"SkSL(\n"
|
|
|
|
" %s = %s;\n"
|
|
|
|
"} else {\n"
|
|
|
|
" %s = half4(0.5);\n"
|
|
|
|
"}\n"
|
|
|
|
")SkSL\"\n"
|
|
|
|
", args.fOutputColor, _sample196.c_str(), args.fOutputColor);",
|
|
|
|
"child_index = this->cloneAndRegisterChildProcessor(src.childProcessor(src.child_index));",
|
2018-09-07 17:44:21 +00:00
|
|
|
});
|
|
|
|
}
|
2019-03-04 17:25:57 +00:00
|
|
|
|
|
|
|
DEF_TEST(SkSLFPNullableChildProcessor, r) {
|
|
|
|
test(r,
|
2020-06-10 20:40:38 +00:00
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
|
|
|
R"__SkSL__(
|
|
|
|
in fragmentProcessor? child;
|
|
|
|
void main() {
|
|
|
|
if (child != null) {
|
|
|
|
sk_OutColor = sample(child);
|
|
|
|
} else {
|
|
|
|
sk_OutColor = half4(0.5);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{},
|
|
|
|
/*expectedCPP=*/{
|
2020-06-18 17:00:38 +00:00
|
|
|
"fragBuilder->codeAppendf(\n"
|
|
|
|
"R\"SkSL(if (%s) {)SkSL\"\n"
|
|
|
|
", _outer.child_index >= 0 ? \"true\" : \"false\");",
|
2020-06-10 20:40:38 +00:00
|
|
|
"SkString _sample149;",
|
2019-04-09 14:40:41 +00:00
|
|
|
"if (_outer.child_index >= 0) {",
|
2020-06-10 20:40:38 +00:00
|
|
|
"_sample149 = this->invokeChild(_outer.child_index, args);",
|
2020-06-18 17:00:38 +00:00
|
|
|
"fragBuilder->codeAppendf(\n"
|
|
|
|
"R\"SkSL(\n"
|
|
|
|
" %s = %s;\n"
|
|
|
|
"} else {\n"
|
|
|
|
" %s = half4(0.5);\n"
|
|
|
|
"}\n"
|
|
|
|
")SkSL\"\n"
|
|
|
|
", args.fOutputColor, _sample149.c_str(), args.fOutputColor);",
|
2019-03-04 17:25:57 +00:00
|
|
|
});
|
|
|
|
}
|
2019-08-13 14:21:38 +00:00
|
|
|
|
|
|
|
DEF_TEST(SkSLFPBadIn, r) {
|
|
|
|
test_failure(r,
|
2020-06-10 20:40:38 +00:00
|
|
|
R"__SkSL__(
|
|
|
|
in half4 c;
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = c;
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
"error: 4: 'in' variable must be either 'uniform' or 'layout(key)', or there must be a "
|
2019-08-13 14:21:38 +00:00
|
|
|
"custom @setData function\n1 error\n");
|
|
|
|
}
|
2019-08-29 20:10:13 +00:00
|
|
|
|
|
|
|
DEF_TEST(SkSLFPSampleCoords, r) {
|
|
|
|
test(r,
|
2020-06-10 20:40:38 +00:00
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
|
|
|
R"__SkSL__(
|
|
|
|
in fragmentProcessor child;
|
|
|
|
@coordTransform { SkMatrix() }
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = sample(child) + sample(child, sk_TransformedCoords2D[0] / 2);
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
2020-06-22 18:46:36 +00:00
|
|
|
/*expectedH=*/{
|
|
|
|
"child_index = this->registerExplicitlySampledChild(std::move(child));"
|
|
|
|
},
|
2020-06-10 20:40:38 +00:00
|
|
|
/*expectedCPP=*/{
|
|
|
|
"SkString _sample150;\n",
|
|
|
|
"_sample150 = this->invokeChild(_outer.child_index, args);\n",
|
|
|
|
"SkString _sample166;\n",
|
2019-08-29 20:10:13 +00:00
|
|
|
"SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D("
|
2020-04-14 13:54:02 +00:00
|
|
|
"args.fTransformedCoords[0].fVaryingPoint, "
|
|
|
|
"_outer.sampleMatrix());\n",
|
2020-06-10 20:40:38 +00:00
|
|
|
"SkString _coords166 = SkStringPrintf(\"%s / 2.0\", "
|
2019-11-11 19:55:28 +00:00
|
|
|
"sk_TransformedCoords2D_0.c_str());\n",
|
2020-06-10 20:40:38 +00:00
|
|
|
"_sample166 = this->invokeChild(_outer.child_index, args, _coords166.c_str());\n",
|
2020-06-18 17:00:38 +00:00
|
|
|
"fragBuilder->codeAppendf(\n"
|
|
|
|
"R\"SkSL(%s = %s + %s;\n"
|
|
|
|
")SkSL\"\n"
|
|
|
|
", args.fOutputColor, _sample150.c_str(), _sample166.c_str());"
|
|
|
|
});
|
2019-08-29 20:10:13 +00:00
|
|
|
}
|
2019-08-30 15:51:41 +00:00
|
|
|
|
|
|
|
DEF_TEST(SkSLFPFunction, r) {
|
|
|
|
test(r,
|
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
2020-06-10 20:40:38 +00:00
|
|
|
R"__SkSL__(
|
|
|
|
in fragmentProcessor? child;
|
|
|
|
half4 flip(half4 c) { return c.abgr; }
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = flip(sk_InColor);
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{},
|
|
|
|
/*expectedCPP=*/{
|
2019-08-30 15:51:41 +00:00
|
|
|
"SkString flip_name;",
|
|
|
|
"const GrShaderVar flip_args[] = { GrShaderVar(\"c\", kHalf4_GrSLType)};",
|
2020-06-18 17:00:38 +00:00
|
|
|
"fragBuilder->emitFunction(kHalf4_GrSLType, \"flip\", 1, flip_args,\n"
|
|
|
|
"R\"SkSL(return c.wzyx;\n"
|
|
|
|
")SkSL\", &flip_name);",
|
|
|
|
"fragBuilder->codeAppendf(\n"
|
|
|
|
"R\"SkSL(half4 inlineResult157;\n"
|
|
|
|
"half4 inlineArg157_0 = %s;\n"
|
|
|
|
"{\n"
|
|
|
|
" inlineResult157 = inlineArg157_0.wzyx;\n"
|
|
|
|
"}\n"
|
|
|
|
"%s = inlineResult157;\n"
|
|
|
|
"\n"
|
|
|
|
")SkSL\"\n"
|
|
|
|
", args.fInputColor, args.fOutputColor);"
|
2019-08-30 15:51:41 +00:00
|
|
|
});
|
|
|
|
}
|
2020-04-14 13:54:02 +00:00
|
|
|
|
|
|
|
DEF_TEST(SkSLFPMatrixSample, r) {
|
|
|
|
test(r,
|
|
|
|
*SkSL::ShaderCapsFactory::Default(),
|
2020-06-10 20:40:38 +00:00
|
|
|
R"__SkSL__(
|
|
|
|
in fragmentProcessor? child;
|
|
|
|
void main() {
|
|
|
|
sk_OutColor = sample(child, float3x3(2));
|
|
|
|
}
|
|
|
|
)__SkSL__",
|
|
|
|
/*expectedH=*/{},
|
|
|
|
/*expectedCPP=*/{});
|
2020-04-14 13:54:02 +00:00
|
|
|
}
|