diff options
author | ethannicholas <ethannicholas@google.com> | 2016-10-10 06:40:23 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-10-10 06:40:24 -0700 |
commit | 08b2ccf398e2b81bc05d2c105837e5419899469b (patch) | |
tree | f9338540266391ee920965581d44541b398487aa /src/sksl | |
parent | 3f748606d8dcac21c7fcdd07c2083f611c633ad5 (diff) |
Turned on SkSL->GLSL compiler
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2288033003
Committed: https://skia.googlesource.com/skia/+/9b0fe3d125f237d9884732a48414fa85fc71b4e3
Committed: https://skia.googlesource.com/skia/+/b12b3c6908c62c908b3680be01e3b5bfd30de310
Committed: https://skia.googlesource.com/skia/+/f008b0a59f45c0d4bea3e66faf3b01805009ec89
Review-Url: https://codereview.chromium.org/2288033003
Diffstat (limited to 'src/sksl')
31 files changed, 996 insertions, 369 deletions
diff --git a/src/sksl/README b/src/sksl/README new file mode 100644 index 0000000000..1427c21926 --- /dev/null +++ b/src/sksl/README @@ -0,0 +1,35 @@ +Overview +======== + +SkSL ("Skia Shading Language") is a variant of GLSL which is used as Skia's +internal shading language. SkSL is, at its heart, a single standardized version +of GLSL which avoids all of the various version and dialect differences found +in GLSL "in the wild", but it does bring a few of its own changes to the table. + +Skia uses the SkSL compiler to convert SkSL code to GLSL, GLSL ES, or SPIR-V +before handing it over to the graphics driver. + +Differences from GLSL +===================== + +SkSL is based on GLSL 4.5. For the most part, write SkSL exactly as you would +desktop GLSL, and the SkSL compiler will take care of version and dialect +differences (for instance, you always use "in" and "out", and skslc will handle +translating them to "varying" and "attribute" as appropriate). Be aware of the +following differences between SkSL and GLSL: + +* no #version or "precision" statement is required, and they will be ignored if + present +* the output color is sk_FragColor (do not declare it) +* lowp, mediump, and highp are always permitted (but will only be respected if + you run on a GLES device) +* you do not need to include ".0" to make a number a float (meaning that + "vec2(x, y) * 4" is perfectly legal in SkSL, unlike GLSL where it would often + have to be expressed "vec2(x, y) * 4.0". There is no performance penalty for + this, as the number is converted to a float at compile time) +* type suffixes on numbers (1.0f, 0xFFu) are both unnecessary and unsupported +* some built-in functions and one or two rarely-used language features are not + yet supported (sorry!) + +SkSL is still under development, and is expected to diverge further from GLSL +over time. diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp index d2ad81223e..88df8aeb57 100644 --- a/src/sksl/SkSLCompiler.cpp +++ b/src/sksl/SkSLCompiler.cpp @@ -10,11 +10,13 @@ #include <fstream> #include <streambuf> +#include "ast/SkSLASTPrecision.h" #include "SkSLIRGenerator.h" #include "SkSLParser.h" #include "SkSLSPIRVCodeGenerator.h" #include "ir/SkSLExpression.h" #include "ir/SkSLIntLiteral.h" +#include "ir/SkSLModifiersDeclaration.h" #include "ir/SkSLSymbolTable.h" #include "ir/SkSLVarDeclaration.h" #include "SkMutex.h" @@ -97,6 +99,7 @@ Compiler::Compiler() ADD_TYPE(Sampler1D); ADD_TYPE(Sampler2D); ADD_TYPE(Sampler3D); + ADD_TYPE(SamplerExternalOES); ADD_TYPE(SamplerCube); ADD_TYPE(Sampler2DRect); ADD_TYPE(Sampler1DArray); @@ -128,8 +131,9 @@ Compiler::Compiler() ADD_TYPE(GSampler2DArrayShadow); ADD_TYPE(GSamplerCubeArrayShadow); - std::vector<std::unique_ptr<ProgramElement>> ignored; - this->internalConvertProgram(SKSL_INCLUDE, &ignored); + Modifiers::Flag ignored1; + std::vector<std::unique_ptr<ProgramElement>> ignored2; + this->internalConvertProgram(SKSL_INCLUDE, &ignored1, &ignored2); ASSERT(!fErrorCount); } @@ -138,12 +142,14 @@ Compiler::~Compiler() { } void Compiler::internalConvertProgram(std::string text, + Modifiers::Flag* defaultPrecision, std::vector<std::unique_ptr<ProgramElement>>* result) { Parser parser(text, *fTypes, *this); std::vector<std::unique_ptr<ASTDeclaration>> parsed = parser.file(); if (fErrorCount) { return; } + *defaultPrecision = Modifiers::kHighp_Flag; for (size_t i = 0; i < parsed.size(); i++) { ASTDeclaration& decl = *parsed[i]; switch (decl.fKind) { @@ -164,6 +170,14 @@ void Compiler::internalConvertProgram(std::string text, } break; } + case ASTDeclaration::kModifiers_Kind: { + std::unique_ptr<ModifiersDeclaration> f = fIRGenerator->convertModifiersDeclaration( + (ASTModifiersDeclaration&) decl); + if (f) { + result->push_back(std::move(f)); + } + break; + } case ASTDeclaration::kInterfaceBlock_Kind: { std::unique_ptr<InterfaceBlock> i = fIRGenerator->convertInterfaceBlock( (ASTInterfaceBlock&) decl); @@ -179,6 +193,10 @@ void Compiler::internalConvertProgram(std::string text, } break; } + case ASTDeclaration::kPrecision_Kind: { + *defaultPrecision = ((ASTPrecision&) decl).fPrecision; + break; + } default: ABORT("unsupported declaration: %s\n", decl.description().c_str()); } @@ -190,16 +208,18 @@ std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, std::strin fErrorCount = 0; fIRGenerator->pushSymbolTable(); std::vector<std::unique_ptr<ProgramElement>> elements; + Modifiers::Flag ignored; switch (kind) { case Program::kVertex_Kind: - this->internalConvertProgram(SKSL_VERT_INCLUDE, &elements); + this->internalConvertProgram(SKSL_VERT_INCLUDE, &ignored, &elements); break; case Program::kFragment_Kind: - this->internalConvertProgram(SKSL_FRAG_INCLUDE, &elements); + this->internalConvertProgram(SKSL_FRAG_INCLUDE, &ignored, &elements); break; } - this->internalConvertProgram(text, &elements); - auto result = std::unique_ptr<Program>(new Program(kind, std::move(elements), + Modifiers::Flag defaultPrecision; + this->internalConvertProgram(text, &defaultPrecision, &elements); + auto result = std::unique_ptr<Program>(new Program(kind, defaultPrecision, std::move(elements), fIRGenerator->fSymbolTable));; fIRGenerator->popSymbolTable(); this->writeErrorCount(); diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h index 9cd1eac3f9..96ae7d06bc 100644 --- a/src/sksl/SkSLCompiler.h +++ b/src/sksl/SkSLCompiler.h @@ -15,6 +15,8 @@ #include "SkSLErrorReporter.h" #include "SkSLGLSLCodeGenerator.h" +#define SK_FRAGCOLOR_BUILTIN 10001 + namespace SkSL { class IRGenerator; @@ -24,6 +26,8 @@ class IRGenerator; * file into an abstract syntax tree (a tree of ASTNodes), then performs semantic analysis to * produce a Program (a tree of IRNodes), then feeds the Program into a CodeGenerator to produce * compiled output. + * + * See the README for information about SkSL. */ class Compiler : public ErrorReporter { public: @@ -50,6 +54,7 @@ public: private: void internalConvertProgram(std::string text, + Modifiers::Flag* defaultPrecision, std::vector<std::unique_ptr<ProgramElement>>* result); std::shared_ptr<SymbolTable> fTypes; diff --git a/src/sksl/SkSLContext.h b/src/sksl/SkSLContext.h index 1f124d05eb..82c265bbb2 100644 --- a/src/sksl/SkSLContext.h +++ b/src/sksl/SkSLContext.h @@ -60,6 +60,7 @@ public: , fSampler1D_Type(new Type("sampler1D", SpvDim1D, false, false, false, true)) , fSampler2D_Type(new Type("sampler2D", SpvDim2D, false, false, false, true)) , fSampler3D_Type(new Type("sampler3D", SpvDim3D, false, false, false, true)) + , fSamplerExternalOES_Type(new Type("samplerExternalOES", SpvDim2D, false, false, false, true)) , fSamplerCube_Type(new Type("samplerCube")) , fSampler2DRect_Type(new Type("sampler2DRect")) , fSampler1DArray_Type(new Type("sampler1DArray")) @@ -169,6 +170,7 @@ public: const std::unique_ptr<Type> fSampler1D_Type; const std::unique_ptr<Type> fSampler2D_Type; const std::unique_ptr<Type> fSampler3D_Type; + const std::unique_ptr<Type> fSamplerExternalOES_Type; const std::unique_ptr<Type> fSamplerCube_Type; const std::unique_ptr<Type> fSampler2DRect_Type; const std::unique_ptr<Type> fSampler1DArray_Type; diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp index da0bcb903c..58cf7d3c36 100644 --- a/src/sksl/SkSLGLSLCodeGenerator.cpp +++ b/src/sksl/SkSLGLSLCodeGenerator.cpp @@ -14,8 +14,11 @@ #include "ir/SkSLExpressionStatement.h" #include "ir/SkSLExtension.h" #include "ir/SkSLIndexExpression.h" +#include "ir/SkSLModifiersDeclaration.h" #include "ir/SkSLVariableReference.h" +#define SK_FRAGCOLOR_BUILTIN 10001 + namespace SkSL { void GLSLCodeGenerator::write(const char* s) { @@ -66,7 +69,7 @@ void GLSLCodeGenerator::writeType(const Type& type) { this->writeLine("struct " + type.name() + " {"); fIndentation++; for (const auto& f : type.fields()) { - this->writeModifiers(f.fModifiers); + this->writeModifiers(f.fModifiers, false); // sizes (which must be static in structs) are part of the type name here this->writeType(*f.fType); this->writeLine(" " + f.fName + ";"); @@ -124,7 +127,42 @@ void GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence paren } } +static bool is_abs(Expression& expr) { + if (expr.fKind != Expression::kFunctionCall_Kind) { + return false; + } + return ((FunctionCall&) expr).fFunction.fName == "abs"; +} + +// turns min(abs(x), y) into ((tmpVar1 = abs(x)) < (tmpVar2 = y) ? tmpVar1 : tmpVar2) to avoid a +// Tegra3 compiler bug. +void GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherExpr) { + ASSERT(!fCaps.fCanUseMinAndAbsTogether); + std::string tmpVar1 = "minAbsHackVar" + to_string(fVarCount++); + std::string tmpVar2 = "minAbsHackVar" + to_string(fVarCount++); + this->fFunctionHeader += " " + absExpr.fType.name() + " " + tmpVar1 + ";\n"; + this->fFunctionHeader += " " + otherExpr.fType.name() + " " + tmpVar2 + ";\n"; + this->write("((" + tmpVar1 + " = "); + this->writeExpression(absExpr, kTopLevel_Precedence); + this->write(") < (" + tmpVar2 + " = "); + this->writeExpression(otherExpr, kAssignment_Precedence); + this->write(") ? " + tmpVar1 + " : " + tmpVar2 + ")"); +} + void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) { + if (!fCaps.fCanUseMinAndAbsTogether && c.fFunction.fName == "min") { + ASSERT(c.fArguments.size() == 2); + if (is_abs(*c.fArguments[0])) { + this->writeMinAbsHack(*c.fArguments[0], *c.fArguments[1]); + return; + } + if (is_abs(*c.fArguments[1])) { + // note that this violates the GLSL left-to-right evaluation semantics. I doubt it will + // ever end up mattering, but it's worth calling out. + this->writeMinAbsHack(*c.fArguments[1], *c.fArguments[0]); + return; + } + } this->write(c.fFunction.fName + "("); const char* separator = ""; for (const auto& arg : c.fArguments) { @@ -147,7 +185,15 @@ void GLSLCodeGenerator::writeConstructor(const Constructor& c) { } void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) { - this->write(ref.fVariable.fName); + if (ref.fVariable.fModifiers.fLayout.fBuiltin == SK_FRAGCOLOR_BUILTIN) { + if (fCaps.fMustDeclareFragmentShaderOutput) { + this->write("sk_FragColor"); + } else { + this->write("gl_FragColor"); + } + } else { + this->write(ref.fVariable.fName); + } } void GLSLCodeGenerator::writeIndexExpression(const IndexExpression& expr) { @@ -270,7 +316,11 @@ void GLSLCodeGenerator::writeBoolLiteral(const BoolLiteral& b) { } void GLSLCodeGenerator::writeIntLiteral(const IntLiteral& i) { - this->write(to_string(i.fValue)); + if (i.fType == *fContext.fUInt_Type) { + this->write(to_string(i.fValue & 0xffffffff) + "u"); + } else { + this->write(to_string((int32_t) i.fValue)); + } } void GLSLCodeGenerator::writeFloatLiteral(const FloatLiteral& f) { @@ -284,28 +334,99 @@ void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) { for (const auto& param : f.fDeclaration.fParameters) { this->write(separator); separator = ", "; - this->writeModifiers(param->fModifiers); - this->writeType(param->fType); + this->writeModifiers(param->fModifiers, false); + std::vector<int> sizes; + const Type* type = ¶m->fType; + while (type->kind() == Type::kArray_Kind) { + sizes.push_back(type->columns()); + type = &type->componentType(); + } + this->writeType(*type); this->write(" " + param->fName); + for (int s : sizes) { + if (s <= 0) { + this->write("[]"); + } else { + this->write("[" + to_string(s) + "]"); + } + } } - this->write(") "); - this->writeBlock(*f.fBody); - this->writeLine(); + this->writeLine(") {"); + + fFunctionHeader = ""; + std::ostream* oldOut = fOut; + std::stringstream buffer; + fOut = &buffer; + fIndentation++; + for (const auto& s : f.fBody->fStatements) { + this->writeStatement(*s); + this->writeLine(); + } + fIndentation--; + this->writeLine("}"); + + fOut = oldOut; + this->write(fFunctionHeader); + this->write(buffer.str()); } -void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers) { - this->write(modifiers.description()); +void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers, + bool globalContext) { + if (modifiers.fFlags & Modifiers::kNoPerspective_Flag) { + this->write("noperspective "); + } + if (modifiers.fFlags & Modifiers::kFlat_Flag) { + this->write("flat "); + } + std::string layout = modifiers.fLayout.description(); + if (layout.length()) { + this->write(layout + " "); + } + if ((modifiers.fFlags & Modifiers::kIn_Flag) && + (modifiers.fFlags & Modifiers::kOut_Flag)) { + this->write("inout "); + } else if (modifiers.fFlags & Modifiers::kIn_Flag) { + if (globalContext && fCaps.fVersion < 130) { + this->write(fProgramKind == Program::kVertex_Kind ? "attribute " + : "varying "); + } else { + this->write("in "); + } + } else if (modifiers.fFlags & Modifiers::kOut_Flag) { + if (globalContext && fCaps.fVersion < 130) { + this->write("varying "); + } else { + this->write("out "); + } + } + if (modifiers.fFlags & Modifiers::kUniform_Flag) { + this->write("uniform "); + } + if (modifiers.fFlags & Modifiers::kConst_Flag) { + this->write("const "); + } + if (fCaps.fUsesPrecisionModifiers) { + if (modifiers.fFlags & Modifiers::kLowp_Flag) { + this->write("lowp "); + } + if (modifiers.fFlags & Modifiers::kMediump_Flag) { + this->write("mediump "); + } + if (modifiers.fFlags & Modifiers::kHighp_Flag) { + this->write("highp "); + } + } } void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { if (intf.fVariable.fName == "gl_PerVertex") { return; } - this->writeModifiers(intf.fVariable.fModifiers); + this->writeModifiers(intf.fVariable.fModifiers, true); this->writeLine(intf.fVariable.fType.name() + " {"); fIndentation++; for (const auto& f : intf.fVariable.fType.fields()) { - this->writeModifiers(f.fModifiers); + this->writeModifiers(f.fModifiers, false); this->writeType(*f.fType); this->writeLine(" " + f.fName + ";"); } @@ -313,9 +434,9 @@ void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { this->writeLine("};"); } -void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl) { +void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool global) { ASSERT(decl.fVars.size() > 0); - this->writeModifiers(decl.fVars[0].fVar->fModifiers); + this->writeModifiers(decl.fVars[0].fVar->fModifiers, global); this->writeType(decl.fBaseType); std::string separator = " "; for (const auto& var : decl.fVars) { @@ -325,7 +446,9 @@ void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl) { this->write(var.fVar->fName); for (const auto& size : var.fSizes) { this->write("["); - this->writeExpression(*size, kTopLevel_Precedence); + if (size) { + this->writeExpression(*size, kTopLevel_Precedence); + } this->write("]"); } if (var.fValue) { @@ -349,7 +472,7 @@ void GLSLCodeGenerator::writeStatement(const Statement& s) { this->writeReturnStatement((ReturnStatement&) s); break; case Statement::kVarDeclarations_Kind: - this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration); + this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration, false); break; case Statement::kIf_Kind: this->writeIfStatement((IfStatement&) s); @@ -444,22 +567,57 @@ void GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) { void GLSLCodeGenerator::generateCode(const Program& program, std::ostream& out) { ASSERT(fOut == nullptr); fOut = &out; + fProgramKind = program.fKind; this->write("#version " + to_string(fCaps.fVersion)); - if (fCaps.fStandard == GLCaps::kGLES_Standard) { + if (fCaps.fStandard == GLCaps::kGLES_Standard && fCaps.fVersion >= 300) { this->write(" es"); + } else if (fCaps.fIsCoreProfile) { + this->write(" core"); } this->writeLine(); for (const auto& e : program.fElements) { + if (e->fKind == ProgramElement::kExtension_Kind) { + this->writeExtension((Extension&) *e); + } + } + if (fCaps.fStandard == GLCaps::kGLES_Standard) { + this->write("precision "); + switch (program.fDefaultPrecision) { + case Modifiers::kLowp_Flag: + this->write("lowp"); + break; + case Modifiers::kMediump_Flag: + this->write("mediump"); + break; + case Modifiers::kHighp_Flag: + this->write("highp"); + break; + default: + ASSERT(false); + this->write("<error>"); + } + this->writeLine(" float;"); + } + for (const auto& e : program.fElements) { switch (e->fKind) { case ProgramElement::kExtension_Kind: - this->writeExtension((Extension&) *e); break; case ProgramElement::kVar_Kind: { VarDeclarations& decl = (VarDeclarations&) *e; - if (decl.fVars.size() > 0 && - decl.fVars[0].fVar->fModifiers.fLayout.fBuiltin == -1) { - this->writeVarDeclarations(decl); - this->writeLine(); + if (decl.fVars.size() > 0) { + int builtin = decl.fVars[0].fVar->fModifiers.fLayout.fBuiltin; + if (builtin == -1) { + // normal var + this->writeVarDeclarations(decl, true); + this->writeLine(); + } else if (builtin == SK_FRAGCOLOR_BUILTIN && + fCaps.fMustDeclareFragmentShaderOutput) { + this->write("out "); + if (fCaps.fUsesPrecisionModifiers) { + this->write("mediump "); + } + this->writeLine("vec4 sk_FragColor;"); + } } break; } @@ -469,6 +627,10 @@ void GLSLCodeGenerator::generateCode(const Program& program, std::ostream& out) case ProgramElement::kFunction_Kind: this->writeFunction((FunctionDefinition&) *e); break; + case ProgramElement::kModifiers_Kind: + this->writeModifiers(((ModifiersDeclaration&) *e).fModifiers, true); + this->writeLine(";"); + break; default: printf("%s\n", e->description().c_str()); ABORT("unsupported program element"); diff --git a/src/sksl/SkSLGLSLCodeGenerator.h b/src/sksl/SkSLGLSLCodeGenerator.h index 3534affccc..9851123708 100644 --- a/src/sksl/SkSLGLSLCodeGenerator.h +++ b/src/sksl/SkSLGLSLCodeGenerator.h @@ -50,6 +50,11 @@ struct GLCaps { kGL_Standard, kGLES_Standard } fStandard; + bool fIsCoreProfile; + bool fUsesPrecisionModifiers; + bool fMustDeclareFragmentShaderOutput; + // The Tegra3 compiler will sometimes never return if we have min(abs(x), y) + bool fCanUseMinAndAbsTogether; }; /** @@ -81,6 +86,8 @@ public: GLSLCodeGenerator(const Context* context, GLCaps caps) : fContext(*context) , fCaps(caps) + , fOut(nullptr) + , fVarCount(0) , fIndentation(0) , fAtLineStart(true) {} @@ -111,11 +118,11 @@ private: void writeLayout(const Layout& layout); - void writeModifiers(const Modifiers& modifiers); + void writeModifiers(const Modifiers& modifiers, bool globalContext); void writeGlobalVars(const VarDeclaration& vs); - void writeVarDeclarations(const VarDeclarations& decl); + void writeVarDeclarations(const VarDeclarations& decl, bool global); void writeVariableReference(const VariableReference& ref); @@ -123,6 +130,8 @@ private: void writeIntrinsicCall(const FunctionCall& c); + void writeMinAbsHack(Expression& absExpr, Expression& otherExpr); + void writeFunctionCall(const FunctionCall& c); void writeConstructor(const Constructor& c); @@ -164,6 +173,9 @@ private: const Context& fContext; const GLCaps fCaps; std::ostream* fOut; + std::string fFunctionHeader; + Program::Kind fProgramKind; + int fVarCount; int fIndentation; bool fAtLineStart; // Keeps track of which struct types we have written. Given that we are unlikely to ever write diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp index c30cac17d7..d64684e62d 100644 --- a/src/sksl/SkSLIRGenerator.cpp +++ b/src/sksl/SkSLIRGenerator.cpp @@ -189,7 +189,11 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVa } value = this->coerce(std::move(value), *type); } - if ("gl_FragCoord" == varDecl.fName && (*fSymbolTable)[varDecl.fName]) { + if ("sk_FragColor" == varDecl.fName && (*fSymbolTable)[varDecl.fName]) { + // already defined, ignore + } else if ((*fSymbolTable)[varDecl.fName] && + (*fSymbolTable)[varDecl.fName]->fKind == Symbol::kVariable_Kind && + ((Variable*) (*fSymbolTable)[varDecl.fName])->fModifiers.fLayout.fBuiltin >= 0) { // already defined, just update the modifiers Variable* old = (Variable*) (*fSymbolTable)[varDecl.fName]; old->fModifiers = var->fModifiers; @@ -203,6 +207,12 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVa std::move(variables))); } +std::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration( + const ASTModifiersDeclaration& m) { + Modifiers modifiers = this->convertModifiers(m.fModifiers); + return std::unique_ptr<ModifiersDeclaration>(new ModifiersDeclaration(modifiers)); +} + std::unique_ptr<Statement> IRGenerator::convertIf(const ASTIfStatement& s) { std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*s.fTest), *fContext.fBool_Type); @@ -419,8 +429,9 @@ std::unique_ptr<FunctionDefinition> IRGenerator::convertFunction(const ASTFuncti for (size_t i = 0; i < parameters.size(); i++) { if (parameters[i]->fModifiers != other->fParameters[i]->fModifiers) { fErrors.error(f.fPosition, "modifiers on parameter " + - to_string(i + 1) + " differ between " + - "declaration and definition"); + to_string((uint64_t) i + 1) + + " differ between declaration and " + "definition"); return nullptr; } } @@ -616,8 +627,9 @@ std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr ASSERT(ctor); return this->call(Position(), std::move(ctor), std::move(args)); } - ABORT("cannot coerce %s to %s", expr->fType.description().c_str(), - type.description().c_str()); + std::vector<std::unique_ptr<Expression>> args; + args.push_back(std::move(expr)); + return std::unique_ptr<Expression>(new Constructor(Position(), type, std::move(args))); } static bool is_matrix_multiply(const Type& left, const Type& right) { @@ -832,12 +844,12 @@ std::unique_ptr<Expression> IRGenerator::call(Position position, std::vector<std::unique_ptr<Expression>> arguments) { if (function.fParameters.size() != arguments.size()) { std::string msg = "call to '" + function.fName + "' expected " + - to_string(function.fParameters.size()) + + to_string((uint64_t) function.fParameters.size()) + " argument"; if (function.fParameters.size() != 1) { msg += "s"; } - msg += ", but found " + to_string(arguments.size()); + msg += ", but found " + to_string((uint64_t) arguments.size()); fErrors.error(position, msg); return nullptr; } @@ -921,7 +933,8 @@ std::unique_ptr<Expression> IRGenerator::convertConstructor( std::vector<std::unique_ptr<Expression>> args) { // FIXME: add support for structs and arrays Type::Kind kind = type.kind(); - if (!type.isNumber() && kind != Type::kVector_Kind && kind != Type::kMatrix_Kind) { + if (!type.isNumber() && kind != Type::kVector_Kind && kind != Type::kMatrix_Kind && + kind != Type::kArray_Kind) { fErrors.error(position, "cannot construct '" + type.description() + "'"); return nullptr; } @@ -938,7 +951,7 @@ std::unique_ptr<Expression> IRGenerator::convertConstructor( if (args.size() != 1) { fErrors.error(position, "invalid arguments to '" + type.description() + "' constructor, (expected exactly 1 argument, but found " + - to_string(args.size()) + ")"); + to_string((uint64_t) args.size()) + ")"); } if (args[0]->fType == *fContext.fBool_Type) { std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, position, 0)); @@ -953,6 +966,18 @@ std::unique_ptr<Expression> IRGenerator::convertConstructor( "' constructor (expected a number or bool, but found '" + args[0]->fType.description() + "')"); } + if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext.fInt_Type || + type == *fContext.fUInt_Type)) { + return std::unique_ptr<Expression>(new IntLiteral(fContext, + position, + ((IntLiteral&) *args[0]).fValue, + &type)); + } + } else if (kind == Type::kArray_Kind) { + const Type& base = type.componentType(); + for (size_t i = 0; i < args.size(); i++) { + args[i] = this->coerce(std::move(args[i]), base); + } } else { ASSERT(kind == Type::kVector_Kind || kind == Type::kMatrix_Kind); int actual = 0; @@ -1037,7 +1062,7 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression( } this->markWrittenTo(*base); break; - case Token::NOT: + case Token::LOGICALNOT: if (base->fType != *fContext.fBool_Type) { fErrors.error(expression.fPosition, "'" + Token::OperatorName(expression.fOperator) + @@ -1045,6 +1070,14 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression( return nullptr; } break; + case Token::BITWISENOT: + if (base->fType != *fContext.fInt_Type) { + fErrors.error(expression.fPosition, + "'" + Token::OperatorName(expression.fOperator) + + "' cannot operate on '" + base->fType.description() + "'"); + return nullptr; + } + break; default: ABORT("unsupported prefix operator\n"); } @@ -1054,7 +1087,8 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression( std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression> base, const ASTExpression& index) { - if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind) { + if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind && + base->fType.kind() != Type::kVector_Kind) { fErrors.error(base->fPosition, "expected array, but found '" + base->fType.description() + "'"); return nullptr; @@ -1063,9 +1097,11 @@ std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression if (!converted) { return nullptr; } - converted = this->coerce(std::move(converted), *fContext.fInt_Type); - if (!converted) { - return nullptr; + if (converted->fType != *fContext.fUInt_Type) { + converted = this->coerce(std::move(converted), *fContext.fInt_Type); + if (!converted) { + return nullptr; + } } return std::unique_ptr<Expression>(new IndexExpression(fContext, std::move(base), std::move(converted))); @@ -1143,9 +1179,21 @@ std::unique_ptr<Expression> IRGenerator::convertSuffixExpression( return nullptr; } switch (expression.fSuffix->fKind) { - case ASTSuffix::kIndex_Kind: - return this->convertIndex(std::move(base), - *((ASTIndexSuffix&) *expression.fSuffix).fExpression); + case ASTSuffix::kIndex_Kind: { + const ASTExpression* expr = ((ASTIndexSuffix&) *expression.fSuffix).fExpression.get(); + if (expr) { + return this->convertIndex(std::move(base), *expr); + } else if (base->fKind == Expression::kTypeReference_Kind) { + const Type& oldType = ((TypeReference&) *base).fValue; + Type* newType = new Type(oldType.name() + "[]", Type::kArray_Kind, oldType, + -1); + fSymbolTable->takeOwnership(newType); + return std::unique_ptr<Expression>(new TypeReference(fContext, base->fPosition, + *newType)); + } else { + fErrors.error(expression.fPosition, "'[]' must follow a type name"); + } + } case ASTSuffix::kCall_Kind: { auto rawArguments = &((ASTCallSuffix&) *expression.fSuffix).fArguments; std::vector<std::unique_ptr<Expression>> arguments; diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h index a3ff210b45..834ed8de81 100644 --- a/src/sksl/SkSLIRGenerator.h +++ b/src/sksl/SkSLIRGenerator.h @@ -25,6 +25,7 @@ #include "ast/SkSLASTIfStatement.h" #include "ast/SkSLASTInterfaceBlock.h" #include "ast/SkSLASTModifiers.h" +#include "ast/SkSLASTModifiersDeclaration.h" #include "ast/SkSLASTPrefixExpression.h" #include "ast/SkSLASTReturnStatement.h" #include "ast/SkSLASTStatement.h" @@ -39,6 +40,7 @@ #include "ir/SkSLFunctionDefinition.h" #include "ir/SkSLInterfaceBlock.h" #include "ir/SkSLModifiers.h" +#include "ir/SkSLModifiersDeclaration.h" #include "ir/SkSLSymbolTable.h" #include "ir/SkSLStatement.h" #include "ir/SkSLType.h" @@ -61,6 +63,8 @@ public: std::unique_ptr<FunctionDefinition> convertFunction(const ASTFunction& f); std::unique_ptr<Statement> convertStatement(const ASTStatement& statement); std::unique_ptr<Expression> convertExpression(const ASTExpression& expression); + std::unique_ptr<ModifiersDeclaration> convertModifiersDeclaration( + const ASTModifiersDeclaration& m); private: void pushSymbolTable(); diff --git a/src/sksl/SkSLMain.cpp b/src/sksl/SkSLMain.cpp index 24fbb6c260..de1b9819d5 100644 --- a/src/sksl/SkSLMain.cpp +++ b/src/sksl/SkSLMain.cpp @@ -9,6 +9,24 @@ #include <fstream> #include "SkSLCompiler.h" +bool endsWith(const std::string& s, const std::string& ending) { + if (s.length() >= ending.length()) { + return (0 == s.compare(s.length() - ending.length(), ending.length(), ending)); + } + return false; +} + +static SkSL::GLCaps default_caps() { + return { + 400, + SkSL::GLCaps::kGL_Standard, + false, // isCoreProfile + false, // usesPrecisionModifiers; + false, // mustDeclareFragmentShaderOutput + true // canUseMinAndAbsTogether + }; +} + /** * Very simple standalone executable to facilitate testing. */ @@ -35,14 +53,30 @@ int main(int argc, const char** argv) { printf("error reading '%s'\n", argv[1]); exit(2); } - std::ofstream out(argv[2], std::ofstream::binary); - SkSL::Compiler compiler; - if (!compiler.toSPIRV(kind, text, out)) { - printf("%s", compiler.errorText().c_str()); - exit(3); - } - if (out.rdstate()) { - printf("error writing '%s'\n", argv[2]); - exit(4); + std::string name(argv[2]); + if (endsWith(name, ".spirv")) { + std::ofstream out(argv[2], std::ofstream::binary); + SkSL::Compiler compiler; + if (!compiler.toSPIRV(kind, text, out)) { + printf("%s", compiler.errorText().c_str()); + exit(3); + } + if (out.rdstate()) { + printf("error writing '%s'\n", argv[2]); + exit(4); + } + } else if (endsWith(name, ".glsl")) { + std::ofstream out(argv[2], std::ofstream::binary); + SkSL::Compiler compiler; + if (!compiler.toGLSL(kind, text, default_caps(), out)) { + printf("%s", compiler.errorText().c_str()); + exit(3); + } + if (out.rdstate()) { + printf("error writing '%s'\n", argv[2]); + exit(4); + } + } else { + printf("expected output filename to end with '.spirv' or '.glsl'"); } } diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp index b240e4501e..29f1dbd178 100644 --- a/src/sksl/SkSLParser.cpp +++ b/src/sksl/SkSLParser.cpp @@ -56,7 +56,9 @@ #include "ast/SkSLASTIndexSuffix.h" #include "ast/SkSLASTInterfaceBlock.h" #include "ast/SkSLASTIntLiteral.h" +#include "ast/SkSLASTModifiersDeclaration.h" #include "ast/SkSLASTParameter.h" +#include "ast/SkSLASTPrecision.h" #include "ast/SkSLASTPrefixExpression.h" #include "ast/SkSLASTReturnStatement.h" #include "ast/SkSLASTStatement.h" @@ -97,9 +99,13 @@ std::vector<std::unique_ptr<ASTDeclaration>> Parser::file() { switch (this->peek().fKind) { case Token::END_OF_FILE: return result; - case Token::PRECISION: - this->precision(); + case Token::PRECISION: { + std::unique_ptr<ASTDeclaration> precision = this->precision(); + if (precision) { + result.push_back(std::move(precision)); + } break; + } case Token::DIRECTIVE: { std::unique_ptr<ASTDeclaration> decl = this->directive(); if (decl) { @@ -163,29 +169,37 @@ bool Parser::isType(std::string name) { } /* PRECISION (LOWP | MEDIUMP | HIGHP) type SEMICOLON */ -void Parser::precision() { +std::unique_ptr<ASTDeclaration> Parser::precision() { if (!this->expect(Token::PRECISION, "'precision'")) { - return; + return nullptr; } + Modifiers::Flag result; Token p = this->nextToken(); switch (p.fKind) { - case Token::LOWP: // fall through - case Token::MEDIUMP: // fall through + case Token::LOWP: + result = Modifiers::kLowp_Flag; + break; + case Token::MEDIUMP: + result = Modifiers::kMediump_Flag; + break; case Token::HIGHP: - // ignored for now + result = Modifiers::kHighp_Flag; break; default: this->error(p.fPosition, "expected 'lowp', 'mediump', or 'highp', but found '" + p.fText + "'"); - return; + return nullptr; } + // FIXME handle the type if (!this->type()) { - return; + return nullptr; } this->expect(Token::SEMICOLON, "';'"); + return std::unique_ptr<ASTDeclaration>(new ASTPrecision(p.fPosition, result)); } -/* DIRECTIVE(#version) INT_LITERAL | DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */ +/* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? | + DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */ std::unique_ptr<ASTDeclaration> Parser::directive() { Token start; if (!this->expect(Token::DIRECTIVE, "a directive", &start)) { @@ -193,7 +207,12 @@ std::unique_ptr<ASTDeclaration> Parser::directive() { } if (start.fText == "#version") { this->expect(Token::INT_LITERAL, "a version number"); - // ignored for now + Token next = this->peek(); + if (next.fText == "es" || next.fText == "compatibility") { + this->nextToken(); + } + // version is ignored for now; it will eventually become an error when we stop pretending + // to be GLSL return nullptr; } else if (start.fText == "#extension") { Token name; @@ -227,6 +246,10 @@ std::unique_ptr<ASTDeclaration> Parser::declaration() { if (lookahead.fKind == Token::STRUCT) { return this->structVarDeclaration(modifiers); } + if (lookahead.fKind == Token::SEMICOLON) { + this->nextToken(); + return std::unique_ptr<ASTDeclaration>(new ASTModifiersDeclaration(modifiers)); + } std::unique_ptr<ASTType> type(this->type()); if (!type) { return nullptr; @@ -477,10 +500,13 @@ ASTLayout Parser::layout() { int set = -1; int builtin = -1; bool originUpperLeft = false; + bool overrideCoverage = false; + bool blendSupportAllEquations = false; if (this->peek().fKind == Token::LAYOUT) { this->nextToken(); if (!this->expect(Token::LPAREN, "'('")) { - return ASTLayout(location, binding, index, set, builtin, originUpperLeft); + return ASTLayout(location, binding, index, set, builtin, originUpperLeft, + overrideCoverage, blendSupportAllEquations); } for (;;) { Token t = this->nextToken(); @@ -496,6 +522,10 @@ ASTLayout Parser::layout() { builtin = this->layoutInt(); } else if (t.fText == "origin_upper_left") { originUpperLeft = true; + } else if (t.fText == "override_coverage") { + overrideCoverage = true; + } else if (t.fText == "blend_support_all_equations") { + blendSupportAllEquations = true; } else { this->error(t.fPosition, ("'" + t.fText + "' is not a valid layout qualifier").c_str()); @@ -509,7 +539,8 @@ ASTLayout Parser::layout() { } } } - return ASTLayout(location, binding, index, set, builtin, originUpperLeft); + return ASTLayout(location, binding, index, set, builtin, originUpperLeft, overrideCoverage, + blendSupportAllEquations); } /* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT | NOPERSPECTIVE)* */ @@ -1211,10 +1242,11 @@ std::unique_ptr<ASTExpression> Parser::multiplicativeExpression() { /* postfixExpression | (PLUS | MINUS | NOT | PLUSPLUS | MINUSMINUS) unaryExpression */ std::unique_ptr<ASTExpression> Parser::unaryExpression() { switch (this->peek().fKind) { - case Token::PLUS: // fall through - case Token::MINUS: // fall through - case Token::NOT: // fall through - case Token::PLUSPLUS: // fall through + case Token::PLUS: // fall through + case Token::MINUS: // fall through + case Token::LOGICALNOT: // fall through + case Token::BITWISENOT: // fall through + case Token::PLUSPLUS: // fall through case Token::MINUSMINUS: { Token t = this->nextToken(); std::unique_ptr<ASTExpression> expr = this->unaryExpression(); @@ -1254,12 +1286,16 @@ std::unique_ptr<ASTExpression> Parser::postfixExpression() { } } -/* LBRACKET expression RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN | +/* LBRACKET expression? RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN | PLUSPLUS | MINUSMINUS */ std::unique_ptr<ASTSuffix> Parser::suffix() { Token next = this->nextToken(); switch (next.fKind) { case Token::LBRACKET: { + if (this->peek().fKind == Token::RBRACKET) { + this->nextToken(); + return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(next.fPosition)); + } std::unique_ptr<ASTExpression> e = this->expression(); if (!e) { return nullptr; diff --git a/src/sksl/SkSLParser.h b/src/sksl/SkSLParser.h index 75f304bc8c..d1ae0d0e9f 100644 --- a/src/sksl/SkSLParser.h +++ b/src/sksl/SkSLParser.h @@ -35,6 +35,7 @@ struct ASTInterfaceBlock; struct ASTLayout; struct ASTModifiers; struct ASTParameter; +struct ASTPrecision; struct ASTReturnStatement; struct ASTStatement; struct ASTSuffix; @@ -100,7 +101,7 @@ private: // don't need to call any of these outside of the parser. The function declarations in the .cpp // file have comments describing the grammar rules. - void precision(); + std::unique_ptr<ASTDeclaration> precision(); std::unique_ptr<ASTDeclaration> directive(); diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp index d17e3c42a2..5403ba3628 100644 --- a/src/sksl/SkSLSPIRVCodeGenerator.cpp +++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp @@ -15,6 +15,7 @@ #include "ir/SkSLExtension.h" #include "ir/SkSLIndexExpression.h" #include "ir/SkSLVariableReference.h" +#include "SkSLCompiler.h" namespace SkSL { @@ -2162,13 +2163,19 @@ SpvId SPIRVCodeGenerator::writePrefixExpression(const PrefixExpression& p, std:: lv->store(result, out); return result; } - case Token::NOT: { + case Token::LOGICALNOT: { ASSERT(p.fOperand->fType == *fContext.fBool_Type); SpvId result = this->nextId(); this->writeInstruction(SpvOpLogicalNot, this->getType(p.fOperand->fType), result, this->writeExpression(*p.fOperand, out), out); return result; } + case Token::BITWISENOT: { + SpvId result = this->nextId(); + this->writeInstruction(SpvOpNot, this->getType(p.fOperand->fType), result, + this->writeExpression(*p.fOperand, out), out); + return result; + } default: ABORT("unsupported prefix expression: %s", p.description().c_str()); } @@ -2321,7 +2328,7 @@ void SPIRVCodeGenerator::writeLayout(const Layout& layout, SpvId target) { this->writeInstruction(SpvOpDecorate, target, SpvDecorationDescriptorSet, layout.fSet, fDecorationBuffer); } - if (layout.fBuiltin >= 0) { + if (layout.fBuiltin >= 0 && layout.fBuiltin != SK_FRAGCOLOR_BUILTIN) { this->writeInstruction(SpvOpDecorate, target, SpvDecorationBuiltIn, layout.fBuiltin, fDecorationBuffer); } @@ -2363,10 +2370,19 @@ SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { return result; } -void SPIRVCodeGenerator::writeGlobalVars(const VarDeclarations& decl, std::ostream& out) { +#define BUILTIN_IGNORE 9999 +void SPIRVCodeGenerator::writeGlobalVars(Program::Kind kind, const VarDeclarations& decl, + std::ostream& out) { for (size_t i = 0; i < decl.fVars.size(); i++) { const VarDeclaration& varDecl = decl.fVars[i]; const Variable* var = varDecl.fVar; + if (var->fModifiers.fLayout.fBuiltin == BUILTIN_IGNORE) { + continue; + } + if (var->fModifiers.fLayout.fBuiltin == SK_FRAGCOLOR_BUILTIN && + kind != Program::kFragment_Kind) { + continue; + } if (!var->fIsReadFrom && !var->fIsWrittenTo && !(var->fModifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kOut_Flag | @@ -2562,7 +2578,8 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, std::ostream& } for (size_t i = 0; i < program.fElements.size(); i++) { if (program.fElements[i]->fKind == ProgramElement::kVar_Kind) { - this->writeGlobalVars(((VarDeclarations&) *program.fElements[i]), body); + this->writeGlobalVars(program.fKind, ((VarDeclarations&) *program.fElements[i]), + body); } } for (size_t i = 0; i < program.fElements.size(); i++) { diff --git a/src/sksl/SkSLSPIRVCodeGenerator.h b/src/sksl/SkSLSPIRVCodeGenerator.h index e7b2b30232..2800a861b8 100644 --- a/src/sksl/SkSLSPIRVCodeGenerator.h +++ b/src/sksl/SkSLSPIRVCodeGenerator.h @@ -115,7 +115,7 @@ private: SpvId writeFunction(const FunctionDefinition& f, std::ostream& out); - void writeGlobalVars(const VarDeclarations& v, std::ostream& out); + void writeGlobalVars(Program::Kind kind, const VarDeclarations& v, std::ostream& out); void writeVarDeclarations(const VarDeclarations& decl, std::ostream& out); diff --git a/src/sksl/SkSLToken.h b/src/sksl/SkSLToken.h index 29fa81e2e0..b8a364c269 100644 --- a/src/sksl/SkSLToken.h +++ b/src/sksl/SkSLToken.h @@ -49,10 +49,11 @@ struct Token { BITWISEOR, BITWISEXOR, BITWISEAND, + BITWISENOT, LOGICALOR, LOGICALXOR, LOGICALAND, - NOT, + LOGICALNOT, QUESTION, COLON, EQ, @@ -111,9 +112,11 @@ struct Token { case Token::PERCENT: return "%"; case Token::SHL: return "<<"; case Token::SHR: return ">>"; + case Token::LOGICALNOT: return "!"; case Token::LOGICALAND: return "&&"; case Token::LOGICALOR: return "||"; case Token::LOGICALXOR: return "^^"; + case Token::BITWISENOT: return "~"; case Token::BITWISEAND: return "&"; case Token::BITWISEOR: return "|"; case Token::BITWISEXOR: return "^"; @@ -139,7 +142,6 @@ struct Token { case Token::BITWISEXOREQ: return "^="; case Token::PLUSPLUS: return "++"; case Token::MINUSMINUS: return "--"; - case Token::NOT: return "!"; default: ABORT("unsupported operator: %d\n", kind); } diff --git a/src/sksl/SkSLUtil.cpp b/src/sksl/SkSLUtil.cpp index 327bffe4f1..51ad9fe808 100644 --- a/src/sksl/SkSLUtil.cpp +++ b/src/sksl/SkSLUtil.cpp @@ -9,7 +9,48 @@ namespace SkSL { +std::string to_string(double value) { + std::stringstream buffer; + buffer << std::setprecision(std::numeric_limits<double>::digits10) << value; + std::string result = buffer.str(); + if (result.find_last_of(".") == std::string::npos && + result.find_last_of("e") == std::string::npos) { + result += ".0"; + } + return result; +} + +std::string to_string(int32_t value) { + std::stringstream buffer; + buffer << value; + return buffer.str(); +} + +std::string to_string(uint32_t value) { + std::stringstream buffer; + buffer << value; + return buffer.str(); +} + +std::string to_string(int64_t value) { + std::stringstream buffer; + buffer << value; + return buffer.str(); +} + +std::string to_string(uint64_t value) { + std::stringstream buffer; + buffer << value; + return buffer.str(); +} + int stoi(std::string s) { + if (s.size() > 2 && s[0] == '0' && s[1] == 'x') { + char* p; + int result = strtoul(s.substr(2).c_str(), &p, 16); + ASSERT(*p == 0); + return result; + } return atoi(s.c_str()); } @@ -18,6 +59,12 @@ double stod(std::string s) { } long stol(std::string s) { + if (s.size() > 2 && s[0] == '0' && s[1] == 'x') { + char* p; + long result = strtoul(s.substr(2).c_str(), &p, 16); + ASSERT(*p == 0); + return result; + } return atol(s.c_str()); } diff --git a/src/sksl/SkSLUtil.h b/src/sksl/SkSLUtil.h index 33611cde02..efffaaec01 100644 --- a/src/sksl/SkSLUtil.h +++ b/src/sksl/SkSLUtil.h @@ -19,11 +19,15 @@ namespace SkSL { // our own definitions of certain std:: functions, because they are not always present on Android -template <typename T> std::string to_string(T value) { - std::stringstream buffer; - buffer << std::setprecision(std::numeric_limits<T>::digits10) << value; - return buffer.str(); -} +std::string to_string(double value); + +std::string to_string(int32_t value); + +std::string to_string(uint32_t value); + +std::string to_string(int64_t value); + +std::string to_string(uint64_t value); #if _MSC_VER #define NORETURN __declspec(noreturn) diff --git a/src/sksl/ast/SkSLASTDeclaration.h b/src/sksl/ast/SkSLASTDeclaration.h index 8b55ecf832..70f0ebc72d 100644 --- a/src/sksl/ast/SkSLASTDeclaration.h +++ b/src/sksl/ast/SkSLASTDeclaration.h @@ -20,7 +20,9 @@ struct ASTDeclaration : public ASTPositionNode { kVar_Kind, kFunction_Kind, kInterfaceBlock_Kind, - kExtension_Kind + kExtension_Kind, + kPrecision_Kind, + kModifiers_Kind }; ASTDeclaration(Position position, Kind kind) diff --git a/src/sksl/ast/SkSLASTIndexSuffix.h b/src/sksl/ast/SkSLASTIndexSuffix.h index 44d91fa4c4..755029b0a2 100644 --- a/src/sksl/ast/SkSLASTIndexSuffix.h +++ b/src/sksl/ast/SkSLASTIndexSuffix.h @@ -14,17 +14,27 @@ namespace SkSL { /** - * A bracketed expression, as in '[0]', indicating an array access. + * A bracketed expression, as in '[0]', indicating an array access. Empty brackets (as occur in + * 'float[](5, 6)' are represented with a null fExpression. */ struct ASTIndexSuffix : public ASTSuffix { + ASTIndexSuffix(Position position) + : INHERITED(position, ASTSuffix::kIndex_Kind) + , fExpression(nullptr) {} + ASTIndexSuffix(std::unique_ptr<ASTExpression> expression) - : INHERITED(expression->fPosition, ASTSuffix::kIndex_Kind) + : INHERITED(expression ? expression->fPosition : Position(), ASTSuffix::kIndex_Kind) , fExpression(std::move(expression)) {} std::string description() const override { - return "[" + fExpression->description() + "]"; + if (fExpression) { + return "[" + fExpression->description() + "]"; + } else { + return "[]"; + } } + // may be null std::unique_ptr<ASTExpression> fExpression; typedef ASTSuffix INHERITED; diff --git a/src/sksl/ast/SkSLASTLayout.h b/src/sksl/ast/SkSLASTLayout.h index 08d67531c3..515eb2bdbb 100644 --- a/src/sksl/ast/SkSLASTLayout.h +++ b/src/sksl/ast/SkSLASTLayout.h @@ -20,13 +20,16 @@ namespace SkSL { */ struct ASTLayout : public ASTNode { // For all parameters, a -1 means no value - ASTLayout(int location, int binding, int index, int set, int builtin, bool originUpperLeft) + ASTLayout(int location, int binding, int index, int set, int builtin, bool originUpperLeft, + bool overrideCoverage, bool blendSupportAllEquations) : fLocation(location) , fBinding(binding) , fIndex(index) , fSet(set) , fBuiltin(builtin) - , fOriginUpperLeft(originUpperLeft) {} + , fOriginUpperLeft(originUpperLeft) + , fOverrideCoverage(overrideCoverage) + , fBlendSupportAllEquations(blendSupportAllEquations) {} std::string description() const { std::string result; @@ -55,6 +58,14 @@ struct ASTLayout : public ASTNode { result += separator + "origin_upper_left"; separator = ", "; } + if (fOverrideCoverage) { + result += separator + "override_coverage"; + separator = ", "; + } + if (fBlendSupportAllEquations) { + result += separator + "blend_support_all_equations"; + separator = ", "; + } if (result.length() > 0) { result = "layout (" + result + ")"; } @@ -67,6 +78,8 @@ struct ASTLayout : public ASTNode { const int fSet; const int fBuiltin; const bool fOriginUpperLeft; + const bool fOverrideCoverage; + const bool fBlendSupportAllEquations; }; } // namespace diff --git a/src/sksl/ast/SkSLASTModifiersDeclaration.h b/src/sksl/ast/SkSLASTModifiersDeclaration.h new file mode 100644 index 0000000000..f5cc620899 --- /dev/null +++ b/src/sksl/ast/SkSLASTModifiersDeclaration.h @@ -0,0 +1,37 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SKSL_ASTMODIFIERDECLARATION +#define SKSL_ASTMODIFIERDECLARATION + +#include "SkSLASTDeclaration.h" +#include "SkSLASTModifiers.h" + +namespace SkSL { + +/** + * A declaration that consists only of modifiers, e.g.: + * + * layout(blend_support_all_equations) out; + */ +struct ASTModifiersDeclaration : public ASTDeclaration { + ASTModifiersDeclaration(ASTModifiers modifiers) + : INHERITED(Position(), kModifiers_Kind) + , fModifiers(modifiers) {} + + std::string description() const { + return fModifiers.description() + ";"; + } + + ASTModifiers fModifiers; + + typedef ASTDeclaration INHERITED; +}; + +} // namespace + +#endif diff --git a/src/sksl/ast/SkSLASTPrecision.h b/src/sksl/ast/SkSLASTPrecision.h new file mode 100644 index 0000000000..a7df57948e --- /dev/null +++ b/src/sksl/ast/SkSLASTPrecision.h @@ -0,0 +1,45 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SKSL_ASTPRECISION +#define SKSL_ASTPRECISION + +#include "SkSLASTDeclaration.h" +#include "../ir/SkSLModifiers.h" + +namespace SkSL { + +/** + * Represents a precision declaration (e.g. 'precision mediump float;'). + */ +struct ASTPrecision : public ASTDeclaration { + // FIXME handle the type + ASTPrecision(Position position, Modifiers::Flag precision) + : INHERITED(position, kPrecision_Kind) + , fPrecision(precision) {} + + std::string description() const { + switch (fPrecision) { + case Modifiers::kLowp_Flag: return "precision lowp float;"; + case Modifiers::kMediump_Flag: return "precision mediump float;"; + case Modifiers::kHighp_Flag: return "precision highp float;"; + default: + ASSERT(false); + return "<error>"; + } + ASSERT(false); + return "<error>"; + } + + const Modifiers::Flag fPrecision; + + typedef ASTDeclaration INHERITED; +}; + +} // namespace + +#endif diff --git a/src/sksl/ir/SkSLIndexExpression.h b/src/sksl/ir/SkSLIndexExpression.h index f5b0d09c2c..ea9af3d897 100644 --- a/src/sksl/ir/SkSLIndexExpression.h +++ b/src/sksl/ir/SkSLIndexExpression.h @@ -19,7 +19,7 @@ namespace SkSL { static const Type& index_type(const Context& context, const Type& type) { if (type.kind() == Type::kMatrix_Kind) { if (type.componentType() == *context.fFloat_Type) { - switch (type.columns()) { + switch (type.rows()) { case 2: return *context.fVec2_Type; case 3: return *context.fVec3_Type; case 4: return *context.fVec4_Type; @@ -27,7 +27,7 @@ static const Type& index_type(const Context& context, const Type& type) { } } else { ASSERT(type.componentType() == *context.fDouble_Type); - switch (type.columns()) { + switch (type.rows()) { case 2: return *context.fDVec2_Type; case 3: return *context.fDVec3_Type; case 4: return *context.fDVec4_Type; @@ -47,7 +47,7 @@ struct IndexExpression : public Expression { : INHERITED(base->fPosition, kIndex_Kind, index_type(context, base->fType)) , fBase(std::move(base)) , fIndex(std::move(index)) { - ASSERT(fIndex->fType == *context.fInt_Type); + ASSERT(fIndex->fType == *context.fInt_Type || fIndex->fType == *context.fUInt_Type); } std::string description() const override { diff --git a/src/sksl/ir/SkSLIntLiteral.h b/src/sksl/ir/SkSLIntLiteral.h index 2bc565712e..8921c283b5 100644 --- a/src/sksl/ir/SkSLIntLiteral.h +++ b/src/sksl/ir/SkSLIntLiteral.h @@ -18,8 +18,8 @@ namespace SkSL { struct IntLiteral : public Expression { // FIXME: we will need to revisit this if/when we add full support for both signed and unsigned // 64-bit integers, but for right now an int64_t will hold every value we care about - IntLiteral(const Context& context, Position position, int64_t value) - : INHERITED(position, kIntLiteral_Kind, *context.fInt_Type) + IntLiteral(const Context& context, Position position, int64_t value, const Type* type = nullptr) + : INHERITED(position, kIntLiteral_Kind, type ? *type : *context.fInt_Type) , fValue(value) {} virtual std::string description() const override { diff --git a/src/sksl/ir/SkSLLayout.h b/src/sksl/ir/SkSLLayout.h index d8dc98096f..24087d0612 100644 --- a/src/sksl/ir/SkSLLayout.h +++ b/src/sksl/ir/SkSLLayout.h @@ -22,15 +22,20 @@ struct Layout { , fIndex(layout.fIndex) , fSet(layout.fSet) , fBuiltin(layout.fBuiltin) - , fOriginUpperLeft(layout.fOriginUpperLeft) {} + , fOriginUpperLeft(layout.fOriginUpperLeft) + , fOverrideCoverage(layout.fOverrideCoverage) + , fBlendSupportAllEquations(layout.fBlendSupportAllEquations) {} - Layout(int location, int binding, int index, int set, int builtin, bool originUpperLeft) + Layout(int location, int binding, int index, int set, int builtin, bool originUpperLeft, + bool overrideCoverage, bool blendSupportAllEquations) : fLocation(location) , fBinding(binding) , fIndex(index) , fSet(set) , fBuiltin(builtin) - , fOriginUpperLeft(originUpperLeft) {} + , fOriginUpperLeft(originUpperLeft) + , fOverrideCoverage(overrideCoverage) + , fBlendSupportAllEquations(blendSupportAllEquations) {} std::string description() const { std::string result; @@ -59,6 +64,14 @@ struct Layout { result += separator + "origin_upper_left"; separator = ", "; } + if (fOverrideCoverage) { + result += separator + "override_coverage"; + separator = ", "; + } + if (fBlendSupportAllEquations) { + result += separator + "blend_support_all_equations"; + separator = ", "; + } if (result.length() > 0) { result = "layout (" + result + ")"; } @@ -66,11 +79,14 @@ struct Layout { } bool operator==(const Layout& other) const { - return fLocation == other.fLocation && - fBinding == other.fBinding && - fIndex == other.fIndex && - fSet == other.fSet && - fBuiltin == other.fBuiltin; + return fLocation == other.fLocation && + fBinding == other.fBinding && + fIndex == other.fIndex && + fSet == other.fSet && + fBuiltin == other.fBuiltin && + fOriginUpperLeft == other.fOriginUpperLeft && + fOverrideCoverage == other.fOverrideCoverage && + fBlendSupportAllEquations == other.fBlendSupportAllEquations; } bool operator!=(const Layout& other) const { @@ -85,6 +101,8 @@ struct Layout { int fSet; int fBuiltin; bool fOriginUpperLeft; + bool fOverrideCoverage; + bool fBlendSupportAllEquations; }; } // namespace diff --git a/src/sksl/ir/SkSLModifiersDeclaration.h b/src/sksl/ir/SkSLModifiersDeclaration.h new file mode 100644 index 0000000000..0066fab877 --- /dev/null +++ b/src/sksl/ir/SkSLModifiersDeclaration.h @@ -0,0 +1,37 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SKSL_MODIFIERDECLARATION +#define SKSL_MODIFIERDECLARATION + +#include "SkSLProgramElement.h" +#include "SkSLModifiers.h" + +namespace SkSL { + +/** + * A declaration that consists only of modifiers, e.g.: + * + * layout(blend_support_all_equations) out; + */ +struct ModifiersDeclaration : public ProgramElement { + ModifiersDeclaration(Modifiers modifiers) + : INHERITED(Position(), kModifiers_Kind) + , fModifiers(modifiers) {} + + std::string description() const { + return fModifiers.description() + ";"; + } + + Modifiers fModifiers; + + typedef ProgramElement INHERITED; +}; + +} // namespace + +#endif diff --git a/src/sksl/ir/SkSLProgram.h b/src/sksl/ir/SkSLProgram.h index 205db6e932..8393341269 100644 --- a/src/sksl/ir/SkSLProgram.h +++ b/src/sksl/ir/SkSLProgram.h @@ -11,6 +11,7 @@ #include <vector> #include <memory> +#include "SkSLModifiers.h" #include "SkSLProgramElement.h" #include "SkSLSymbolTable.h" @@ -25,14 +26,18 @@ struct Program { kVertex_Kind }; - Program(Kind kind, std::vector<std::unique_ptr<ProgramElement>> elements, + Program(Kind kind, + Modifiers::Flag defaultPrecision, + std::vector<std::unique_ptr<ProgramElement>> elements, std::shared_ptr<SymbolTable> symbols) : fKind(kind) + , fDefaultPrecision(defaultPrecision) , fElements(std::move(elements)) , fSymbols(symbols) {} Kind fKind; - + // FIXME handle different types; currently it assumes this is for floats + Modifiers::Flag fDefaultPrecision; std::vector<std::unique_ptr<ProgramElement>> fElements; std::shared_ptr<SymbolTable> fSymbols; }; diff --git a/src/sksl/ir/SkSLProgramElement.h b/src/sksl/ir/SkSLProgramElement.h index 44fc340667..2f1ce77199 100644 --- a/src/sksl/ir/SkSLProgramElement.h +++ b/src/sksl/ir/SkSLProgramElement.h @@ -20,7 +20,8 @@ struct ProgramElement : public IRNode { kVar_Kind, kFunction_Kind, kInterfaceBlock_Kind, - kExtension_Kind + kExtension_Kind, + kModifiers_Kind }; ProgramElement(Position position, Kind kind) diff --git a/src/sksl/lex.sksl.c b/src/sksl/lex.sksl.c index 4993fac3a5..710b67bba5 100644 --- a/src/sksl/lex.sksl.c +++ b/src/sksl/lex.sksl.c @@ -4,7 +4,7 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ - + #line 3 "lex.sksl.c" #define YY_INT_ALIGNED short int @@ -14,7 +14,7 @@ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 -#define YY_FLEX_SUBMINOR_VERSION 37 +#define YY_FLEX_SUBMINOR_VERSION 35 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif @@ -52,6 +52,7 @@ typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; +typedef uint64_t flex_uint64_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; @@ -59,6 +60,7 @@ typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ /* Limits of integral types. */ #ifndef INT8_MIN @@ -89,8 +91,6 @@ typedef unsigned int flex_uint32_t; #define UINT32_MAX (4294967295U) #endif -#endif /* ! C99 */ - #endif /* ! FLEXINT_H */ #ifdef __cplusplus @@ -194,7 +194,7 @@ typedef size_t yy_size_t; */ #define YY_LESS_LINENO(n) \ do { \ - int yyl;\ + yy_size_t yyl;\ for ( yyl = n; yyl < yyleng; ++yyl )\ if ( yytext[yyl] == '\n' )\ --yylineno;\ @@ -360,13 +360,13 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); */ #define YY_DO_BEFORE_ACTION \ yyg->yytext_ptr = yy_bp; \ - yyleng = (size_t) (yy_cp - yy_bp); \ + yyleng = (yy_size_t) (yy_cp - yy_bp); \ yyg->yy_hold_char = *yy_cp; \ *yy_cp = '\0'; \ yyg->yy_c_buf_p = yy_cp; -#define YY_NUM_RULES 82 -#define YY_END_OF_BUFFER 83 +#define YY_NUM_RULES 84 +#define YY_END_OF_BUFFER 85 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -374,30 +374,31 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[201] = +static yyconst flex_int16_t yy_accept[205] = { 0, - 0, 0, 83, 81, 80, 80, 54, 81, 29, 45, - 50, 31, 32, 43, 41, 38, 42, 37, 44, 4, - 56, 77, 61, 57, 60, 55, 35, 36, 49, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 33, 48, 34, 80, - 59, 30, 29, 68, 53, 73, 66, 39, 64, 40, - 65, 1, 0, 78, 67, 2, 4, 0, 46, 63, - 58, 62, 47, 72, 52, 29, 29, 29, 11, 29, - 29, 29, 29, 29, 7, 16, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 71, 51, 30, - - 76, 0, 0, 0, 78, 1, 0, 0, 3, 69, - 70, 75, 29, 29, 29, 29, 29, 29, 9, 29, - 29, 29, 29, 29, 29, 17, 29, 29, 29, 29, - 29, 29, 74, 0, 1, 79, 0, 0, 2, 29, - 29, 29, 29, 8, 29, 24, 29, 29, 29, 21, - 29, 29, 29, 29, 29, 5, 29, 29, 0, 1, - 12, 20, 29, 29, 6, 23, 18, 29, 29, 29, - 29, 29, 29, 29, 10, 29, 29, 27, 29, 29, - 29, 15, 26, 29, 29, 14, 22, 29, 29, 19, - 13, 29, 29, 29, 28, 29, 29, 29, 25, 0 - + 0, 0, 85, 83, 82, 82, 56, 83, 30, 46, + 51, 32, 33, 44, 42, 39, 43, 38, 45, 4, + 4, 58, 79, 63, 59, 62, 57, 36, 37, 50, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 34, 49, 35, + 52, 82, 61, 31, 30, 70, 55, 75, 68, 40, + 66, 41, 67, 1, 0, 80, 69, 2, 4, 0, + 0, 47, 65, 60, 64, 48, 74, 54, 30, 30, + 30, 12, 30, 30, 30, 30, 30, 8, 17, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + + 73, 53, 31, 78, 0, 0, 0, 80, 1, 0, + 0, 3, 5, 71, 72, 77, 30, 30, 30, 30, + 30, 30, 10, 30, 30, 30, 30, 30, 30, 18, + 30, 30, 30, 30, 30, 30, 76, 0, 1, 81, + 0, 0, 2, 30, 30, 30, 30, 9, 30, 25, + 30, 30, 30, 22, 30, 30, 30, 30, 30, 6, + 30, 30, 0, 1, 13, 21, 30, 30, 7, 24, + 19, 30, 30, 30, 30, 30, 30, 30, 11, 30, + 30, 28, 30, 30, 30, 16, 27, 30, 30, 15, + 23, 30, 30, 20, 14, 30, 30, 30, 29, 30, + + 30, 30, 26, 0 } ; static yyconst flex_int32_t yy_ec[256] = @@ -406,16 +407,16 @@ static yyconst flex_int32_t yy_ec[256] = 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 1, 5, 6, 7, 8, 1, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 17, 17, - 17, 17, 17, 17, 17, 17, 17, 18, 19, 20, - 21, 22, 23, 1, 6, 6, 6, 6, 24, 6, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 19, 20, 21, + 22, 23, 24, 1, 25, 25, 25, 25, 26, 25, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 25, 1, 26, 27, 6, 1, 28, 29, 30, 31, + 27, 1, 28, 29, 6, 1, 30, 31, 32, 33, - 32, 33, 34, 35, 36, 6, 37, 38, 39, 40, - 41, 42, 6, 43, 44, 45, 46, 47, 48, 6, - 49, 6, 50, 51, 52, 1, 1, 1, 1, 1, + 34, 35, 36, 37, 38, 6, 39, 40, 41, 42, + 43, 44, 6, 45, 46, 47, 48, 49, 50, 51, + 52, 6, 53, 54, 55, 56, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -432,152 +433,158 @@ static yyconst flex_int32_t yy_ec[256] = 1, 1, 1, 1, 1 } ; -static yyconst flex_int32_t yy_meta[53] = +static yyconst flex_int32_t yy_meta[57] = { 0, 1, 1, 2, 1, 1, 3, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, - 1, 1, 1, 3, 1, 1, 1, 3, 3, 3, + 1, 1, 1, 1, 1, 1, 4, 4, 1, 1, + 1, 1, 1, 1, 5, 5, 1, 1, 1, 5, + 5, 5, 5, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, - 1, 1 + 3, 3, 1, 1, 1, 1 } ; -static yyconst flex_int16_t yy_base[206] = +static yyconst flex_int16_t yy_base[211] = { 0, - 0, 0, 238, 239, 51, 53, 216, 0, 0, 215, - 49, 239, 239, 214, 46, 239, 45, 217, 52, 45, - 239, 239, 44, 212, 50, 239, 239, 239, 53, 189, - 190, 40, 192, 47, 193, 46, 50, 196, 186, 180, - 182, 192, 178, 179, 181, 185, 239, 61, 239, 81, - 239, 0, 0, 239, 198, 239, 239, 239, 239, 239, - 239, 70, 207, 0, 239, 72, 75, 81, 196, 239, - 239, 239, 195, 239, 194, 182, 173, 168, 0, 167, - 172, 181, 165, 173, 0, 165, 156, 156, 172, 160, - 156, 168, 154, 155, 151, 160, 159, 239, 173, 0, - - 239, 89, 182, 176, 0, 91, 97, 174, 173, 239, - 239, 239, 161, 72, 158, 155, 142, 140, 0, 149, - 137, 141, 139, 144, 147, 0, 148, 131, 130, 143, - 141, 135, 239, 155, 154, 239, 107, 153, 152, 131, - 122, 130, 137, 0, 132, 0, 121, 117, 115, 0, - 114, 116, 122, 114, 126, 0, 114, 122, 136, 135, - 0, 0, 111, 107, 0, 0, 0, 104, 109, 103, - 102, 105, 99, 100, 0, 96, 110, 0, 98, 97, - 102, 0, 0, 98, 102, 0, 0, 90, 79, 0, - 0, 88, 73, 65, 0, 69, 53, 65, 0, 239, - - 58, 122, 124, 128, 132 + 0, 0, 273, 274, 55, 57, 250, 0, 0, 249, + 53, 274, 274, 248, 50, 274, 49, 47, 57, 52, + 59, 274, 274, 59, 247, 60, 274, 274, 274, 62, + 223, 224, 49, 226, 58, 227, 54, 64, 230, 220, + 214, 216, 226, 212, 213, 215, 219, 274, 68, 274, + 274, 97, 274, 0, 0, 274, 233, 274, 274, 274, + 274, 274, 274, 87, 243, 0, 274, 91, 97, 112, + 0, 231, 274, 274, 274, 230, 274, 229, 216, 207, + 202, 0, 201, 206, 215, 199, 207, 0, 199, 189, + 190, 206, 194, 190, 202, 188, 189, 185, 194, 193, + + 274, 208, 0, 274, 120, 218, 212, 0, 93, 127, + 118, 125, 0, 274, 274, 274, 197, 100, 194, 191, + 178, 176, 0, 185, 173, 177, 175, 180, 183, 0, + 184, 167, 166, 179, 177, 171, 274, 131, 133, 274, + 140, 138, 142, 171, 162, 170, 177, 0, 172, 0, + 161, 157, 155, 0, 154, 156, 162, 154, 166, 0, + 154, 162, 144, 146, 0, 0, 153, 149, 0, 0, + 0, 146, 151, 145, 144, 147, 141, 142, 0, 138, + 147, 0, 122, 109, 102, 0, 0, 92, 94, 0, + 0, 86, 75, 0, 0, 84, 64, 55, 0, 59, + + 46, 32, 0, 274, 162, 165, 168, 173, 178, 180 } ; -static yyconst flex_int16_t yy_def[206] = +static yyconst flex_int16_t yy_def[211] = { 0, - 200, 1, 200, 200, 200, 200, 200, 201, 202, 200, - 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, - 200, 200, 200, 200, 200, 200, 200, 200, 200, 202, - 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, - 202, 202, 202, 202, 202, 202, 200, 200, 200, 200, - 200, 203, 202, 200, 200, 200, 200, 200, 200, 200, - 200, 200, 204, 205, 200, 200, 200, 200, 200, 200, - 200, 200, 200, 200, 200, 202, 202, 202, 202, 202, - 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, - 202, 202, 202, 202, 202, 202, 202, 200, 200, 203, - - 200, 200, 204, 204, 205, 200, 200, 200, 200, 200, - 200, 200, 202, 202, 202, 202, 202, 202, 202, 202, - 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, - 202, 202, 200, 200, 200, 200, 200, 200, 200, 202, - 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, - 202, 202, 202, 202, 202, 202, 202, 202, 200, 200, - 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, - 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, - 202, 202, 202, 202, 202, 202, 202, 202, 202, 202, - 202, 202, 202, 202, 202, 202, 202, 202, 202, 0, - - 200, 200, 200, 200, 200 + 204, 1, 204, 204, 204, 204, 204, 205, 206, 204, + 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, + 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 204, 204, 204, + 204, 204, 204, 207, 206, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 208, 209, 204, 204, 204, 204, + 210, 204, 204, 204, 204, 204, 204, 204, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, + + 204, 204, 207, 204, 204, 208, 208, 209, 204, 204, + 204, 204, 210, 204, 204, 204, 206, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 204, 204, 204, 204, + 204, 204, 204, 206, 206, 206, 206, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, + 206, 206, 204, 204, 206, 206, 206, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, + + 206, 206, 206, 0, 204, 204, 204, 204, 204, 204 } ; -static yyconst flex_int16_t yy_nxt[292] = +static yyconst flex_int16_t yy_nxt[331] = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 9, 27, 28, 29, 9, 30, 31, - 32, 33, 34, 9, 35, 36, 9, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 9, 46, 9, 47, - 48, 49, 50, 50, 50, 50, 55, 58, 60, 66, - 52, 67, 63, 69, 70, 61, 59, 64, 68, 56, - 72, 73, 65, 74, 81, 78, 68, 87, 85, 75, - 79, 98, 50, 50, 82, 86, 62, 83, 106, 66, - 88, 67, 108, 102, 108, 107, 199, 109, 68, 198, - - 134, 102, 134, 107, 197, 135, 68, 106, 138, 196, - 138, 99, 195, 139, 137, 141, 142, 194, 159, 193, - 159, 192, 137, 160, 53, 53, 100, 100, 103, 103, - 103, 103, 105, 191, 105, 105, 190, 189, 188, 187, - 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, - 176, 160, 160, 175, 174, 173, 172, 171, 170, 169, - 168, 167, 166, 165, 164, 163, 162, 161, 139, 139, - 135, 135, 158, 157, 156, 155, 154, 153, 152, 151, - 150, 149, 148, 147, 146, 145, 144, 143, 140, 109, - 109, 136, 104, 133, 132, 131, 130, 129, 128, 127, - + 24, 25, 26, 27, 9, 9, 28, 29, 30, 9, + 31, 32, 33, 34, 35, 9, 36, 37, 9, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 9, 47, + 9, 9, 48, 49, 50, 51, 52, 52, 52, 52, + 57, 60, 62, 64, 64, 203, 68, 65, 69, 69, + 63, 61, 66, 68, 58, 69, 69, 70, 67, 72, + 73, 75, 76, 77, 70, 70, 81, 84, 88, 101, + 78, 82, 70, 90, 202, 89, 201, 85, 52, 52, + + 86, 200, 71, 64, 64, 199, 91, 109, 109, 109, + 109, 68, 105, 69, 69, 198, 110, 197, 141, 196, + 105, 102, 70, 111, 110, 111, 141, 195, 112, 112, + 70, 138, 194, 138, 112, 112, 139, 139, 142, 193, + 142, 112, 112, 143, 143, 145, 146, 139, 139, 139, + 139, 163, 192, 163, 143, 143, 164, 164, 143, 143, + 164, 164, 164, 164, 54, 191, 54, 55, 55, 55, + 103, 103, 103, 106, 106, 106, 106, 106, 108, 190, + 108, 108, 108, 113, 113, 189, 188, 187, 186, 185, + 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, + + 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, + 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, + 152, 151, 150, 149, 148, 147, 144, 140, 107, 137, + 136, 135, 134, 133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, - 116, 115, 114, 113, 112, 111, 110, 104, 101, 97, - 96, 95, 94, 93, 92, 91, 90, 89, 84, 80, - 77, 76, 71, 62, 57, 54, 51, 200, 3, 200, - 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, - 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, - 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, - 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, - 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, - 200 - + 116, 115, 114, 107, 104, 100, 99, 98, 97, 96, + 95, 94, 93, 92, 87, 83, 80, 79, 74, 59, + 56, 53, 204, 3, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, + + 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, 204, 204 } ; -static yyconst flex_int16_t yy_chk[292] = +static yyconst flex_int16_t yy_chk[331] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 5, 5, 6, 6, 11, 15, 17, 20, - 201, 20, 19, 23, 23, 17, 15, 19, 20, 11, - 25, 25, 19, 29, 34, 32, 20, 37, 36, 29, - 32, 48, 50, 50, 34, 36, 62, 34, 66, 67, - 37, 67, 68, 62, 68, 66, 198, 68, 67, 197, - - 102, 62, 102, 66, 196, 102, 67, 106, 107, 194, - 107, 48, 193, 107, 106, 114, 114, 192, 137, 189, - 137, 188, 106, 137, 202, 202, 203, 203, 204, 204, - 204, 204, 205, 185, 205, 205, 184, 181, 180, 179, - 177, 176, 174, 173, 172, 171, 170, 169, 168, 164, - 163, 160, 159, 158, 157, 155, 154, 153, 152, 151, - 149, 148, 147, 145, 143, 142, 141, 140, 139, 138, - 135, 134, 132, 131, 130, 129, 128, 127, 125, 124, - 123, 122, 121, 120, 118, 117, 116, 115, 113, 109, - 108, 104, 103, 99, 97, 96, 95, 94, 93, 92, - - 91, 90, 89, 88, 87, 86, 84, 83, 82, 81, - 80, 78, 77, 76, 75, 73, 69, 63, 55, 46, - 45, 44, 43, 42, 41, 40, 39, 38, 35, 33, - 31, 30, 24, 18, 14, 10, 7, 3, 200, 200, - 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, - 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, - 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, - 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, - 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, - 200 - + 1, 1, 1, 1, 1, 1, 5, 5, 6, 6, + 11, 15, 17, 18, 18, 202, 20, 19, 20, 20, + 17, 15, 19, 21, 11, 21, 21, 20, 19, 24, + 24, 26, 26, 30, 21, 20, 33, 35, 37, 49, + 30, 33, 21, 38, 201, 37, 200, 35, 52, 52, + + 35, 198, 20, 64, 64, 197, 38, 68, 68, 109, + 109, 69, 64, 69, 69, 196, 68, 193, 109, 192, + 64, 49, 69, 70, 68, 70, 109, 189, 70, 70, + 69, 105, 188, 105, 111, 111, 105, 105, 110, 185, + 110, 112, 112, 110, 110, 118, 118, 138, 138, 139, + 139, 141, 184, 141, 142, 142, 141, 141, 143, 143, + 163, 163, 164, 164, 205, 183, 205, 206, 206, 206, + 207, 207, 207, 208, 208, 208, 208, 208, 209, 181, + 209, 209, 209, 210, 210, 180, 178, 177, 176, 175, + 174, 173, 172, 168, 167, 162, 161, 159, 158, 157, + + 156, 155, 153, 152, 151, 149, 147, 146, 145, 144, + 136, 135, 134, 133, 132, 131, 129, 128, 127, 126, + 125, 124, 122, 121, 120, 119, 117, 107, 106, 102, + 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, + 90, 89, 87, 86, 85, 84, 83, 81, 80, 79, + 78, 76, 72, 65, 57, 47, 46, 45, 44, 43, + 42, 41, 40, 39, 36, 34, 32, 31, 25, 14, + 10, 7, 3, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, + + 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, 204, 204 } ; /* Table of booleans, true if rule could match eol. */ -static yyconst flex_int32_t yy_rule_can_match_eol[83] = +static yyconst flex_int32_t yy_rule_can_match_eol[85] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 0, 0, }; + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 0, 0, }; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. @@ -600,7 +607,7 @@ static yyconst flex_int32_t yy_rule_can_match_eol[83] = */ #define YY_NO_UNISTD_H 1 -#line 598 "lex.sksl.c" +#line 605 "lex.sksl.c" #define INITIAL 0 @@ -685,10 +692,6 @@ int skslget_lineno (yyscan_t yyscanner ); void skslset_lineno (int line_number ,yyscan_t yyscanner ); -int skslget_column (yyscan_t yyscanner ); - -void skslset_column (int column_no ,yyscan_t yyscanner ); - /* Macros after this point can all be overridden by user definitions in * section 1. */ @@ -731,7 +734,7 @@ static int input (yyscan_t yyscanner ); /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ -#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) +#define ECHO fwrite( yytext, yyleng, 1, yyout ) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, @@ -742,7 +745,7 @@ static int input (yyscan_t yyscanner ); if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ - size_t n; \ + yy_size_t n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ @@ -828,7 +831,7 @@ YY_DECL #line 23 "sksl.flex" -#line 826 "lex.sksl.c" +#line 829 "lex.sksl.c" if ( !yyg->yy_init ) { @@ -881,13 +884,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 201 ) + if ( yy_current_state >= 205 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_current_state != 200 ); + while ( yy_current_state != 204 ); yy_cp = yyg->yy_last_accepting_cpos; yy_current_state = yyg->yy_last_accepting_state; @@ -898,7 +901,7 @@ yy_find_action: if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) { - int yyl; + yy_size_t yyl; for ( yyl = 0; yyl < yyleng; ++yyl ) if ( yytext[yyl] == '\n' ) @@ -942,396 +945,406 @@ YY_RULE_SETUP case 5: YY_RULE_SETUP #line 33 "sksl.flex" -{ return SkSL::Token::TRUE_LITERAL; } +{ return SkSL::Token::INT_LITERAL; } YY_BREAK case 6: YY_RULE_SETUP #line 35 "sksl.flex" -{ return SkSL::Token::FALSE_LITERAL; } +{ return SkSL::Token::TRUE_LITERAL; } YY_BREAK case 7: YY_RULE_SETUP #line 37 "sksl.flex" -{ return SkSL::Token::IF; } +{ return SkSL::Token::FALSE_LITERAL; } YY_BREAK case 8: YY_RULE_SETUP #line 39 "sksl.flex" -{ return SkSL::Token::ELSE; } +{ return SkSL::Token::IF; } YY_BREAK case 9: YY_RULE_SETUP #line 41 "sksl.flex" -{ return SkSL::Token::FOR; } +{ return SkSL::Token::ELSE; } YY_BREAK case 10: YY_RULE_SETUP #line 43 "sksl.flex" -{ return SkSL::Token::WHILE; } +{ return SkSL::Token::FOR; } YY_BREAK case 11: YY_RULE_SETUP #line 45 "sksl.flex" -{ return SkSL::Token::DO; } +{ return SkSL::Token::WHILE; } YY_BREAK case 12: YY_RULE_SETUP #line 47 "sksl.flex" -{ return SkSL::Token::BREAK; } +{ return SkSL::Token::DO; } YY_BREAK case 13: YY_RULE_SETUP #line 49 "sksl.flex" -{ return SkSL::Token::CONTINUE; } +{ return SkSL::Token::BREAK; } YY_BREAK case 14: YY_RULE_SETUP #line 51 "sksl.flex" -{ return SkSL::Token::DISCARD; } +{ return SkSL::Token::CONTINUE; } YY_BREAK case 15: YY_RULE_SETUP #line 53 "sksl.flex" -{ return SkSL::Token::RETURN; } +{ return SkSL::Token::DISCARD; } YY_BREAK case 16: YY_RULE_SETUP #line 55 "sksl.flex" -{ return SkSL::Token::IN; } +{ return SkSL::Token::RETURN; } YY_BREAK case 17: YY_RULE_SETUP #line 57 "sksl.flex" -{ return SkSL::Token::OUT; } +{ return SkSL::Token::IN; } YY_BREAK case 18: YY_RULE_SETUP #line 59 "sksl.flex" -{ return SkSL::Token::INOUT; } +{ return SkSL::Token::OUT; } YY_BREAK case 19: YY_RULE_SETUP #line 61 "sksl.flex" -{ return SkSL::Token::UNIFORM; } +{ return SkSL::Token::INOUT; } YY_BREAK case 20: YY_RULE_SETUP #line 63 "sksl.flex" -{ return SkSL::Token::CONST; } +{ return SkSL::Token::UNIFORM; } YY_BREAK case 21: YY_RULE_SETUP #line 65 "sksl.flex" -{ return SkSL::Token::LOWP; } +{ return SkSL::Token::CONST; } YY_BREAK case 22: YY_RULE_SETUP #line 67 "sksl.flex" -{ return SkSL::Token::MEDIUMP; } +{ return SkSL::Token::LOWP; } YY_BREAK case 23: YY_RULE_SETUP #line 69 "sksl.flex" -{ return SkSL::Token::HIGHP; } +{ return SkSL::Token::MEDIUMP; } YY_BREAK case 24: YY_RULE_SETUP #line 71 "sksl.flex" -{ return SkSL::Token::FLAT; } +{ return SkSL::Token::HIGHP; } YY_BREAK case 25: YY_RULE_SETUP #line 73 "sksl.flex" -{ return SkSL::Token::NOPERSPECTIVE; } +{ return SkSL::Token::FLAT; } YY_BREAK case 26: YY_RULE_SETUP #line 75 "sksl.flex" -{ return SkSL::Token::STRUCT; } +{ return SkSL::Token::NOPERSPECTIVE; } YY_BREAK case 27: YY_RULE_SETUP #line 77 "sksl.flex" -{ return SkSL::Token::LAYOUT; } +{ return SkSL::Token::STRUCT; } YY_BREAK case 28: YY_RULE_SETUP #line 79 "sksl.flex" -{ return SkSL::Token::PRECISION; } +{ return SkSL::Token::LAYOUT; } YY_BREAK case 29: YY_RULE_SETUP #line 81 "sksl.flex" -{ return SkSL::Token::IDENTIFIER; } +{ return SkSL::Token::PRECISION; } YY_BREAK case 30: YY_RULE_SETUP #line 83 "sksl.flex" -{ return SkSL::Token::DIRECTIVE; } +{ return SkSL::Token::IDENTIFIER; } YY_BREAK case 31: YY_RULE_SETUP #line 85 "sksl.flex" -{ return SkSL::Token::LPAREN; } +{ return SkSL::Token::DIRECTIVE; } YY_BREAK case 32: YY_RULE_SETUP #line 87 "sksl.flex" -{ return SkSL::Token::RPAREN; } +{ return SkSL::Token::LPAREN; } YY_BREAK case 33: YY_RULE_SETUP #line 89 "sksl.flex" -{ return SkSL::Token::LBRACE; } +{ return SkSL::Token::RPAREN; } YY_BREAK case 34: YY_RULE_SETUP #line 91 "sksl.flex" -{ return SkSL::Token::RBRACE; } +{ return SkSL::Token::LBRACE; } YY_BREAK case 35: YY_RULE_SETUP #line 93 "sksl.flex" -{ return SkSL::Token::LBRACKET; } +{ return SkSL::Token::RBRACE; } YY_BREAK case 36: YY_RULE_SETUP #line 95 "sksl.flex" -{ return SkSL::Token::RBRACKET; } +{ return SkSL::Token::LBRACKET; } YY_BREAK case 37: YY_RULE_SETUP #line 97 "sksl.flex" -{ return SkSL::Token::DOT; } +{ return SkSL::Token::RBRACKET; } YY_BREAK case 38: YY_RULE_SETUP #line 99 "sksl.flex" -{ return SkSL::Token::COMMA; } +{ return SkSL::Token::DOT; } YY_BREAK case 39: YY_RULE_SETUP #line 101 "sksl.flex" -{ return SkSL::Token::PLUSPLUS; } +{ return SkSL::Token::COMMA; } YY_BREAK case 40: YY_RULE_SETUP #line 103 "sksl.flex" -{ return SkSL::Token::MINUSMINUS; } +{ return SkSL::Token::PLUSPLUS; } YY_BREAK case 41: YY_RULE_SETUP #line 105 "sksl.flex" -{ return SkSL::Token::PLUS; } +{ return SkSL::Token::MINUSMINUS; } YY_BREAK case 42: YY_RULE_SETUP #line 107 "sksl.flex" -{ return SkSL::Token::MINUS; } +{ return SkSL::Token::PLUS; } YY_BREAK case 43: YY_RULE_SETUP #line 109 "sksl.flex" -{ return SkSL::Token::STAR; } +{ return SkSL::Token::MINUS; } YY_BREAK case 44: YY_RULE_SETUP #line 111 "sksl.flex" -{ return SkSL::Token::SLASH; } +{ return SkSL::Token::STAR; } YY_BREAK case 45: YY_RULE_SETUP #line 113 "sksl.flex" -{ return SkSL::Token::PERCENT; } +{ return SkSL::Token::SLASH; } YY_BREAK case 46: YY_RULE_SETUP #line 115 "sksl.flex" -{ return SkSL::Token::SHL; } +{ return SkSL::Token::PERCENT; } YY_BREAK case 47: YY_RULE_SETUP #line 117 "sksl.flex" -{ return SkSL::Token::SHR; } +{ return SkSL::Token::SHL; } YY_BREAK case 48: YY_RULE_SETUP #line 119 "sksl.flex" -{ return SkSL::Token::BITWISEOR; } +{ return SkSL::Token::SHR; } YY_BREAK case 49: YY_RULE_SETUP #line 121 "sksl.flex" -{ return SkSL::Token::BITWISEXOR; } +{ return SkSL::Token::BITWISEOR; } YY_BREAK case 50: YY_RULE_SETUP #line 123 "sksl.flex" -{ return SkSL::Token::BITWISEAND; } +{ return SkSL::Token::BITWISEXOR; } YY_BREAK case 51: YY_RULE_SETUP #line 125 "sksl.flex" -{ return SkSL::Token::LOGICALOR; } +{ return SkSL::Token::BITWISEAND; } YY_BREAK case 52: YY_RULE_SETUP #line 127 "sksl.flex" -{ return SkSL::Token::LOGICALXOR; } +{ return SkSL::Token::BITWISENOT; } YY_BREAK case 53: YY_RULE_SETUP #line 129 "sksl.flex" -{ return SkSL::Token::LOGICALAND; } +{ return SkSL::Token::LOGICALOR; } YY_BREAK case 54: YY_RULE_SETUP #line 131 "sksl.flex" -{ return SkSL::Token::NOT; } +{ return SkSL::Token::LOGICALXOR; } YY_BREAK case 55: YY_RULE_SETUP #line 133 "sksl.flex" -{ return SkSL::Token::QUESTION; } +{ return SkSL::Token::LOGICALAND; } YY_BREAK case 56: YY_RULE_SETUP #line 135 "sksl.flex" -{ return SkSL::Token::COLON; } +{ return SkSL::Token::LOGICALNOT; } YY_BREAK case 57: YY_RULE_SETUP #line 137 "sksl.flex" -{ return SkSL::Token::EQ; } +{ return SkSL::Token::QUESTION; } YY_BREAK case 58: YY_RULE_SETUP #line 139 "sksl.flex" -{ return SkSL::Token::EQEQ; } +{ return SkSL::Token::COLON; } YY_BREAK case 59: YY_RULE_SETUP #line 141 "sksl.flex" -{ return SkSL::Token::NEQ; } +{ return SkSL::Token::EQ; } YY_BREAK case 60: YY_RULE_SETUP #line 143 "sksl.flex" -{ return SkSL::Token::GT; } +{ return SkSL::Token::EQEQ; } YY_BREAK case 61: YY_RULE_SETUP #line 145 "sksl.flex" -{ return SkSL::Token::LT; } +{ return SkSL::Token::NEQ; } YY_BREAK case 62: YY_RULE_SETUP #line 147 "sksl.flex" -{ return SkSL::Token::GTEQ; } +{ return SkSL::Token::GT; } YY_BREAK case 63: YY_RULE_SETUP #line 149 "sksl.flex" -{ return SkSL::Token::LTEQ; } +{ return SkSL::Token::LT; } YY_BREAK case 64: YY_RULE_SETUP #line 151 "sksl.flex" -{ return SkSL::Token::PLUSEQ; } +{ return SkSL::Token::GTEQ; } YY_BREAK case 65: YY_RULE_SETUP #line 153 "sksl.flex" -{ return SkSL::Token::MINUSEQ; } +{ return SkSL::Token::LTEQ; } YY_BREAK case 66: YY_RULE_SETUP #line 155 "sksl.flex" -{ return SkSL::Token::STAREQ; } +{ return SkSL::Token::PLUSEQ; } YY_BREAK case 67: YY_RULE_SETUP #line 157 "sksl.flex" -{ return SkSL::Token::SLASHEQ; } +{ return SkSL::Token::MINUSEQ; } YY_BREAK case 68: YY_RULE_SETUP #line 159 "sksl.flex" -{ return SkSL::Token::PERCENTEQ; } +{ return SkSL::Token::STAREQ; } YY_BREAK case 69: YY_RULE_SETUP #line 161 "sksl.flex" -{ return SkSL::Token::SHLEQ; } +{ return SkSL::Token::SLASHEQ; } YY_BREAK case 70: YY_RULE_SETUP #line 163 "sksl.flex" -{ return SkSL::Token::SHREQ; } +{ return SkSL::Token::PERCENTEQ; } YY_BREAK case 71: YY_RULE_SETUP #line 165 "sksl.flex" -{ return SkSL::Token::BITWISEOREQ; } +{ return SkSL::Token::SHLEQ; } YY_BREAK case 72: YY_RULE_SETUP #line 167 "sksl.flex" -{ return SkSL::Token::BITWISEXOREQ; } +{ return SkSL::Token::SHREQ; } YY_BREAK case 73: YY_RULE_SETUP #line 169 "sksl.flex" -{ return SkSL::Token::BITWISEANDEQ; } +{ return SkSL::Token::BITWISEOREQ; } YY_BREAK case 74: YY_RULE_SETUP #line 171 "sksl.flex" -{ return SkSL::Token::LOGICALOREQ; } +{ return SkSL::Token::BITWISEXOREQ; } YY_BREAK case 75: YY_RULE_SETUP #line 173 "sksl.flex" -{ return SkSL::Token::LOGICALXOREQ; } +{ return SkSL::Token::BITWISEANDEQ; } YY_BREAK case 76: YY_RULE_SETUP #line 175 "sksl.flex" -{ return SkSL::Token::LOGICALANDEQ; } +{ return SkSL::Token::LOGICALOREQ; } YY_BREAK case 77: YY_RULE_SETUP #line 177 "sksl.flex" -{ return SkSL::Token::SEMICOLON; } +{ return SkSL::Token::LOGICALXOREQ; } YY_BREAK case 78: YY_RULE_SETUP #line 179 "sksl.flex" -/* line comment */ +{ return SkSL::Token::LOGICALANDEQ; } YY_BREAK case 79: -/* rule 79 can match eol */ YY_RULE_SETUP #line 181 "sksl.flex" -/* block comment */ +{ return SkSL::Token::SEMICOLON; } YY_BREAK case 80: -/* rule 80 can match eol */ YY_RULE_SETUP #line 183 "sksl.flex" -/* whitespace */ +/* line comment */ YY_BREAK case 81: +/* rule 81 can match eol */ YY_RULE_SETUP #line 185 "sksl.flex" -{ return SkSL::Token::INVALID_TOKEN; } +/* block comment */ YY_BREAK case 82: +/* rule 82 can match eol */ YY_RULE_SETUP #line 187 "sksl.flex" +/* whitespace */ + YY_BREAK +case 83: +YY_RULE_SETUP +#line 189 "sksl.flex" +{ return SkSL::Token::INVALID_TOKEN; } + YY_BREAK +case 84: +YY_RULE_SETUP +#line 191 "sksl.flex" ECHO; YY_BREAK -#line 1329 "lex.sksl.c" +#line 1342 "lex.sksl.c" case YY_STATE_EOF(INITIAL): yyterminate(); @@ -1526,7 +1539,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; int yy_c_buf_p_offset = (int) (yyg->yy_c_buf_p - b->yy_ch_buf); @@ -1626,7 +1639,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 201 ) + if ( yy_current_state >= 205 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1655,13 +1668,12 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 201 ) + if ( yy_current_state >= 205 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 200); + yy_is_jam = (yy_current_state == 204); - (void)yyg; return yy_is_jam ? 0 : yy_current_state; } @@ -1756,7 +1768,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) case EOB_ACT_END_OF_FILE: { if ( skslwrap(yyscanner ) ) - return EOF; + return 0; if ( ! yyg->yy_did_buffer_switch_on_eof ) YY_NEW_FILE; @@ -2112,8 +2124,8 @@ YY_BUFFER_STATE sksl_scan_string (yyconst char * yystr , yyscan_t yyscanner) /** Setup the input buffer state to scan the given bytes. The next call to sksllex() will * scan from a @e copy of @a bytes. - * @param yybytes the byte buffer to scan - * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. * @param yyscanner The scanner object. * @return the newly allocated buffer state object. */ @@ -2121,8 +2133,7 @@ YY_BUFFER_STATE sksl_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_le { YY_BUFFER_STATE b; char *buf; - yy_size_t n; - int i; + yy_size_t n, i; /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; @@ -2268,7 +2279,7 @@ void skslset_lineno (int line_number , yyscan_t yyscanner) /* lineno is only valid if an input buffer exists. */ if (! YY_CURRENT_BUFFER ) - YY_FATAL_ERROR( "skslset_lineno called with no buffer" ); + yy_fatal_error( "skslset_lineno called with no buffer" , yyscanner); yylineno = line_number; } @@ -2283,7 +2294,7 @@ void skslset_column (int column_no , yyscan_t yyscanner) /* column is only valid if an input buffer exists. */ if (! YY_CURRENT_BUFFER ) - YY_FATAL_ERROR( "skslset_column called with no buffer" ); + yy_fatal_error( "skslset_column called with no buffer" , yyscanner); yycolumn = column_no; } @@ -2495,7 +2506,7 @@ void skslfree (void * ptr , yyscan_t yyscanner) #define YYTABLES_NAME "yytables" -#line 187 "sksl.flex" +#line 191 "sksl.flex" diff --git a/src/sksl/sksl.flex b/src/sksl/sksl.flex index 67b48e9cb9..4455f50084 100644 --- a/src/sksl/sksl.flex +++ b/src/sksl/sksl.flex @@ -30,6 +30,8 @@ LETTER [a-zA-Z_$] {DIGIT}+ { return SkSL::Token::INT_LITERAL; } +"0x"[0-9a-fA-F]+ { return SkSL::Token::INT_LITERAL; } + true { return SkSL::Token::TRUE_LITERAL; } false { return SkSL::Token::FALSE_LITERAL; } @@ -122,13 +124,15 @@ precision { return SkSL::Token::PRECISION; } "&" { return SkSL::Token::BITWISEAND; } +"~" { return SkSL::Token::BITWISENOT; } + "||" { return SkSL::Token::LOGICALOR; } "^^" { return SkSL::Token::LOGICALXOR; } "&&" { return SkSL::Token::LOGICALAND; } -"!" { return SkSL::Token::NOT; } +"!" { return SkSL::Token::LOGICALNOT; } "?" { return SkSL::Token::QUESTION; } diff --git a/src/sksl/sksl.include b/src/sksl/sksl.include index 4fd5511ee3..6dc1ff8cf2 100644 --- a/src/sksl/sksl.include +++ b/src/sksl/sksl.include @@ -244,6 +244,8 @@ int textureQueryLevels(samplerCubeArrayShadow sampler); $gvec4 texture($gsampler1D sampler, float P); $gvec4 texture($gsampler1D sampler, float P, float bias); $gvec4 texture($gsampler2D sampler, vec2 P); +vec4 texture(samplerExternalOES sampler, vec2 P, float bias); +vec4 texture(samplerExternalOES sampler, vec2 P); $gvec4 texture($gsampler2D sampler, vec2 P, float bias); $gvec4 texture($gsampler3D sampler, vec3 P); $gvec4 texture($gsampler3D sampler, vec3 P, float bias); @@ -464,6 +466,7 @@ vec4 texture1DLod(sampler1D sampler, float coord, float lod); vec4 texture1DProjLod(sampler1D sampler, vec2 coord, float lod); vec4 texture1DProjLod(sampler1D sampler, vec4 coord, float lod); vec4 texture2D(sampler2D sampler, vec2 coord); +vec4 texture2D(samplerExternalOES sampler, vec2 coord); vec4 texture2D(sampler2D sampler, vec2 coord, float bias); vec4 texture2DProj(sampler2D sampler, vec3 coord); vec4 texture2DProj(sampler2D sampler, vec3 coord, float bias); diff --git a/src/sksl/sksl_frag.include b/src/sksl/sksl_frag.include index 123c3393a2..98dbc90252 100644 --- a/src/sksl/sksl_frag.include +++ b/src/sksl/sksl_frag.include @@ -4,5 +4,17 @@ STRINGIFY( layout(builtin=15) in vec4 gl_FragCoord; -) +// 9999 is a temporary value that causes us to ignore these declarations beyond +// adding them to the symbol table. This works fine in GLSL (where they do not +// require any further handling) but will fail in SPIR-V. We'll have a better +// solution for this soon. +layout(builtin=9999) vec4 gl_LastFragData[1]; +layout(builtin=9999) vec4 gl_LastFragColor; +layout(builtin=9999) vec4 gl_LastFragColorARM; +layout(builtin=9999) int gl_SampleMaskIn[]; +layout(builtin=9999) out int gl_SampleMask[]; +layout(builtin=9999) vec4 gl_SecondaryFragColorEXT; + +layout(location=0,index=0,builtin=10001) out vec4 sk_FragColor; +) |