From: ethannicholas Date: Wed, 3 Aug 2016 19:43:36 +0000 (-0700) Subject: added initial GLSL support to skslc X-Git-Tag: accepted/tizen/5.0/unified/20181102.025319~116^2~424 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f789b3893579b773bb4d7be6c2c65311500b53bb;p=platform%2Fupstream%2FlibSkiaSharp.git added initial GLSL support to skslc BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2185393003 Review-Url: https://codereview.chromium.org/2185393003 --- diff --git a/BUILD.gn b/BUILD.gn index 0780f1b..91c2b43 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -459,6 +459,7 @@ test_lib("tests") { rebase_path("tests/PathOpsSkpClipTest.cpp"), # alternate main rebase_path("tests/RTConfRegistryTest.cpp"), # TODO: delete rebase_path("tests/SkSLErrorTest.cpp"), # TODO: make work + rebase_path("tests/SkSLGLSLTest.cpp"), # TODO: make work rebase_path("tests/SkpSkGrTest.cpp"), # doesn't compile rebase_path("tests/skia_test.cpp"), # alternate main ] diff --git a/gyp/sksl.gypi b/gyp/sksl.gypi index be2e715..8718c8a 100644 --- a/gyp/sksl.gypi +++ b/gyp/sksl.gypi @@ -14,6 +14,7 @@ '../src/sksl/SkSLCompiler.cpp', '../src/sksl/SkSLIRGenerator.cpp', '../src/sksl/SkSLParser.cpp', + '../src/sksl/SkSLGLSLCodeGenerator.cpp', '../src/sksl/SkSLSPIRVCodeGenerator.cpp', '../src/sksl/SkSLUtil.cpp', '../src/sksl/ir/SkSLSymbolTable.cpp', diff --git a/public.bzl b/public.bzl index 5734888..36896f7 100644 --- a/public.bzl +++ b/public.bzl @@ -435,7 +435,7 @@ DM_SRCS_ALL = struct( "tests/PathOpsSkpClipTest.cpp", # Alternate main. "tests/skia_test.cpp", # Old main. "tests/SkpSkGrTest.cpp", # Alternate main. - "tests/SkSLErrorTest.cpp", # Excluded along with Vulkan. + "tests/SkSL*.cpp", # Excluded along with Vulkan. "tests/SVGDeviceTest.cpp", "tools/gpu/gl/angle/*", "tools/gpu/gl/command_buffer/*", diff --git a/src/sksl/SkSLCodeGenerator.h b/src/sksl/SkSLCodeGenerator.h index cd50cc8..7fa8c19 100644 --- a/src/sksl/SkSLCodeGenerator.h +++ b/src/sksl/SkSLCodeGenerator.h @@ -20,9 +20,9 @@ namespace SkSL { */ class CodeGenerator { public: - virtual ~CodeGenerator() {} - - virtual void generateCode(Program& program, std::ostream& out) = 0; + virtual ~CodeGenerator() {} + + virtual void generateCode(const Program& program, std::ostream& out) = 0; }; } // namespace diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp index 0d65b10..f55150c 100644 --- a/src/sksl/SkSLCompiler.cpp +++ b/src/sksl/SkSLCompiler.cpp @@ -67,14 +67,17 @@ Compiler::Compiler() ADD_TYPE(BVec3); ADD_TYPE(BVec4); ADD_TYPE(Mat2x2); + types->addWithoutOwnership("mat2x2", fContext.fMat2x2_Type.get()); ADD_TYPE(Mat2x3); ADD_TYPE(Mat2x4); ADD_TYPE(Mat3x2); ADD_TYPE(Mat3x3); + types->addWithoutOwnership("mat3x3", fContext.fMat3x3_Type.get()); ADD_TYPE(Mat3x4); ADD_TYPE(Mat4x2); ADD_TYPE(Mat4x3); ADD_TYPE(Mat4x4); + types->addWithoutOwnership("mat4x4", fContext.fMat4x4_Type.get()); ADD_TYPE(GenType); ADD_TYPE(GenDType); ADD_TYPE(GenIType); @@ -223,8 +226,7 @@ void Compiler::writeErrorCount() { } } -#include -bool Compiler::toSPIRV(Program::Kind kind, std::string text, std::ostream& out) { +bool Compiler::toSPIRV(Program::Kind kind, const std::string& text, std::ostream& out) { auto program = this->convertProgram(kind, text); if (fErrorCount == 0) { SkSL::SPIRVCodeGenerator cg(&fContext); @@ -234,13 +236,34 @@ bool Compiler::toSPIRV(Program::Kind kind, std::string text, std::ostream& out) return fErrorCount == 0; } -bool Compiler::toSPIRV(Program::Kind kind, std::string text, std::string* out) { +bool Compiler::toSPIRV(Program::Kind kind, const std::string& text, std::string* out) { std::stringstream buffer; bool result = this->toSPIRV(kind, text, buffer); if (result) { *out = buffer.str(); } + return result; +} + +bool Compiler::toGLSL(Program::Kind kind, const std::string& text, GLCaps caps, + std::ostream& out) { + auto program = this->convertProgram(kind, text); + if (fErrorCount == 0) { + SkSL::GLSLCodeGenerator cg(&fContext, caps); + cg.generateCode(*program.get(), out); + ASSERT(!out.rdstate()); + } return fErrorCount == 0; } +bool Compiler::toGLSL(Program::Kind kind, const std::string& text, GLCaps caps, + std::string* out) { + std::stringstream buffer; + bool result = this->toGLSL(kind, text, caps, buffer); + if (result) { + *out = buffer.str(); + } + return result; +} + } // namespace diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h index e63d5f4..9cd1eac 100644 --- a/src/sksl/SkSLCompiler.h +++ b/src/sksl/SkSLCompiler.h @@ -13,6 +13,7 @@ #include "ir/SkSLSymbolTable.h" #include "SkSLContext.h" #include "SkSLErrorReporter.h" +#include "SkSLGLSLCodeGenerator.h" namespace SkSL { @@ -32,9 +33,13 @@ public: std::unique_ptr convertProgram(Program::Kind kind, std::string text); - bool toSPIRV(Program::Kind kind, std::string text, std::ostream& out); - - bool toSPIRV(Program::Kind kind, std::string text, std::string* out); + bool toSPIRV(Program::Kind kind, const std::string& text, std::ostream& out); + + bool toSPIRV(Program::Kind kind, const std::string& text, std::string* out); + + bool toGLSL(Program::Kind kind, const std::string& text, GLCaps caps, std::ostream& out); + + bool toGLSL(Program::Kind kind, const std::string& text, GLCaps caps, std::string* out); void error(Position position, std::string msg) override; @@ -45,7 +50,7 @@ public: private: void internalConvertProgram(std::string text, - std::vector>* result); + std::vector>* result); std::shared_ptr fTypes; IRGenerator* fIRGenerator; diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp new file mode 100644 index 0000000..8e69a2f --- /dev/null +++ b/src/sksl/SkSLGLSLCodeGenerator.cpp @@ -0,0 +1,479 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkSLGLSLCodeGenerator.h" + +#include "string.h" + +#include "GLSL.std.450.h" + +#include "ir/SkSLExpressionStatement.h" +#include "ir/SkSLExtension.h" +#include "ir/SkSLIndexExpression.h" +#include "ir/SkSLVariableReference.h" + +namespace SkSL { + +void GLSLCodeGenerator::write(const char* s) { + if (s[0] == 0) { + return; + } + if (fAtLineStart) { + for (int i = 0; i < fIndentation; i++) { + *fOut << " "; + } + } + *fOut << s; + fAtLineStart = false; +} + +void GLSLCodeGenerator::writeLine(const char* s) { + this->write(s); + *fOut << "\n"; + fAtLineStart = true; +} + +void GLSLCodeGenerator::write(const std::string& s) { + this->write(s.c_str()); +} + +void GLSLCodeGenerator::writeLine(const std::string& s) { + this->writeLine(s.c_str()); +} + +void GLSLCodeGenerator::writeLine() { + this->writeLine(""); +} + +void GLSLCodeGenerator::writeExtension(const Extension& ext) { + this->writeLine("#extension " + ext.fName + " : enable"); +} + +void GLSLCodeGenerator::writeType(const Type& type) { + if (type.kind() == Type::kStruct_Kind) { + for (const Type* search : fWrittenStructs) { + if (*search == type) { + // already written + this->write(type.name()); + return; + } + } + fWrittenStructs.push_back(&type); + this->writeLine("struct " + type.name() + " {"); + fIndentation++; + for (const auto& f : type.fields()) { + this->writeModifiers(f.fModifiers); + // sizes (which must be static in structs) are part of the type name here + this->writeType(f.fType); + this->writeLine(" " + f.fName + ";"); + } + fIndentation--; + this->writeLine("}"); + } else { + this->write(type.name()); + } +} + +void GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence parentPrecedence) { + switch (expr.fKind) { + case Expression::kBinary_Kind: + this->writeBinaryExpression((BinaryExpression&) expr, parentPrecedence); + break; + case Expression::kBoolLiteral_Kind: + this->writeBoolLiteral((BoolLiteral&) expr); + break; + case Expression::kConstructor_Kind: + this->writeConstructor((Constructor&) expr); + break; + case Expression::kIntLiteral_Kind: + this->writeIntLiteral((IntLiteral&) expr); + break; + case Expression::kFieldAccess_Kind: + this->writeFieldAccess(((FieldAccess&) expr)); + break; + case Expression::kFloatLiteral_Kind: + this->writeFloatLiteral(((FloatLiteral&) expr)); + break; + case Expression::kFunctionCall_Kind: + this->writeFunctionCall((FunctionCall&) expr); + break; + case Expression::kPrefix_Kind: + this->writePrefixExpression((PrefixExpression&) expr, parentPrecedence); + break; + case Expression::kPostfix_Kind: + this->writePostfixExpression((PostfixExpression&) expr, parentPrecedence); + break; + case Expression::kSwizzle_Kind: + this->writeSwizzle((Swizzle&) expr); + break; + case Expression::kVariableReference_Kind: + this->writeVariableReference((VariableReference&) expr); + break; + case Expression::kTernary_Kind: + this->writeTernaryExpression((TernaryExpression&) expr, parentPrecedence); + break; + case Expression::kIndex_Kind: + this->writeIndexExpression((IndexExpression&) expr); + break; + default: + ABORT("unsupported expression: %s", expr.description().c_str()); + } +} + +void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) { + this->write(c.fFunction.fName + "("); + const char* separator = ""; + for (const auto& arg : c.fArguments) { + this->write(separator); + separator = ", "; + this->writeExpression(*arg, kSequence_Precedence); + } + this->write(")"); +} + +void GLSLCodeGenerator::writeConstructor(const Constructor& c) { + this->write(c.fType.name() + "("); + const char* separator = ""; + for (const auto& arg : c.fArguments) { + this->write(separator); + separator = ", "; + this->writeExpression(*arg, kSequence_Precedence); + } + this->write(")"); +} + +void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) { + this->write(ref.fVariable.fName); +} + +void GLSLCodeGenerator::writeIndexExpression(const IndexExpression& expr) { + this->writeExpression(*expr.fBase, kPostfix_Precedence); + this->write("["); + this->writeExpression(*expr.fIndex, kTopLevel_Precedence); + this->write("]"); +} + +void GLSLCodeGenerator::writeFieldAccess(const FieldAccess& f) { + if (f.fOwnerKind == FieldAccess::kDefault_OwnerKind) { + this->writeExpression(*f.fBase, kPostfix_Precedence); + this->write("."); + } + this->write(f.fBase->fType.fields()[f.fFieldIndex].fName); +} + +void GLSLCodeGenerator::writeSwizzle(const Swizzle& swizzle) { + this->writeExpression(*swizzle.fBase, kPostfix_Precedence); + this->write("."); + for (int c : swizzle.fComponents) { + this->write(&("x\0y\0z\0w\0"[c * 2])); + } +} + +static GLSLCodeGenerator::Precedence get_binary_precedence(Token::Kind op) { + switch (op) { + case Token::STAR: // fall through + case Token::SLASH: // fall through + case Token::PERCENT: return GLSLCodeGenerator::kMultiplicative_Precedence; + case Token::PLUS: // fall through + case Token::MINUS: return GLSLCodeGenerator::kAdditive_Precedence; + case Token::SHL: // fall through + case Token::SHR: return GLSLCodeGenerator::kShift_Precedence; + case Token::LT: // fall through + case Token::GT: // fall through + case Token::LTEQ: // fall through + case Token::GTEQ: return GLSLCodeGenerator::kRelational_Precedence; + case Token::EQEQ: // fall through + case Token::NEQ: return GLSLCodeGenerator::kEquality_Precedence; + case Token::BITWISEAND: return GLSLCodeGenerator::kBitwiseAnd_Precedence; + case Token::BITWISEXOR: return GLSLCodeGenerator::kBitwiseXor_Precedence; + case Token::BITWISEOR: return GLSLCodeGenerator::kBitwiseOr_Precedence; + case Token::LOGICALAND: return GLSLCodeGenerator::kLogicalAnd_Precedence; + case Token::LOGICALXOR: return GLSLCodeGenerator::kLogicalXor_Precedence; + case Token::LOGICALOR: return GLSLCodeGenerator::kLogicalOr_Precedence; + case Token::EQ: // fall through + case Token::PLUSEQ: // fall through + case Token::MINUSEQ: // fall through + case Token::STAREQ: // fall through + case Token::SLASHEQ: // fall through + case Token::PERCENTEQ: // fall through + case Token::SHLEQ: // fall through + case Token::SHREQ: // fall through + case Token::LOGICALANDEQ: // fall through + case Token::LOGICALXOREQ: // fall through + case Token::LOGICALOREQ: // fall through + case Token::BITWISEANDEQ: // fall through + case Token::BITWISEXOREQ: // fall through + case Token::BITWISEOREQ: return GLSLCodeGenerator::kAssignment_Precedence; + default: ABORT("unsupported binary operator"); + } +} + +void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b, + Precedence parentPrecedence) { + Precedence precedence = get_binary_precedence(b.fOperator); + if (precedence >= parentPrecedence) { + this->write("("); + } + this->writeExpression(*b.fLeft, precedence); + this->write(" " + Token::OperatorName(b.fOperator) + " "); + this->writeExpression(*b.fRight, precedence); + if (precedence >= parentPrecedence) { + this->write(")"); + } +} + +void GLSLCodeGenerator::writeTernaryExpression(const TernaryExpression& t, + Precedence parentPrecedence) { + if (kTernary_Precedence >= parentPrecedence) { + this->write("("); + } + this->writeExpression(*t.fTest, kTernary_Precedence); + this->write(" ? "); + this->writeExpression(*t.fIfTrue, kTernary_Precedence); + this->write(" : "); + this->writeExpression(*t.fIfFalse, kTernary_Precedence); + if (kTernary_Precedence >= parentPrecedence) { + this->write(")"); + } +} + +void GLSLCodeGenerator::writePrefixExpression(const PrefixExpression& p, + Precedence parentPrecedence) { + if (kPrefix_Precedence >= parentPrecedence) { + this->write("("); + } + this->write(Token::OperatorName(p.fOperator)); + this->writeExpression(*p.fOperand, kPrefix_Precedence); + if (kPrefix_Precedence >= parentPrecedence) { + this->write(")"); + } +} + +void GLSLCodeGenerator::writePostfixExpression(const PostfixExpression& p, + Precedence parentPrecedence) { + if (kPostfix_Precedence >= parentPrecedence) { + this->write("("); + } + this->writeExpression(*p.fOperand, kPostfix_Precedence); + this->write(Token::OperatorName(p.fOperator)); + if (kPostfix_Precedence >= parentPrecedence) { + this->write(")"); + } +} + +void GLSLCodeGenerator::writeBoolLiteral(const BoolLiteral& b) { + this->write(b.fValue ? "true" : "false"); +} + +void GLSLCodeGenerator::writeIntLiteral(const IntLiteral& i) { + this->write(to_string(i.fValue)); +} + +void GLSLCodeGenerator::writeFloatLiteral(const FloatLiteral& f) { + this->write(to_string(f.fValue)); +} + +void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) { + this->writeType(f.fDeclaration.fReturnType); + this->write(" " + f.fDeclaration.fName + "("); + const char* separator = ""; + for (const auto& param : f.fDeclaration.fParameters) { + this->write(separator); + separator = ", "; + this->writeModifiers(param->fModifiers); + this->writeType(param->fType); + this->write(" " + param->fName); + } + this->write(") "); + this->writeBlock(*f.fBody); + this->writeLine(); +} + +void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers) { + this->write(modifiers.description()); +} + +void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { + if (intf.fVariable.fName == "gl_PerVertex") { + return; + } + this->writeModifiers(intf.fVariable.fModifiers); + this->writeLine(intf.fVariable.fType.name() + " {"); + fIndentation++; + for (const auto& f : intf.fVariable.fType.fields()) { + this->writeModifiers(f.fModifiers); + this->writeType(f.fType); + this->writeLine(" " + f.fName + ";"); + } + fIndentation--; + this->writeLine("};"); +} + +void GLSLCodeGenerator::writeVarDeclaration(const VarDeclaration& decl) { + ASSERT(decl.fVars.size() > 0); + this->writeModifiers(decl.fVars[0]->fModifiers); + this->writeType(decl.fBaseType); + std::string separator = " "; + for (size_t i = 0; i < decl.fVars.size(); i++) { + ASSERT(decl.fVars[i]->fModifiers == decl.fVars[0]->fModifiers); + this->write(separator); + separator = ", "; + this->write(decl.fVars[i]->fName); + for (const auto& size : decl.fSizes[i]) { + this->write("["); + this->writeExpression(*size, kTopLevel_Precedence); + this->write("]"); + } + if (decl.fValues[i]) { + this->write(" = "); + this->writeExpression(*decl.fValues[i], kTopLevel_Precedence); + } + } + this->write(";"); +} + +void GLSLCodeGenerator::writeStatement(const Statement& s) { + switch (s.fKind) { + case Statement::kBlock_Kind: + this->writeBlock((Block&) s); + break; + case Statement::kExpression_Kind: + this->writeExpression(*((ExpressionStatement&) s).fExpression, kTopLevel_Precedence); + this->write(";"); + break; + case Statement::kReturn_Kind: + this->writeReturnStatement((ReturnStatement&) s); + break; + case Statement::kVarDeclaration_Kind: + this->writeVarDeclaration(*((VarDeclarationStatement&) s).fDeclaration); + break; + case Statement::kIf_Kind: + this->writeIfStatement((IfStatement&) s); + break; + case Statement::kFor_Kind: + this->writeForStatement((ForStatement&) s); + break; + case Statement::kWhile_Kind: + this->writeWhileStatement((WhileStatement&) s); + break; + case Statement::kDo_Kind: + this->writeDoStatement((DoStatement&) s); + break; + case Statement::kBreak_Kind: + this->write("break;"); + break; + case Statement::kContinue_Kind: + this->write("continue;"); + break; + case Statement::kDiscard_Kind: + this->write("discard;"); + break; + default: + ABORT("unsupported statement: %s", s.description().c_str()); + } +} + +void GLSLCodeGenerator::writeBlock(const Block& b) { + this->writeLine("{"); + fIndentation++; + for (const auto& s : b.fStatements) { + this->writeStatement(*s); + this->writeLine(); + } + fIndentation--; + this->write("}"); +} + +void GLSLCodeGenerator::writeIfStatement(const IfStatement& stmt) { + this->write("if ("); + this->writeExpression(*stmt.fTest, kTopLevel_Precedence); + this->write(") "); + this->writeStatement(*stmt.fIfTrue); + if (stmt.fIfFalse) { + this->write(" else "); + this->writeStatement(*stmt.fIfFalse); + } +} + +void GLSLCodeGenerator::writeForStatement(const ForStatement& f) { + this->write("for ("); + if (f.fInitializer) { + this->writeStatement(*f.fInitializer); + } else { + this->write("; "); + } + if (f.fTest) { + this->writeExpression(*f.fTest, kTopLevel_Precedence); + } + this->write("; "); + if (f.fNext) { + this->writeExpression(*f.fNext, kTopLevel_Precedence); + } + this->write(") "); + this->writeStatement(*f.fStatement); +} + +void GLSLCodeGenerator::writeWhileStatement(const WhileStatement& w) { + this->write("while ("); + this->writeExpression(*w.fTest, kTopLevel_Precedence); + this->write(") "); + this->writeStatement(*w.fStatement); +} + +void GLSLCodeGenerator::writeDoStatement(const DoStatement& d) { + this->write("do "); + this->writeStatement(*d.fStatement); + this->write(" while ("); + this->writeExpression(*d.fTest, kTopLevel_Precedence); + this->write(");"); +} + +void GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) { + this->write("return"); + if (r.fExpression) { + this->write(" "); + this->writeExpression(*r.fExpression, kTopLevel_Precedence); + } + this->write(";"); +} + +void GLSLCodeGenerator::generateCode(const Program& program, std::ostream& out) { + ASSERT(fOut == nullptr); + fOut = &out; + this->write("#version " + to_string(fCaps.fVersion)); + if (fCaps.fStandard == GLCaps::kGLES_Standard) { + this->write(" es"); + } + this->writeLine(); + for (const auto& e : program.fElements) { + switch (e->fKind) { + case ProgramElement::kExtension_Kind: + this->writeExtension((Extension&) *e); + break; + case ProgramElement::kVar_Kind: { + VarDeclaration& decl = (VarDeclaration&) *e; + if (decl.fVars.size() > 0 && decl.fVars[0]->fModifiers.fLayout.fBuiltin == -1) { + this->writeVarDeclaration(decl); + this->writeLine(); + } + break; + } + case ProgramElement::kInterfaceBlock_Kind: + this->writeInterfaceBlock((InterfaceBlock&) *e); + break; + case ProgramElement::kFunction_Kind: + this->writeFunction((FunctionDefinition&) *e); + break; + default: + printf("%s\n", e->description().c_str()); + ABORT("unsupported program element"); + } + } + fOut = nullptr; +} + +} diff --git a/src/sksl/SkSLGLSLCodeGenerator.h b/src/sksl/SkSLGLSLCodeGenerator.h new file mode 100644 index 0000000..76512e0 --- /dev/null +++ b/src/sksl/SkSLGLSLCodeGenerator.h @@ -0,0 +1,177 @@ +/* + * 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_GLSLCODEGENERATOR +#define SKSL_GLSLCODEGENERATOR + +#include +#include +#include + +#include "SkSLCodeGenerator.h" +#include "ir/SkSLBinaryExpression.h" +#include "ir/SkSLBoolLiteral.h" +#include "ir/SkSLConstructor.h" +#include "ir/SkSLDoStatement.h" +#include "ir/SkSLExtension.h" +#include "ir/SkSLFloatLiteral.h" +#include "ir/SkSLIfStatement.h" +#include "ir/SkSLIndexExpression.h" +#include "ir/SkSLInterfaceBlock.h" +#include "ir/SkSLIntLiteral.h" +#include "ir/SkSLFieldAccess.h" +#include "ir/SkSLForStatement.h" +#include "ir/SkSLFunctionCall.h" +#include "ir/SkSLFunctionDeclaration.h" +#include "ir/SkSLFunctionDefinition.h" +#include "ir/SkSLPrefixExpression.h" +#include "ir/SkSLPostfixExpression.h" +#include "ir/SkSLProgramElement.h" +#include "ir/SkSLReturnStatement.h" +#include "ir/SkSLStatement.h" +#include "ir/SkSLSwizzle.h" +#include "ir/SkSLTernaryExpression.h" +#include "ir/SkSLVarDeclaration.h" +#include "ir/SkSLVarDeclarationStatement.h" +#include "ir/SkSLVariableReference.h" +#include "ir/SkSLWhileStatement.h" + +namespace SkSL { + +#define kLast_Capability SpvCapabilityMultiViewport + +struct GLCaps { + int fVersion; + enum { + kGL_Standard, + kGLES_Standard + } fStandard; +}; + +/** + * Converts a Program into GLSL code. + */ +class GLSLCodeGenerator : public CodeGenerator { +public: + enum Precedence { + kParentheses_Precedence = 1, + kPostfix_Precedence = 2, + kPrefix_Precedence = 3, + kMultiplicative_Precedence = 4, + kAdditive_Precedence = 5, + kShift_Precedence = 6, + kRelational_Precedence = 7, + kEquality_Precedence = 8, + kBitwiseAnd_Precedence = 9, + kBitwiseXor_Precedence = 10, + kBitwiseOr_Precedence = 11, + kLogicalAnd_Precedence = 12, + kLogicalXor_Precedence = 13, + kLogicalOr_Precedence = 14, + kTernary_Precedence = 15, + kAssignment_Precedence = 16, + kSequence_Precedence = 17, + kTopLevel_Precedence = 18 + }; + + GLSLCodeGenerator(const Context* context, GLCaps caps) + : fContext(*context) + , fCaps(caps) + , fIndentation(0) + , fAtLineStart(true) {} + + void generateCode(const Program& program, std::ostream& out) override; + +private: + void write(const char* s); + + void writeLine(); + + void writeLine(const char* s); + + void write(const std::string& s); + + void writeLine(const std::string& s); + + void writeType(const Type& type); + + void writeExtension(const Extension& ext); + + void writeInterfaceBlock(const InterfaceBlock& intf); + + void writeFunctionStart(const FunctionDeclaration& f); + + void writeFunctionDeclaration(const FunctionDeclaration& f); + + void writeFunction(const FunctionDefinition& f); + + void writeLayout(const Layout& layout); + + void writeModifiers(const Modifiers& modifiers); + + void writeGlobalVars(const VarDeclaration& vs); + + void writeVarDeclaration(const VarDeclaration& decl); + + void writeVariableReference(const VariableReference& ref); + + void writeExpression(const Expression& expr, Precedence parentPrecedence); + + void writeIntrinsicCall(const FunctionCall& c); + + void writeFunctionCall(const FunctionCall& c); + + void writeConstructor(const Constructor& c); + + void writeFieldAccess(const FieldAccess& f); + + void writeSwizzle(const Swizzle& swizzle); + + void writeBinaryExpression(const BinaryExpression& b, Precedence parentPrecedence); + + void writeTernaryExpression(const TernaryExpression& t, Precedence parentPrecedence); + + void writeIndexExpression(const IndexExpression& expr); + + void writePrefixExpression(const PrefixExpression& p, Precedence parentPrecedence); + + void writePostfixExpression(const PostfixExpression& p, Precedence parentPrecedence); + + void writeBoolLiteral(const BoolLiteral& b); + + void writeIntLiteral(const IntLiteral& i); + + void writeFloatLiteral(const FloatLiteral& f); + + void writeStatement(const Statement& s); + + void writeBlock(const Block& b); + + void writeIfStatement(const IfStatement& stmt); + + void writeForStatement(const ForStatement& f); + + void writeWhileStatement(const WhileStatement& w); + + void writeDoStatement(const DoStatement& d); + + void writeReturnStatement(const ReturnStatement& r); + + const Context& fContext; + const GLCaps fCaps; + std::ostream* fOut; + int fIndentation; + bool fAtLineStart; + // Keeps track of which struct types we have written. Given that we are unlikely to ever write + // more than one or two structs per shader, a simple linear search will be faster than anything + // fancier. + std::vector fWrittenStructs; +}; + +} + +#endif diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp index f250c4b..db033d6 100644 --- a/src/sksl/SkSLIRGenerator.cpp +++ b/src/sksl/SkSLIRGenerator.cpp @@ -182,7 +182,6 @@ std::unique_ptr IRGenerator::convertVarDeclaration(const ASTVarD currentVarSizes.push_back(nullptr); } } - sizes.push_back(std::move(currentVarSizes)); auto var = std::unique_ptr(new Variable(decl.fPosition, modifiers, decl.fNames[i], *type, storage)); std::unique_ptr value; @@ -193,12 +192,22 @@ std::unique_ptr IRGenerator::convertVarDeclaration(const ASTVarD } value = this->coerce(std::move(value), *type); } - variables.push_back(var.get()); - fSymbolTable->add(decl.fNames[i], std::move(var)); - values.push_back(std::move(value)); + if ("gl_FragCoord" == decl.fNames[i] && (*fSymbolTable)[decl.fNames[i]]) { + // already defined, just update the modifiers + Variable* old = (Variable*) (*fSymbolTable)[decl.fNames[i]]; + old->fModifiers = var->fModifiers; + } else { + variables.push_back(var.get()); + fSymbolTable->add(decl.fNames[i], std::move(var)); + values.push_back(std::move(value)); + sizes.push_back(std::move(currentVarSizes)); + } } - return std::unique_ptr(new VarDeclaration(decl.fPosition, std::move(variables), - std::move(sizes), std::move(values))); + return std::unique_ptr(new VarDeclaration(decl.fPosition, + baseType, + std::move(variables), + std::move(sizes), + std::move(values))); } std::unique_ptr IRGenerator::convertIf(const ASTIfStatement& s) { @@ -573,8 +582,10 @@ std::unique_ptr IRGenerator::convertIdentifier(const ASTIdentifier& case Symbol::kField_Kind: { const Field* field = (const Field*) result; VariableReference* base = new VariableReference(identifier.fPosition, field->fOwner); - return std::unique_ptr(new FieldAccess(std::unique_ptr(base), - field->fFieldIndex)); + return std::unique_ptr(new FieldAccess( + std::unique_ptr(base), + field->fFieldIndex, + FieldAccess::kAnonymousInterfaceBlock_OwnerKind)); } case Symbol::kType_Kind: { const Type* t = (const Type*) result; @@ -616,6 +627,12 @@ std::unique_ptr IRGenerator::coerce(std::unique_ptr expr type.description().c_str()); } +static bool is_matrix_multiply(const Type& left, const Type& right) { + if (left.kind() == Type::kMatrix_Kind) { + return right.kind() == Type::kMatrix_Kind || right.kind() == Type::kVector_Kind; + } + return left.kind() == Type::kVector_Kind && right.kind() == Type::kMatrix_Kind; +} /** * Determines the operand and result types of a binary expression. Returns true if the expression is * legal, false otherwise. If false, the values of the out parameters are undefined. @@ -651,18 +668,41 @@ static bool determine_binary_type(const Context& context, right.canCoerceTo(*context.fBool_Type); case Token::STAR: // fall through case Token::STAREQ: - // FIXME need to handle non-square matrices - if (left.kind() == Type::kMatrix_Kind && right.kind() == Type::kVector_Kind) { - *outLeftType = &left; - *outRightType = &right; - *outResultType = &right; - return left.rows() == right.columns(); - } - if (left.kind() == Type::kVector_Kind && right.kind() == Type::kMatrix_Kind) { - *outLeftType = &left; - *outRightType = &right; - *outResultType = &left; - return left.columns() == right.columns(); + if (is_matrix_multiply(left, right)) { + // determine final component type + if (determine_binary_type(context, Token::STAR, left.componentType(), + right.componentType(), outLeftType, outRightType, + outResultType, false)) { + *outLeftType = &(*outResultType)->toCompound(context, left.columns(), + left.rows());; + *outRightType = &(*outResultType)->toCompound(context, right.columns(), + right.rows());; + int leftColumns = left.columns(); + int leftRows = left.rows(); + int rightColumns; + int rightRows; + if (right.kind() == Type::kVector_Kind) { + // matrix * vector treats the vector as a column vector, so we need to + // transpose it + rightColumns = right.rows(); + rightRows = right.columns(); + ASSERT(rightColumns == 1); + } else { + rightColumns = right.columns(); + rightRows = right.rows(); + } + if (rightColumns > 1) { + *outResultType = &(*outResultType)->toCompound(context, rightColumns, + leftRows); + } else { + // result was a column vector, transpose it back to a row + *outResultType = &(*outResultType)->toCompound(context, leftRows, + rightColumns); + } + return leftColumns == rightRows; + } else { + return false; + } } // fall through default: diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp index edff0c6..d6acc7d 100644 --- a/src/sksl/SkSLParser.cpp +++ b/src/sksl/SkSLParser.cpp @@ -14,11 +14,26 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunneeded-internal-declaration" #pragma clang diagnostic ignored "-Wnull-conversion" +#pragma clang diagnostic ignored "-Wsign-compare" +#endif +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-compare" +#endif +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4018) #endif #include "lex.sksl.c" #ifdef __clang__ #pragma clang diagnostic pop #endif +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif +#ifdef _MSC_VER +#pragma warning(pop) +#endif #undef register #include "ast/SkSLASTBinaryExpression.h" @@ -471,10 +486,11 @@ ASTLayout Parser::layout() { int index = -1; int set = -1; int builtin = -1; + bool originUpperLeft = false; if (this->peek().fKind == Token::LAYOUT) { this->nextToken(); if (!this->expect(Token::LPAREN, "'('")) { - return ASTLayout(location, binding, index, set, builtin); + return ASTLayout(location, binding, index, set, builtin, originUpperLeft); } for (;;) { Token t = this->nextToken(); @@ -488,6 +504,8 @@ ASTLayout Parser::layout() { set = this->layoutInt(); } else if (t.fText == "builtin") { builtin = this->layoutInt(); + } else if (t.fText == "origin_upper_left") { + originUpperLeft = true; } else { this->error(t.fPosition, ("'" + t.fText + "' is not a valid layout qualifier").c_str()); @@ -501,11 +519,10 @@ ASTLayout Parser::layout() { } } } - return ASTLayout(location, binding, index, set, builtin); + return ASTLayout(location, binding, index, set, builtin, originUpperLeft); } -/* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | - MEDIUMP | HIGHP)* */ +/* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT | NOPERSPECTIVE)* */ ASTModifiers Parser::modifiers() { ASTLayout layout = this->layout(); int flags = 0; @@ -545,6 +562,14 @@ ASTModifiers Parser::modifiers() { this->nextToken(); flags |= ASTModifiers::kHighp_Flag; break; + case Token::FLAT: + this->nextToken(); + flags |= ASTModifiers::kFlat_Flag; + break; + case Token::NOPERSPECTIVE: + this->nextToken(); + flags |= ASTModifiers::kNoPerspective_Flag; + break; default: return ASTModifiers(layout, flags); } diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp index 2771e02..8a38cf7 100644 --- a/src/sksl/SkSLSPIRVCodeGenerator.cpp +++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp @@ -1151,7 +1151,7 @@ SpvId SPIRVCodeGenerator::getPointerType(const Type& type, return entry->second; } -SpvId SPIRVCodeGenerator::writeExpression(Expression& expr, std::ostream& out) { +SpvId SPIRVCodeGenerator::writeExpression(const Expression& expr, std::ostream& out) { switch (expr.fKind) { case Expression::kBinary_Kind: return this->writeBinaryExpression((BinaryExpression&) expr, out); @@ -1185,7 +1185,7 @@ SpvId SPIRVCodeGenerator::writeExpression(Expression& expr, std::ostream& out) { return -1; } -SpvId SPIRVCodeGenerator::writeIntrinsicCall(FunctionCall& c, std::ostream& out) { +SpvId SPIRVCodeGenerator::writeIntrinsicCall(const FunctionCall& c, std::ostream& out) { auto intrinsic = fIntrinsicMap.find(c.fFunction.fName); ASSERT(intrinsic != fIntrinsicMap.end()); const Type& type = c.fArguments[0]->fType; @@ -1240,7 +1240,7 @@ SpvId SPIRVCodeGenerator::writeIntrinsicCall(FunctionCall& c, std::ostream& out) } } -SpvId SPIRVCodeGenerator::writeSpecialIntrinsic(FunctionCall& c, SpecialIntrinsic kind, +SpvId SPIRVCodeGenerator::writeSpecialIntrinsic(const FunctionCall& c, SpecialIntrinsic kind, std::ostream& out) { SpvId result = this->nextId(); switch (kind) { @@ -1305,7 +1305,7 @@ SpvId SPIRVCodeGenerator::writeSpecialIntrinsic(FunctionCall& c, SpecialIntrinsi return result; } -SpvId SPIRVCodeGenerator::writeFunctionCall(FunctionCall& c, std::ostream& out) { +SpvId SPIRVCodeGenerator::writeFunctionCall(const FunctionCall& c, std::ostream& out) { const auto& entry = fFunctionMap.find(&c.fFunction); if (entry == fFunctionMap.end()) { return this->writeIntrinsicCall(c, out); @@ -1366,7 +1366,7 @@ SpvId SPIRVCodeGenerator::writeFunctionCall(FunctionCall& c, std::ostream& out) return result; } -SpvId SPIRVCodeGenerator::writeConstantVector(Constructor& c) { +SpvId SPIRVCodeGenerator::writeConstantVector(const Constructor& c) { ASSERT(c.fType.kind() == Type::kVector_Kind && c.isConstant()); SpvId result = this->nextId(); std::vector arguments; @@ -1394,7 +1394,7 @@ SpvId SPIRVCodeGenerator::writeConstantVector(Constructor& c) { return result; } -SpvId SPIRVCodeGenerator::writeFloatConstructor(Constructor& c, std::ostream& out) { +SpvId SPIRVCodeGenerator::writeFloatConstructor(const Constructor& c, std::ostream& out) { ASSERT(c.fType == *fContext.fFloat_Type); ASSERT(c.fArguments.size() == 1); ASSERT(c.fArguments[0]->fType.isNumber()); @@ -1412,7 +1412,7 @@ SpvId SPIRVCodeGenerator::writeFloatConstructor(Constructor& c, std::ostream& ou return result; } -SpvId SPIRVCodeGenerator::writeIntConstructor(Constructor& c, std::ostream& out) { +SpvId SPIRVCodeGenerator::writeIntConstructor(const Constructor& c, std::ostream& out) { ASSERT(c.fType == *fContext.fInt_Type); ASSERT(c.fArguments.size() == 1); ASSERT(c.fArguments[0]->fType.isNumber()); @@ -1430,7 +1430,7 @@ SpvId SPIRVCodeGenerator::writeIntConstructor(Constructor& c, std::ostream& out) return result; } -SpvId SPIRVCodeGenerator::writeMatrixConstructor(Constructor& c, std::ostream& out) { +SpvId SPIRVCodeGenerator::writeMatrixConstructor(const Constructor& c, std::ostream& out) { ASSERT(c.fType.kind() == Type::kMatrix_Kind); // go ahead and write the arguments so we don't try to write new instructions in the middle of // an instruction @@ -1502,7 +1502,7 @@ SpvId SPIRVCodeGenerator::writeMatrixConstructor(Constructor& c, std::ostream& o return result; } -SpvId SPIRVCodeGenerator::writeVectorConstructor(Constructor& c, std::ostream& out) { +SpvId SPIRVCodeGenerator::writeVectorConstructor(const Constructor& c, std::ostream& out) { ASSERT(c.fType.kind() == Type::kVector_Kind); if (c.isConstant()) { return this->writeConstantVector(c); @@ -1532,7 +1532,7 @@ SpvId SPIRVCodeGenerator::writeVectorConstructor(Constructor& c, std::ostream& o return result; } -SpvId SPIRVCodeGenerator::writeConstructor(Constructor& c, std::ostream& out) { +SpvId SPIRVCodeGenerator::writeConstructor(const Constructor& c, std::ostream& out) { if (c.fType == *fContext.fFloat_Type) { return this->writeFloatConstructor(c, out); } else if (c.fType == *fContext.fInt_Type) { @@ -1560,7 +1560,7 @@ SpvStorageClass_ get_storage_class(const Modifiers& modifiers) { } } -SpvStorageClass_ get_storage_class(Expression& expr) { +SpvStorageClass_ get_storage_class(const Expression& expr) { switch (expr.fKind) { case Expression::kVariableReference_Kind: return get_storage_class(((VariableReference&) expr).fVariable.fModifiers); @@ -1573,7 +1573,7 @@ SpvStorageClass_ get_storage_class(Expression& expr) { } } -std::vector SPIRVCodeGenerator::getAccessChain(Expression& expr, std::ostream& out) { +std::vector SPIRVCodeGenerator::getAccessChain(const Expression& expr, std::ostream& out) { std::vector chain; switch (expr.fKind) { case Expression::kIndex_Kind: { @@ -1697,7 +1697,7 @@ private: const Type& fSwizzleType; }; -std::unique_ptr SPIRVCodeGenerator::getLValue(Expression& expr, +std::unique_ptr SPIRVCodeGenerator::getLValue(const Expression& expr, std::ostream& out) { switch (expr.fKind) { case Expression::kVariableReference_Kind: { @@ -1771,7 +1771,7 @@ std::unique_ptr SPIRVCodeGenerator::getLValue(Expres } } -SpvId SPIRVCodeGenerator::writeVariableReference(VariableReference& ref, std::ostream& out) { +SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, std::ostream& out) { auto entry = fVariableMap.find(&ref.fVariable); ASSERT(entry != fVariableMap.end()); SpvId var = entry->second; @@ -1780,15 +1780,15 @@ SpvId SPIRVCodeGenerator::writeVariableReference(VariableReference& ref, std::os return result; } -SpvId SPIRVCodeGenerator::writeIndexExpression(IndexExpression& expr, std::ostream& out) { +SpvId SPIRVCodeGenerator::writeIndexExpression(const IndexExpression& expr, std::ostream& out) { return getLValue(expr, out)->load(out); } -SpvId SPIRVCodeGenerator::writeFieldAccess(FieldAccess& f, std::ostream& out) { +SpvId SPIRVCodeGenerator::writeFieldAccess(const FieldAccess& f, std::ostream& out) { return getLValue(f, out)->load(out); } -SpvId SPIRVCodeGenerator::writeSwizzle(Swizzle& swizzle, std::ostream& out) { +SpvId SPIRVCodeGenerator::writeSwizzle(const Swizzle& swizzle, std::ostream& out) { SpvId base = this->writeExpression(*swizzle.fBase, out); SpvId result = this->nextId(); size_t count = swizzle.fComponents.size(); @@ -1849,7 +1849,7 @@ bool is_assignment(Token::Kind op) { } } -SpvId SPIRVCodeGenerator::writeBinaryExpression(BinaryExpression& b, std::ostream& out) { +SpvId SPIRVCodeGenerator::writeBinaryExpression(const BinaryExpression& b, std::ostream& out) { // handle cases where we don't necessarily evaluate both LHS and RHS switch (b.fOperator) { case Token::EQ: { @@ -2041,7 +2041,7 @@ SpvId SPIRVCodeGenerator::writeBinaryExpression(BinaryExpression& b, std::ostrea } } -SpvId SPIRVCodeGenerator::writeLogicalAnd(BinaryExpression& a, std::ostream& out) { +SpvId SPIRVCodeGenerator::writeLogicalAnd(const BinaryExpression& a, std::ostream& out) { ASSERT(a.fOperator == Token::LOGICALAND); BoolLiteral falseLiteral(fContext, Position(), false); SpvId falseConstant = this->writeBoolLiteral(falseLiteral); @@ -2062,7 +2062,7 @@ SpvId SPIRVCodeGenerator::writeLogicalAnd(BinaryExpression& a, std::ostream& out return result; } -SpvId SPIRVCodeGenerator::writeLogicalOr(BinaryExpression& o, std::ostream& out) { +SpvId SPIRVCodeGenerator::writeLogicalOr(const BinaryExpression& o, std::ostream& out) { ASSERT(o.fOperator == Token::LOGICALOR); BoolLiteral trueLiteral(fContext, Position(), true); SpvId trueConstant = this->writeBoolLiteral(trueLiteral); @@ -2083,7 +2083,7 @@ SpvId SPIRVCodeGenerator::writeLogicalOr(BinaryExpression& o, std::ostream& out) return result; } -SpvId SPIRVCodeGenerator::writeTernaryExpression(TernaryExpression& t, std::ostream& out) { +SpvId SPIRVCodeGenerator::writeTernaryExpression(const TernaryExpression& t, std::ostream& out) { SpvId test = this->writeExpression(*t.fTest, out); if (t.fIfTrue->isConstant() && t.fIfFalse->isConstant()) { // both true and false are constants, can just use OpSelect @@ -2127,7 +2127,7 @@ std::unique_ptr create_literal_1(const Context& context, const Type& } } -SpvId SPIRVCodeGenerator::writePrefixExpression(PrefixExpression& p, std::ostream& out) { +SpvId SPIRVCodeGenerator::writePrefixExpression(const PrefixExpression& p, std::ostream& out) { if (p.fOperator == Token::MINUS) { SpvId result = this->nextId(); SpvId typeId = this->getType(p.fType); @@ -2174,7 +2174,7 @@ SpvId SPIRVCodeGenerator::writePrefixExpression(PrefixExpression& p, std::ostrea } } -SpvId SPIRVCodeGenerator::writePostfixExpression(PostfixExpression& p, std::ostream& out) { +SpvId SPIRVCodeGenerator::writePostfixExpression(const PostfixExpression& p, std::ostream& out) { std::unique_ptr lv = this->getLValue(*p.fOperand, out); SpvId result = lv->load(out); SpvId one = this->writeExpression(*create_literal_1(fContext, p.fType), out); @@ -2196,7 +2196,7 @@ SpvId SPIRVCodeGenerator::writePostfixExpression(PostfixExpression& p, std::ostr } } -SpvId SPIRVCodeGenerator::writeBoolLiteral(BoolLiteral& b) { +SpvId SPIRVCodeGenerator::writeBoolLiteral(const BoolLiteral& b) { if (b.fValue) { if (fBoolTrue == 0) { fBoolTrue = this->nextId(); @@ -2214,7 +2214,7 @@ SpvId SPIRVCodeGenerator::writeBoolLiteral(BoolLiteral& b) { } } -SpvId SPIRVCodeGenerator::writeIntLiteral(IntLiteral& i) { +SpvId SPIRVCodeGenerator::writeIntLiteral(const IntLiteral& i) { if (i.fType == *fContext.fInt_Type) { auto entry = fIntConstants.find(i.fValue); if (entry == fIntConstants.end()) { @@ -2239,7 +2239,7 @@ SpvId SPIRVCodeGenerator::writeIntLiteral(IntLiteral& i) { } } -SpvId SPIRVCodeGenerator::writeFloatLiteral(FloatLiteral& f) { +SpvId SPIRVCodeGenerator::writeFloatLiteral(const FloatLiteral& f) { if (f.fType == *fContext.fFloat_Type) { float value = (float) f.fValue; auto entry = fFloatConstants.find(value); @@ -2350,7 +2350,7 @@ void SPIRVCodeGenerator::writeLayout(const Layout& layout, SpvId target, int mem } } -SpvId SPIRVCodeGenerator::writeInterfaceBlock(InterfaceBlock& intf) { +SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { SpvId type = this->getType(intf.fVariable.fType); SpvId result = this->nextId(); this->writeInstruction(SpvOpDecorate, type, SpvDecorationBlock, fDecorationBuffer); @@ -2363,7 +2363,7 @@ SpvId SPIRVCodeGenerator::writeInterfaceBlock(InterfaceBlock& intf) { return result; } -void SPIRVCodeGenerator::writeGlobalVars(VarDeclaration& decl, std::ostream& out) { +void SPIRVCodeGenerator::writeGlobalVars(const VarDeclaration& decl, std::ostream& out) { for (size_t i = 0; i < decl.fVars.size(); i++) { if (!decl.fVars[i]->fIsReadFrom && !decl.fVars[i]->fIsWrittenTo && !(decl.fVars[i]->fModifiers.fFlags & (Modifiers::kIn_Flag | @@ -2399,17 +2399,17 @@ void SPIRVCodeGenerator::writeGlobalVars(VarDeclaration& decl, std::ostream& out (SpvId) decl.fVars[i]->fType.stride(), fDecorationBuffer); } if (decl.fValues[i]) { - ASSERT(!fCurrentBlock); - fCurrentBlock = -1; + ASSERT(!fCurrentBlock); + fCurrentBlock = -1; SpvId value = this->writeExpression(*decl.fValues[i], fGlobalInitializersBuffer); this->writeInstruction(SpvOpStore, id, value, fGlobalInitializersBuffer); - fCurrentBlock = 0; + fCurrentBlock = 0; } this->writeLayout(decl.fVars[i]->fModifiers.fLayout, id); } } -void SPIRVCodeGenerator::writeVarDeclaration(VarDeclaration& decl, std::ostream& out) { +void SPIRVCodeGenerator::writeVarDeclaration(const VarDeclaration& decl, std::ostream& out) { for (size_t i = 0; i < decl.fVars.size(); i++) { SpvId id = this->nextId(); fVariableMap[decl.fVars[i]] = id; @@ -2423,7 +2423,7 @@ void SPIRVCodeGenerator::writeVarDeclaration(VarDeclaration& decl, std::ostream& } } -void SPIRVCodeGenerator::writeStatement(Statement& s, std::ostream& out) { +void SPIRVCodeGenerator::writeStatement(const Statement& s, std::ostream& out) { switch (s.fKind) { case Statement::kBlock_Kind: this->writeBlock((Block&) s, out); @@ -2457,13 +2457,13 @@ void SPIRVCodeGenerator::writeStatement(Statement& s, std::ostream& out) { } } -void SPIRVCodeGenerator::writeBlock(Block& b, std::ostream& out) { +void SPIRVCodeGenerator::writeBlock(const Block& b, std::ostream& out) { for (size_t i = 0; i < b.fStatements.size(); i++) { this->writeStatement(*b.fStatements[i], out); } } -void SPIRVCodeGenerator::writeIfStatement(IfStatement& stmt, std::ostream& out) { +void SPIRVCodeGenerator::writeIfStatement(const IfStatement& stmt, std::ostream& out) { SpvId test = this->writeExpression(*stmt.fTest, out); SpvId ifTrue = this->nextId(); SpvId ifFalse = this->nextId(); @@ -2494,7 +2494,7 @@ void SPIRVCodeGenerator::writeIfStatement(IfStatement& stmt, std::ostream& out) } } -void SPIRVCodeGenerator::writeForStatement(ForStatement& f, std::ostream& out) { +void SPIRVCodeGenerator::writeForStatement(const ForStatement& f, std::ostream& out) { if (f.fInitializer) { this->writeStatement(*f.fInitializer, out); } @@ -2508,7 +2508,7 @@ void SPIRVCodeGenerator::writeForStatement(ForStatement& f, std::ostream& out) { this->writeInstruction(SpvOpBranch, header, out); this->writeLabel(header, out); this->writeInstruction(SpvOpLoopMerge, end, next, SpvLoopControlMaskNone, out); - this->writeInstruction(SpvOpBranch, start, out); + this->writeInstruction(SpvOpBranch, start, out); this->writeLabel(start, out); SpvId test = this->writeExpression(*f.fTest, out); this->writeInstruction(SpvOpBranchConditional, test, body, end, out); @@ -2527,7 +2527,7 @@ void SPIRVCodeGenerator::writeForStatement(ForStatement& f, std::ostream& out) { fContinueTarget.pop(); } -void SPIRVCodeGenerator::writeReturnStatement(ReturnStatement& r, std::ostream& out) { +void SPIRVCodeGenerator::writeReturnStatement(const ReturnStatement& r, std::ostream& out) { if (r.fExpression) { this->writeInstruction(SpvOpReturnValue, this->writeExpression(*r.fExpression, out), out); @@ -2536,7 +2536,7 @@ void SPIRVCodeGenerator::writeReturnStatement(ReturnStatement& r, std::ostream& } } -void SPIRVCodeGenerator::writeInstructions(Program& program, std::ostream& out) { +void SPIRVCodeGenerator::writeInstructions(const Program& program, std::ostream& out) { fGLSLExtendedInstructions = this->nextId(); std::stringstream body; std::vector interfaceVars; @@ -2569,7 +2569,7 @@ void SPIRVCodeGenerator::writeInstructions(Program& program, std::ostream& out) } const FunctionDeclaration* main = nullptr; for (auto entry : fFunctionMap) { - if (entry.first->fName == "main") { + if (entry.first->fName == "main") { main = entry.first; } } @@ -2621,7 +2621,7 @@ void SPIRVCodeGenerator::writeInstructions(Program& program, std::ostream& out) out << body.str(); } -void SPIRVCodeGenerator::generateCode(Program& program, std::ostream& out) { +void SPIRVCodeGenerator::generateCode(const Program& program, std::ostream& out) { this->writeWord(SpvMagicNumber, out); this->writeWord(SpvVersion, out); this->writeWord(SKSL_MAGIC, out); diff --git a/src/sksl/SkSLSPIRVCodeGenerator.h b/src/sksl/SkSLSPIRVCodeGenerator.h index a20ad9f..caae201 100644 --- a/src/sksl/SkSLSPIRVCodeGenerator.h +++ b/src/sksl/SkSLSPIRVCodeGenerator.h @@ -71,7 +71,7 @@ public: this->setupIntrinsics(); } - void generateCode(Program& program, std::ostream& out) override; + void generateCode(const Program& program, std::ostream& out) override; private: enum IntrinsicKind { @@ -97,7 +97,7 @@ private: SpvId getPointerType(const Type& type, SpvStorageClass_ storageClass); - std::vector getAccessChain(Expression& expr, std::ostream& out); + std::vector getAccessChain(const Expression& expr, std::ostream& out); void writeLayout(const Layout& layout, SpvId target); @@ -105,9 +105,9 @@ private: void writeStruct(const Type& type, SpvId resultId); - void writeProgramElement(ProgramElement& pe, std::ostream& out); + void writeProgramElement(const ProgramElement& pe, std::ostream& out); - SpvId writeInterfaceBlock(InterfaceBlock& intf); + SpvId writeInterfaceBlock(const InterfaceBlock& intf); SpvId writeFunctionStart(const FunctionDeclaration& f, std::ostream& out); @@ -115,78 +115,78 @@ private: SpvId writeFunction(const FunctionDefinition& f, std::ostream& out); - void writeGlobalVars(VarDeclaration& v, std::ostream& out); + void writeGlobalVars(const VarDeclaration& v, std::ostream& out); - void writeVarDeclaration(VarDeclaration& decl, std::ostream& out); + void writeVarDeclaration(const VarDeclaration& decl, std::ostream& out); - SpvId writeVariableReference(VariableReference& ref, std::ostream& out); + SpvId writeVariableReference(const VariableReference& ref, std::ostream& out); - std::unique_ptr getLValue(Expression& value, std::ostream& out); + std::unique_ptr getLValue(const Expression& value, std::ostream& out); - SpvId writeExpression(Expression& expr, std::ostream& out); + SpvId writeExpression(const Expression& expr, std::ostream& out); - SpvId writeIntrinsicCall(FunctionCall& c, std::ostream& out); + SpvId writeIntrinsicCall(const FunctionCall& c, std::ostream& out); - SpvId writeFunctionCall(FunctionCall& c, std::ostream& out); + SpvId writeFunctionCall(const FunctionCall& c, std::ostream& out); - SpvId writeSpecialIntrinsic(FunctionCall& c, SpecialIntrinsic kind, std::ostream& out); + SpvId writeSpecialIntrinsic(const FunctionCall& c, SpecialIntrinsic kind, std::ostream& out); - SpvId writeConstantVector(Constructor& c); + SpvId writeConstantVector(const Constructor& c); - SpvId writeFloatConstructor(Constructor& c, std::ostream& out); + SpvId writeFloatConstructor(const Constructor& c, std::ostream& out); - SpvId writeIntConstructor(Constructor& c, std::ostream& out); + SpvId writeIntConstructor(const Constructor& c, std::ostream& out); - SpvId writeMatrixConstructor(Constructor& c, std::ostream& out); + SpvId writeMatrixConstructor(const Constructor& c, std::ostream& out); - SpvId writeVectorConstructor(Constructor& c, std::ostream& out); + SpvId writeVectorConstructor(const Constructor& c, std::ostream& out); - SpvId writeConstructor(Constructor& c, std::ostream& out); + SpvId writeConstructor(const Constructor& c, std::ostream& out); - SpvId writeFieldAccess(FieldAccess& f, std::ostream& out); + SpvId writeFieldAccess(const FieldAccess& f, std::ostream& out); - SpvId writeSwizzle(Swizzle& swizzle, std::ostream& out); + SpvId writeSwizzle(const Swizzle& swizzle, std::ostream& out); SpvId writeBinaryOperation(const Type& resultType, const Type& operandType, SpvId lhs, SpvId rhs, SpvOp_ ifFloat, SpvOp_ ifInt, SpvOp_ ifUInt, SpvOp_ ifBool, std::ostream& out); - SpvId writeBinaryOperation(BinaryExpression& expr, SpvOp_ ifFloat, SpvOp_ ifInt, SpvOp_ ifUInt, - std::ostream& out); + SpvId writeBinaryOperation(const BinaryExpression& expr, SpvOp_ ifFloat, SpvOp_ ifInt, + SpvOp_ ifUInt, std::ostream& out); - SpvId writeBinaryExpression(BinaryExpression& b, std::ostream& out); + SpvId writeBinaryExpression(const BinaryExpression& b, std::ostream& out); - SpvId writeTernaryExpression(TernaryExpression& t, std::ostream& out); + SpvId writeTernaryExpression(const TernaryExpression& t, std::ostream& out); - SpvId writeIndexExpression(IndexExpression& expr, std::ostream& out); + SpvId writeIndexExpression(const IndexExpression& expr, std::ostream& out); - SpvId writeLogicalAnd(BinaryExpression& b, std::ostream& out); + SpvId writeLogicalAnd(const BinaryExpression& b, std::ostream& out); - SpvId writeLogicalOr(BinaryExpression& o, std::ostream& out); + SpvId writeLogicalOr(const BinaryExpression& o, std::ostream& out); - SpvId writePrefixExpression(PrefixExpression& p, std::ostream& out); + SpvId writePrefixExpression(const PrefixExpression& p, std::ostream& out); - SpvId writePostfixExpression(PostfixExpression& p, std::ostream& out); + SpvId writePostfixExpression(const PostfixExpression& p, std::ostream& out); - SpvId writeBoolLiteral(BoolLiteral& b); + SpvId writeBoolLiteral(const BoolLiteral& b); - SpvId writeIntLiteral(IntLiteral& i); + SpvId writeIntLiteral(const IntLiteral& i); - SpvId writeFloatLiteral(FloatLiteral& f); + SpvId writeFloatLiteral(const FloatLiteral& f); - void writeStatement(Statement& s, std::ostream& out); + void writeStatement(const Statement& s, std::ostream& out); - void writeBlock(Block& b, std::ostream& out); + void writeBlock(const Block& b, std::ostream& out); - void writeIfStatement(IfStatement& stmt, std::ostream& out); + void writeIfStatement(const IfStatement& stmt, std::ostream& out); - void writeForStatement(ForStatement& f, std::ostream& out); + void writeForStatement(const ForStatement& f, std::ostream& out); - void writeReturnStatement(ReturnStatement& r, std::ostream& out); + void writeReturnStatement(const ReturnStatement& r, std::ostream& out); void writeCapabilities(std::ostream& out); - void writeInstructions(Program& program, std::ostream& out); + void writeInstructions(const Program& program, std::ostream& out); void writeOpCode(SpvOp_ opCode, int length, std::ostream& out); diff --git a/src/sksl/SkSLToken.h b/src/sksl/SkSLToken.h index 538ae50..29fa81e 100644 --- a/src/sksl/SkSLToken.h +++ b/src/sksl/SkSLToken.h @@ -13,6 +13,10 @@ namespace SkSL { +#undef IN +#undef OUT +#undef CONST + /** * Represents a lexical analysis token. Token is generally only used during the parse process, but * Token::Kind is also used to represent operator kinds. @@ -89,6 +93,8 @@ struct Token { MEDIUMP, HIGHP, UNIFORM, + FLAT, + NOPERSPECTIVE, STRUCT, LAYOUT, DIRECTIVE, diff --git a/src/sksl/SkSLUtil.h b/src/sksl/SkSLUtil.h index 5536d93..33611cd 100644 --- a/src/sksl/SkSLUtil.h +++ b/src/sksl/SkSLUtil.h @@ -8,6 +8,7 @@ #ifndef SKSL_UTIL #define SKSL_UTIL +#include #include #include #include "stdlib.h" @@ -19,13 +20,9 @@ namespace SkSL { // our own definitions of certain std:: functions, because they are not always present on Android template std::string to_string(T value) { -#ifdef SK_BUILD_FOR_ANDROID std::stringstream buffer; - buffer << value; + buffer << std::setprecision(std::numeric_limits::digits10) << value; return buffer.str(); -#else - return std::to_string(value); -#endif } #if _MSC_VER diff --git a/src/sksl/ast/SkSLASTLayout.h b/src/sksl/ast/SkSLASTLayout.h index 487e6e9..08d6753 100644 --- a/src/sksl/ast/SkSLASTLayout.h +++ b/src/sksl/ast/SkSLASTLayout.h @@ -20,12 +20,13 @@ 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) + ASTLayout(int location, int binding, int index, int set, int builtin, bool originUpperLeft) : fLocation(location) , fBinding(binding) , fIndex(index) , fSet(set) - , fBuiltin(builtin) {} + , fBuiltin(builtin) + , fOriginUpperLeft(originUpperLeft) {} std::string description() const { std::string result; @@ -50,6 +51,10 @@ struct ASTLayout : public ASTNode { result += separator + "builtin = " + to_string(fBuiltin); separator = ", "; } + if (fOriginUpperLeft) { + result += separator + "origin_upper_left"; + separator = ", "; + } if (result.length() > 0) { result = "layout (" + result + ")"; } @@ -61,6 +66,7 @@ struct ASTLayout : public ASTNode { const int fIndex; const int fSet; const int fBuiltin; + const bool fOriginUpperLeft; }; } // namespace diff --git a/src/sksl/ast/SkSLASTModifiers.h b/src/sksl/ast/SkSLASTModifiers.h index 6ef29aa..61d2e9f 100644 --- a/src/sksl/ast/SkSLASTModifiers.h +++ b/src/sksl/ast/SkSLASTModifiers.h @@ -18,14 +18,16 @@ namespace SkSL { */ struct ASTModifiers : public ASTNode { enum Flag { - kNo_Flag = 0, - kConst_Flag = 1, - kIn_Flag = 2, - kOut_Flag = 4, - kLowp_Flag = 8, - kMediump_Flag = 16, - kHighp_Flag = 32, - kUniform_Flag = 64 + kNo_Flag = 0, + kConst_Flag = 1, + kIn_Flag = 2, + kOut_Flag = 4, + kLowp_Flag = 8, + kMediump_Flag = 16, + kHighp_Flag = 32, + kUniform_Flag = 64, + kFlat_Flag = 128, + kNoPerspective_Flag = 256 }; ASTModifiers(ASTLayout layout, int flags) @@ -49,6 +51,12 @@ struct ASTModifiers : public ASTNode { if (fFlags & kHighp_Flag) { result += "highp "; } + if (fFlags & kFlat_Flag) { + result += "flat "; + } + if (fFlags & kNoPerspective_Flag) { + result += "noperspective "; + } if ((fFlags & kIn_Flag) && (fFlags & kOut_Flag)) { result += "inout "; diff --git a/src/sksl/ast/SkSLASTNode.h b/src/sksl/ast/SkSLASTNode.h index 26be769..4305011 100644 --- a/src/sksl/ast/SkSLASTNode.h +++ b/src/sksl/ast/SkSLASTNode.h @@ -19,7 +19,7 @@ namespace SkSL { */ struct ASTNode { virtual ~ASTNode() {} - + virtual std::string description() const = 0; }; diff --git a/src/sksl/ir/SkSLBoolLiteral.h b/src/sksl/ir/SkSLBoolLiteral.h index 8f55a69..ba054e4 100644 --- a/src/sksl/ir/SkSLBoolLiteral.h +++ b/src/sksl/ir/SkSLBoolLiteral.h @@ -26,7 +26,7 @@ struct BoolLiteral : public Expression { } bool isConstant() const override { - return true; + return true; } const bool fValue; diff --git a/src/sksl/ir/SkSLFieldAccess.h b/src/sksl/ir/SkSLFieldAccess.h index f09c3a3..bcdd7ee 100644 --- a/src/sksl/ir/SkSLFieldAccess.h +++ b/src/sksl/ir/SkSLFieldAccess.h @@ -17,10 +17,19 @@ namespace SkSL { * An expression which extracts a field from a struct, as in 'foo.bar'. */ struct FieldAccess : public Expression { - FieldAccess(std::unique_ptr base, int fieldIndex) + enum OwnerKind { + kDefault_OwnerKind, + // this field access is to a field of an anonymous interface block (and thus, the field name + // is actually in global scope, so only the field name needs to be written in GLSL) + kAnonymousInterfaceBlock_OwnerKind + }; + + FieldAccess(std::unique_ptr base, int fieldIndex, + OwnerKind ownerKind = kDefault_OwnerKind) : INHERITED(base->fPosition, kFieldAccess_Kind, base->fType.fields()[fieldIndex].fType) , fBase(std::move(base)) - , fFieldIndex(fieldIndex) {} + , fFieldIndex(fieldIndex) + , fOwnerKind(ownerKind) {} virtual std::string description() const override { return fBase->description() + "." + fBase->fType.fields()[fFieldIndex].fName; @@ -28,6 +37,7 @@ struct FieldAccess : public Expression { const std::unique_ptr fBase; const int fFieldIndex; + const OwnerKind fOwnerKind; typedef Expression INHERITED; }; diff --git a/src/sksl/ir/SkSLFloatLiteral.h b/src/sksl/ir/SkSLFloatLiteral.h index d9c8b65..a8fcfcf 100644 --- a/src/sksl/ir/SkSLFloatLiteral.h +++ b/src/sksl/ir/SkSLFloatLiteral.h @@ -26,7 +26,7 @@ struct FloatLiteral : public Expression { } bool isConstant() const override { - return true; + return true; } const double fValue; diff --git a/src/sksl/ir/SkSLFunctionReference.h b/src/sksl/ir/SkSLFunctionReference.h index 5d97a58..f3f8fb7 100644 --- a/src/sksl/ir/SkSLFunctionReference.h +++ b/src/sksl/ir/SkSLFunctionReference.h @@ -24,8 +24,8 @@ struct FunctionReference : public Expression { , fFunctions(function) {} virtual std::string description() const override { - ASSERT(false); - return ""; + ASSERT(false); + return ""; } const std::vector fFunctions; diff --git a/src/sksl/ir/SkSLIntLiteral.h b/src/sksl/ir/SkSLIntLiteral.h index f2bf40b..2bc5657 100644 --- a/src/sksl/ir/SkSLIntLiteral.h +++ b/src/sksl/ir/SkSLIntLiteral.h @@ -27,7 +27,7 @@ struct IntLiteral : public Expression { } bool isConstant() const override { - return true; + return true; } const int64_t fValue; diff --git a/src/sksl/ir/SkSLLayout.h b/src/sksl/ir/SkSLLayout.h index bab2f0e..d8dc980 100644 --- a/src/sksl/ir/SkSLLayout.h +++ b/src/sksl/ir/SkSLLayout.h @@ -21,14 +21,16 @@ struct Layout { , fBinding(layout.fBinding) , fIndex(layout.fIndex) , fSet(layout.fSet) - , fBuiltin(layout.fBuiltin) {} + , fBuiltin(layout.fBuiltin) + , fOriginUpperLeft(layout.fOriginUpperLeft) {} - Layout(int location, int binding, int index, int set, int builtin) + Layout(int location, int binding, int index, int set, int builtin, bool originUpperLeft) : fLocation(location) , fBinding(binding) , fIndex(index) , fSet(set) - , fBuiltin(builtin) {} + , fBuiltin(builtin) + , fOriginUpperLeft(originUpperLeft) {} std::string description() const { std::string result; @@ -53,6 +55,10 @@ struct Layout { result += separator + "builtin = " + to_string(fBuiltin); separator = ", "; } + if (fOriginUpperLeft) { + result += separator + "origin_upper_left"; + separator = ", "; + } if (result.length() > 0) { result = "layout (" + result + ")"; } @@ -71,11 +77,14 @@ struct Layout { return !(*this == other); } - const int fLocation; - const int fBinding; - const int fIndex; - const int fSet; - const int fBuiltin; + // everything but builtin is in the GLSL spec; builtin comes from SPIR-V and identifies which + // particular builtin value this object represents. + int fLocation; + int fBinding; + int fIndex; + int fSet; + int fBuiltin; + bool fOriginUpperLeft; }; } // namespace diff --git a/src/sksl/ir/SkSLModifiers.h b/src/sksl/ir/SkSLModifiers.h index d3b9c40..f39e929 100644 --- a/src/sksl/ir/SkSLModifiers.h +++ b/src/sksl/ir/SkSLModifiers.h @@ -18,14 +18,16 @@ namespace SkSL { */ struct Modifiers { enum Flag { - kNo_Flag = ASTModifiers::kNo_Flag, - kConst_Flag = ASTModifiers::kConst_Flag, - kIn_Flag = ASTModifiers::kIn_Flag, - kOut_Flag = ASTModifiers::kOut_Flag, - kLowp_Flag = ASTModifiers::kLowp_Flag, - kMediump_Flag = ASTModifiers::kMediump_Flag, - kHighp_Flag = ASTModifiers::kHighp_Flag, - kUniform_Flag = ASTModifiers::kUniform_Flag + kNo_Flag = ASTModifiers::kNo_Flag, + kConst_Flag = ASTModifiers::kConst_Flag, + kIn_Flag = ASTModifiers::kIn_Flag, + kOut_Flag = ASTModifiers::kOut_Flag, + kLowp_Flag = ASTModifiers::kLowp_Flag, + kMediump_Flag = ASTModifiers::kMediump_Flag, + kHighp_Flag = ASTModifiers::kHighp_Flag, + kUniform_Flag = ASTModifiers::kUniform_Flag, + kFlat_Flag = ASTModifiers::kFlat_Flag, + kNoPerspective_Flag = ASTModifiers::kNoPerspective_Flag }; Modifiers(const ASTModifiers& modifiers) @@ -53,6 +55,12 @@ struct Modifiers { if (fFlags & kHighp_Flag) { result += "highp "; } + if (fFlags & kFlat_Flag) { + result += "flat "; + } + if (fFlags & kNoPerspective_Flag) { + result += "noperspective "; + } if ((fFlags & kIn_Flag) && (fFlags & kOut_Flag)) { result += "inout "; @@ -73,8 +81,8 @@ struct Modifiers { return !(*this == other); } - const Layout fLayout; - const int fFlags; + Layout fLayout; + int fFlags; }; } // namespace diff --git a/src/sksl/ir/SkSLTypeReference.h b/src/sksl/ir/SkSLTypeReference.h index 76923aa..10f36aa 100644 --- a/src/sksl/ir/SkSLTypeReference.h +++ b/src/sksl/ir/SkSLTypeReference.h @@ -23,8 +23,8 @@ struct TypeReference : public Expression { , fValue(type) {} std::string description() const override { - ASSERT(false); - return ""; + ASSERT(false); + return ""; } const Type& fValue; diff --git a/src/sksl/ir/SkSLUnresolvedFunction.h b/src/sksl/ir/SkSLUnresolvedFunction.h index 3a368ad..7e8a360 100644 --- a/src/sksl/ir/SkSLUnresolvedFunction.h +++ b/src/sksl/ir/SkSLUnresolvedFunction.h @@ -20,9 +20,9 @@ struct UnresolvedFunction : public Symbol { : INHERITED(Position(), kUnresolvedFunction_Kind, funcs[0]->fName) , fFunctions(std::move(funcs)) { #ifdef DEBUG - for (auto func : funcs) { - ASSERT(func->fName == fName); - } + for (auto func : funcs) { + ASSERT(func->fName == fName); + } #endif } diff --git a/src/sksl/ir/SkSLVarDeclaration.h b/src/sksl/ir/SkSLVarDeclaration.h index b234231..ca3c7f9 100644 --- a/src/sksl/ir/SkSLVarDeclaration.h +++ b/src/sksl/ir/SkSLVarDeclaration.h @@ -16,14 +16,15 @@ namespace SkSL { /** * A variable declaration, which may consist of multiple individual variables. For instance - * 'int x, y = 1, z[4][2];' is a single VarDeclaration. This declaration would have a type of 'int', - * names ['x', 'y', 'z'], sizes of [[], [], [4, 2]], and values of [null, 1, null]. + * 'int x, y = 1, z[4][2];' is a single VarDeclaration. This declaration would have a base type of + * 'int', names ['x', 'y', 'z'], sizes of [[], [], [4, 2]], and values of [null, 1, null]. */ struct VarDeclaration : public ProgramElement { - VarDeclaration(Position position, std::vector vars, + VarDeclaration(Position position, const Type* baseType, std::vector vars, std::vector>> sizes, std::vector> values) - : INHERITED(position, kVar_Kind) + : INHERITED(position, kVar_Kind) + , fBaseType(*baseType) , fVars(std::move(vars)) , fSizes(std::move(sizes)) , fValues(std::move(values)) {} @@ -55,6 +56,7 @@ struct VarDeclaration : public ProgramElement { return result; } + const Type& fBaseType; const std::vector fVars; const std::vector>> fSizes; const std::vector> fValues; diff --git a/src/sksl/ir/SkSLVariable.h b/src/sksl/ir/SkSLVariable.h index 39af309..217b100 100644 --- a/src/sksl/ir/SkSLVariable.h +++ b/src/sksl/ir/SkSLVariable.h @@ -40,7 +40,7 @@ struct Variable : public Symbol { return fModifiers.description() + fType.fName + " " + fName; } - const Modifiers fModifiers; + mutable Modifiers fModifiers; const Type& fType; const Storage fStorage; diff --git a/src/sksl/lex.sksl.c b/src/sksl/lex.sksl.c index 7afbd94..4993fac 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 35 +#define YY_FLEX_SUBMINOR_VERSION 37 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif @@ -52,7 +52,6 @@ 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; @@ -60,7 +59,6 @@ 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 @@ -91,6 +89,8 @@ 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 { \ - yy_size_t yyl;\ + int 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 = (yy_size_t) (yy_cp - yy_bp); \ + yyleng = (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 80 -#define YY_END_OF_BUFFER 81 +#define YY_NUM_RULES 82 +#define YY_END_OF_BUFFER 83 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -374,28 +374,30 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[185] = +static yyconst flex_int16_t yy_accept[201] = { 0, - 0, 0, 81, 79, 78, 78, 52, 79, 27, 43, - 48, 29, 30, 41, 39, 36, 40, 35, 42, 4, - 54, 75, 59, 55, 58, 53, 33, 34, 47, 27, - 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 31, 46, 32, 78, 57, - 28, 27, 66, 51, 71, 64, 37, 62, 38, 63, - 1, 0, 76, 65, 2, 4, 0, 44, 61, 56, - 60, 45, 70, 50, 27, 27, 27, 11, 27, 27, - 27, 27, 7, 16, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 69, 49, 28, 74, 0, 0, - - 0, 76, 1, 0, 0, 3, 67, 68, 73, 27, - 27, 27, 27, 27, 9, 27, 27, 27, 27, 27, - 17, 27, 27, 27, 27, 27, 27, 72, 0, 1, - 77, 0, 0, 2, 27, 27, 27, 27, 8, 27, - 27, 27, 27, 21, 27, 27, 27, 27, 5, 27, - 27, 0, 1, 12, 20, 27, 27, 6, 23, 18, - 27, 27, 27, 27, 27, 27, 10, 27, 27, 25, - 27, 27, 15, 24, 27, 27, 14, 22, 27, 19, - 13, 27, 26, 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 + } ; static yyconst flex_int32_t yy_ec[256] = @@ -412,8 +414,8 @@ static yyconst flex_int32_t yy_ec[256] = 25, 1, 26, 27, 6, 1, 28, 29, 30, 31, 32, 33, 34, 35, 36, 6, 37, 38, 39, 40, - 41, 42, 6, 43, 44, 45, 46, 6, 47, 6, - 48, 6, 49, 50, 51, 1, 1, 1, 1, 1, + 41, 42, 6, 43, 44, 45, 46, 47, 48, 6, + 49, 6, 50, 51, 52, 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, @@ -430,140 +432,152 @@ static yyconst flex_int32_t yy_ec[256] = 1, 1, 1, 1, 1 } ; -static yyconst flex_int32_t yy_meta[52] = +static yyconst flex_int32_t yy_meta[53] = { 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, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, - 1 + 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, + 1, 1 } ; -static yyconst flex_int16_t yy_base[190] = +static yyconst flex_int16_t yy_base[206] = { 0, - 0, 0, 222, 223, 50, 52, 200, 0, 0, 199, - 48, 223, 223, 198, 45, 223, 44, 201, 51, 44, - 223, 223, 43, 196, 49, 223, 223, 223, 52, 173, - 174, 39, 176, 46, 177, 44, 50, 180, 165, 167, - 177, 163, 164, 166, 170, 223, 39, 223, 79, 223, - 0, 0, 223, 183, 223, 223, 223, 223, 223, 223, - 66, 192, 0, 223, 68, 71, 82, 181, 223, 223, - 223, 180, 223, 179, 167, 158, 153, 0, 152, 157, - 151, 159, 0, 151, 143, 143, 158, 143, 155, 141, - 142, 138, 147, 146, 223, 160, 0, 223, 90, 169, - - 163, 0, 84, 97, 161, 160, 223, 223, 223, 148, - 61, 145, 142, 129, 0, 137, 125, 129, 127, 132, - 0, 137, 120, 119, 132, 130, 124, 223, 144, 143, - 223, 98, 142, 141, 120, 111, 119, 126, 0, 121, - 110, 106, 104, 0, 103, 112, 104, 116, 0, 104, - 112, 126, 125, 0, 0, 101, 97, 0, 0, 0, - 94, 99, 93, 96, 90, 91, 0, 87, 101, 0, - 89, 94, 0, 0, 90, 94, 0, 0, 72, 0, - 0, 57, 0, 223, 90, 114, 116, 120, 124 + 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 } ; -static yyconst flex_int16_t yy_def[190] = +static yyconst flex_int16_t yy_def[206] = { 0, - 184, 1, 184, 184, 184, 184, 184, 185, 186, 184, - 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 184, 184, 184, 184, 184, 184, 186, - 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 186, 186, 186, 184, 184, 184, 184, 184, - 187, 186, 184, 184, 184, 184, 184, 184, 184, 184, - 184, 188, 189, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 184, 186, 186, 186, 186, 186, 186, - 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 186, 186, 184, 184, 187, 184, 184, 188, - - 188, 189, 184, 184, 184, 184, 184, 184, 184, 186, - 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 186, 186, 186, 186, 186, 184, 184, 184, - 184, 184, 184, 184, 186, 186, 186, 186, 186, 186, - 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, - 186, 184, 184, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, - 186, 186, 186, 0, 184, 184, 184, 184, 184 + 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 } ; -static yyconst flex_int16_t yy_nxt[275] = +static yyconst flex_int16_t yy_nxt[292] = { 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, 9, - 39, 40, 41, 42, 43, 44, 45, 9, 46, 47, - 48, 49, 49, 49, 49, 54, 57, 59, 65, 95, - 66, 62, 68, 69, 60, 58, 63, 67, 55, 71, - 72, 64, 73, 80, 77, 67, 83, 85, 74, 78, - 49, 49, 61, 84, 103, 65, 81, 66, 96, 99, - 86, 104, 51, 105, 67, 105, 183, 99, 106, 104, - - 103, 129, 67, 129, 136, 137, 130, 132, 133, 152, - 133, 152, 182, 134, 153, 132, 52, 52, 97, 97, - 100, 100, 100, 100, 102, 181, 102, 102, 180, 179, - 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, - 168, 153, 153, 167, 166, 165, 164, 163, 162, 161, - 160, 159, 158, 157, 156, 155, 154, 134, 134, 130, - 130, 151, 150, 149, 148, 147, 146, 145, 144, 143, - 142, 141, 140, 139, 138, 135, 106, 106, 131, 101, - 128, 127, 126, 125, 124, 123, 122, 121, 120, 119, - 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, - - 108, 107, 101, 98, 94, 93, 92, 91, 90, 89, - 88, 87, 82, 79, 76, 75, 70, 61, 56, 53, - 50, 184, 3, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 184 + 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, + + 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 + } ; -static yyconst flex_int16_t yy_chk[275] = +static yyconst flex_int16_t yy_chk[292] = { 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, 5, 5, 6, 6, 11, 15, 17, 20, 47, - 20, 19, 23, 23, 17, 15, 19, 20, 11, 25, - 25, 19, 29, 34, 32, 20, 36, 37, 29, 32, - 49, 49, 61, 36, 65, 66, 34, 66, 47, 61, - 37, 65, 185, 67, 66, 67, 182, 61, 67, 65, - - 103, 99, 66, 99, 111, 111, 99, 103, 104, 132, - 104, 132, 179, 104, 132, 103, 186, 186, 187, 187, - 188, 188, 188, 188, 189, 176, 189, 189, 175, 172, - 171, 169, 168, 166, 165, 164, 163, 162, 161, 157, - 156, 153, 152, 151, 150, 148, 147, 146, 145, 143, - 142, 141, 140, 138, 137, 136, 135, 134, 133, 130, - 129, 127, 126, 125, 124, 123, 122, 120, 119, 118, - 117, 116, 114, 113, 112, 110, 106, 105, 101, 100, - 96, 94, 93, 92, 91, 90, 89, 88, 87, 86, - 85, 84, 82, 81, 80, 79, 77, 76, 75, 74, - - 72, 68, 62, 54, 45, 44, 43, 42, 41, 40, - 39, 38, 35, 33, 31, 30, 24, 18, 14, 10, - 7, 3, 184, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, - 184, 184, 184, 184 + 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 + } ; /* Table of booleans, true if rule could match eol. */ -static yyconst flex_int32_t yy_rule_can_match_eol[81] = +static yyconst flex_int32_t yy_rule_can_match_eol[83] = { 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, 1, + 1, 0, 0, }; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. @@ -582,9 +596,11 @@ static yyconst flex_int32_t yy_rule_can_match_eol[81] = flex sksl.flex + You will have to manually add a copyright notice to the top of lex.sksl.c. + */ #define YY_NO_UNISTD_H 1 -#line 582 "lex.sksl.c" +#line 598 "lex.sksl.c" #define INITIAL 0 @@ -669,6 +685,10 @@ 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. */ @@ -711,7 +731,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 fwrite( yytext, yyleng, 1, yyout ) +#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, @@ -722,7 +742,7 @@ static int input (yyscan_t yyscanner ); if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ - yy_size_t n; \ + size_t n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ @@ -805,10 +825,10 @@ YY_DECL register int yy_act; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; -#line 21 "sksl.flex" +#line 23 "sksl.flex" -#line 806 "lex.sksl.c" +#line 826 "lex.sksl.c" if ( !yyg->yy_init ) { @@ -861,13 +881,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 >= 185 ) + if ( yy_current_state >= 201 ) 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 != 184 ); + while ( yy_current_state != 200 ); yy_cp = yyg->yy_last_accepting_cpos; yy_current_state = yyg->yy_last_accepting_state; @@ -878,7 +898,7 @@ yy_find_action: if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) { - yy_size_t yyl; + int yyl; for ( yyl = 0; yyl < yyleng; ++yyl ) if ( yytext[yyl] == '\n' ) @@ -901,407 +921,417 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP -#line 23 "sksl.flex" +#line 25 "sksl.flex" { return SkSL::Token::FLOAT_LITERAL; } YY_BREAK case 2: YY_RULE_SETUP -#line 25 "sksl.flex" +#line 27 "sksl.flex" { return SkSL::Token::FLOAT_LITERAL; } YY_BREAK case 3: YY_RULE_SETUP -#line 27 "sksl.flex" +#line 29 "sksl.flex" { return SkSL::Token::FLOAT_LITERAL; } YY_BREAK case 4: YY_RULE_SETUP -#line 29 "sksl.flex" +#line 31 "sksl.flex" { return SkSL::Token::INT_LITERAL; } YY_BREAK case 5: YY_RULE_SETUP -#line 31 "sksl.flex" +#line 33 "sksl.flex" { return SkSL::Token::TRUE_LITERAL; } YY_BREAK case 6: YY_RULE_SETUP -#line 33 "sksl.flex" +#line 35 "sksl.flex" { return SkSL::Token::FALSE_LITERAL; } YY_BREAK case 7: YY_RULE_SETUP -#line 35 "sksl.flex" +#line 37 "sksl.flex" { return SkSL::Token::IF; } YY_BREAK case 8: YY_RULE_SETUP -#line 37 "sksl.flex" +#line 39 "sksl.flex" { return SkSL::Token::ELSE; } YY_BREAK case 9: YY_RULE_SETUP -#line 39 "sksl.flex" +#line 41 "sksl.flex" { return SkSL::Token::FOR; } YY_BREAK case 10: YY_RULE_SETUP -#line 41 "sksl.flex" +#line 43 "sksl.flex" { return SkSL::Token::WHILE; } YY_BREAK case 11: YY_RULE_SETUP -#line 43 "sksl.flex" +#line 45 "sksl.flex" { return SkSL::Token::DO; } YY_BREAK case 12: YY_RULE_SETUP -#line 45 "sksl.flex" +#line 47 "sksl.flex" { return SkSL::Token::BREAK; } YY_BREAK case 13: YY_RULE_SETUP -#line 47 "sksl.flex" +#line 49 "sksl.flex" { return SkSL::Token::CONTINUE; } YY_BREAK case 14: YY_RULE_SETUP -#line 49 "sksl.flex" +#line 51 "sksl.flex" { return SkSL::Token::DISCARD; } YY_BREAK case 15: YY_RULE_SETUP -#line 51 "sksl.flex" +#line 53 "sksl.flex" { return SkSL::Token::RETURN; } YY_BREAK case 16: YY_RULE_SETUP -#line 53 "sksl.flex" +#line 55 "sksl.flex" { return SkSL::Token::IN; } YY_BREAK case 17: YY_RULE_SETUP -#line 55 "sksl.flex" +#line 57 "sksl.flex" { return SkSL::Token::OUT; } YY_BREAK case 18: YY_RULE_SETUP -#line 57 "sksl.flex" +#line 59 "sksl.flex" { return SkSL::Token::INOUT; } YY_BREAK case 19: YY_RULE_SETUP -#line 59 "sksl.flex" +#line 61 "sksl.flex" { return SkSL::Token::UNIFORM; } YY_BREAK case 20: YY_RULE_SETUP -#line 61 "sksl.flex" +#line 63 "sksl.flex" { return SkSL::Token::CONST; } YY_BREAK case 21: YY_RULE_SETUP -#line 63 "sksl.flex" +#line 65 "sksl.flex" { return SkSL::Token::LOWP; } YY_BREAK case 22: YY_RULE_SETUP -#line 65 "sksl.flex" +#line 67 "sksl.flex" { return SkSL::Token::MEDIUMP; } YY_BREAK case 23: YY_RULE_SETUP -#line 67 "sksl.flex" +#line 69 "sksl.flex" { return SkSL::Token::HIGHP; } YY_BREAK case 24: YY_RULE_SETUP -#line 69 "sksl.flex" -{ return SkSL::Token::STRUCT; } +#line 71 "sksl.flex" +{ return SkSL::Token::FLAT; } YY_BREAK case 25: YY_RULE_SETUP -#line 71 "sksl.flex" -{ return SkSL::Token::LAYOUT; } +#line 73 "sksl.flex" +{ return SkSL::Token::NOPERSPECTIVE; } YY_BREAK case 26: YY_RULE_SETUP -#line 73 "sksl.flex" -{ return SkSL::Token::PRECISION; } +#line 75 "sksl.flex" +{ return SkSL::Token::STRUCT; } YY_BREAK case 27: YY_RULE_SETUP -#line 75 "sksl.flex" -{ return SkSL::Token::IDENTIFIER; } +#line 77 "sksl.flex" +{ return SkSL::Token::LAYOUT; } YY_BREAK case 28: YY_RULE_SETUP -#line 77 "sksl.flex" -{ return SkSL::Token::DIRECTIVE; } +#line 79 "sksl.flex" +{ return SkSL::Token::PRECISION; } YY_BREAK case 29: YY_RULE_SETUP -#line 79 "sksl.flex" -{ return SkSL::Token::LPAREN; } +#line 81 "sksl.flex" +{ return SkSL::Token::IDENTIFIER; } YY_BREAK case 30: YY_RULE_SETUP -#line 81 "sksl.flex" -{ return SkSL::Token::RPAREN; } +#line 83 "sksl.flex" +{ return SkSL::Token::DIRECTIVE; } YY_BREAK case 31: YY_RULE_SETUP -#line 83 "sksl.flex" -{ return SkSL::Token::LBRACE; } +#line 85 "sksl.flex" +{ return SkSL::Token::LPAREN; } YY_BREAK case 32: YY_RULE_SETUP -#line 85 "sksl.flex" -{ return SkSL::Token::RBRACE; } +#line 87 "sksl.flex" +{ return SkSL::Token::RPAREN; } YY_BREAK case 33: YY_RULE_SETUP -#line 87 "sksl.flex" -{ return SkSL::Token::LBRACKET; } +#line 89 "sksl.flex" +{ return SkSL::Token::LBRACE; } YY_BREAK case 34: YY_RULE_SETUP -#line 89 "sksl.flex" -{ return SkSL::Token::RBRACKET; } +#line 91 "sksl.flex" +{ return SkSL::Token::RBRACE; } YY_BREAK case 35: YY_RULE_SETUP -#line 91 "sksl.flex" -{ return SkSL::Token::DOT; } +#line 93 "sksl.flex" +{ return SkSL::Token::LBRACKET; } YY_BREAK case 36: YY_RULE_SETUP -#line 93 "sksl.flex" -{ return SkSL::Token::COMMA; } +#line 95 "sksl.flex" +{ return SkSL::Token::RBRACKET; } YY_BREAK case 37: YY_RULE_SETUP -#line 95 "sksl.flex" -{ return SkSL::Token::PLUSPLUS; } +#line 97 "sksl.flex" +{ return SkSL::Token::DOT; } YY_BREAK case 38: YY_RULE_SETUP -#line 97 "sksl.flex" -{ return SkSL::Token::MINUSMINUS; } +#line 99 "sksl.flex" +{ return SkSL::Token::COMMA; } YY_BREAK case 39: YY_RULE_SETUP -#line 99 "sksl.flex" -{ return SkSL::Token::PLUS; } +#line 101 "sksl.flex" +{ return SkSL::Token::PLUSPLUS; } YY_BREAK case 40: YY_RULE_SETUP -#line 101 "sksl.flex" -{ return SkSL::Token::MINUS; } +#line 103 "sksl.flex" +{ return SkSL::Token::MINUSMINUS; } YY_BREAK case 41: YY_RULE_SETUP -#line 103 "sksl.flex" -{ return SkSL::Token::STAR; } +#line 105 "sksl.flex" +{ return SkSL::Token::PLUS; } YY_BREAK case 42: YY_RULE_SETUP -#line 105 "sksl.flex" -{ return SkSL::Token::SLASH; } +#line 107 "sksl.flex" +{ return SkSL::Token::MINUS; } YY_BREAK case 43: YY_RULE_SETUP -#line 107 "sksl.flex" -{ return SkSL::Token::PERCENT; } +#line 109 "sksl.flex" +{ return SkSL::Token::STAR; } YY_BREAK case 44: YY_RULE_SETUP -#line 109 "sksl.flex" -{ return SkSL::Token::SHL; } +#line 111 "sksl.flex" +{ return SkSL::Token::SLASH; } YY_BREAK case 45: YY_RULE_SETUP -#line 111 "sksl.flex" -{ return SkSL::Token::SHR; } +#line 113 "sksl.flex" +{ return SkSL::Token::PERCENT; } YY_BREAK case 46: YY_RULE_SETUP -#line 113 "sksl.flex" -{ return SkSL::Token::BITWISEOR; } +#line 115 "sksl.flex" +{ return SkSL::Token::SHL; } YY_BREAK case 47: YY_RULE_SETUP -#line 115 "sksl.flex" -{ return SkSL::Token::BITWISEXOR; } +#line 117 "sksl.flex" +{ return SkSL::Token::SHR; } YY_BREAK case 48: YY_RULE_SETUP -#line 117 "sksl.flex" -{ return SkSL::Token::BITWISEAND; } +#line 119 "sksl.flex" +{ return SkSL::Token::BITWISEOR; } YY_BREAK case 49: YY_RULE_SETUP -#line 119 "sksl.flex" -{ return SkSL::Token::LOGICALOR; } +#line 121 "sksl.flex" +{ return SkSL::Token::BITWISEXOR; } YY_BREAK case 50: YY_RULE_SETUP -#line 121 "sksl.flex" -{ return SkSL::Token::LOGICALXOR; } +#line 123 "sksl.flex" +{ return SkSL::Token::BITWISEAND; } YY_BREAK case 51: YY_RULE_SETUP -#line 123 "sksl.flex" -{ return SkSL::Token::LOGICALAND; } +#line 125 "sksl.flex" +{ return SkSL::Token::LOGICALOR; } YY_BREAK case 52: YY_RULE_SETUP -#line 125 "sksl.flex" -{ return SkSL::Token::NOT; } +#line 127 "sksl.flex" +{ return SkSL::Token::LOGICALXOR; } YY_BREAK case 53: YY_RULE_SETUP -#line 127 "sksl.flex" -{ return SkSL::Token::QUESTION; } +#line 129 "sksl.flex" +{ return SkSL::Token::LOGICALAND; } YY_BREAK case 54: YY_RULE_SETUP -#line 129 "sksl.flex" -{ return SkSL::Token::COLON; } +#line 131 "sksl.flex" +{ return SkSL::Token::NOT; } YY_BREAK case 55: YY_RULE_SETUP -#line 131 "sksl.flex" -{ return SkSL::Token::EQ; } +#line 133 "sksl.flex" +{ return SkSL::Token::QUESTION; } YY_BREAK case 56: YY_RULE_SETUP -#line 133 "sksl.flex" -{ return SkSL::Token::EQEQ; } +#line 135 "sksl.flex" +{ return SkSL::Token::COLON; } YY_BREAK case 57: YY_RULE_SETUP -#line 135 "sksl.flex" -{ return SkSL::Token::NEQ; } +#line 137 "sksl.flex" +{ return SkSL::Token::EQ; } YY_BREAK case 58: YY_RULE_SETUP -#line 137 "sksl.flex" -{ return SkSL::Token::GT; } +#line 139 "sksl.flex" +{ return SkSL::Token::EQEQ; } YY_BREAK case 59: YY_RULE_SETUP -#line 139 "sksl.flex" -{ return SkSL::Token::LT; } +#line 141 "sksl.flex" +{ return SkSL::Token::NEQ; } YY_BREAK case 60: YY_RULE_SETUP -#line 141 "sksl.flex" -{ return SkSL::Token::GTEQ; } +#line 143 "sksl.flex" +{ return SkSL::Token::GT; } YY_BREAK case 61: YY_RULE_SETUP -#line 143 "sksl.flex" -{ return SkSL::Token::LTEQ; } +#line 145 "sksl.flex" +{ return SkSL::Token::LT; } YY_BREAK case 62: YY_RULE_SETUP -#line 145 "sksl.flex" -{ return SkSL::Token::PLUSEQ; } +#line 147 "sksl.flex" +{ return SkSL::Token::GTEQ; } YY_BREAK case 63: YY_RULE_SETUP -#line 147 "sksl.flex" -{ return SkSL::Token::MINUSEQ; } +#line 149 "sksl.flex" +{ return SkSL::Token::LTEQ; } YY_BREAK case 64: YY_RULE_SETUP -#line 149 "sksl.flex" -{ return SkSL::Token::STAREQ; } +#line 151 "sksl.flex" +{ return SkSL::Token::PLUSEQ; } YY_BREAK case 65: YY_RULE_SETUP -#line 151 "sksl.flex" -{ return SkSL::Token::SLASHEQ; } +#line 153 "sksl.flex" +{ return SkSL::Token::MINUSEQ; } YY_BREAK case 66: YY_RULE_SETUP -#line 153 "sksl.flex" -{ return SkSL::Token::PERCENTEQ; } +#line 155 "sksl.flex" +{ return SkSL::Token::STAREQ; } YY_BREAK case 67: YY_RULE_SETUP -#line 155 "sksl.flex" -{ return SkSL::Token::SHLEQ; } +#line 157 "sksl.flex" +{ return SkSL::Token::SLASHEQ; } YY_BREAK case 68: YY_RULE_SETUP -#line 157 "sksl.flex" -{ return SkSL::Token::SHREQ; } +#line 159 "sksl.flex" +{ return SkSL::Token::PERCENTEQ; } YY_BREAK case 69: YY_RULE_SETUP -#line 159 "sksl.flex" -{ return SkSL::Token::BITWISEOREQ; } +#line 161 "sksl.flex" +{ return SkSL::Token::SHLEQ; } YY_BREAK case 70: YY_RULE_SETUP -#line 161 "sksl.flex" -{ return SkSL::Token::BITWISEXOREQ; } +#line 163 "sksl.flex" +{ return SkSL::Token::SHREQ; } YY_BREAK case 71: YY_RULE_SETUP -#line 163 "sksl.flex" -{ return SkSL::Token::BITWISEANDEQ; } +#line 165 "sksl.flex" +{ return SkSL::Token::BITWISEOREQ; } YY_BREAK case 72: YY_RULE_SETUP -#line 165 "sksl.flex" -{ return SkSL::Token::LOGICALOREQ; } +#line 167 "sksl.flex" +{ return SkSL::Token::BITWISEXOREQ; } YY_BREAK case 73: YY_RULE_SETUP -#line 167 "sksl.flex" -{ return SkSL::Token::LOGICALXOREQ; } +#line 169 "sksl.flex" +{ return SkSL::Token::BITWISEANDEQ; } YY_BREAK case 74: YY_RULE_SETUP -#line 169 "sksl.flex" -{ return SkSL::Token::LOGICALANDEQ; } +#line 171 "sksl.flex" +{ return SkSL::Token::LOGICALOREQ; } YY_BREAK case 75: YY_RULE_SETUP -#line 171 "sksl.flex" -{ return SkSL::Token::SEMICOLON; } +#line 173 "sksl.flex" +{ return SkSL::Token::LOGICALXOREQ; } YY_BREAK case 76: YY_RULE_SETUP -#line 173 "sksl.flex" -/* line comment */ +#line 175 "sksl.flex" +{ return SkSL::Token::LOGICALANDEQ; } YY_BREAK case 77: -/* rule 77 can match eol */ YY_RULE_SETUP -#line 175 "sksl.flex" -/* block comment */ +#line 177 "sksl.flex" +{ return SkSL::Token::SEMICOLON; } YY_BREAK case 78: -/* rule 78 can match eol */ YY_RULE_SETUP -#line 177 "sksl.flex" -/* whitespace */ +#line 179 "sksl.flex" +/* line comment */ YY_BREAK case 79: +/* rule 79 can match eol */ YY_RULE_SETUP -#line 179 "sksl.flex" -{ return SkSL::Token::INVALID_TOKEN; } +#line 181 "sksl.flex" +/* block comment */ YY_BREAK case 80: +/* rule 80 can match eol */ YY_RULE_SETUP -#line 181 "sksl.flex" +#line 183 "sksl.flex" +/* whitespace */ + YY_BREAK +case 81: +YY_RULE_SETUP +#line 185 "sksl.flex" +{ return SkSL::Token::INVALID_TOKEN; } + YY_BREAK +case 82: +YY_RULE_SETUP +#line 187 "sksl.flex" ECHO; YY_BREAK -#line 1299 "lex.sksl.c" +#line 1329 "lex.sksl.c" case YY_STATE_EOF(INITIAL): yyterminate(); @@ -1496,7 +1526,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; + YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; int yy_c_buf_p_offset = (int) (yyg->yy_c_buf_p - b->yy_ch_buf); @@ -1596,7 +1626,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 >= 185 ) + if ( yy_current_state >= 201 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1625,12 +1655,13 @@ 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 >= 185 ) + if ( yy_current_state >= 201 ) 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 == 184); + yy_is_jam = (yy_current_state == 200); + (void)yyg; return yy_is_jam ? 0 : yy_current_state; } @@ -1725,7 +1756,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) case EOB_ACT_END_OF_FILE: { if ( skslwrap(yyscanner ) ) - return 0; + return EOF; if ( ! yyg->yy_did_buffer_switch_on_eof ) YY_NEW_FILE; @@ -2081,8 +2112,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 bytes the byte buffer to scan - * @param len the number of bytes in the buffer pointed to by @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 yyscanner The scanner object. * @return the newly allocated buffer state object. */ @@ -2090,7 +2121,8 @@ YY_BUFFER_STATE sksl_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_le { YY_BUFFER_STATE b; char *buf; - yy_size_t n, i; + yy_size_t n; + int i; /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; @@ -2236,7 +2268,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" , yyscanner); + YY_FATAL_ERROR( "skslset_lineno called with no buffer" ); yylineno = line_number; } @@ -2251,7 +2283,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" , yyscanner); + YY_FATAL_ERROR( "skslset_column called with no buffer" ); yycolumn = column_no; } @@ -2463,7 +2495,7 @@ void skslfree (void * ptr , yyscan_t yyscanner) #define YYTABLES_NAME "yytables" -#line 181 "sksl.flex" +#line 187 "sksl.flex" diff --git a/src/sksl/sksl.flex b/src/sksl/sksl.flex index cbc938a..67b48e9 100644 --- a/src/sksl/sksl.flex +++ b/src/sksl/sksl.flex @@ -68,6 +68,10 @@ mediump { return SkSL::Token::MEDIUMP; } highp { return SkSL::Token::HIGHP; } +flat { return SkSL::Token::FLAT; } + +noperspective { return SkSL::Token::NOPERSPECTIVE; } + struct { return SkSL::Token::STRUCT; } layout { return SkSL::Token::LAYOUT; } diff --git a/tests/SkSLGLSLTest.cpp b/tests/SkSLGLSLTest.cpp new file mode 100644 index 0000000..3906f67 --- /dev/null +++ b/tests/SkSLGLSLTest.cpp @@ -0,0 +1,227 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkSLCompiler.h" + +#include "Test.h" + +static void test(skiatest::Reporter* r, const char* src, SkSL::GLCaps caps, const char* expected) { + SkSL::Compiler compiler; + std::string output; + bool result = compiler.toGLSL(SkSL::Program::kFragment_Kind, src, caps, &output); + if (!result) { + SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str()); + } + REPORTER_ASSERT(r, result); + if (result) { + if (output != expected) { + SkDebugf("GLSL MISMATCH:\nsource:\n%s\n\nexpected:\n'%s'\n\nreceived:\n'%s'", src, + expected, output.c_str()); + } + REPORTER_ASSERT(r, output == expected); + } +} + +DEF_TEST(SkSLHelloWorld, r) { + SkSL::GLCaps caps = { 400, SkSL::GLCaps::kGL_Standard }; + test(r, + "out vec4 fragColor; void main() { fragColor = vec4(0.75); }", + caps, + "#version 400\n" + "out vec4 fragColor;\n" + "void main() {\n" + " fragColor = vec4(0.75);\n" + "}\n"); +} + +DEF_TEST(SkSLControl, r) { + SkSL::GLCaps caps = { 400, SkSL::GLCaps::kGL_Standard }; + test(r, + "out vec4 fragColor;" + "void main() {" + "if (1 + 2 + 3 > 5) { fragColor = vec4(0.75); } else { discard; }" + "int i = 0;" + "while (i < 10) fragColor *= 0.5;" + "do { fragColor += 0.01; } while (fragColor.x < 0.7);" + "for (int i = 0; i < 10; i++) {" + "if (i % 0 == 1) break; else continue;" + "}" + "return;" + "}", + caps, + "#version 400\n" + "out vec4 fragColor;\n" + "void main() {\n" + " if ((1 + 2) + 3 > 5) {\n" + " fragColor = vec4(0.75);\n" + " } else {\n" + " discard;\n" + " }\n" + " int i = 0;\n" + " while (i < 10) fragColor *= 0.5;\n" + " do {\n" + " fragColor += 0.01;\n" + " } while (fragColor.x < 0.7);\n" + " for (int i = 0;i < 10; i++) {\n" + " if (i % 0 == 1) break; else continue;\n" + " }\n" + " return;\n" + "}\n"); +} + +DEF_TEST(SkSLFunctions, r) { + SkSL::GLCaps caps = { 400, SkSL::GLCaps::kGL_Standard }; + test(r, + "out vec4 fragColor;" + "float foo(float v[2]) { return v[0] * v[1]; }" + "void bar(inout float x) { float y[2], z; y[0] = x; y[1] = x * 2; z = foo(y); x = z; }" + "void main() { float x = 10; bar(x); fragColor = vec4(x); }", + caps, + "#version 400\n" + "out vec4 fragColor;\n" + "float foo(in float[2] v) {\n" + " return v[0] * v[1];\n" + "}\n" + "void bar(inout float x) {\n" + " float y[2], z;\n" + " y[0] = x;\n" + " y[1] = x * 2;\n" + " z = foo(y);\n" + " x = z;\n" + "}\n" + "void main() {\n" + " float x = 10;\n" + " bar(x);\n" + " fragColor = vec4(x);\n" + "}\n"); +} + +DEF_TEST(SkSLOperators, r) { + SkSL::GLCaps caps = { 400, SkSL::GLCaps::kGL_Standard }; + test(r, + "void main() {" + "float x = 1, y = 2;" + "int z = 3;" + "x = x + y * z * x * (y - z);" + "y = x / y / z;" + "z = (z / 2 % 3 << 4) >> 2 << 1;" + "bool b = (x > 4) == x < 2 || 2 >= 5 && y <= z && 12 != 11;" + "x += 12;" + "x -= 12;" + "x *= y /= z = 10;" + "b ||= false;" + "b &&= true;" + "b ^^= false;" + "z |= 0;" + "z &= -1;" + "z ^= 0;" + "z >>= 2;" + "z <<= 4;" + "z %= 5;" + "}", + caps, + "#version 400\n" + "void main() {\n" + " float x = 1, y = 2;\n" + " int z = 3;\n" + " x = x + ((y * float(z)) * x) * (y - float(z));\n" + " y = (x / y) / float(z);\n" + " z = (((z / 2) % 3 << 4) >> 2) << 1;\n" + " bool b = x > 4 == x < 2 || (2 >= 5 && y <= float(z)) && 12 != 11;\n" + " x += 12;\n" + " x -= 12;\n" + " x *= (y /= float(z = 10));\n" + " b ||= false;\n" + " b &&= true;\n" + " b ^^= false;\n" + " z |= 0;\n" + " z &= -1;\n" + " z ^= 0;\n" + " z >>= 2;\n" + " z <<= 4;\n" + " z %= 5;\n" + "}\n"); +} + +DEF_TEST(SkSLMatrices, r) { + SkSL::GLCaps caps = { 400, SkSL::GLCaps::kGL_Standard }; + test(r, + "void main() {" + "mat2x4 x = mat2x4(1);" + "mat3x2 y = mat3x2(1, 0, 0, 1, vec2(2, 2));" + "mat3x4 z = x * y;" + "vec3 v1 = mat3(1) * vec3(1);" + "vec3 v2 = vec3(1) * mat3(1);" + "}", + caps, + "#version 400\n" + "void main() {\n" + " mat2x4 x = mat2x4(1);\n" + " mat3x2 y = mat3x2(1, 0, 0, 1, vec2(2, 2));\n" + " mat3x4 z = x * y;\n" + " vec3 v1 = mat3(1) * vec3(1);\n" + " vec3 v2 = vec3(1) * mat3(1);\n" + "}\n"); +} + +DEF_TEST(SkSLInterfaceBlock, r) { + SkSL::GLCaps caps = { 400, SkSL::GLCaps::kGL_Standard }; + test(r, + "uniform testBlock {" + "float x;" + "float y[2];" + "layout(binding=12) mat3x2 z;" + "bool w;" + "};" + "void main() {" + "}", + caps, + "#version 400\n" + "uniform testBlock {\n" + " float x;\n" + " float[2] y;\n" + " layout (binding = 12)mat3x2 z;\n" + " bool w;\n" + "};\n" + "void main() {\n" + "}\n"); +} + +DEF_TEST(SkSLStructs, r) { + SkSL::GLCaps caps = { 400, SkSL::GLCaps::kGL_Standard }; + test(r, + "struct A {" + "int x;" + "int y;" + "} a1, a2;" + "A a3;" + "struct B {" + "float x;" + "float y[2];" + "layout(binding=1) A z;" + "};" + "B b1, b2, b3;" + "void main() {" + "}", + caps, + "#version 400\n" + "struct A {\n" + " int x;\n" + " int y;\n" + "}\n" + " a1, a2;\n" + "A a3;\n" + "struct B {\n" + " float x;\n" + " float[2] y;\n" + " layout (binding = 1)A z;\n" + "}\n" + " b1, b2, b3;\n" + "void main() {\n" + "}\n"); + +}