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>
This commit is contained in:
parent
9a03642ad2
commit
6e1cbc012b
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user