Only include one variable per declaration statement
This removes VarDeclarationsStatement entirely. VarDeclaration instances
appear directly as statements in Programs. SkSL that declares multiple
variables in a single declaration is transformed to represent that as a
series of VarDeclaration statements.
Similarly, global variable declarations are represented by
GlobalVarDeclaration program elements, one per variable.
Bug: skia:10806
Change-Id: Idd8a2d971a8217733ed57f0dd2249d62f2f0e9c5
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/323102
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
diff --git a/src/sksl/SkSLMetalCodeGenerator.cpp b/src/sksl/SkSLMetalCodeGenerator.cpp
index d510af3..2ef5451 100644
--- a/src/sksl/SkSLMetalCodeGenerator.cpp
+++ b/src/sksl/SkSLMetalCodeGenerator.cpp
@@ -951,36 +951,31 @@
to_string(fUniformBuffer) + ")]]");
}
for (const auto& e : fProgram) {
- if (e.kind() == ProgramElement::Kind::kVar) {
- const VarDeclarations& decls = e.as<VarDeclarations>();
- if (!decls.fVars.size()) {
- continue;
- }
- for (const auto& stmt: decls.fVars) {
- VarDeclaration& var = stmt->as<VarDeclaration>();
- if (var.fVar->type().typeKind() == Type::TypeKind::kSampler) {
- if (var.fVar->fModifiers.fLayout.fBinding < 0) {
- fErrors.error(decls.fOffset,
- "Metal samplers must have 'layout(binding=...)'");
- return;
- }
- if (var.fVar->type().dimensions() != SpvDim2D) {
- // TODO: Support other texture types (skbug.com/10797)
- fErrors.error(decls.fOffset, "Unsupported texture dimensions");
- return;
- }
- this->write(", texture2d<float> ");
- this->writeName(var.fVar->name());
- this->write("[[texture(");
- this->write(to_string(var.fVar->fModifiers.fLayout.fBinding));
- this->write(")]]");
- this->write(", sampler ");
- this->writeName(var.fVar->name());
- this->write(SAMPLER_SUFFIX);
- this->write("[[sampler(");
- this->write(to_string(var.fVar->fModifiers.fLayout.fBinding));
- this->write(")]]");
+ if (e.is<GlobalVarDeclaration>()) {
+ const GlobalVarDeclaration& decls = e.as<GlobalVarDeclaration>();
+ const VarDeclaration& var = *decls.fDecl;
+ if (var.fVar->type().typeKind() == Type::TypeKind::kSampler) {
+ if (var.fVar->fModifiers.fLayout.fBinding < 0) {
+ fErrors.error(decls.fOffset,
+ "Metal samplers must have 'layout(binding=...)'");
+ return;
}
+ if (var.fVar->type().dimensions() != SpvDim2D) {
+ // TODO: Support other texture types (skbug.com/10797)
+ fErrors.error(decls.fOffset, "Unsupported texture dimensions");
+ return;
+ }
+ this->write(", texture2d<float> ");
+ this->writeName(var.fVar->name());
+ this->write("[[texture(");
+ this->write(to_string(var.fVar->fModifiers.fLayout.fBinding));
+ this->write(")]]");
+ this->write(", sampler ");
+ this->writeName(var.fVar->name());
+ this->write(SAMPLER_SUFFIX);
+ this->write("[[sampler(");
+ this->write(to_string(var.fVar->fModifiers.fLayout.fBinding));
+ this->write(")]]");
}
} else if (e.kind() == ProgramElement::Kind::kInterfaceBlock) {
InterfaceBlock& intf = (InterfaceBlock&) e;
@@ -1219,38 +1214,26 @@
this->write(name);
}
-void MetalCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool global) {
- SkASSERT(decl.fVars.size() > 0);
- bool wroteType = false;
- for (const auto& stmt : decl.fVars) {
- VarDeclaration& var = (VarDeclaration&) *stmt;
- if (global && !(var.fVar->fModifiers.fFlags & Modifiers::kConst_Flag)) {
- continue;
- }
- if (wroteType) {
- this->write(", ");
- } else {
- this->writeModifiers(var.fVar->fModifiers, global);
- this->writeType(decl.fBaseType);
- this->write(" ");
- wroteType = true;
- }
- this->writeName(var.fVar->name());
- for (const auto& size : var.fSizes) {
- this->write("[");
- if (size) {
- this->writeExpression(*size, kTopLevel_Precedence);
- }
- this->write("]");
- }
- if (var.fValue) {
- this->write(" = ");
- this->writeVarInitializer(*var.fVar, *var.fValue);
- }
+void MetalCodeGenerator::writeVarDeclaration(const VarDeclaration& var, bool global) {
+ if (global && !(var.fVar->fModifiers.fFlags & Modifiers::kConst_Flag)) {
+ return;
}
- if (wroteType) {
- this->write(";");
+ this->writeModifiers(var.fVar->fModifiers, global);
+ this->writeType(var.fBaseType);
+ this->write(" ");
+ this->writeName(var.fVar->name());
+ for (const auto& size : var.fSizes) {
+ this->write("[");
+ if (size) {
+ this->writeExpression(*size, kTopLevel_Precedence);
+ }
+ this->write("]");
}
+ if (var.fValue) {
+ this->write(" = ");
+ this->writeVarInitializer(*var.fVar, *var.fValue);
+ }
+ this->write(";");
}
void MetalCodeGenerator::writeStatement(const Statement& s) {
@@ -1265,8 +1248,8 @@
case Statement::Kind::kReturn:
this->writeReturnStatement(s.as<ReturnStatement>());
break;
- case Statement::Kind::kVarDeclarations:
- this->writeVarDeclarations(*s.as<VarDeclarationsStatement>().fDeclaration, false);
+ case Statement::Kind::kVarDeclaration:
+ this->writeVarDeclaration(s.as<VarDeclaration>(), false);
break;
case Statement::Kind::kIf:
this->writeIfStatement(s.as<IfStatement>());
@@ -1407,33 +1390,27 @@
void MetalCodeGenerator::writeUniformStruct() {
for (const auto& e : fProgram) {
- if (e.kind() == ProgramElement::Kind::kVar) {
- const VarDeclarations& decls = e.as<VarDeclarations>();
- if (!decls.fVars.size()) {
- continue;
- }
- const Variable& first = *decls.fVars[0]->as<VarDeclaration>().fVar;
- if (first.fModifiers.fFlags & Modifiers::kUniform_Flag &&
- first.type().typeKind() != Type::TypeKind::kSampler) {
+ if (e.is<GlobalVarDeclaration>()) {
+ const GlobalVarDeclaration& decls = e.as<GlobalVarDeclaration>();
+ const Variable& var = *decls.fDecl->fVar;
+ if (var.fModifiers.fFlags & Modifiers::kUniform_Flag &&
+ var.type().typeKind() != Type::TypeKind::kSampler) {
if (-1 == fUniformBuffer) {
this->write("struct Uniforms {\n");
- fUniformBuffer = first.fModifiers.fLayout.fSet;
+ fUniformBuffer = var.fModifiers.fLayout.fSet;
if (-1 == fUniformBuffer) {
fErrors.error(decls.fOffset, "Metal uniforms must have 'layout(set=...)'");
}
- } else if (first.fModifiers.fLayout.fSet != fUniformBuffer) {
+ } else if (var.fModifiers.fLayout.fSet != fUniformBuffer) {
if (-1 == fUniformBuffer) {
fErrors.error(decls.fOffset, "Metal backend requires all uniforms to have "
"the same 'layout(set=...)'");
}
}
this->write(" ");
- this->writeType(first.type());
+ this->writeType(var.type());
this->write(" ");
- for (const auto& stmt : decls.fVars) {
- const VarDeclaration& var = stmt->as<VarDeclaration>();
- this->writeName(var.fVar->name());
- }
+ this->writeName(var.name());
this->write(";\n");
}
}
@@ -1446,28 +1423,22 @@
void MetalCodeGenerator::writeInputStruct() {
this->write("struct Inputs {\n");
for (const auto& e : fProgram) {
- if (e.kind() == ProgramElement::Kind::kVar) {
- const VarDeclarations& decls = e.as<VarDeclarations>();
- if (!decls.fVars.size()) {
- continue;
- }
- const Variable& first = *decls.fVars[0]->as<VarDeclaration>().fVar;
- if (first.fModifiers.fFlags & Modifiers::kIn_Flag &&
- -1 == first.fModifiers.fLayout.fBuiltin) {
+ if (e.is<GlobalVarDeclaration>()) {
+ const GlobalVarDeclaration& decls = e.as<GlobalVarDeclaration>();
+ const Variable& var = *decls.fDecl->fVar;
+ if (var.fModifiers.fFlags & Modifiers::kIn_Flag &&
+ -1 == var.fModifiers.fLayout.fBuiltin) {
this->write(" ");
- this->writeType(first.type());
+ this->writeType(var.type());
this->write(" ");
- for (const auto& stmt : decls.fVars) {
- const VarDeclaration& var = stmt->as<VarDeclaration>();
- this->writeName(var.fVar->name());
- if (-1 != var.fVar->fModifiers.fLayout.fLocation) {
- if (fProgram.fKind == Program::kVertex_Kind) {
- this->write(" [[attribute(" +
- to_string(var.fVar->fModifiers.fLayout.fLocation) + ")]]");
- } else if (fProgram.fKind == Program::kFragment_Kind) {
- this->write(" [[user(locn" +
- to_string(var.fVar->fModifiers.fLayout.fLocation) + ")]]");
- }
+ this->writeName(var.name());
+ if (-1 != var.fModifiers.fLayout.fLocation) {
+ if (fProgram.fKind == Program::kVertex_Kind) {
+ this->write(" [[attribute(" +
+ to_string(var.fModifiers.fLayout.fLocation) + ")]]");
+ } else if (fProgram.fKind == Program::kFragment_Kind) {
+ this->write(" [[user(locn" +
+ to_string(var.fModifiers.fLayout.fLocation) + ")]]");
}
}
this->write(";\n");
@@ -1485,32 +1456,26 @@
this->write(" float4 sk_FragColor [[color(0)]];\n");
}
for (const auto& e : fProgram) {
- if (e.kind() == ProgramElement::Kind::kVar) {
- const VarDeclarations& decls = e.as<VarDeclarations>();
- if (!decls.fVars.size()) {
- continue;
- }
- const Variable& first = *decls.fVars[0]->as<VarDeclaration>().fVar;
- if (first.fModifiers.fFlags & Modifiers::kOut_Flag &&
- -1 == first.fModifiers.fLayout.fBuiltin) {
+ if (e.is<GlobalVarDeclaration>()) {
+ const GlobalVarDeclaration& decls = e.as<GlobalVarDeclaration>();
+ const Variable& var = *decls.fDecl->fVar;
+ if (var.fModifiers.fFlags & Modifiers::kOut_Flag &&
+ -1 == var.fModifiers.fLayout.fBuiltin) {
this->write(" ");
- this->writeType(first.type());
+ this->writeType(var.type());
this->write(" ");
- for (const auto& stmt : decls.fVars) {
- const VarDeclaration& var = stmt->as<VarDeclaration>();
- this->writeName(var.fVar->name());
- if (fProgram.fKind == Program::kVertex_Kind) {
- this->write(" [[user(locn" +
- to_string(var.fVar->fModifiers.fLayout.fLocation) + ")]]");
- } else if (fProgram.fKind == Program::kFragment_Kind) {
- this->write(" [[color(" +
- to_string(var.fVar->fModifiers.fLayout.fLocation) +")");
- int colorIndex = var.fVar->fModifiers.fLayout.fIndex;
- if (colorIndex) {
- this->write(", index(" + to_string(colorIndex) + ")");
- }
- this->write("]]");
+ this->writeName(var.name());
+ if (fProgram.fKind == Program::kVertex_Kind) {
+ this->write(" [[user(locn" +
+ to_string(var.fModifiers.fLayout.fLocation) + ")]]");
+ } else if (fProgram.fKind == Program::kFragment_Kind) {
+ this->write(" [[color(" +
+ to_string(var.fModifiers.fLayout.fLocation) +")");
+ int colorIndex = var.fModifiers.fLayout.fIndex;
+ if (colorIndex) {
+ this->write(", index(" + to_string(colorIndex) + ")");
}
+ this->write("]]");
}
this->write(";\n");
}
@@ -1543,27 +1508,21 @@
visitor->VisitInterfaceBlock(*interfaceType, interfaceName);
}
for (const ProgramElement& element : fProgram) {
- if (element.kind() != ProgramElement::Kind::kVar) {
+ if (!element.is<GlobalVarDeclaration>()) {
continue;
}
- const VarDeclarations& decls = static_cast<const VarDeclarations&>(element);
- if (decls.fVars.empty()) {
- continue;
- }
- const Variable& first = *((VarDeclaration&) *decls.fVars[0]).fVar;
- if ((!first.fModifiers.fFlags && -1 == first.fModifiers.fLayout.fBuiltin) ||
- first.type().typeKind() == Type::TypeKind::kSampler) {
- for (const auto& stmt : decls.fVars) {
- VarDeclaration& var = static_cast<VarDeclaration&>(*stmt);
-
- if (var.fVar->type().typeKind() == Type::TypeKind::kSampler) {
- // Samplers are represented as a "texture/sampler" duo in the global struct.
- visitor->VisitTexture(first.type(), var.fVar->name());
- visitor->VisitSampler(first.type(), String(var.fVar->name()) + SAMPLER_SUFFIX);
- } else {
- // Visit a regular variable.
- visitor->VisitVariable(*var.fVar, var.fValue.get());
- }
+ const GlobalVarDeclaration& decls = element.as<GlobalVarDeclaration>();
+ const VarDeclaration& decl = *decls.fDecl;
+ const Variable& var = *decl.fVar;
+ if ((!var.fModifiers.fFlags && -1 == var.fModifiers.fLayout.fBuiltin) ||
+ var.type().typeKind() == Type::TypeKind::kSampler) {
+ if (var.type().typeKind() == Type::TypeKind::kSampler) {
+ // Samplers are represented as a "texture/sampler" duo in the global struct.
+ visitor->VisitTexture(var.type(), var.name());
+ visitor->VisitSampler(var.type(), String(var.name()) + SAMPLER_SUFFIX);
+ } else {
+ // Visit a regular variable.
+ visitor->VisitVariable(var, decl.fValue.get());
}
}
}
@@ -1677,17 +1636,15 @@
switch (e.kind()) {
case ProgramElement::Kind::kExtension:
break;
- case ProgramElement::Kind::kVar: {
- const VarDeclarations& decl = e.as<VarDeclarations>();
- if (decl.fVars.size() > 0) {
- int builtin = decl.fVars[0]->as<VarDeclaration>().fVar->fModifiers.fLayout.fBuiltin;
- if (-1 == builtin) {
- // normal var
- this->writeVarDeclarations(decl, true);
- this->writeLine();
- } else if (SK_FRAGCOLOR_BUILTIN == builtin) {
- // ignore
- }
+ case ProgramElement::Kind::kGlobalVar: {
+ const VarDeclaration& decl = *e.as<GlobalVarDeclaration>().fDecl;
+ int builtin = decl.fVar->fModifiers.fLayout.fBuiltin;
+ if (-1 == builtin) {
+ // normal var
+ this->writeVarDeclaration(decl, true);
+ this->writeLine();
+ } else if (SK_FRAGCOLOR_BUILTIN == builtin) {
+ // ignore
}
break;
}
@@ -1797,14 +1754,6 @@
const VarDeclaration& var = s->as<VarDeclaration>();
return this->requirements(var.fValue.get());
}
- case Statement::Kind::kVarDeclarations: {
- Requirements result = kNo_Requirements;
- const VarDeclarations& decls = *s->as<VarDeclarationsStatement>().fDeclaration;
- for (const auto& stmt : decls.fVars) {
- result |= this->requirements(stmt.get());
- }
- return result;
- }
case Statement::Kind::kExpression:
return this->requirements(s->as<ExpressionStatement>().expression().get());
case Statement::Kind::kReturn: {