diff options
-rw-r--r-- | src/sksl/SkSLGLSLCodeGenerator.cpp | 24 | ||||
-rw-r--r-- | src/sksl/SkSLIRGenerator.cpp | 73 | ||||
-rw-r--r-- | src/sksl/SkSLParser.cpp | 46 | ||||
-rw-r--r-- | src/sksl/SkSLSPIRVCodeGenerator.cpp | 3 | ||||
-rw-r--r-- | src/sksl/ast/SkSLASTInterfaceBlock.h | 32 | ||||
-rw-r--r-- | src/sksl/ast/SkSLASTType.h | 8 | ||||
-rw-r--r-- | src/sksl/ir/SkSLInterfaceBlock.h | 40 | ||||
-rw-r--r-- | tests/SkSLGLSLTest.cpp | 48 |
8 files changed, 229 insertions, 45 deletions
diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp index 4b1eea3451..18cfba79e9 100644 --- a/src/sksl/SkSLGLSLCodeGenerator.cpp +++ b/src/sksl/SkSLGLSLCodeGenerator.cpp @@ -584,19 +584,35 @@ void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers, } void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { - if (intf.fVariable.fName == "gl_PerVertex") { + if (intf.fTypeName == "gl_PerVertex") { return; } this->writeModifiers(intf.fVariable.fModifiers, true); - this->writeLine(intf.fVariable.fType.name() + " {"); + this->writeLine(intf.fTypeName + " {"); fIndentation++; - for (const auto& f : intf.fVariable.fType.fields()) { + const Type* structType = &intf.fVariable.fType; + while (structType->kind() == Type::kArray_Kind) { + structType = &structType->componentType(); + } + for (const auto& f : structType->fields()) { this->writeModifiers(f.fModifiers, false); this->writeType(*f.fType); this->writeLine(" " + f.fName + ";"); } fIndentation--; - this->writeLine("};"); + this->write("}"); + if (intf.fInstanceName.size()) { + this->write(" "); + this->write(intf.fInstanceName); + for (const auto& size : intf.fSizes) { + this->write("["); + if (size) { + this->writeExpression(*size, kTopLevel_Precedence); + } + this->write("]"); + } + } + this->writeLine(";"); } void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool global) { diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp index 70df81b62e..247766f51e 100644 --- a/src/sksl/SkSLIRGenerator.cpp +++ b/src/sksl/SkSLIRGenerator.cpp @@ -197,7 +197,6 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVa } for (const auto& varDecl : decl.fVars) { const Type* type = baseType; - ASSERT(type->kind() != Type::kArray_Kind); std::vector<std::unique_ptr<Expression>> sizes; for (const auto& rawSize : varDecl.fSizes) { if (rawSize) { @@ -206,7 +205,7 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVa return nullptr; } SkString name = type->fName; - uint64_t count; + int64_t count; if (size->fKind == Expression::kIntLiteral_Kind) { count = ((IntLiteral&) *size).fValue; if (count <= 0) { @@ -550,26 +549,67 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInte } } } - Type* type = new Type(intf.fPosition, intf.fInterfaceName, fields); + Type* type = new Type(intf.fPosition, intf.fTypeName, fields); old->takeOwnership(type); - SkString name = intf.fValueName.size() > 0 ? intf.fValueName : intf.fInterfaceName; - Variable* var = new Variable(intf.fPosition, intf.fModifiers, name, *type, - Variable::kGlobal_Storage); + std::vector<std::unique_ptr<Expression>> sizes; + for (const auto& size : intf.fSizes) { + if (size) { + std::unique_ptr<Expression> converted = this->convertExpression(*size); + if (!converted) { + return nullptr; + } + SkString name = type->fName; + int64_t count; + if (converted->fKind == Expression::kIntLiteral_Kind) { + count = ((IntLiteral&) *converted).fValue; + if (count <= 0) { + fErrors.error(converted->fPosition, "array size must be positive"); + } + name += "[" + to_string(count) + "]"; + } else { + count = -1; + name += "[]"; + } + type = new Type(name, Type::kArray_Kind, *type, (int) count); + fSymbolTable->takeOwnership((Type*) type); + sizes.push_back(std::move(converted)); + } else { + type = new Type(type->fName + "[]", Type::kArray_Kind, *type, -1); + fSymbolTable->takeOwnership((Type*) type); + sizes.push_back(nullptr); + } + } + Variable* var = new Variable(intf.fPosition, intf.fModifiers, + intf.fInstanceName.size() ? intf.fInstanceName : intf.fTypeName, + *type, Variable::kGlobal_Storage); old->takeOwnership(var); - if (intf.fValueName.size()) { - old->addWithoutOwnership(intf.fValueName, var); + if (intf.fInstanceName.size()) { + old->addWithoutOwnership(intf.fInstanceName, var); } else { for (size_t i = 0; i < fields.size(); i++) { old->add(fields[i].fName, std::unique_ptr<Field>(new Field(intf.fPosition, *var, (int) i))); } } - return std::unique_ptr<InterfaceBlock>(new InterfaceBlock(intf.fPosition, *var, fSymbolTable)); + return std::unique_ptr<InterfaceBlock>(new InterfaceBlock(intf.fPosition, *var, + intf.fTypeName, + intf.fInstanceName, + std::move(sizes), + fSymbolTable)); } const Type* IRGenerator::convertType(const ASTType& type) { const Symbol* result = (*fSymbolTable)[type.fName]; if (result && result->fKind == Symbol::kType_Kind) { + for (int size : type.fSizes) { + SkString name = result->fName + "["; + if (size != -1) { + name += to_string(size); + } + name += "]"; + result = new Type(name, Type::kArray_Kind, (const Type&) *result, size); + fSymbolTable->takeOwnership((Type*) result); + } return (const Type*) result; } fErrors.error(type.fPosition, "unknown type '" + type.fName + "'"); @@ -1315,6 +1355,21 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression( std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression> base, const ASTExpression& index) { + if (base->fKind == Expression::kTypeReference_Kind) { + if (index.fKind == ASTExpression::kInt_Kind) { + const Type& oldType = ((TypeReference&) *base).fValue; + int64_t size = ((const ASTIntLiteral&) index).fValue; + Type* newType = new Type(oldType.name() + "[" + to_string(size) + "]", + Type::kArray_Kind, oldType, size); + fSymbolTable->takeOwnership(newType); + return std::unique_ptr<Expression>(new TypeReference(fContext, base->fPosition, + *newType)); + + } else { + fErrors.error(base->fPosition, "array size must be a constant"); + return nullptr; + } + } if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind && base->fType.kind() != Type::kVector_Kind) { fErrors.error(base->fPosition, "expected array, but found '" + base->fType.description() + diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp index e7733cdc82..5bffe1e8c3 100644 --- a/src/sksl/SkSLParser.cpp +++ b/src/sksl/SkSLParser.cpp @@ -415,7 +415,7 @@ std::unique_ptr<ASTType> Parser::structDeclaration() { } fTypes.add(name.fText, std::unique_ptr<Type>(new Type(name.fPosition, name.fText, fields))); return std::unique_ptr<ASTType>(new ASTType(name.fPosition, name.fText, - ASTType::kStruct_Kind)); + ASTType::kStruct_Kind, std::vector<int>())); } /* structDeclaration ((IDENTIFIER varDeclarationEnd) | SEMICOLON) */ @@ -770,7 +770,7 @@ std::unique_ptr<ASTStatement> Parser::statement() { } } -/* IDENTIFIER(type) */ +/* IDENTIFIER(type) (LBRACKET intLiteral? RBRACKET)* */ std::unique_ptr<ASTType> Parser::type() { Token type; if (!this->expect(Token::IDENTIFIER, "a type", &type)) { @@ -780,11 +780,26 @@ std::unique_ptr<ASTType> Parser::type() { this->error(type.fPosition, ("no type named '" + type.fText + "'").c_str()); return nullptr; } + std::vector<int> sizes; + while (this->peek().fKind == Token::LBRACKET) { + this->expect(Token::LBRACKET, "'['"); + if (this->peek().fKind != Token::RBRACKET) { + int64_t i; + if (this->intLiteral(&i)) { + sizes.push_back(i); + } else { + return nullptr; + } + } else { + sizes.push_back(-1); + } + this->expect(Token::RBRACKET, "']'"); + } return std::unique_ptr<ASTType>(new ASTType(type.fPosition, std::move(type.fText), - ASTType::kIdentifier_Kind)); + ASTType::kIdentifier_Kind, sizes)); } -/* IDENTIFIER LBRACE varDeclaration* RBRACE */ +/* IDENTIFIER LBRACE varDeclaration* RBRACE (IDENTIFIER (LBRACKET expression? RBRACKET)*)? */ std::unique_ptr<ASTDeclaration> Parser::interfaceBlock(Modifiers mods) { Token name; if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) { @@ -807,14 +822,29 @@ std::unique_ptr<ASTDeclaration> Parser::interfaceBlock(Modifiers mods) { decls.push_back(std::move(decl)); } this->nextToken(); - SkString valueName; + SkString instanceName; + std::vector<std::unique_ptr<ASTExpression>> sizes; if (this->peek().fKind == Token::IDENTIFIER) { - valueName = this->nextToken().fText; + instanceName = this->nextToken().fText; + while (this->peek().fKind == Token::LBRACKET) { + this->expect(Token::LBRACKET, "'['"); + if (this->peek().fKind != Token::RBRACKET) { + std::unique_ptr<ASTExpression> size = this->expression(); + if (!size) { + return nullptr; + } + sizes.push_back(std::move(size)); + } else { + sizes.push_back(nullptr); + } + this->expect(Token::RBRACKET, "']'"); + } } this->expect(Token::SEMICOLON, "';'"); return std::unique_ptr<ASTDeclaration>(new ASTInterfaceBlock(name.fPosition, mods, - name.fText, std::move(valueName), - std::move(decls))); + name.fText, std::move(decls), + std::move(instanceName), + std::move(sizes))); } /* IF LPAREN expression RPAREN statement (ELSE statement)? */ diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp index 1158f94826..0b7da5771b 100644 --- a/src/sksl/SkSLSPIRVCodeGenerator.cpp +++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp @@ -1876,7 +1876,8 @@ SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, S false); Variable intfVar(Position(), Modifiers(layout, Modifiers::kUniform_Flag), name, intfStruct, Variable::kGlobal_Storage); - InterfaceBlock intf(Position(), intfVar, st); + InterfaceBlock intf(Position(), intfVar, name, SkString(""), + std::vector<std::unique_ptr<Expression>>(), st); fRTHeightStructId = this->writeInterfaceBlock(intf); fRTHeightFieldIndex = 0; } diff --git a/src/sksl/ast/SkSLASTInterfaceBlock.h b/src/sksl/ast/SkSLASTInterfaceBlock.h index 9cd99d5a9d..7647fb5c00 100644 --- a/src/sksl/ast/SkSLASTInterfaceBlock.h +++ b/src/sksl/ast/SkSLASTInterfaceBlock.h @@ -25,31 +25,41 @@ struct ASTInterfaceBlock : public ASTDeclaration { // valueName is empty when it was not present in the source ASTInterfaceBlock(Position position, Modifiers modifiers, - SkString interfaceName, - SkString valueName, - std::vector<std::unique_ptr<ASTVarDeclarations>> declarations) + SkString typeName, + std::vector<std::unique_ptr<ASTVarDeclarations>> declarations, + SkString instanceName, + std::vector<std::unique_ptr<ASTExpression>> sizes) : INHERITED(position, kInterfaceBlock_Kind) , fModifiers(modifiers) - , fInterfaceName(std::move(interfaceName)) - , fValueName(std::move(valueName)) - , fDeclarations(std::move(declarations)) {} + , fTypeName(std::move(typeName)) + , fDeclarations(std::move(declarations)) + , fInstanceName(std::move(instanceName)) + , fSizes(std::move(sizes)) {} SkString description() const override { - SkString result = fModifiers.description() + fInterfaceName + " {\n"; + SkString result = fModifiers.description() + fTypeName + " {\n"; for (size_t i = 0; i < fDeclarations.size(); i++) { result += fDeclarations[i]->description() + "\n"; } result += "}"; - if (fValueName.size()) { - result += " " + fValueName; + if (fInstanceName.size()) { + result += " " + fInstanceName; + for (const auto& size : fSizes) { + result += "["; + if (size) { + result += size->description(); + } + result += "]"; + } } return result + ";"; } const Modifiers fModifiers; - const SkString fInterfaceName; - const SkString fValueName; + const SkString fTypeName; const std::vector<std::unique_ptr<ASTVarDeclarations>> fDeclarations; + const SkString fInstanceName; + const std::vector<std::unique_ptr<ASTExpression>> fSizes; typedef ASTDeclaration INHERITED; }; diff --git a/src/sksl/ast/SkSLASTType.h b/src/sksl/ast/SkSLASTType.h index 9cbded1043..b95c3d7a0b 100644 --- a/src/sksl/ast/SkSLASTType.h +++ b/src/sksl/ast/SkSLASTType.h @@ -21,10 +21,11 @@ struct ASTType : public ASTPositionNode { kStruct_Kind }; - ASTType(Position position, SkString name, Kind kind) + ASTType(Position position, SkString name, Kind kind, std::vector<int> sizes) : INHERITED(position) , fName(std::move(name)) - , fKind(kind) {} + , fKind(kind) + , fSizes(std::move(sizes)) {} SkString description() const override { return fName; @@ -34,6 +35,9 @@ struct ASTType : public ASTPositionNode { const Kind fKind; + // array sizes, -1 meaning unspecified + const std::vector<int> fSizes; + typedef ASTPositionNode INHERITED; }; diff --git a/src/sksl/ir/SkSLInterfaceBlock.h b/src/sksl/ir/SkSLInterfaceBlock.h index 0141953c35..0de37c59e8 100644 --- a/src/sksl/ir/SkSLInterfaceBlock.h +++ b/src/sksl/ir/SkSLInterfaceBlock.h @@ -25,23 +25,43 @@ namespace SkSL { * At the IR level, this is represented by a single variable of struct type. */ struct InterfaceBlock : public ProgramElement { - InterfaceBlock(Position position, const Variable& var, std::shared_ptr<SymbolTable> typeOwner) - : INHERITED(position, kInterfaceBlock_Kind) + InterfaceBlock(Position position, const Variable& var, SkString typeName, SkString instanceName, + std::vector<std::unique_ptr<Expression>> sizes, + std::shared_ptr<SymbolTable> typeOwner) + : INHERITED(position, kInterfaceBlock_Kind) , fVariable(std::move(var)) - , fTypeOwner(typeOwner) { - ASSERT(fVariable.fType.kind() == Type::kStruct_Kind); - } + , fTypeName(std::move(typeName)) + , fInstanceName(std::move(instanceName)) + , fSizes(std::move(sizes)) + , fTypeOwner(typeOwner) {} SkString description() const override { - SkString result = fVariable.fModifiers.description() + fVariable.fName + " {\n"; - for (size_t i = 0; i < fVariable.fType.fields().size(); i++) { - result += fVariable.fType.fields()[i].description() + "\n"; + SkString result = fVariable.fModifiers.description() + fTypeName + " {\n"; + const Type* structType = &fVariable.fType; + while (structType->kind() == Type::kArray_Kind) { + structType = &structType->componentType(); + } + for (const auto& f : structType->fields()) { + result += f.description() + "\n"; + } + result += "}"; + if (fInstanceName.size()) { + result += " " + fInstanceName; + for (const auto& size : fSizes) { + result += "["; + if (size) { + result += size->description(); + } + result += "]"; + } } - result += "};"; - return result; + return result + ";"; } const Variable& fVariable; + const SkString fTypeName; + const SkString fInstanceName; + const std::vector<std::unique_ptr<Expression>> fSizes; const std::shared_ptr<SymbolTable> fTypeOwner; typedef ProgramElement INHERITED; diff --git a/tests/SkSLGLSLTest.cpp b/tests/SkSLGLSLTest.cpp index 533c203036..a57fd9d4fb 100644 --- a/tests/SkSLGLSLTest.cpp +++ b/tests/SkSLGLSLTest.cpp @@ -187,6 +187,7 @@ DEF_TEST(SkSLInterfaceBlock, r) { "bool w;" "};" "void main() {" + " sk_FragColor = vec4(x, y[0], y[1], 0);" "}", *SkSL::ShaderCapsFactory::Default(), "#version 400\n" @@ -198,6 +199,39 @@ DEF_TEST(SkSLInterfaceBlock, r) { " bool w;\n" "};\n" "void main() {\n" + " sk_FragColor = vec4(x, y[0], y[1], 0.0);\n" + "}\n"); + test(r, + "uniform testBlock {" + "float x;" + "} test;" + "void main() {" + " sk_FragColor = vec4(test.x);" + "}", + *SkSL::ShaderCapsFactory::Default(), + "#version 400\n" + "out vec4 sk_FragColor;\n" + "uniform testBlock {\n" + " float x;\n" + "} test;\n" + "void main() {\n" + " sk_FragColor = vec4(test.x);\n" + "}\n"); + test(r, + "uniform testBlock {" + "float x;" + "} test[2];" + "void main() {" + " sk_FragColor = vec4(test[1].x);" + "}", + *SkSL::ShaderCapsFactory::Default(), + "#version 400\n" + "out vec4 sk_FragColor;\n" + "uniform testBlock {\n" + " float x;\n" + "} test[2];\n" + "void main() {\n" + " sk_FragColor = vec4(test[1].x);\n" "}\n"); } @@ -702,4 +736,18 @@ DEF_TEST(SkSLClipDistance, r) { " sk_FragColor = vec4(gl_ClipDistance[0]);\n" "}\n"); } + +DEF_TEST(SkSLArrayTypes, r) { + test(r, + "void main() { vec2 x[2] = vec2[2](vec2(1), vec2(2));" + "vec2[2] y = vec2[2](vec2(3), vec2(4)); }", + *SkSL::ShaderCapsFactory::Default(), + "#version 400\n" + "out vec4 sk_FragColor;\n" + "void main() {\n" + " vec2 x[2] = vec2[2](vec2(1.0), vec2(2.0));\n" + " vec2[2] y = vec2[2](vec2(3.0), vec2(4.0));\n" + "}\n"); +} + #endif |