Fixed a couple of spots where sksl didn't have proper array support.

vec2 x[3] worked, but vec2[3] x didn't. Interface blocks also did
not work with array sizes.

BUG=skia:

Change-Id: I45b424891db46804f1e3c1f4793470b7b501a6de
Reviewed-on: https://skia-review.googlesource.com/8523
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Ben Wagner <benjaminwagner@google.com>
This commit is contained in:
Ethan Nicholas 2017-02-16 14:49:57 -05:00 committed by Skia Commit-Bot
parent 3bf12c60e2
commit 50afc17655
8 changed files with 229 additions and 45 deletions

View File

@ -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) {

View File

@ -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() +

View File

@ -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)? */

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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;
};

View File

@ -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();
}
result += "};";
return result;
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 += "]";
}
}
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;

View File

@ -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