aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Ethan Nicholas <ethannicholas@google.com>2017-07-14 10:12:15 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-07-14 14:41:04 +0000
commit6e1cbc012b10e99d9caed19eef43939778d1d8ff (patch)
tree94a884a96e8412ab0e852f6489321fd83de4b2a6 /src
parent9a03642ad2fce5805642783f68078a0a6bf03554 (diff)
fixed sksl static ifs to work for CircleEffect
static ifs (and switches) in .fp files are a bit tricky, because they aren't necessarily static when the CPP file is being produced. They become static when the CPP file produces the final SkSL; at this point the final values of the 'in' variables are known. This change permits 'deferred' static ifs and switches. The initial compilation (.fp -> .cpp) passes the @if / @switch through, and then the final compilation (.cpp's generated SkSL -> GLSL or whatever) enforces the static test. Bug: skia: Change-Id: I0087dfe1725c8fd350507ac77f64db1d82659cdf Reviewed-on: https://skia-review.googlesource.com/23403 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/gpu/effects/GrCircleEffect.cpp2
-rw-r--r--src/gpu/effects/GrCircleEffect.fp10
-rw-r--r--src/sksl/SkSLCPPCodeGenerator.cpp14
-rw-r--r--src/sksl/SkSLCPPCodeGenerator.h4
-rw-r--r--src/sksl/SkSLCompiler.cpp15
-rw-r--r--src/sksl/SkSLCompiler.h11
-rw-r--r--src/sksl/SkSLGLSLCodeGenerator.h4
-rw-r--r--src/sksl/SkSLMain.cpp4
8 files changed, 47 insertions, 17 deletions
diff --git a/src/gpu/effects/GrCircleEffect.cpp b/src/gpu/effects/GrCircleEffect.cpp
index acd2a9b977..23d6551770 100644
--- a/src/gpu/effects/GrCircleEffect.cpp
+++ b/src/gpu/effects/GrCircleEffect.cpp
@@ -25,7 +25,7 @@ public:
(void) _outer;
prevRadius = -1.0;
fCircleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType, kDefault_GrSLPrecision, "circle");
- fragBuilder->codeAppendf("vec2 prevCenter;\nfloat prevRadius = %f;\nfloat d;\nif (%d == 2 || %d == 3) {\n d = (length((%s.xy - sk_FragCoord.xy) * %s.w) - 1.0) * %s.z;\n} else {\n d = (1.0 - length((%s.xy - sk_FragCoord.xy) * %s.w)) * %s.z;\n}\nif ((%d == 1 || %d == 3) || %d == 4) {\n d = clamp(d, 0.0, 1.0);\n} else {\n d = d > 0.5 ? 1.0 : 0.0;\n}\n%s = %s * d;\n", prevRadius, _outer.edgeType(), _outer.edgeType(), args.fUniformHandler->getUniformCStr(fCircleVar), args.fUniformHandler->getUniformCStr(fCircleVar), args.fUniformHandler->getUniformCStr(fCircleVar), args.fUniformHandler->getUniformCStr(fCircleVar), args.fUniformHandler->getUniformCStr(fCircleVar), args.fUniformHandler->getUniformCStr(fCircleVar), _outer.edgeType(), _outer.edgeType(), _outer.edgeType(), args.fOutputColor, args.fInputColor ? args.fInputColor : "vec4(1)");
+ fragBuilder->codeAppendf("vec2 prevCenter;\nfloat prevRadius = %f;\nfloat d;\n@if (%d == 2 || %d == 3) {\n d = (length((%s.xy - sk_FragCoord.xy) * %s.w) - 1.0) * %s.z;\n} else {\n d = (1.0 - length((%s.xy - sk_FragCoord.xy) * %s.w)) * %s.z;\n}\n@if ((%d == 1 || %d == 3) || %d == 4) {\n d = clamp(d, 0.0, 1.0);\n} else {\n d = d > 0.5 ? 1.0 : 0.0;\n}\n%s = %s * d;\n", prevRadius, _outer.edgeType(), _outer.edgeType(), args.fUniformHandler->getUniformCStr(fCircleVar), args.fUniformHandler->getUniformCStr(fCircleVar), args.fUniformHandler->getUniformCStr(fCircleVar), args.fUniformHandler->getUniformCStr(fCircleVar), args.fUniformHandler->getUniformCStr(fCircleVar), args.fUniformHandler->getUniformCStr(fCircleVar), _outer.edgeType(), _outer.edgeType(), _outer.edgeType(), args.fOutputColor, args.fInputColor ? args.fInputColor : "vec4(1)");
}
private:
void onSetData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& _proc) override {
diff --git a/src/gpu/effects/GrCircleEffect.fp b/src/gpu/effects/GrCircleEffect.fp
index 3f0b85017e..74973ca064 100644
--- a/src/gpu/effects/GrCircleEffect.fp
+++ b/src/gpu/effects/GrCircleEffect.fp
@@ -37,15 +37,15 @@ void main() {
// radius and then denormalized. This is to prevent overflow on devices that have a "real"
// mediump. It'd be nice to only do this on mediump devices.
float d;
- if (edgeType == 2 /* kInverseFillBW_GrProcessorEdgeType */ ||
- edgeType == 3 /* kInverseFillAA_GrProcessorEdgeType */) {
+ @if (edgeType == 2 /* kInverseFillBW_GrProcessorEdgeType */ ||
+ edgeType == 3 /* kInverseFillAA_GrProcessorEdgeType */) {
d = (length((circle.xy - sk_FragCoord.xy) * circle.w) - 1.0) * circle.z;
} else {
d = (1.0 - length((circle.xy - sk_FragCoord.xy) * circle.w)) * circle.z;
}
- if (edgeType == 1 /* kFillAA_GrProcessorEdgeType */ ||
- edgeType == 3 /* kInverseFillAA_GrProcessorEdgeType */ ||
- edgeType == 4 /* kHairlineAA_GrProcessorEdgeType */) {
+ @if (edgeType == 1 /* kFillAA_GrProcessorEdgeType */ ||
+ edgeType == 3 /* kInverseFillAA_GrProcessorEdgeType */ ||
+ edgeType == 4 /* kHairlineAA_GrProcessorEdgeType */) {
d = clamp(d, 0.0, 1.0);
} else {
d = d > 0.5 ? 1.0 : 0.0;
diff --git a/src/sksl/SkSLCPPCodeGenerator.cpp b/src/sksl/SkSLCPPCodeGenerator.cpp
index 238615db49..3da7e8e5f0 100644
--- a/src/sksl/SkSLCPPCodeGenerator.cpp
+++ b/src/sksl/SkSLCPPCodeGenerator.cpp
@@ -225,6 +225,20 @@ void CPPCodeGenerator::writeVariableReference(const VariableReference& ref) {
}
}
+void CPPCodeGenerator::writeIfStatement(const IfStatement& s) {
+ if (s.fIsStatic) {
+ this->write("@");
+ }
+ INHERITED::writeIfStatement(s);
+}
+
+void CPPCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
+ if (s.fIsStatic) {
+ this->write("@");
+ }
+ INHERITED::writeSwitchStatement(s);
+}
+
void CPPCodeGenerator::writeFunctionCall(const FunctionCall& c) {
if (c.fFunction.fBuiltin && c.fFunction.fName == "COLORSPACE") {
String tmpVar = "_tmpVar" + to_string(++fVarCount);
diff --git a/src/sksl/SkSLCPPCodeGenerator.h b/src/sksl/SkSLCPPCodeGenerator.h
index 0f6da5f5c4..7f60563e51 100644
--- a/src/sksl/SkSLCPPCodeGenerator.h
+++ b/src/sksl/SkSLCPPCodeGenerator.h
@@ -41,6 +41,10 @@ private:
String getSamplerHandle(const Variable& var);
+ void writeIfStatement(const IfStatement& s) override;
+
+ void writeSwitchStatement(const SwitchStatement& s) override;
+
void writeFunctionCall(const FunctionCall& c) override;
void writeFunction(const FunctionDefinition& f) override;
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index 593397bd2a..3a037e798e 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -54,8 +54,9 @@ static const char* SKSL_FP_INCLUDE =
namespace SkSL {
-Compiler::Compiler()
-: fErrorCount(0) {
+Compiler::Compiler(Flags flags)
+: fFlags(flags)
+, fErrorCount(0) {
auto types = std::shared_ptr<SymbolTable>(new SymbolTable(this));
auto symbols = std::shared_ptr<SymbolTable>(new SymbolTable(types, this));
fIRGenerator = new IRGenerator(&fContext, symbols, *this);
@@ -931,7 +932,7 @@ void Compiler::simplifyStatement(DefinitionMap& definitions,
(*iter)->setStatement(std::move(newBlock));
break;
} else {
- if (s.fIsStatic) {
+ if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) {
this->error(s.fPosition,
"static switch contains non-static conditional break");
s.fIsStatic = false;
@@ -947,7 +948,7 @@ void Compiler::simplifyStatement(DefinitionMap& definitions,
if (newBlock) {
(*iter)->setStatement(std::move(newBlock));
} else {
- if (s.fIsStatic) {
+ if (s.fIsStatic && !(fFlags & kPermitInvalidStaticTests_Flag)) {
this->error(s.fPosition,
"static switch contains non-static conditional break");
s.fIsStatic = false;
@@ -1047,13 +1048,15 @@ void Compiler::scanCFG(FunctionDefinition& f) {
const Statement& s = **iter->statement();
switch (s.fKind) {
case Statement::kIf_Kind:
- if (((const IfStatement&) s).fIsStatic) {
+ if (((const IfStatement&) s).fIsStatic &&
+ !(fFlags & kPermitInvalidStaticTests_Flag)) {
this->error(s.fPosition, "static if has non-static test");
}
++iter;
break;
case Statement::kSwitch_Kind:
- if (((const SwitchStatement&) s).fIsStatic) {
+ if (((const SwitchStatement&) s).fIsStatic &&
+ !(fFlags & kPermitInvalidStaticTests_Flag)) {
this->error(s.fPosition, "static switch has non-static test");
}
++iter;
diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h
index 2acb55958f..38f63e542c 100644
--- a/src/sksl/SkSLCompiler.h
+++ b/src/sksl/SkSLCompiler.h
@@ -43,7 +43,15 @@ class IRGenerator;
*/
class Compiler : public ErrorReporter {
public:
- Compiler();
+ enum Flags {
+ kNone_Flags = 0,
+ // permits static if/switch statements to be used with non-constant tests. This is used when
+ // producing H and CPP code; the static tests don't have to have constant values *yet*, but
+ // the generated code will contain a static test which then does have to be a constant.
+ kPermitInvalidStaticTests_Flag = 1,
+ };
+
+ Compiler(Flags flags = kNone_Flags);
~Compiler() override;
@@ -109,6 +117,7 @@ private:
std::shared_ptr<SymbolTable> fTypes;
IRGenerator* fIRGenerator;
String fSkiaVertText; // FIXME store parsed version instead
+ int fFlags;
Context fContext;
int fErrorCount;
diff --git a/src/sksl/SkSLGLSLCodeGenerator.h b/src/sksl/SkSLGLSLCodeGenerator.h
index 5716bde70d..6fe25d3a69 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.h
+++ b/src/sksl/SkSLGLSLCodeGenerator.h
@@ -162,7 +162,7 @@ protected:
void writeBlock(const Block& b);
- void writeIfStatement(const IfStatement& stmt);
+ virtual void writeIfStatement(const IfStatement& stmt);
void writeForStatement(const ForStatement& f);
@@ -170,7 +170,7 @@ protected:
void writeDoStatement(const DoStatement& d);
- void writeSwitchStatement(const SwitchStatement& s);
+ virtual void writeSwitchStatement(const SwitchStatement& s);
void writeReturnStatement(const ReturnStatement& r);
diff --git a/src/sksl/SkSLMain.cpp b/src/sksl/SkSLMain.cpp
index 3e3d747304..9f1fec1f1b 100644
--- a/src/sksl/SkSLMain.cpp
+++ b/src/sksl/SkSLMain.cpp
@@ -95,7 +95,7 @@ int main(int argc, const char** argv) {
}
} else if (name.endsWith(".h")) {
SkSL::FileOutputStream out(argv[2]);
- SkSL::Compiler compiler;
+ SkSL::Compiler compiler(SkSL::Compiler::kPermitInvalidStaticTests_Flag);
if (!out.isValid()) {
printf("error writing '%s'\n", argv[2]);
exit(4);
@@ -112,7 +112,7 @@ int main(int argc, const char** argv) {
}
} else if (name.endsWith(".cpp")) {
SkSL::FileOutputStream out(argv[2]);
- SkSL::Compiler compiler;
+ SkSL::Compiler compiler(SkSL::Compiler::kPermitInvalidStaticTests_Flag);
if (!out.isValid()) {
printf("error writing '%s'\n", argv[2]);
exit(4);