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:
parent
3bf12c60e2
commit
50afc17655
@ -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) {
|
||||
|
@ -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() +
|
||||
|
@ -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)? */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user