moved SkSL Variable data into IRNode
Change-Id: I53af66c1b65971c204ac7c515e0d0e39481b015d Reviewed-on: https://skia-review.googlesource.com/c/skia/+/323097 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
parent
54c1b3dd43
commit
041fd0ad7d
@ -160,7 +160,7 @@ SkRuntimeEffect::EffectResult SkRuntimeEffect::Make(SkString sksl) {
|
||||
const SkSL::Type& varType = var.type();
|
||||
|
||||
// Varyings (only used in conjunction with drawVertices)
|
||||
if (var.fModifiers.fFlags & SkSL::Modifiers::kVarying_Flag) {
|
||||
if (var.modifiers().fFlags & SkSL::Modifiers::kVarying_Flag) {
|
||||
varyings.push_back({var.name(),
|
||||
varType.typeKind() == SkSL::Type::TypeKind::kVector
|
||||
? varType.columns()
|
||||
@ -172,7 +172,7 @@ SkRuntimeEffect::EffectResult SkRuntimeEffect::Make(SkString sksl) {
|
||||
sampleUsages.push_back(SkSL::Analysis::GetSampleUsage(*program, var));
|
||||
}
|
||||
// 'uniform' variables
|
||||
else if (var.fModifiers.fFlags & SkSL::Modifiers::kUniform_Flag) {
|
||||
else if (var.modifiers().fFlags & SkSL::Modifiers::kUniform_Flag) {
|
||||
Uniform uni;
|
||||
uni.fName = var.name();
|
||||
uni.fFlags = 0;
|
||||
@ -189,7 +189,7 @@ SkRuntimeEffect::EffectResult SkRuntimeEffect::Make(SkString sksl) {
|
||||
RETURN_FAILURE("Invalid uniform type: '%s'", type->displayName().c_str());
|
||||
}
|
||||
|
||||
const SkSL::StringFragment& marker(var.fModifiers.fLayout.fMarker);
|
||||
const SkSL::StringFragment& marker(var.modifiers().fLayout.fMarker);
|
||||
if (marker.fLength) {
|
||||
uni.fFlags |= Uniform::kMarker_Flag;
|
||||
allowColorFilter = false;
|
||||
@ -199,7 +199,7 @@ SkRuntimeEffect::EffectResult SkRuntimeEffect::Make(SkString sksl) {
|
||||
}
|
||||
}
|
||||
|
||||
if (var.fModifiers.fLayout.fFlags & SkSL::Layout::Flag::kSRGBUnpremul_Flag) {
|
||||
if (var.modifiers().fLayout.fFlags & SkSL::Layout::Flag::kSRGBUnpremul_Flag) {
|
||||
uni.fFlags |= Uniform::kSRGBUnpremul_Flag;
|
||||
}
|
||||
|
||||
|
@ -139,7 +139,7 @@ public:
|
||||
bool visitExpression(const Expression& e) override {
|
||||
if (e.is<VariableReference>()) {
|
||||
const VariableReference& var = e.as<VariableReference>();
|
||||
return var.fVariable->fModifiers.fLayout.fBuiltin == fBuiltin;
|
||||
return var.fVariable->modifiers().fLayout.fBuiltin == fBuiltin;
|
||||
}
|
||||
return INHERITED::visitExpression(e);
|
||||
}
|
||||
@ -240,8 +240,8 @@ public:
|
||||
case Expression::Kind::kVariableReference: {
|
||||
VariableReference& varRef = expr.as<VariableReference>();
|
||||
const Variable* var = varRef.fVariable;
|
||||
if (var->fModifiers.fFlags & (Modifiers::kConst_Flag | Modifiers::kUniform_Flag |
|
||||
Modifiers::kVarying_Flag)) {
|
||||
if (var->modifiers().fFlags & (Modifiers::kConst_Flag | Modifiers::kUniform_Flag |
|
||||
Modifiers::kVarying_Flag)) {
|
||||
fErrors->error(expr.fOffset,
|
||||
"cannot modify immutable variable '" + var->name() + "'");
|
||||
} else if (fAssignableVar) {
|
||||
|
@ -21,7 +21,7 @@ struct FunctionDefinition;
|
||||
struct Program;
|
||||
struct ProgramElement;
|
||||
struct Statement;
|
||||
struct Variable;
|
||||
class Variable;
|
||||
struct VariableReference;
|
||||
|
||||
/**
|
||||
|
@ -117,11 +117,11 @@ int ByteCodeGenerator::SlotCount(const Type& type) {
|
||||
}
|
||||
|
||||
static inline bool is_uniform(const SkSL::Variable& var) {
|
||||
return var.fModifiers.fFlags & Modifiers::kUniform_Flag;
|
||||
return var.modifiers().fFlags & Modifiers::kUniform_Flag;
|
||||
}
|
||||
|
||||
static inline bool is_in(const SkSL::Variable& var) {
|
||||
return var.fModifiers.fFlags & Modifiers::kIn_Flag;
|
||||
return var.modifiers().fFlags & Modifiers::kIn_Flag;
|
||||
}
|
||||
|
||||
void ByteCodeGenerator::gatherUniforms(const Type& type, const String& name) {
|
||||
@ -165,7 +165,7 @@ bool ByteCodeGenerator::generateCode() {
|
||||
if (declVar->type() == *fContext.fFragmentProcessor_Type) {
|
||||
fOutput->fChildFPCount++;
|
||||
}
|
||||
if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
|
||||
if (declVar->modifiers().fLayout.fBuiltin >= 0 || is_in(*declVar)) {
|
||||
continue;
|
||||
}
|
||||
if (is_uniform(*declVar)) {
|
||||
@ -218,8 +218,8 @@ std::unique_ptr<ByteCodeFunction> ByteCodeGenerator::writeFunction(const Functio
|
||||
static int expression_as_builtin(const Expression& e) {
|
||||
if (e.is<VariableReference>()) {
|
||||
const Variable& var(*e.as<VariableReference>().fVariable);
|
||||
if (var.fStorage == Variable::kGlobal_Storage) {
|
||||
return var.fModifiers.fLayout.fBuiltin;
|
||||
if (var.storage() == Variable::kGlobal_Storage) {
|
||||
return var.modifiers().fLayout.fBuiltin;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
@ -423,7 +423,7 @@ int ByteCodeGenerator::StackUsage(ByteCodeInstruction inst, int count_) {
|
||||
ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var) {
|
||||
// given that we seldom have more than a couple of variables, linear search is probably the most
|
||||
// efficient way to handle lookups
|
||||
switch (var.fStorage) {
|
||||
switch (var.storage()) {
|
||||
case Variable::kLocal_Storage: {
|
||||
for (int i = fLocals.size() - 1; i >= 0; --i) {
|
||||
if (fLocals[i] == &var) {
|
||||
@ -486,7 +486,7 @@ ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var)
|
||||
if (e.is<GlobalVarDeclaration>()) {
|
||||
const GlobalVarDeclaration& decl = e.as<GlobalVarDeclaration>();
|
||||
const Variable* declVar = decl.fDecl->fVar;
|
||||
if (declVar->fModifiers.fLayout.fBuiltin >= 0 || is_in(*declVar)) {
|
||||
if (declVar->modifiers().fLayout.fBuiltin >= 0 || is_in(*declVar)) {
|
||||
continue;
|
||||
}
|
||||
if (isUniform != is_uniform(*declVar)) {
|
||||
@ -1265,7 +1265,7 @@ void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
|
||||
for (int i = 0; i < argCount; ++i) {
|
||||
const auto& param = f.function().fParameters[i];
|
||||
const auto& arg = f.arguments()[i];
|
||||
if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
|
||||
if (param->modifiers().fFlags & Modifiers::kOut_Flag) {
|
||||
lvalues.emplace_back(this->getLValue(*arg));
|
||||
lvalues.back()->load();
|
||||
} else {
|
||||
@ -1298,7 +1298,7 @@ void ByteCodeGenerator::writeFunctionCall(const FunctionCall& f) {
|
||||
for (int i = argCount - 1; i >= 0; --i) {
|
||||
const auto& param = f.function().fParameters[i];
|
||||
const auto& arg = f.arguments()[i];
|
||||
if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
|
||||
if (param->modifiers().fFlags & Modifiers::kOut_Flag) {
|
||||
pop();
|
||||
lvalues.back()->store(true);
|
||||
lvalues.pop_back();
|
||||
@ -1834,7 +1834,7 @@ ByteCodeFunction::ByteCodeFunction(const FunctionDeclaration* declaration)
|
||||
fParameterCount = 0;
|
||||
for (const auto& p : declaration->fParameters) {
|
||||
int slots = ByteCodeGenerator::SlotCount(p->type());
|
||||
fParameters.push_back({ slots, (bool)(p->fModifiers.fFlags & Modifiers::kOut_Flag) });
|
||||
fParameters.push_back({ slots, (bool)(p->modifiers().fFlags & Modifiers::kOut_Flag) });
|
||||
fParameterCount += slots;
|
||||
}
|
||||
}
|
||||
|
@ -20,8 +20,8 @@
|
||||
namespace SkSL {
|
||||
|
||||
static bool needs_uniform_var(const Variable& var) {
|
||||
return (var.fModifiers.fFlags & Modifiers::kUniform_Flag) &&
|
||||
var.type().typeKind() != Type::TypeKind::kSampler;
|
||||
return (var.modifiers().fFlags & Modifiers::kUniform_Flag) &&
|
||||
var.type().typeKind() != Type::TypeKind::kSampler;
|
||||
}
|
||||
|
||||
CPPCodeGenerator::CPPCodeGenerator(const Context* context, const Program* program,
|
||||
@ -128,22 +128,24 @@ static String default_value(const Type& type) {
|
||||
}
|
||||
|
||||
static String default_value(const Variable& var) {
|
||||
if (var.fModifiers.fLayout.fCType == SkSL::Layout::CType::kSkPMColor4f) {
|
||||
if (var.modifiers().fLayout.fCType == SkSL::Layout::CType::kSkPMColor4f) {
|
||||
return "{SK_FloatNaN, SK_FloatNaN, SK_FloatNaN, SK_FloatNaN}";
|
||||
}
|
||||
return default_value(var.type());
|
||||
}
|
||||
|
||||
static bool is_private(const Variable& var) {
|
||||
return !(var.fModifiers.fFlags & Modifiers::kUniform_Flag) &&
|
||||
!(var.fModifiers.fFlags & Modifiers::kIn_Flag) &&
|
||||
var.fStorage == Variable::kGlobal_Storage &&
|
||||
var.fModifiers.fLayout.fBuiltin == -1;
|
||||
const Modifiers& modifiers = var.modifiers();
|
||||
return !(modifiers.fFlags & Modifiers::kUniform_Flag) &&
|
||||
!(modifiers.fFlags & Modifiers::kIn_Flag) &&
|
||||
var.storage() == Variable::kGlobal_Storage &&
|
||||
modifiers.fLayout.fBuiltin == -1;
|
||||
}
|
||||
|
||||
static bool is_uniform_in(const Variable& var) {
|
||||
return (var.fModifiers.fFlags & Modifiers::kUniform_Flag) &&
|
||||
(var.fModifiers.fFlags & Modifiers::kIn_Flag) &&
|
||||
const Modifiers& modifiers = var.modifiers();
|
||||
return (modifiers.fFlags & Modifiers::kUniform_Flag) &&
|
||||
(modifiers.fFlags & Modifiers::kIn_Flag) &&
|
||||
var.type().typeKind() != Type::TypeKind::kSampler;
|
||||
}
|
||||
|
||||
@ -260,7 +262,7 @@ void CPPCodeGenerator::writeRuntimeValue(const Type& type, const Layout& layout,
|
||||
|
||||
void CPPCodeGenerator::writeVarInitializer(const Variable& var, const Expression& value) {
|
||||
if (is_private(var)) {
|
||||
this->writeRuntimeValue(var.type(), var.fModifiers.fLayout, var.name());
|
||||
this->writeRuntimeValue(var.type(), var.modifiers().fLayout, var.name());
|
||||
} else {
|
||||
this->writeExpression(value, kTopLevel_Precedence);
|
||||
}
|
||||
@ -312,7 +314,7 @@ void CPPCodeGenerator::writeVariableReference(const VariableReference& ref) {
|
||||
this->write(ref.fVariable->name());
|
||||
return;
|
||||
}
|
||||
switch (ref.fVariable->fModifiers.fLayout.fBuiltin) {
|
||||
switch (ref.fVariable->modifiers().fLayout.fBuiltin) {
|
||||
case SK_OUTCOLOR_BUILTIN:
|
||||
this->write("%s");
|
||||
fFormatArgs.push_back(String("args.fOutputColor"));
|
||||
@ -336,13 +338,13 @@ void CPPCodeGenerator::writeVariableReference(const VariableReference& ref) {
|
||||
this->getSamplerHandle(*ref.fVariable) + ")");
|
||||
return;
|
||||
}
|
||||
if (ref.fVariable->fModifiers.fFlags & Modifiers::kUniform_Flag) {
|
||||
if (ref.fVariable->modifiers().fFlags & Modifiers::kUniform_Flag) {
|
||||
this->write("%s");
|
||||
String name = ref.fVariable->name();
|
||||
String var = String::printf("args.fUniformHandler->getUniformCStr(%sVar)",
|
||||
HCodeGenerator::FieldName(name.c_str()).c_str());
|
||||
String code;
|
||||
if (ref.fVariable->fModifiers.fLayout.fWhen.fLength) {
|
||||
if (ref.fVariable->modifiers().fLayout.fWhen.fLength) {
|
||||
code = String::printf("%sVar.isValid() ? %s : \"%s\"",
|
||||
HCodeGenerator::FieldName(name.c_str()).c_str(),
|
||||
var.c_str(),
|
||||
@ -353,7 +355,7 @@ void CPPCodeGenerator::writeVariableReference(const VariableReference& ref) {
|
||||
fFormatArgs.push_back(code);
|
||||
} else if (SectionAndParameterHelper::IsParameter(*ref.fVariable)) {
|
||||
String name(ref.fVariable->name());
|
||||
this->writeRuntimeValue(ref.fVariable->type(), ref.fVariable->fModifiers.fLayout,
|
||||
this->writeRuntimeValue(ref.fVariable->type(), ref.fVariable->modifiers().fLayout,
|
||||
String::printf("_outer.%s", name.c_str()).c_str());
|
||||
} else {
|
||||
this->write(ref.fVariable->name());
|
||||
@ -657,8 +659,8 @@ void CPPCodeGenerator::writeProgramElement(const ProgramElement& p) {
|
||||
case ProgramElement::Kind::kGlobalVar: {
|
||||
const GlobalVarDeclaration& decl = p.as<GlobalVarDeclaration>();
|
||||
const Variable& var = *decl.fDecl->fVar;
|
||||
if (var.fModifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kUniform_Flag) ||
|
||||
-1 != var.fModifiers.fLayout.fBuiltin) {
|
||||
if (var.modifiers().fFlags & (Modifiers::kIn_Flag | Modifiers::kUniform_Flag) ||
|
||||
-1 != var.modifiers().fLayout.fBuiltin) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@ -673,8 +675,8 @@ void CPPCodeGenerator::addUniform(const Variable& var) {
|
||||
if (!needs_uniform_var(var)) {
|
||||
return;
|
||||
}
|
||||
if (var.fModifiers.fLayout.fWhen.fLength) {
|
||||
this->writef(" if (%s) {\n ", String(var.fModifiers.fLayout.fWhen).c_str());
|
||||
if (var.modifiers().fLayout.fWhen.fLength) {
|
||||
this->writef(" if (%s) {\n ", String(var.modifiers().fLayout.fWhen).c_str());
|
||||
}
|
||||
String name(var.name());
|
||||
if (var.type().typeKind() != Type::TypeKind::kArray) {
|
||||
@ -691,7 +693,7 @@ void CPPCodeGenerator::addUniform(const Variable& var) {
|
||||
name.c_str(),
|
||||
var.type().columns());
|
||||
}
|
||||
if (var.fModifiers.fLayout.fWhen.fLength) {
|
||||
if (var.modifiers().fLayout.fWhen.fLength) {
|
||||
this->write(" }\n");
|
||||
}
|
||||
}
|
||||
@ -711,11 +713,11 @@ void CPPCodeGenerator::writePrivateVars() {
|
||||
}
|
||||
this->writef("%s %s = %s;\n",
|
||||
HCodeGenerator::FieldType(fContext, decl.fVar->type(),
|
||||
decl.fVar->fModifiers.fLayout)
|
||||
decl.fVar->modifiers().fLayout)
|
||||
.c_str(),
|
||||
String(decl.fVar->name()).c_str(),
|
||||
default_value(*decl.fVar).c_str());
|
||||
} else if (decl.fVar->fModifiers.fLayout.fFlags & Layout::kTracked_Flag) {
|
||||
} else if (decl.fVar->modifiers().fLayout.fFlags & Layout::kTracked_Flag) {
|
||||
// An auto-tracked uniform in variable, so add a field to hold onto the prior
|
||||
// state. Note that tracked variables must be uniform in's and that is validated
|
||||
// before writePrivateVars() is called.
|
||||
@ -1010,8 +1012,8 @@ void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) {
|
||||
const char* name = nameString.c_str();
|
||||
|
||||
// Switches for setData behavior in the generated code
|
||||
bool conditionalUniform = u->fModifiers.fLayout.fWhen != "";
|
||||
bool isTracked = u->fModifiers.fLayout.fFlags & Layout::kTracked_Flag;
|
||||
bool conditionalUniform = u->modifiers().fLayout.fWhen != "";
|
||||
bool isTracked = u->modifiers().fLayout.fFlags & Layout::kTracked_Flag;
|
||||
bool needsValueDeclaration = isTracked || !mapper->canInlineUniformValue();
|
||||
|
||||
String uniformName = HCodeGenerator::FieldName(name) + "Var";
|
||||
@ -1029,7 +1031,7 @@ void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) {
|
||||
valueVar.appendf("%sValue", name);
|
||||
// Use AccessType since that will match the return type of _outer's public API.
|
||||
String valueType = HCodeGenerator::AccessType(fContext, u->type(),
|
||||
u->fModifiers.fLayout);
|
||||
u->modifiers().fLayout);
|
||||
this->writef("%s%s %s = _outer.%s;\n",
|
||||
indent.c_str(), valueType.c_str(), valueVar.c_str(), name);
|
||||
} else {
|
||||
@ -1189,7 +1191,7 @@ void CPPCodeGenerator::writeDumpInfo() {
|
||||
// Add this field onto the format string and argument list.
|
||||
String fieldName = HCodeGenerator::FieldName(String(param->name()).c_str());
|
||||
String runtimeValue = this->formatRuntimeValue(param->type(),
|
||||
param->fModifiers.fLayout,
|
||||
param->modifiers().fLayout,
|
||||
param->name(),
|
||||
&argumentList);
|
||||
formatString.appendf("%s%s=%s",
|
||||
@ -1245,16 +1247,16 @@ void CPPCodeGenerator::writeGetKey() {
|
||||
const Type& varType = var.type();
|
||||
String nameString(var.name());
|
||||
const char* name = nameString.c_str();
|
||||
if (var.fModifiers.fLayout.fKey != Layout::kNo_Key &&
|
||||
(var.fModifiers.fFlags & Modifiers::kUniform_Flag)) {
|
||||
if (var.modifiers().fLayout.fKey != Layout::kNo_Key &&
|
||||
(var.modifiers().fFlags & Modifiers::kUniform_Flag)) {
|
||||
fErrors.error(var.fOffset, "layout(key) may not be specified on uniforms");
|
||||
}
|
||||
switch (var.fModifiers.fLayout.fKey) {
|
||||
switch (var.modifiers().fLayout.fKey) {
|
||||
case Layout::kKey_Key:
|
||||
if (is_private(var)) {
|
||||
this->writef("%s %s =",
|
||||
HCodeGenerator::FieldType(fContext, varType,
|
||||
var.fModifiers.fLayout).c_str(),
|
||||
var.modifiers().fLayout).c_str(),
|
||||
String(var.name()).c_str());
|
||||
if (decl.fValue) {
|
||||
fCPPMode = true;
|
||||
@ -1265,8 +1267,8 @@ void CPPCodeGenerator::writeGetKey() {
|
||||
}
|
||||
this->write(";\n");
|
||||
}
|
||||
if (var.fModifiers.fLayout.fWhen.fLength) {
|
||||
this->writef("if (%s) {", String(var.fModifiers.fLayout.fWhen).c_str());
|
||||
if (var.modifiers().fLayout.fWhen.fLength) {
|
||||
this->writef("if (%s) {", String(var.modifiers().fLayout.fWhen).c_str());
|
||||
}
|
||||
if (varType == *fContext.fHalf4_Type) {
|
||||
this->writef(" uint16_t red = SkFloatToHalf(%s.fR);\n",
|
||||
@ -1291,7 +1293,7 @@ void CPPCodeGenerator::writeGetKey() {
|
||||
ABORT("NOT YET IMPLEMENTED: automatic key handling for %s\n",
|
||||
varType.displayName().c_str());
|
||||
}
|
||||
if (var.fModifiers.fLayout.fWhen.fLength) {
|
||||
if (var.modifiers().fLayout.fWhen.fLength) {
|
||||
this->write("}");
|
||||
}
|
||||
break;
|
||||
@ -1315,7 +1317,7 @@ bool CPPCodeGenerator::generateCode() {
|
||||
for (const auto& p : fProgram) {
|
||||
if (p.is<GlobalVarDeclaration>()) {
|
||||
const VarDeclaration& decl = *p.as<GlobalVarDeclaration>().fDecl;
|
||||
if ((decl.fVar->fModifiers.fFlags & Modifiers::kUniform_Flag) &&
|
||||
if ((decl.fVar->modifiers().fFlags & Modifiers::kUniform_Flag) &&
|
||||
decl.fVar->type().typeKind() != Type::TypeKind::kSampler) {
|
||||
uniforms.push_back(decl.fVar);
|
||||
}
|
||||
@ -1330,7 +1332,7 @@ bool CPPCodeGenerator::generateCode() {
|
||||
+ "'s type is not supported for use as a 'uniform in'");
|
||||
return false;
|
||||
}
|
||||
if (decl.fVar->fModifiers.fLayout.fFlags & Layout::kTracked_Flag) {
|
||||
if (decl.fVar->modifiers().fLayout.fFlags & Layout::kTracked_Flag) {
|
||||
if (!mapper->supportsTracking()) {
|
||||
fErrors.error(decl.fOffset, String(decl.fVar->name())
|
||||
+ "'s type does not support state tracking");
|
||||
@ -1340,7 +1342,7 @@ bool CPPCodeGenerator::generateCode() {
|
||||
|
||||
} else {
|
||||
// If it's not a uniform_in, it's an error to be tracked
|
||||
if (decl.fVar->fModifiers.fLayout.fFlags & Layout::kTracked_Flag) {
|
||||
if (decl.fVar->modifiers().fLayout.fFlags & Layout::kTracked_Flag) {
|
||||
fErrors.error(decl.fOffset, "Non-'in uniforms' cannot be tracked");
|
||||
return false;
|
||||
}
|
||||
@ -1369,7 +1371,7 @@ bool CPPCodeGenerator::generateCode() {
|
||||
this->writeSetData(uniforms);
|
||||
this->writePrivateVars();
|
||||
for (const auto& u : uniforms) {
|
||||
if (needs_uniform_var(*u) && !(u->fModifiers.fFlags & Modifiers::kIn_Flag)) {
|
||||
if (needs_uniform_var(*u) && !(u->modifiers().fFlags & Modifiers::kIn_Flag)) {
|
||||
this->writef(" UniformHandle %sVar;\n",
|
||||
HCodeGenerator::FieldName(String(u->name()).c_str()).c_str());
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ public:
|
||||
const Layout& layout);
|
||||
|
||||
static const UniformCTypeMapper* Get(const Context& context, const Variable& variable) {
|
||||
return Get(context, variable.type(), variable.fModifiers.fLayout);
|
||||
return Get(context, variable.type(), variable.modifiers().fLayout);
|
||||
}
|
||||
|
||||
// The C++ type name that this mapper applies to
|
||||
|
@ -250,8 +250,9 @@ Compiler::Compiler(Flags flags)
|
||||
// treat it as builtin (ie, no need to clone it into the Program).
|
||||
StringFragment skCapsName("sk_Caps");
|
||||
fRootSymbolTable->add(skCapsName,
|
||||
std::make_unique<Variable>(/*offset=*/-1, Modifiers(), skCapsName,
|
||||
fContext->fSkCaps_Type.get(),
|
||||
std::make_unique<Variable>(/*offset=*/-1,
|
||||
fIRGenerator->fModifiers->handle(Modifiers()),
|
||||
skCapsName, fContext->fSkCaps_Type.get(),
|
||||
/*builtin=*/false, Variable::kGlobal_Storage));
|
||||
|
||||
fIRGenerator->fIntrinsics = nullptr;
|
||||
@ -266,22 +267,28 @@ Compiler::Compiler(Flags flags)
|
||||
&fragElements, &fFragmentSymbolTable);
|
||||
#else
|
||||
{
|
||||
Rehydrator rehydrator(fContext.get(), fRootSymbolTable, this, SKSL_INCLUDE_sksl_gpu,
|
||||
Rehydrator rehydrator(&fIRGenerator->fContext, fIRGenerator->fModifiers.get(),
|
||||
fRootSymbolTable, this, SKSL_INCLUDE_sksl_gpu,
|
||||
SKSL_INCLUDE_sksl_gpu_LENGTH);
|
||||
fGpuSymbolTable = rehydrator.symbolTable();
|
||||
gpuElements = rehydrator.elements();
|
||||
fModifiers.push_back(fIRGenerator->releaseModifiers());
|
||||
}
|
||||
{
|
||||
Rehydrator rehydrator(fContext.get(), fGpuSymbolTable, this, SKSL_INCLUDE_sksl_vert,
|
||||
Rehydrator rehydrator(&fIRGenerator->fContext, fIRGenerator->fModifiers.get(),
|
||||
fGpuSymbolTable, this, SKSL_INCLUDE_sksl_vert,
|
||||
SKSL_INCLUDE_sksl_vert_LENGTH);
|
||||
fVertexSymbolTable = rehydrator.symbolTable();
|
||||
fVertexInclude = rehydrator.elements();
|
||||
fModifiers.push_back(fIRGenerator->releaseModifiers());
|
||||
}
|
||||
{
|
||||
Rehydrator rehydrator(fContext.get(), fGpuSymbolTable, this, SKSL_INCLUDE_sksl_frag,
|
||||
Rehydrator rehydrator(&fIRGenerator->fContext, fIRGenerator->fModifiers.get(),
|
||||
fGpuSymbolTable, this, SKSL_INCLUDE_sksl_frag,
|
||||
SKSL_INCLUDE_sksl_frag_LENGTH);
|
||||
fFragmentSymbolTable = rehydrator.symbolTable();
|
||||
fragElements = rehydrator.elements();
|
||||
fModifiers.push_back(fIRGenerator->releaseModifiers());
|
||||
}
|
||||
#endif
|
||||
// Call counts are used to track dead-stripping and inlinability within the program being
|
||||
@ -308,10 +315,12 @@ void Compiler::loadGeometryIntrinsics() {
|
||||
}
|
||||
#if !SKSL_STANDALONE
|
||||
{
|
||||
Rehydrator rehydrator(fContext.get(), fGpuSymbolTable, this, SKSL_INCLUDE_sksl_geom,
|
||||
SKSL_INCLUDE_sksl_geom_LENGTH);
|
||||
Rehydrator rehydrator(&fIRGenerator->fContext, fIRGenerator->fModifiers.get(),
|
||||
fGpuSymbolTable, this, SKSL_INCLUDE_sksl_geom,
|
||||
SKSL_INCLUDE_sksl_geom_LENGTH);
|
||||
fGeometrySymbolTable = rehydrator.symbolTable();
|
||||
fGeometryInclude = rehydrator.elements();
|
||||
fModifiers.push_back(fIRGenerator->releaseModifiers());
|
||||
}
|
||||
#else
|
||||
this->processIncludeFile(Program::kGeometry_Kind, SKSL_GEOM_INCLUDE, fGpuSymbolTable,
|
||||
@ -327,7 +336,8 @@ void Compiler::loadFPIntrinsics() {
|
||||
std::vector<std::unique_ptr<ProgramElement>> fpElements;
|
||||
#if !SKSL_STANDALONE
|
||||
{
|
||||
Rehydrator rehydrator(fContext.get(), fGpuSymbolTable, this, SKSL_INCLUDE_sksl_fp,
|
||||
Rehydrator rehydrator(&fIRGenerator->fContext, fIRGenerator->fModifiers.get(),
|
||||
fGpuSymbolTable, this, SKSL_INCLUDE_sksl_fp,
|
||||
SKSL_INCLUDE_sksl_fp_LENGTH);
|
||||
fFPSymbolTable = rehydrator.symbolTable();
|
||||
fpElements = rehydrator.elements();
|
||||
@ -347,11 +357,12 @@ void Compiler::loadPipelineIntrinsics() {
|
||||
std::vector<std::unique_ptr<ProgramElement>> pipelineIntrinics;
|
||||
#if !SKSL_STANDALONE
|
||||
{
|
||||
Rehydrator rehydrator(fContext.get(), fGpuSymbolTable, this,
|
||||
SKSL_INCLUDE_sksl_pipeline,
|
||||
Rehydrator rehydrator(&fIRGenerator->fContext, fIRGenerator->fModifiers.get(),
|
||||
fGpuSymbolTable, this, SKSL_INCLUDE_sksl_pipeline,
|
||||
SKSL_INCLUDE_sksl_pipeline_LENGTH);
|
||||
fPipelineSymbolTable = rehydrator.symbolTable();
|
||||
pipelineIntrinics = rehydrator.elements();
|
||||
fModifiers.push_back(fIRGenerator->releaseModifiers());
|
||||
}
|
||||
#else
|
||||
this->processIncludeFile(Program::kPipelineStage_Kind, SKSL_PIPELINE_INCLUDE,
|
||||
@ -368,11 +379,12 @@ void Compiler::loadInterpreterIntrinsics() {
|
||||
std::vector<std::unique_ptr<ProgramElement>> interpElements;
|
||||
#if !SKSL_STANDALONE
|
||||
{
|
||||
Rehydrator rehydrator(fContext.get(), fRootSymbolTable, this,
|
||||
SKSL_INCLUDE_sksl_interp,
|
||||
Rehydrator rehydrator(&fIRGenerator->fContext, fIRGenerator->fModifiers.get(),
|
||||
fRootSymbolTable, this, SKSL_INCLUDE_sksl_interp,
|
||||
SKSL_INCLUDE_sksl_interp_LENGTH);
|
||||
fInterpreterSymbolTable = rehydrator.symbolTable();
|
||||
interpElements = rehydrator.elements();
|
||||
fModifiers.push_back(fIRGenerator->releaseModifiers());
|
||||
}
|
||||
#else
|
||||
this->processIncludeFile(Program::kGeneric_Kind, SKSL_INTERP_INCLUDE,
|
||||
@ -414,6 +426,7 @@ void Compiler::processIncludeFile(Program::Kind kind, const char* path,
|
||||
#ifdef SK_DEBUG
|
||||
fSource = nullptr;
|
||||
#endif
|
||||
fModifiers.push_back(fIRGenerator->releaseModifiers());
|
||||
fIRGenerator->finish();
|
||||
}
|
||||
|
||||
@ -423,7 +436,7 @@ void Compiler::addDefinition(const Expression* lvalue, std::unique_ptr<Expressio
|
||||
switch (lvalue->kind()) {
|
||||
case Expression::Kind::kVariableReference: {
|
||||
const Variable& var = *lvalue->as<VariableReference>().fVariable;
|
||||
if (var.fStorage == Variable::kLocal_Storage) {
|
||||
if (var.storage() == Variable::kLocal_Storage) {
|
||||
(*definitions)[&var] = expr;
|
||||
}
|
||||
break;
|
||||
@ -492,7 +505,7 @@ void Compiler::addDefinitions(const BasicBlock::Node& node,
|
||||
case Expression::Kind::kFunctionCall: {
|
||||
const FunctionCall& c = expr->as<FunctionCall>();
|
||||
for (size_t i = 0; i < c.function().fParameters.size(); ++i) {
|
||||
if (c.function().fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag) {
|
||||
if (c.function().fParameters[i]->modifiers().fFlags & Modifiers::kOut_Flag) {
|
||||
this->addDefinition(
|
||||
c.arguments()[i].get(),
|
||||
(std::unique_ptr<Expression>*) &fContext->fDefined_Expression,
|
||||
@ -905,7 +918,7 @@ void Compiler::simplifyExpression(DefinitionMap& definitions,
|
||||
const Variable* var = ref.fVariable;
|
||||
if (ref.refKind() != VariableReference::kWrite_RefKind &&
|
||||
ref.refKind() != VariableReference::kPointer_RefKind &&
|
||||
var->fStorage == Variable::kLocal_Storage && !definitions[var] &&
|
||||
var->storage() == Variable::kLocal_Storage && !definitions[var] &&
|
||||
(*undefinedVariables).find(var) == (*undefinedVariables).end()) {
|
||||
(*undefinedVariables).insert(var);
|
||||
this->error(expr->fOffset,
|
||||
@ -1572,7 +1585,7 @@ std::unique_ptr<Program> Compiler::convertProgram(
|
||||
|
||||
fErrorText = "";
|
||||
fErrorCount = 0;
|
||||
fInliner.reset(context(), settings);
|
||||
fInliner.reset(&fIRGenerator->fContext, fIRGenerator->fModifiers.get(), &settings);
|
||||
std::vector<std::unique_ptr<ProgramElement>>* inherited;
|
||||
std::vector<std::unique_ptr<ProgramElement>> elements;
|
||||
switch (kind) {
|
||||
@ -1627,6 +1640,7 @@ std::unique_ptr<Program> Compiler::convertProgram(
|
||||
fContext,
|
||||
inherited,
|
||||
std::move(elements),
|
||||
fIRGenerator->releaseModifiers(),
|
||||
fIRGenerator->fSymbolTable,
|
||||
fIRGenerator->fInputs);
|
||||
fIRGenerator->finish();
|
||||
@ -1696,6 +1710,7 @@ bool Compiler::optimize(Program& program) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
program.finish();
|
||||
return fErrorCount == 0;
|
||||
}
|
||||
|
||||
@ -1705,7 +1720,8 @@ bool Compiler::toSPIRV(Program& program, OutputStream& out) {
|
||||
#ifdef SK_ENABLE_SPIRV_VALIDATION
|
||||
StringStream buffer;
|
||||
fSource = program.fSource.get();
|
||||
SPIRVCodeGenerator cg(fContext.get(), &program, this, &buffer);
|
||||
SPIRVCodeGenerator cg(&fIRGenerator->fContext, fIRGenerator->fModifiers.get(), &program, this,
|
||||
&buffer);
|
||||
bool result = cg.generateCode();
|
||||
fSource = nullptr;
|
||||
if (result) {
|
||||
@ -1723,7 +1739,8 @@ bool Compiler::toSPIRV(Program& program, OutputStream& out) {
|
||||
}
|
||||
#else
|
||||
fSource = program.fSource.get();
|
||||
SPIRVCodeGenerator cg(fContext.get(), &program, this, &out);
|
||||
SPIRVCodeGenerator cg(&fIRGenerator->fContext, fIRGenerator->fModifiers.get(), &program, this,
|
||||
&out);
|
||||
bool result = cg.generateCode();
|
||||
fSource = nullptr;
|
||||
#endif
|
||||
|
@ -252,6 +252,9 @@ private:
|
||||
std::shared_ptr<SymbolTable> fFPSymbolTable;
|
||||
std::unique_ptr<IRIntrinsicMap> fFPIntrinsics;
|
||||
|
||||
// holds ModifiersPools belonging to the core includes for lifetime purposes
|
||||
std::vector<std::unique_ptr<ModifiersPool>> fModifiers;
|
||||
|
||||
Inliner fInliner;
|
||||
std::unique_ptr<IRGenerator> fIRGenerator;
|
||||
int fFlags;
|
||||
|
@ -216,10 +216,10 @@ void Dehydrator::write(const Symbol& s) {
|
||||
const Variable& v = s.as<Variable>();
|
||||
this->writeU8(Rehydrator::kVariable_Command);
|
||||
this->writeId(&v);
|
||||
this->write(v.fModifiers);
|
||||
this->write(v.modifiers());
|
||||
this->write(v.name());
|
||||
this->write(v.type());
|
||||
this->writeU8(v.fStorage);
|
||||
this->writeU8(v.storage());
|
||||
break;
|
||||
}
|
||||
case Symbol::Kind::kField: {
|
||||
@ -519,8 +519,8 @@ void Dehydrator::write(const ProgramElement& e) {
|
||||
for (const std::unique_ptr<const Symbol>& s : en.symbols()->fOwnedSymbols) {
|
||||
SkASSERT(s->kind() == Symbol::Kind::kVariable);
|
||||
Variable& v = (Variable&) *s;
|
||||
SkASSERT(v.fInitialValue);
|
||||
const IntLiteral& i = v.fInitialValue->as<IntLiteral>();
|
||||
SkASSERT(v.initialValue());
|
||||
const IntLiteral& i = v.initialValue()->as<IntLiteral>();
|
||||
this->writeS32(i.value());
|
||||
}
|
||||
break;
|
||||
|
@ -785,7 +785,7 @@ void GLSLCodeGenerator::writeFragCoord() {
|
||||
}
|
||||
|
||||
void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) {
|
||||
switch (ref.fVariable->fModifiers.fLayout.fBuiltin) {
|
||||
switch (ref.fVariable->modifiers().fLayout.fBuiltin) {
|
||||
case SK_FRAGCOLOR_BUILTIN:
|
||||
if (fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) {
|
||||
this->write("sk_FragColor");
|
||||
@ -1050,7 +1050,7 @@ void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) {
|
||||
for (const auto& param : f.fDeclaration.fParameters) {
|
||||
this->write(separator);
|
||||
separator = ", ";
|
||||
this->writeModifiers(param->fModifiers, false);
|
||||
this->writeModifiers(param->modifiers(), false);
|
||||
std::vector<int> sizes;
|
||||
const Type* type = ¶m->type();
|
||||
while (type->typeKind() == Type::TypeKind::kArray) {
|
||||
@ -1177,7 +1177,7 @@ void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
|
||||
if (intf.fTypeName == "sk_PerVertex") {
|
||||
return;
|
||||
}
|
||||
this->writeModifiers(intf.fVariable.fModifiers, true);
|
||||
this->writeModifiers(intf.fVariable.modifiers(), true);
|
||||
this->writeLine(intf.fTypeName + " {");
|
||||
fIndentation++;
|
||||
const Type* structType = &intf.fVariable.type();
|
||||
@ -1245,7 +1245,7 @@ void GLSLCodeGenerator::writeTypePrecision(const Type& type) {
|
||||
}
|
||||
|
||||
void GLSLCodeGenerator::writeVarDeclaration(const VarDeclaration& var, bool global) {
|
||||
this->writeModifiers(var.fVar->fModifiers, global);
|
||||
this->writeModifiers(var.fVar->modifiers(), global);
|
||||
this->writeTypePrecision(var.fBaseType);
|
||||
this->writeType(var.fBaseType);
|
||||
this->write(" ");
|
||||
@ -1487,14 +1487,14 @@ void GLSLCodeGenerator::writeProgramElement(const ProgramElement& e) {
|
||||
break;
|
||||
case ProgramElement::Kind::kGlobalVar: {
|
||||
const VarDeclaration& decl = *e.as<GlobalVarDeclaration>().fDecl;
|
||||
int builtin = decl.fVar->fModifiers.fLayout.fBuiltin;
|
||||
int builtin = decl.fVar->modifiers().fLayout.fBuiltin;
|
||||
if (builtin == -1) {
|
||||
// normal var
|
||||
this->writeVarDeclaration(decl, true);
|
||||
this->writeLine();
|
||||
} else if (builtin == SK_FRAGCOLOR_BUILTIN &&
|
||||
fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput() &&
|
||||
decl.fVar->fWriteCount) {
|
||||
decl.fVar->writeCount()) {
|
||||
if (fProgram.fSettings.fFragColorIsInOut) {
|
||||
this->write("inout ");
|
||||
} else {
|
||||
|
@ -190,7 +190,7 @@ void HCodeGenerator::writeMake() {
|
||||
separator = "";
|
||||
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
|
||||
this->writef("%s%s %s", separator, ParameterType(fContext, param->type(),
|
||||
param->fModifiers.fLayout).c_str(),
|
||||
param->modifiers().fLayout).c_str(),
|
||||
String(param->name()).c_str());
|
||||
separator = ", ";
|
||||
}
|
||||
@ -234,7 +234,7 @@ void HCodeGenerator::writeConstructor() {
|
||||
const char* separator = "";
|
||||
for (const auto& param : fSectionAndParameterHelper.getParameters()) {
|
||||
this->writef("%s%s %s", separator, ParameterType(fContext, param->type(),
|
||||
param->fModifiers.fLayout).c_str(),
|
||||
param->modifiers().fLayout).c_str(),
|
||||
String(param->name()).c_str());
|
||||
separator = ", ";
|
||||
}
|
||||
@ -287,7 +287,7 @@ void HCodeGenerator::writeConstructor() {
|
||||
std::string perspExpression;
|
||||
if (usage.hasUniformMatrix()) {
|
||||
for (const Variable* p : fSectionAndParameterHelper.getParameters()) {
|
||||
if ((p->fModifiers.fFlags & Modifiers::kIn_Flag) &&
|
||||
if ((p->modifiers().fFlags & Modifiers::kIn_Flag) &&
|
||||
usage.fExpression == String(p->name())) {
|
||||
perspExpression = usage.fExpression + ".hasPerspective()";
|
||||
break;
|
||||
@ -315,7 +315,7 @@ void HCodeGenerator::writeFields() {
|
||||
// Don't need to write any fields, FPs are held as children
|
||||
} else {
|
||||
this->writef(" %s %s;\n", FieldType(fContext, param->type(),
|
||||
param->fModifiers.fLayout).c_str(),
|
||||
param->modifiers().fLayout).c_str(),
|
||||
name.c_str());
|
||||
}
|
||||
}
|
||||
|
@ -127,7 +127,8 @@ IRGenerator::IRGenerator(const Context* context, Inliner* inliner,
|
||||
, fSymbolTable(symbolTable)
|
||||
, fLoopLevel(0)
|
||||
, fSwitchLevel(0)
|
||||
, fErrors(errorReporter) {
|
||||
, fErrors(errorReporter)
|
||||
, fModifiers(new ModifiersPool()) {
|
||||
SkASSERT(fInliner);
|
||||
}
|
||||
|
||||
@ -211,6 +212,14 @@ std::unique_ptr<Extension> IRGenerator::convertExtension(int offset, StringFragm
|
||||
void IRGenerator::finish() {
|
||||
this->popSymbolTable();
|
||||
fSettings = nullptr;
|
||||
// releaseModifiers should have been called before now
|
||||
SkASSERT(fModifiers->empty());
|
||||
}
|
||||
|
||||
std::unique_ptr<ModifiersPool> IRGenerator::releaseModifiers() {
|
||||
std::unique_ptr<ModifiersPool> result = std::move(fModifiers);
|
||||
fModifiers = std::make_unique<ModifiersPool>();
|
||||
return result;
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement> IRGenerator::convertSingleStatement(const ASTNode& statement) {
|
||||
@ -444,8 +453,8 @@ std::vector<std::unique_ptr<Statement>> IRGenerator::convertVarDeclarations(
|
||||
sizes.push_back(nullptr);
|
||||
}
|
||||
}
|
||||
auto var = std::make_unique<Variable>(varDecl.fOffset, modifiers, varData.fName, type,
|
||||
fIsBuiltinCode, storage);
|
||||
auto var = std::make_unique<Variable>(varDecl.fOffset, fModifiers->handle(modifiers),
|
||||
varData.fName, type, fIsBuiltinCode, storage);
|
||||
if (var->name() == Compiler::RTADJUST_NAME) {
|
||||
SkASSERT(!fRTAdjust);
|
||||
SkASSERT(var->type() == *fContext.fFloat4_Type);
|
||||
@ -461,17 +470,16 @@ std::vector<std::unique_ptr<Statement>> IRGenerator::convertVarDeclarations(
|
||||
if (!value) {
|
||||
return {};
|
||||
}
|
||||
var->fWriteCount = 1;
|
||||
var->fInitialValue = value.get();
|
||||
var->setInitialValue(value.get());
|
||||
}
|
||||
const Symbol* symbol = (*fSymbolTable)[var->name()];
|
||||
Symbol* symbol = (*fSymbolTable)[var->name()];
|
||||
if (symbol && storage == Variable::kGlobal_Storage && var->name() == "sk_FragColor") {
|
||||
// Already defined, ignore.
|
||||
} else if (symbol && storage == Variable::kGlobal_Storage &&
|
||||
symbol->kind() == Symbol::Kind::kVariable &&
|
||||
symbol->as<Variable>().fModifiers.fLayout.fBuiltin >= 0) {
|
||||
symbol->as<Variable>().modifiers().fLayout.fBuiltin >= 0) {
|
||||
// Already defined, just update the modifiers.
|
||||
symbol->as<Variable>().fModifiers = var->fModifiers;
|
||||
symbol->as<Variable>().setModifiersHandle(var->modifiersHandle());
|
||||
} else {
|
||||
varDecls.emplace_back(std::make_unique<VarDeclaration>(
|
||||
var.get(), baseType, std::move(sizes), std::move(value)));
|
||||
@ -500,9 +508,11 @@ std::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration(c
|
||||
fInvocations = modifiers.fLayout.fInvocations;
|
||||
if (fSettings->fCaps && !fSettings->fCaps->gsInvocationsSupport()) {
|
||||
modifiers.fLayout.fInvocations = -1;
|
||||
const Variable& invocationId = (*fSymbolTable)["sk_InvocationID"]->as<Variable>();
|
||||
invocationId.fModifiers.fFlags = 0;
|
||||
invocationId.fModifiers.fLayout.fBuiltin = -1;
|
||||
Variable& invocationId = (*fSymbolTable)["sk_InvocationID"]->as<Variable>();
|
||||
Modifiers modifiers = invocationId.modifiers();
|
||||
modifiers.fFlags = 0;
|
||||
modifiers.fLayout.fBuiltin = -1;
|
||||
invocationId.setModifiersHandle(fModifiers->handle(modifiers));
|
||||
if (modifiers.fLayout.description() == "") {
|
||||
return nullptr;
|
||||
}
|
||||
@ -768,7 +778,7 @@ std::unique_ptr<Block> IRGenerator::applyInvocationIDWorkaround(std::unique_ptr<
|
||||
"_invoke", std::make_unique<FunctionDeclaration>(/*offset=*/-1,
|
||||
invokeModifiers,
|
||||
"_invoke",
|
||||
std::vector<const Variable*>(),
|
||||
std::vector<Variable*>(),
|
||||
*fContext.fVoid_Type,
|
||||
/*builtin=*/false));
|
||||
fProgramElements->push_back(std::make_unique<FunctionDefinition>(/*offset=*/-1,
|
||||
@ -930,7 +940,7 @@ void IRGenerator::convertFunction(const ASTNode& f) {
|
||||
const ASTNode::FunctionData& funcData = f.getFunctionData();
|
||||
this->checkModifiers(f.fOffset, funcData.fModifiers, Modifiers::kHasSideEffects_Flag |
|
||||
Modifiers::kInline_Flag);
|
||||
std::vector<const Variable*> parameters;
|
||||
std::vector<Variable*> parameters;
|
||||
for (size_t i = 0; i < funcData.fParameterCount; ++i) {
|
||||
const ASTNode& param = *(iter++);
|
||||
SkASSERT(param.fKind == ASTNode::Kind::kParameter);
|
||||
@ -956,15 +966,16 @@ void IRGenerator::convertFunction(const ASTNode& f) {
|
||||
return;
|
||||
}
|
||||
StringFragment name = pd.fName;
|
||||
const Variable* var = fSymbolTable->takeOwnershipOfSymbol(
|
||||
std::make_unique<Variable>(param.fOffset, pd.fModifiers, name, type,
|
||||
fIsBuiltinCode, Variable::kParameter_Storage));
|
||||
Variable* var = fSymbolTable->takeOwnershipOfSymbol(
|
||||
std::make_unique<Variable>(param.fOffset, fModifiers->handle(pd.fModifiers),
|
||||
name, type, fIsBuiltinCode,
|
||||
Variable::kParameter_Storage));
|
||||
parameters.push_back(var);
|
||||
}
|
||||
|
||||
auto paramIsCoords = [&](int idx) {
|
||||
return parameters[idx]->type() == *fContext.fFloat2_Type &&
|
||||
parameters[idx]->fModifiers.fFlags == 0;
|
||||
parameters[idx]->modifiers().fFlags == 0;
|
||||
};
|
||||
|
||||
if (funcData.fName == "main") {
|
||||
@ -1036,7 +1047,7 @@ void IRGenerator::convertFunction(const ASTNode& f) {
|
||||
}
|
||||
decl = other;
|
||||
for (size_t i = 0; i < parameters.size(); i++) {
|
||||
if (parameters[i]->fModifiers != other->fParameters[i]->fModifiers) {
|
||||
if (parameters[i]->modifiers() != other->fParameters[i]->modifiers()) {
|
||||
fErrors.error(f.fOffset, "modifiers on parameter " +
|
||||
to_string((uint64_t) i + 1) +
|
||||
" differ between declaration and definition");
|
||||
@ -1077,7 +1088,9 @@ void IRGenerator::convertFunction(const ASTNode& f) {
|
||||
fKind == Program::kFragmentProcessor_Kind)) {
|
||||
if (parameters.size() == 1) {
|
||||
SkASSERT(paramIsCoords(0));
|
||||
parameters[0]->fModifiers.fLayout.fBuiltin = SK_MAIN_COORDS_BUILTIN;
|
||||
Modifiers m = parameters[0]->modifiers();
|
||||
m.fLayout.fBuiltin = SK_MAIN_COORDS_BUILTIN;
|
||||
parameters[0]->setModifiersHandle(fModifiers->handle(m));
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < parameters.size(); i++) {
|
||||
@ -1140,7 +1153,7 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTNode
|
||||
SkASSERT(vd.fVar->type() == *fContext.fFloat4_Type);
|
||||
fRTAdjustFieldIndex = fields.size();
|
||||
}
|
||||
fields.push_back(Type::Field(vd.fVar->fModifiers, vd.fVar->name(),
|
||||
fields.push_back(Type::Field(vd.fVar->modifiers(), vd.fVar->name(),
|
||||
&vd.fVar->type()));
|
||||
if (vd.fValue) {
|
||||
fErrors.error(decl->fOffset,
|
||||
@ -1186,9 +1199,9 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTNode
|
||||
sizes.push_back(nullptr);
|
||||
}
|
||||
}
|
||||
const Variable* var = old->takeOwnershipOfSymbol(
|
||||
Variable* var = old->takeOwnershipOfSymbol(
|
||||
std::make_unique<Variable>(intf.fOffset,
|
||||
id.fModifiers,
|
||||
fModifiers->handle(id.fModifiers),
|
||||
id.fInstanceName.fLength ? id.fInstanceName : id.fTypeName,
|
||||
type,
|
||||
fIsBuiltinCode,
|
||||
@ -1218,9 +1231,8 @@ bool IRGenerator::getConstantInt(const Expression& value, int64_t* out) {
|
||||
return true;
|
||||
case Expression::Kind::kVariableReference: {
|
||||
const Variable& var = *value.as<VariableReference>().fVariable;
|
||||
return (var.fModifiers.fFlags & Modifiers::kConst_Flag) &&
|
||||
var.fInitialValue &&
|
||||
this->getConstantInt(*var.fInitialValue, out);
|
||||
return (var.modifiers().fFlags & Modifiers::kConst_Flag) &&
|
||||
var.initialValue() && this->getConstantInt(*var.initialValue(), out);
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
@ -1262,8 +1274,9 @@ void IRGenerator::convertEnum(const ASTNode& e) {
|
||||
++currentValue;
|
||||
fSymbolTable->add(
|
||||
child.getString(),
|
||||
std::make_unique<Variable>(e.fOffset, modifiers, child.getString(), type,
|
||||
fIsBuiltinCode, Variable::kGlobal_Storage, value.get()));
|
||||
std::make_unique<Variable>(e.fOffset, fModifiers->handle(modifiers),
|
||||
child.getString(), type, fIsBuiltinCode,
|
||||
Variable::kGlobal_Storage, value.get()));
|
||||
fSymbolTable->takeOwnershipOfIRNode(std::move(value));
|
||||
}
|
||||
// Now we orphanize the Enum's symbol table, so that future lookups in it are strict
|
||||
@ -1376,7 +1389,8 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTNode& identi
|
||||
}
|
||||
case Symbol::Kind::kVariable: {
|
||||
const Variable* var = &result->as<Variable>();
|
||||
switch (var->fModifiers.fLayout.fBuiltin) {
|
||||
const Modifiers& modifiers = var->modifiers();
|
||||
switch (modifiers.fLayout.fBuiltin) {
|
||||
case SK_WIDTH_BUILTIN:
|
||||
fInputs.fRTWidth = true;
|
||||
break;
|
||||
@ -1394,10 +1408,10 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTNode& identi
|
||||
#endif
|
||||
}
|
||||
if (fKind == Program::kFragmentProcessor_Kind &&
|
||||
(var->fModifiers.fFlags & Modifiers::kIn_Flag) &&
|
||||
!(var->fModifiers.fFlags & Modifiers::kUniform_Flag) &&
|
||||
!var->fModifiers.fLayout.fKey &&
|
||||
var->fModifiers.fLayout.fBuiltin == -1 &&
|
||||
(modifiers.fFlags & Modifiers::kIn_Flag) &&
|
||||
!(modifiers.fFlags & Modifiers::kUniform_Flag) &&
|
||||
!modifiers.fLayout.fKey &&
|
||||
modifiers.fLayout.fBuiltin == -1 &&
|
||||
var->type().nonnullable() != *fContext.fFragmentProcessor_Type &&
|
||||
var->type().typeKind() != Type::TypeKind::kSampler) {
|
||||
bool valid = false;
|
||||
@ -1454,7 +1468,6 @@ std::unique_ptr<Section> IRGenerator::convertSection(const ASTNode& s) {
|
||||
section.fText);
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr,
|
||||
const Type& type) {
|
||||
if (!expr) {
|
||||
@ -2109,7 +2122,7 @@ std::unique_ptr<Expression> IRGenerator::call(int offset,
|
||||
if (!arguments[i]) {
|
||||
return nullptr;
|
||||
}
|
||||
const Modifiers& paramModifiers = function.fParameters[i]->fModifiers;
|
||||
const Modifiers& paramModifiers = function.fParameters[i]->modifiers();
|
||||
if (paramModifiers.fFlags & Modifiers::kOut_Flag) {
|
||||
if (!this->setRefKind(*arguments[i], paramModifiers.fFlags & Modifiers::kIn_Flag
|
||||
? VariableReference::kReadWrite_RefKind
|
||||
@ -2697,9 +2710,9 @@ std::unique_ptr<Expression> IRGenerator::convertTypeField(int offset, const Type
|
||||
ASTNode(&fFile->fNodes, offset, ASTNode::Kind::kIdentifier, field));
|
||||
if (result) {
|
||||
const Variable& v = *result->as<VariableReference>().fVariable;
|
||||
SkASSERT(v.fInitialValue);
|
||||
SkASSERT(v.initialValue());
|
||||
result = std::make_unique<IntLiteral>(
|
||||
offset, v.fInitialValue->as<IntLiteral>().value(), &type);
|
||||
offset, v.initialValue()->as<IntLiteral>().value(), &type);
|
||||
} else {
|
||||
fErrors.error(offset,
|
||||
"type '" + type.name() + "' does not have a member named '" + field +
|
||||
@ -2860,8 +2873,8 @@ void IRGenerator::cloneBuiltinVariables() {
|
||||
// so we're pointing at a Program-owned expression.
|
||||
const Variable* clonedVar =
|
||||
fGenerator->fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Variable>(
|
||||
sharedVar->fOffset, sharedVar->fModifiers, sharedVar->name(),
|
||||
&sharedVar->type(), /*builtin=*/false, sharedVar->fStorage,
|
||||
sharedVar->fOffset, sharedVar->modifiersHandle(), sharedVar->name(),
|
||||
&sharedVar->type(), /*builtin=*/false, sharedVar->storage(),
|
||||
varDecl.fValue.get()));
|
||||
|
||||
// Go back and update the VarDeclaration to point at the cloned Variable.
|
||||
@ -2877,7 +2890,7 @@ void IRGenerator::cloneBuiltinVariables() {
|
||||
|
||||
bool visitExpression(Expression& e) override {
|
||||
// Look for references to builtin variables.
|
||||
if (e.is<VariableReference>() && e.as<VariableReference>().fVariable->fBuiltin) {
|
||||
if (e.is<VariableReference>() && e.as<VariableReference>().fVariable->isBuiltin()) {
|
||||
const Variable* sharedVar = e.as<VariableReference>().fVariable;
|
||||
|
||||
this->cloneVariable(sharedVar->name());
|
||||
|
@ -123,6 +123,11 @@ private:
|
||||
*/
|
||||
void finish();
|
||||
|
||||
/**
|
||||
* Relinquishes ownership of the Modifiers that have been collected so far and returns them.
|
||||
*/
|
||||
std::unique_ptr<ModifiersPool> releaseModifiers();
|
||||
|
||||
void pushSymbolTable();
|
||||
void popSymbolTable();
|
||||
|
||||
@ -224,6 +229,7 @@ private:
|
||||
bool fCanInline = true;
|
||||
// true if we are currently processing one of the built-in SkSL include files
|
||||
bool fIsBuiltinCode;
|
||||
std::unique_ptr<ModifiersPool> fModifiers;
|
||||
|
||||
friend class AutoSymbolTable;
|
||||
friend class AutoLoopLevel;
|
||||
|
@ -301,9 +301,11 @@ void Inliner::ensureScopedBlocks(Statement* inlinedBody, Statement* parentStmt)
|
||||
}
|
||||
}
|
||||
|
||||
void Inliner::reset(const Context& context, const Program::Settings& settings) {
|
||||
fContext = &context;
|
||||
fSettings = &settings;
|
||||
void Inliner::reset(const Context* context, ModifiersPool* modifiers,
|
||||
const Program::Settings* settings) {
|
||||
fContext = context;
|
||||
fModifiers = modifiers;
|
||||
fSettings = settings;
|
||||
fInlineVarCounter = 0;
|
||||
}
|
||||
|
||||
@ -550,11 +552,11 @@ std::unique_ptr<Statement> Inliner::inlineStatement(int offset,
|
||||
const Type* typePtr = copy_if_needed(&old->type(), *symbolTableForStatement);
|
||||
const Variable* clone = symbolTableForStatement->takeOwnershipOfSymbol(
|
||||
std::make_unique<Variable>(offset,
|
||||
old->fModifiers,
|
||||
old->modifiersHandle(),
|
||||
namePtr->c_str(),
|
||||
typePtr,
|
||||
isBuiltinCode,
|
||||
old->fStorage,
|
||||
old->storage(),
|
||||
initialValue.get()));
|
||||
(*varMap)[old] = std::make_unique<VariableReference>(offset, clone);
|
||||
return std::make_unique<VarDeclaration>(clone, baseTypePtr, std::move(sizes),
|
||||
@ -628,9 +630,10 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
|
||||
StringFragment nameFrag{namePtr->c_str(), namePtr->length()};
|
||||
|
||||
// Add our new variable to the symbol table.
|
||||
auto newVar = std::make_unique<Variable>(/*offset=*/-1, Modifiers(), nameFrag, type,
|
||||
caller->fBuiltin, Variable::kLocal_Storage,
|
||||
initialValue->get());
|
||||
auto newVar = std::make_unique<Variable>(/*offset=*/-1,
|
||||
fModifiers->handle(Modifiers()),
|
||||
nameFrag, type, caller->fBuiltin,
|
||||
Variable::kLocal_Storage, initialValue->get());
|
||||
const Variable* variableSymbol = symbolTableForCall->add(nameFrag, std::move(newVar));
|
||||
|
||||
// Prepare the variable declaration (taking extra care with `out` params to not clobber any
|
||||
@ -667,7 +670,7 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
|
||||
std::vector<int> argsToCopyBack;
|
||||
for (int i = 0; i < (int) arguments.size(); ++i) {
|
||||
const Variable* param = function.fDeclaration.fParameters[i];
|
||||
bool isOutParam = param->fModifiers.fFlags & Modifiers::kOut_Flag;
|
||||
bool isOutParam = param->modifiers().fFlags & Modifiers::kOut_Flag;
|
||||
|
||||
// If this argument can be inlined trivially (e.g. a swizzle, or a constant array index)...
|
||||
if (is_trivial_argument(*arguments[i])) {
|
||||
@ -684,7 +687,7 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
|
||||
}
|
||||
|
||||
varMap[param] = makeInlineVar(String(param->name()), &arguments[i]->type(),
|
||||
param->fModifiers, &arguments[i]);
|
||||
param->modifiers(), &arguments[i]);
|
||||
}
|
||||
|
||||
const Block& body = function.fBody->as<Block>();
|
||||
@ -730,7 +733,8 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
|
||||
} else {
|
||||
// It's a void function, so it doesn't actually result in anything, but we have to return
|
||||
// something non-null as a standin.
|
||||
inlinedCall.fReplacementExpr = std::make_unique<BoolLiteral>(*fContext, offset,
|
||||
inlinedCall.fReplacementExpr = std::make_unique<BoolLiteral>(*fContext,
|
||||
offset,
|
||||
/*value=*/false);
|
||||
}
|
||||
|
||||
|
@ -23,9 +23,10 @@ struct FunctionCall;
|
||||
struct FunctionDefinition;
|
||||
struct InlineCandidate;
|
||||
struct InlineCandidateList;
|
||||
class ModifiersPool;
|
||||
struct Statement;
|
||||
class SymbolTable;
|
||||
struct Variable;
|
||||
class Variable;
|
||||
|
||||
/**
|
||||
* Converts a FunctionCall in the IR to a set of statements to be injected ahead of the function
|
||||
@ -37,7 +38,7 @@ class Inliner {
|
||||
public:
|
||||
Inliner() {}
|
||||
|
||||
void reset(const Context&, const Program::Settings&);
|
||||
void reset(const Context*, ModifiersPool* modifiers, const Program::Settings*);
|
||||
|
||||
/**
|
||||
* Processes the passed-in FunctionCall expression. The FunctionCall expression should be
|
||||
@ -87,6 +88,7 @@ private:
|
||||
bool isLargeFunction(const InlineCandidate& candidate, LargeFunctionCache* cache);
|
||||
|
||||
const Context* fContext = nullptr;
|
||||
ModifiersPool* fModifiers = nullptr;
|
||||
const Program::Settings* fSettings = nullptr;
|
||||
int fInlineVarCounter = 0;
|
||||
};
|
||||
|
@ -265,7 +265,7 @@ void MetalCodeGenerator::writeFunctionCall(const FunctionCall& c) {
|
||||
const Expression& arg = *arguments[i];
|
||||
this->write(separator);
|
||||
separator = ", ";
|
||||
if (function.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag) {
|
||||
if (function.fParameters[i]->modifiers().fFlags & Modifiers::kOut_Flag) {
|
||||
this->write("&");
|
||||
}
|
||||
this->writeExpression(arg, kSequence_Precedence);
|
||||
@ -680,7 +680,7 @@ void MetalCodeGenerator::writeFragCoord() {
|
||||
}
|
||||
|
||||
void MetalCodeGenerator::writeVariableReference(const VariableReference& ref) {
|
||||
switch (ref.fVariable->fModifiers.fLayout.fBuiltin) {
|
||||
switch (ref.fVariable->modifiers().fLayout.fBuiltin) {
|
||||
case SK_FRAGCOLOR_BUILTIN:
|
||||
this->write("_out->sk_FragColor");
|
||||
break;
|
||||
@ -699,12 +699,12 @@ void MetalCodeGenerator::writeVariableReference(const VariableReference& ref) {
|
||||
this->write(fProgram.fSettings.fFlipY ? "_frontFacing" : "(!_frontFacing)");
|
||||
break;
|
||||
default:
|
||||
if (Variable::kGlobal_Storage == ref.fVariable->fStorage) {
|
||||
if (ref.fVariable->fModifiers.fFlags & Modifiers::kIn_Flag) {
|
||||
if (Variable::kGlobal_Storage == ref.fVariable->storage()) {
|
||||
if (ref.fVariable->modifiers().fFlags & Modifiers::kIn_Flag) {
|
||||
this->write("_in.");
|
||||
} else if (ref.fVariable->fModifiers.fFlags & Modifiers::kOut_Flag) {
|
||||
} else if (ref.fVariable->modifiers().fFlags & Modifiers::kOut_Flag) {
|
||||
this->write("_out->");
|
||||
} else if (ref.fVariable->fModifiers.fFlags & Modifiers::kUniform_Flag &&
|
||||
} else if (ref.fVariable->modifiers().fFlags & Modifiers::kUniform_Flag &&
|
||||
ref.fVariable->type().typeKind() != Type::TypeKind::kSampler) {
|
||||
this->write("_uniforms.");
|
||||
} else {
|
||||
@ -836,8 +836,8 @@ void MetalCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
|
||||
this->write("(");
|
||||
}
|
||||
if (Compiler::IsAssignment(op) && left.is<VariableReference>() &&
|
||||
left.as<VariableReference>().fVariable->fStorage == Variable::kParameter_Storage &&
|
||||
left.as<VariableReference>().fVariable->fModifiers.fFlags & Modifiers::kOut_Flag) {
|
||||
left.as<VariableReference>().fVariable->storage() == Variable::kParameter_Storage &&
|
||||
left.as<VariableReference>().fVariable->modifiers().fFlags & Modifiers::kOut_Flag) {
|
||||
// writing to an out parameter. Since we have to turn those into pointers, we have to
|
||||
// dereference it here.
|
||||
this->write("*");
|
||||
@ -955,7 +955,7 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) {
|
||||
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) {
|
||||
if (var.fVar->modifiers().fLayout.fBinding < 0) {
|
||||
fErrors.error(decls.fOffset,
|
||||
"Metal samplers must have 'layout(binding=...)'");
|
||||
return;
|
||||
@ -968,13 +968,13 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) {
|
||||
this->write(", texture2d<float> ");
|
||||
this->writeName(var.fVar->name());
|
||||
this->write("[[texture(");
|
||||
this->write(to_string(var.fVar->fModifiers.fLayout.fBinding));
|
||||
this->write(to_string(var.fVar->modifiers().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(to_string(var.fVar->modifiers().fLayout.fBinding));
|
||||
this->write(")]]");
|
||||
}
|
||||
} else if (e.kind() == ProgramElement::Kind::kInterfaceBlock) {
|
||||
@ -987,7 +987,7 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) {
|
||||
this->write("& " );
|
||||
this->write(fInterfaceBlockNameMap[&intf]);
|
||||
this->write(" [[buffer(");
|
||||
this->write(to_string(intf.fVariable.fModifiers.fLayout.fBinding));
|
||||
this->write(to_string(intf.fVariable.modifiers().fLayout.fBinding));
|
||||
this->write(")]]");
|
||||
}
|
||||
}
|
||||
@ -1036,7 +1036,7 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) {
|
||||
for (const auto& param : f.fDeclaration.fParameters) {
|
||||
this->write(separator);
|
||||
separator = ", ";
|
||||
this->writeModifiers(param->fModifiers, false);
|
||||
this->writeModifiers(param->modifiers(), false);
|
||||
std::vector<int> sizes;
|
||||
const Type* type = ¶m->type();
|
||||
while (type->typeKind() == Type::TypeKind::kArray) {
|
||||
@ -1044,7 +1044,7 @@ void MetalCodeGenerator::writeFunction(const FunctionDefinition& f) {
|
||||
type = &type->componentType();
|
||||
}
|
||||
this->writeType(*type);
|
||||
if (param->fModifiers.fFlags & Modifiers::kOut_Flag) {
|
||||
if (param->modifiers().fFlags & Modifiers::kOut_Flag) {
|
||||
this->write("*");
|
||||
}
|
||||
this->write(" ");
|
||||
@ -1113,7 +1113,7 @@ void MetalCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
|
||||
if ("sk_PerVertex" == intf.fTypeName) {
|
||||
return;
|
||||
}
|
||||
this->writeModifiers(intf.fVariable.fModifiers, true);
|
||||
this->writeModifiers(intf.fVariable.modifiers(), true);
|
||||
this->write("struct ");
|
||||
this->writeLine(intf.fTypeName + " {");
|
||||
const Type* structType = &intf.fVariable.type();
|
||||
@ -1215,10 +1215,10 @@ void MetalCodeGenerator::writeName(const String& name) {
|
||||
}
|
||||
|
||||
void MetalCodeGenerator::writeVarDeclaration(const VarDeclaration& var, bool global) {
|
||||
if (global && !(var.fVar->fModifiers.fFlags & Modifiers::kConst_Flag)) {
|
||||
if (global && !(var.fVar->modifiers().fFlags & Modifiers::kConst_Flag)) {
|
||||
return;
|
||||
}
|
||||
this->writeModifiers(var.fVar->fModifiers, global);
|
||||
this->writeModifiers(var.fVar->modifiers(), global);
|
||||
this->writeType(var.fBaseType);
|
||||
this->write(" ");
|
||||
this->writeName(var.fVar->name());
|
||||
@ -1393,15 +1393,15 @@ void MetalCodeGenerator::writeUniformStruct() {
|
||||
if (e.is<GlobalVarDeclaration>()) {
|
||||
const GlobalVarDeclaration& decls = e.as<GlobalVarDeclaration>();
|
||||
const Variable& var = *decls.fDecl->fVar;
|
||||
if (var.fModifiers.fFlags & Modifiers::kUniform_Flag &&
|
||||
if (var.modifiers().fFlags & Modifiers::kUniform_Flag &&
|
||||
var.type().typeKind() != Type::TypeKind::kSampler) {
|
||||
if (-1 == fUniformBuffer) {
|
||||
this->write("struct Uniforms {\n");
|
||||
fUniformBuffer = var.fModifiers.fLayout.fSet;
|
||||
fUniformBuffer = var.modifiers().fLayout.fSet;
|
||||
if (-1 == fUniformBuffer) {
|
||||
fErrors.error(decls.fOffset, "Metal uniforms must have 'layout(set=...)'");
|
||||
}
|
||||
} else if (var.fModifiers.fLayout.fSet != fUniformBuffer) {
|
||||
} else if (var.modifiers().fLayout.fSet != fUniformBuffer) {
|
||||
if (-1 == fUniformBuffer) {
|
||||
fErrors.error(decls.fOffset, "Metal backend requires all uniforms to have "
|
||||
"the same 'layout(set=...)'");
|
||||
@ -1426,19 +1426,19 @@ void MetalCodeGenerator::writeInputStruct() {
|
||||
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) {
|
||||
if (var.modifiers().fFlags & Modifiers::kIn_Flag &&
|
||||
-1 == var.modifiers().fLayout.fBuiltin) {
|
||||
this->write(" ");
|
||||
this->writeType(var.type());
|
||||
this->write(" ");
|
||||
this->writeName(var.name());
|
||||
if (-1 != var.fModifiers.fLayout.fLocation) {
|
||||
if (-1 != var.modifiers().fLayout.fLocation) {
|
||||
if (fProgram.fKind == Program::kVertex_Kind) {
|
||||
this->write(" [[attribute(" +
|
||||
to_string(var.fModifiers.fLayout.fLocation) + ")]]");
|
||||
to_string(var.modifiers().fLayout.fLocation) + ")]]");
|
||||
} else if (fProgram.fKind == Program::kFragment_Kind) {
|
||||
this->write(" [[user(locn" +
|
||||
to_string(var.fModifiers.fLayout.fLocation) + ")]]");
|
||||
to_string(var.modifiers().fLayout.fLocation) + ")]]");
|
||||
}
|
||||
}
|
||||
this->write(";\n");
|
||||
@ -1459,19 +1459,19 @@ void MetalCodeGenerator::writeOutputStruct() {
|
||||
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) {
|
||||
if (var.modifiers().fFlags & Modifiers::kOut_Flag &&
|
||||
-1 == var.modifiers().fLayout.fBuiltin) {
|
||||
this->write(" ");
|
||||
this->writeType(var.type());
|
||||
this->write(" ");
|
||||
this->writeName(var.name());
|
||||
if (fProgram.fKind == Program::kVertex_Kind) {
|
||||
this->write(" [[user(locn" +
|
||||
to_string(var.fModifiers.fLayout.fLocation) + ")]]");
|
||||
to_string(var.modifiers().fLayout.fLocation) + ")]]");
|
||||
} else if (fProgram.fKind == Program::kFragment_Kind) {
|
||||
this->write(" [[color(" +
|
||||
to_string(var.fModifiers.fLayout.fLocation) +")");
|
||||
int colorIndex = var.fModifiers.fLayout.fIndex;
|
||||
to_string(var.modifiers().fLayout.fLocation) +")");
|
||||
int colorIndex = var.modifiers().fLayout.fIndex;
|
||||
if (colorIndex) {
|
||||
this->write(", index(" + to_string(colorIndex) + ")");
|
||||
}
|
||||
@ -1514,7 +1514,7 @@ void MetalCodeGenerator::visitGlobalStruct(GlobalStructVisitor* visitor) {
|
||||
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) ||
|
||||
if ((!var.modifiers().fFlags && -1 == var.modifiers().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.
|
||||
@ -1638,7 +1638,7 @@ void MetalCodeGenerator::writeProgramElement(const ProgramElement& e) {
|
||||
break;
|
||||
case ProgramElement::Kind::kGlobalVar: {
|
||||
const VarDeclaration& decl = *e.as<GlobalVarDeclaration>().fDecl;
|
||||
int builtin = decl.fVar->fModifiers.fLayout.fBuiltin;
|
||||
int builtin = decl.fVar->modifiers().fLayout.fBuiltin;
|
||||
if (-1 == builtin) {
|
||||
// normal var
|
||||
this->writeVarDeclaration(decl, true);
|
||||
@ -1716,15 +1716,16 @@ MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Expressi
|
||||
}
|
||||
case Expression::Kind::kVariableReference: {
|
||||
const VariableReference& v = e->as<VariableReference>();
|
||||
const Modifiers& modifiers = v.fVariable->modifiers();
|
||||
Requirements result = kNo_Requirements;
|
||||
if (v.fVariable->fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN) {
|
||||
if (modifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN) {
|
||||
result = kGlobals_Requirement | kFragCoord_Requirement;
|
||||
} else if (Variable::kGlobal_Storage == v.fVariable->fStorage) {
|
||||
if (v.fVariable->fModifiers.fFlags & Modifiers::kIn_Flag) {
|
||||
} else if (Variable::kGlobal_Storage == v.fVariable->storage()) {
|
||||
if (modifiers.fFlags & Modifiers::kIn_Flag) {
|
||||
result = kInputs_Requirement;
|
||||
} else if (v.fVariable->fModifiers.fFlags & Modifiers::kOut_Flag) {
|
||||
} else if (modifiers.fFlags & Modifiers::kOut_Flag) {
|
||||
result = kOutputs_Requirement;
|
||||
} else if (v.fVariable->fModifiers.fFlags & Modifiers::kUniform_Flag &&
|
||||
} else if (modifiers.fFlags & Modifiers::kUniform_Flag &&
|
||||
v.fVariable->type().typeKind() != Type::TypeKind::kSampler) {
|
||||
result = kUniforms_Requirement;
|
||||
} else {
|
||||
|
73
src/sksl/SkSLModifiersPool.h
Normal file
73
src/sksl/SkSLModifiersPool.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2020 Google LLC.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SKSL_MODIFIERSPOOL
|
||||
#define SKSL_MODIFIERSPOOL
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
struct Modifiers;
|
||||
|
||||
/**
|
||||
* Stores a pool of Modifiers objects. Modifiers is fairly heavy, so to reduce IRNode's size we only
|
||||
* store a handle to the Modifiers inside of the node and keep the object itself in a ModifiersPool.
|
||||
*/
|
||||
class ModifiersPool {
|
||||
public:
|
||||
class Handle {
|
||||
public:
|
||||
Handle() = default;
|
||||
|
||||
Handle(const ModifiersPool* pool, int index)
|
||||
: fPool(pool)
|
||||
, fIndex(index) {}
|
||||
|
||||
const Modifiers* operator->() const {
|
||||
return &fPool->fModifiers[fIndex];
|
||||
}
|
||||
|
||||
const Modifiers& operator*() const {
|
||||
return fPool->fModifiers[fIndex];
|
||||
}
|
||||
|
||||
private:
|
||||
const ModifiersPool* fPool;
|
||||
int fIndex;
|
||||
};
|
||||
|
||||
bool empty() {
|
||||
return fModifiers.empty();
|
||||
}
|
||||
|
||||
Handle handle(const Modifiers& modifiers) {
|
||||
SkASSERT(fModifiers.size() == fModifiersMap.size());
|
||||
int index;
|
||||
auto found = fModifiersMap.find(modifiers);
|
||||
if (found != fModifiersMap.end()) {
|
||||
index = found->second;
|
||||
} else {
|
||||
index = fModifiers.size();
|
||||
fModifiers.push_back(modifiers);
|
||||
fModifiersMap.insert({modifiers, index});
|
||||
}
|
||||
return Handle(this, index);
|
||||
}
|
||||
|
||||
void finish() {
|
||||
fModifiersMap.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Modifiers> fModifiers;
|
||||
std::unordered_map<Modifiers, int> fModifiersMap;
|
||||
};
|
||||
|
||||
} // namespace SkSL
|
||||
|
||||
#endif
|
@ -107,7 +107,7 @@ void PipelineStageCodeGenerator::writeIntLiteral(const IntLiteral& i) {
|
||||
}
|
||||
|
||||
void PipelineStageCodeGenerator::writeVariableReference(const VariableReference& ref) {
|
||||
switch (ref.fVariable->fModifiers.fLayout.fBuiltin) {
|
||||
switch (ref.fVariable->modifiers().fLayout.fBuiltin) {
|
||||
case SK_OUTCOLOR_BUILTIN:
|
||||
this->write(Compiler::kFormatArgPlaceholderStr);
|
||||
fArgs->fFormatArgs.push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kOutput));
|
||||
@ -130,7 +130,7 @@ void PipelineStageCodeGenerator::writeVariableReference(const VariableReference&
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (var.fModifiers.fFlags & flag) {
|
||||
if (var.modifiers().fFlags & flag) {
|
||||
++index;
|
||||
}
|
||||
}
|
||||
@ -139,12 +139,12 @@ void PipelineStageCodeGenerator::writeVariableReference(const VariableReference&
|
||||
return index;
|
||||
};
|
||||
|
||||
if (ref.fVariable->fModifiers.fFlags & Modifiers::kUniform_Flag) {
|
||||
if (ref.fVariable->modifiers().fFlags & Modifiers::kUniform_Flag) {
|
||||
this->write(Compiler::kFormatArgPlaceholderStr);
|
||||
fArgs->fFormatArgs.push_back(
|
||||
Compiler::FormatArg(Compiler::FormatArg::Kind::kUniform,
|
||||
varIndexByFlag(Modifiers::kUniform_Flag)));
|
||||
} else if (ref.fVariable->fModifiers.fFlags & Modifiers::kVarying_Flag) {
|
||||
} else if (ref.fVariable->modifiers().fFlags & Modifiers::kVarying_Flag) {
|
||||
this->write("_vtx_attr_");
|
||||
this->write(to_string(varIndexByFlag(Modifiers::kVarying_Flag)));
|
||||
} else {
|
||||
@ -214,9 +214,9 @@ void PipelineStageCodeGenerator::writeProgramElement(const ProgramElement& p) {
|
||||
}
|
||||
if (p.is<GlobalVarDeclaration>()) {
|
||||
const Variable& var = *p.as<GlobalVarDeclaration>().fDecl->fVar;
|
||||
if (var.fModifiers.fFlags &
|
||||
if (var.modifiers().fFlags &
|
||||
(Modifiers::kIn_Flag | Modifiers::kUniform_Flag | Modifiers::kVarying_Flag) ||
|
||||
-1 != var.fModifiers.fLayout.fBuiltin) {
|
||||
var.modifiers().fLayout.fBuiltin == -1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ Modifiers Rehydrator::modifiers() {
|
||||
}
|
||||
}
|
||||
|
||||
const Symbol* Rehydrator::symbol() {
|
||||
Symbol* Rehydrator::symbol() {
|
||||
int kind = this->readU8();
|
||||
switch (kind) {
|
||||
case kArrayType_Command: {
|
||||
@ -139,7 +139,7 @@ const Symbol* Rehydrator::symbol() {
|
||||
} else {
|
||||
name += "[" + to_string(count) + "]";
|
||||
}
|
||||
const Type* result = fSymbolTable->takeOwnershipOfSymbol(
|
||||
Type* result = fSymbolTable->takeOwnershipOfSymbol(
|
||||
std::make_unique<Type>(name, Type::TypeKind::kArray, *componentType, count));
|
||||
this->addSymbol(id, result);
|
||||
return result;
|
||||
@ -147,7 +147,7 @@ const Symbol* Rehydrator::symbol() {
|
||||
case kEnumType_Command: {
|
||||
uint16_t id = this->readU16();
|
||||
StringFragment name = this->readString();
|
||||
const Type* result = fSymbolTable->takeOwnershipOfSymbol(
|
||||
Type* result = fSymbolTable->takeOwnershipOfSymbol(
|
||||
std::make_unique<Type>(name, Type::TypeKind::kEnum));
|
||||
this->addSymbol(id, result);
|
||||
return result;
|
||||
@ -157,13 +157,13 @@ const Symbol* Rehydrator::symbol() {
|
||||
Modifiers modifiers = this->modifiers();
|
||||
StringFragment name = this->readString();
|
||||
int parameterCount = this->readU8();
|
||||
std::vector<const Variable*> parameters;
|
||||
std::vector<Variable*> parameters;
|
||||
parameters.reserve(parameterCount);
|
||||
for (int i = 0; i < parameterCount; ++i) {
|
||||
parameters.push_back(this->symbolRef<Variable>(Symbol::Kind::kVariable));
|
||||
}
|
||||
const Type* returnType = this->type();
|
||||
const FunctionDeclaration* result =
|
||||
FunctionDeclaration* result =
|
||||
fSymbolTable->takeOwnershipOfSymbol(std::make_unique<FunctionDeclaration>(
|
||||
/*offset=*/-1, modifiers, name, std::move(parameters), *returnType,
|
||||
/*builtin=*/true));
|
||||
@ -173,14 +173,14 @@ const Symbol* Rehydrator::symbol() {
|
||||
case kField_Command: {
|
||||
const Variable* owner = this->symbolRef<Variable>(Symbol::Kind::kVariable);
|
||||
uint8_t index = this->readU8();
|
||||
const Field* result = fSymbolTable->takeOwnershipOfSymbol(
|
||||
Field* result = fSymbolTable->takeOwnershipOfSymbol(
|
||||
std::make_unique<Field>(/*offset=*/-1, owner, index));
|
||||
return result;
|
||||
}
|
||||
case kNullableType_Command: {
|
||||
uint16_t id = this->readU16();
|
||||
const Type* base = this->type();
|
||||
const Type* result = fSymbolTable->takeOwnershipOfSymbol(
|
||||
Type* result = fSymbolTable->takeOwnershipOfSymbol(
|
||||
std::make_unique<Type>(base->name() + "?", Type::TypeKind::kNullable, *base));
|
||||
this->addSymbol(id, result);
|
||||
return result;
|
||||
@ -197,7 +197,7 @@ const Symbol* Rehydrator::symbol() {
|
||||
const Type* type = this->type();
|
||||
fields.emplace_back(m, fieldName, type);
|
||||
}
|
||||
const Type* result = fSymbolTable->takeOwnershipOfSymbol(
|
||||
Type* result = fSymbolTable->takeOwnershipOfSymbol(
|
||||
std::make_unique<Type>(/*offset=*/-1, name, std::move(fields)));
|
||||
this->addSymbol(id, result);
|
||||
return result;
|
||||
@ -210,8 +210,8 @@ const Symbol* Rehydrator::symbol() {
|
||||
case kSymbolAlias_Command: {
|
||||
uint16_t id = this->readU16();
|
||||
StringFragment name = this->readString();
|
||||
const Symbol* origSymbol = this->symbol();
|
||||
const SymbolAlias* symbolAlias = fSymbolTable->takeOwnershipOfSymbol(
|
||||
Symbol* origSymbol = this->symbol();
|
||||
SymbolAlias* symbolAlias = fSymbolTable->takeOwnershipOfSymbol(
|
||||
std::make_unique<SymbolAlias>(/*offset=*/-1, name, origSymbol));
|
||||
this->addSymbol(id, symbolAlias);
|
||||
return symbolAlias;
|
||||
@ -219,7 +219,7 @@ const Symbol* Rehydrator::symbol() {
|
||||
case kSystemType_Command: {
|
||||
uint16_t id = this->readU16();
|
||||
StringFragment name = this->readString();
|
||||
const Symbol* result = (*fSymbolTable)[name];
|
||||
Symbol* result = (*fSymbolTable)[name];
|
||||
SkASSERT(result && result->kind() == Symbol::Kind::kType);
|
||||
this->addSymbol(id, result);
|
||||
return result;
|
||||
@ -234,18 +234,18 @@ const Symbol* Rehydrator::symbol() {
|
||||
SkASSERT(f && f->kind() == Symbol::Kind::kFunctionDeclaration);
|
||||
functions.push_back((const FunctionDeclaration*) f);
|
||||
}
|
||||
const UnresolvedFunction* result = fSymbolTable->takeOwnershipOfSymbol(
|
||||
UnresolvedFunction* result = fSymbolTable->takeOwnershipOfSymbol(
|
||||
std::make_unique<UnresolvedFunction>(std::move(functions)));
|
||||
this->addSymbol(id, result);
|
||||
return result;
|
||||
}
|
||||
case kVariable_Command: {
|
||||
uint16_t id = this->readU16();
|
||||
Modifiers m = this->modifiers();
|
||||
ModifiersPool::Handle m = fModifiers.handle(this->modifiers());
|
||||
StringFragment name = this->readString();
|
||||
const Type* type = this->type();
|
||||
Variable::Storage storage = (Variable::Storage) this->readU8();
|
||||
const Variable* result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Variable>(
|
||||
Variable* result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Variable>(
|
||||
/*offset=*/-1, m, name, type, /*builtin=*/true, storage));
|
||||
this->addSymbol(id, result);
|
||||
return result;
|
||||
@ -285,9 +285,8 @@ std::unique_ptr<ProgramElement> Rehydrator::element() {
|
||||
SkASSERT(s->kind() == Symbol::Kind::kVariable);
|
||||
Variable& v = (Variable&) *s;
|
||||
int value = this->readS32();
|
||||
v.fInitialValue = symbols->takeOwnershipOfIRNode(
|
||||
std::make_unique<IntLiteral>(fContext, /*offset=*/-1, value));
|
||||
v.fWriteCount = 1;
|
||||
v.setInitialValue(symbols->takeOwnershipOfIRNode(
|
||||
std::make_unique<IntLiteral>(fContext, /*offset=*/-1, value)));
|
||||
}
|
||||
return std::unique_ptr<ProgramElement>(new Enum(-1, typeName, std::move(symbols)));
|
||||
}
|
||||
@ -429,9 +428,7 @@ std::unique_ptr<Statement> Rehydrator::statement() {
|
||||
}
|
||||
std::unique_ptr<Expression> value = this->expression();
|
||||
if (value) {
|
||||
var->fInitialValue = value.get();
|
||||
SkASSERT(var->fWriteCount == 0);
|
||||
++var->fWriteCount;
|
||||
var->setInitialValue(value.get());
|
||||
}
|
||||
return std::unique_ptr<Statement>(
|
||||
new VarDeclaration(var, baseType, std::move(sizes), std::move(value)));
|
||||
@ -567,7 +564,7 @@ std::shared_ptr<SymbolTable> Rehydrator::symbolTable(bool inherit) {
|
||||
std::shared_ptr<SymbolTable> result = inherit ? std::make_shared<SymbolTable>(fSymbolTable)
|
||||
: std::make_shared<SymbolTable>(fErrors);
|
||||
fSymbolTable = result;
|
||||
std::vector<const Symbol*> ownedSymbols;
|
||||
std::vector<Symbol*> ownedSymbols;
|
||||
ownedSymbols.reserve(ownedCount);
|
||||
for (int i = 0; i < ownedCount; ++i) {
|
||||
ownedSymbols.push_back(this->symbol());
|
||||
|
@ -20,6 +20,7 @@ namespace SkSL {
|
||||
class Context;
|
||||
class ErrorReporter;
|
||||
struct Expression;
|
||||
class IRGenerator;
|
||||
struct ProgramElement;
|
||||
struct Statement;
|
||||
class SymbolTable;
|
||||
@ -144,9 +145,11 @@ public:
|
||||
};
|
||||
|
||||
// src must remain in memory as long as the objects created from it do
|
||||
Rehydrator(Context* context, std::shared_ptr<SymbolTable> symbolTable,
|
||||
ErrorReporter* errorReporter, const uint8_t* src, size_t length)
|
||||
Rehydrator(const Context* context, ModifiersPool* modifiers,
|
||||
std::shared_ptr<SymbolTable> symbolTable, ErrorReporter* errorReporter,
|
||||
const uint8_t* src, size_t length)
|
||||
: fContext(*context)
|
||||
, fModifiers(*modifiers)
|
||||
, fErrors(errorReporter)
|
||||
, fSymbolTable(std::move(symbolTable))
|
||||
, fStart(src)
|
||||
@ -200,7 +203,7 @@ private:
|
||||
return StringFragment(chars, length);
|
||||
}
|
||||
|
||||
void addSymbol(int id, const Symbol* symbol) {
|
||||
void addSymbol(int id, Symbol* symbol) {
|
||||
while ((size_t) id >= fSymbols.size()) {
|
||||
fSymbols.push_back(nullptr);
|
||||
}
|
||||
@ -218,7 +221,7 @@ private:
|
||||
|
||||
Modifiers modifiers();
|
||||
|
||||
const Symbol* symbol();
|
||||
Symbol* symbol();
|
||||
|
||||
std::unique_ptr<ProgramElement> element();
|
||||
|
||||
@ -228,10 +231,11 @@ private:
|
||||
|
||||
const Type* type();
|
||||
|
||||
Context& fContext;
|
||||
const Context& fContext;
|
||||
ModifiersPool& fModifiers;
|
||||
ErrorReporter* fErrors;
|
||||
std::shared_ptr<SymbolTable> fSymbolTable;
|
||||
std::vector<const Symbol*> fSymbols;
|
||||
std::vector<Symbol*> fSymbols;
|
||||
|
||||
const uint8_t* fStart;
|
||||
const uint8_t* fIP;
|
||||
|
@ -179,7 +179,7 @@ static bool is_bool(const Context& context, const Type& type) {
|
||||
}
|
||||
|
||||
static bool is_out(const Variable& var) {
|
||||
return (var.fModifiers.fFlags & Modifiers::kOut_Flag) != 0;
|
||||
return (var.modifiers().fFlags & Modifiers::kOut_Flag) != 0;
|
||||
}
|
||||
|
||||
void SPIRVCodeGenerator::writeOpCode(SpvOp_ opCode, int length, OutputStream& out) {
|
||||
@ -717,7 +717,7 @@ SpvId SPIRVCodeGenerator::writeIntrinsicCall(const FunctionCall& c, OutputStream
|
||||
SpvId result = this->nextId();
|
||||
std::vector<SpvId> argumentIds;
|
||||
for (size_t i = 0; i < arguments.size(); i++) {
|
||||
if (function.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag) {
|
||||
if (function.fParameters[i]->modifiers().fFlags & Modifiers::kOut_Flag) {
|
||||
argumentIds.push_back(this->getLValue(*arguments[i], out)->getPointer());
|
||||
} else {
|
||||
argumentIds.push_back(this->writeExpression(*arguments[i], out));
|
||||
@ -737,7 +737,7 @@ SpvId SPIRVCodeGenerator::writeIntrinsicCall(const FunctionCall& c, OutputStream
|
||||
SpvId result = this->nextId();
|
||||
std::vector<SpvId> argumentIds;
|
||||
for (size_t i = 0; i < arguments.size(); i++) {
|
||||
if (function.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag) {
|
||||
if (function.fParameters[i]->modifiers().fFlags & Modifiers::kOut_Flag) {
|
||||
argumentIds.push_back(this->getLValue(*arguments[i], out)->getPointer());
|
||||
} else {
|
||||
argumentIds.push_back(this->writeExpression(*arguments[i], out));
|
||||
@ -1564,10 +1564,10 @@ SpvStorageClass_ get_storage_class(const Expression& expr) {
|
||||
switch (expr.kind()) {
|
||||
case Expression::Kind::kVariableReference: {
|
||||
const Variable& var = *expr.as<VariableReference>().fVariable;
|
||||
if (var.fStorage != Variable::kGlobal_Storage) {
|
||||
if (var.storage() != Variable::kGlobal_Storage) {
|
||||
return SpvStorageClassFunction;
|
||||
}
|
||||
SpvStorageClass_ result = get_storage_class(var.fModifiers);
|
||||
SpvStorageClass_ result = get_storage_class(var.modifiers());
|
||||
if (result == SpvStorageClassFunction) {
|
||||
result = SpvStorageClassPrivate;
|
||||
}
|
||||
@ -1727,7 +1727,7 @@ std::unique_ptr<SPIRVCodeGenerator::LValue> SPIRVCodeGenerator::getLValue(const
|
||||
case Expression::Kind::kVariableReference: {
|
||||
SpvId typeId;
|
||||
const Variable& var = *expr.as<VariableReference>().fVariable;
|
||||
if (var.fModifiers.fLayout.fBuiltin == SK_IN_BUILTIN) {
|
||||
if (var.modifiers().fLayout.fBuiltin == SK_IN_BUILTIN) {
|
||||
typeId = this->getType(Type("sk_in", Type::TypeKind::kArray,
|
||||
var.type().componentType(), fSkInCount));
|
||||
} else {
|
||||
@ -1838,7 +1838,7 @@ SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, O
|
||||
SpvId var = entry->second;
|
||||
this->writeInstruction(SpvOpLoad, this->getType(ref.fVariable->type()), result, var, out);
|
||||
this->writePrecisionModifier(ref.fVariable->type(), result);
|
||||
if (ref.fVariable->fModifiers.fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN &&
|
||||
if (ref.fVariable->modifiers().fLayout.fBuiltin == SK_FRAGCOORD_BUILTIN &&
|
||||
(fProgram.fSettings.fFlipY || fProgram.fSettings.fInverseW)) {
|
||||
// The x component never changes, so just grab it
|
||||
SpvId xId = this->nextId();
|
||||
@ -1875,9 +1875,10 @@ SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, O
|
||||
Layout layout(0, -1, -1, binding, -1, set, -1, -1, Layout::Format::kUnspecified,
|
||||
Layout::kUnspecified_Primitive, -1, -1, "", "", Layout::kNo_Key,
|
||||
Layout::CType::kDefault);
|
||||
Modifiers modifiers(layout, Modifiers::kUniform_Flag);
|
||||
const Variable* intfVar = fSynthetics.takeOwnershipOfSymbol(
|
||||
std::make_unique<Variable>(/*offset=*/-1,
|
||||
Modifiers(layout, Modifiers::kUniform_Flag),
|
||||
fModifiers.handle(modifiers),
|
||||
name,
|
||||
&intfStruct,
|
||||
/*builtin=*/false,
|
||||
@ -1946,7 +1947,7 @@ SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, O
|
||||
|
||||
return adjusted;
|
||||
}
|
||||
if (ref.fVariable->fModifiers.fLayout.fBuiltin == SK_CLOCKWISE_BUILTIN &&
|
||||
if (ref.fVariable->modifiers().fLayout.fBuiltin == SK_CLOCKWISE_BUILTIN &&
|
||||
!fProgram.fSettings.fFlipY) {
|
||||
// FrontFacing in Vulkan is defined in terms of a top-down render target. In skia, we use
|
||||
// the default convention of "counter-clockwise face is front".
|
||||
@ -2692,8 +2693,8 @@ static void update_sk_in_count(const Modifiers& m, int* outSkInCount) {
|
||||
}
|
||||
|
||||
SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf, bool appendRTHeight) {
|
||||
bool isBuffer = (0 != (intf.fVariable.fModifiers.fFlags & Modifiers::kBuffer_Flag));
|
||||
bool pushConstant = (0 != (intf.fVariable.fModifiers.fLayout.fFlags &
|
||||
bool isBuffer = (0 != (intf.fVariable.modifiers().fFlags & Modifiers::kBuffer_Flag));
|
||||
bool pushConstant = (0 != (intf.fVariable.modifiers().fLayout.fFlags &
|
||||
Layout::kPushConstant_Flag));
|
||||
MemoryLayout memoryLayout = (pushConstant || isBuffer) ?
|
||||
MemoryLayout(MemoryLayout::k430_Standard) :
|
||||
@ -2710,7 +2711,8 @@ SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf, bool a
|
||||
type = new Type(type->fOffset, type->name(), fields);
|
||||
}
|
||||
SpvId typeId;
|
||||
if (intf.fVariable.fModifiers.fLayout.fBuiltin == SK_IN_BUILTIN) {
|
||||
Modifiers intfModifiers = intf.fVariable.modifiers();
|
||||
if (intfModifiers.fLayout.fBuiltin == SK_IN_BUILTIN) {
|
||||
for (const auto& e : fProgram) {
|
||||
if (e.kind() == ProgramElement::Kind::kModifiers) {
|
||||
const Modifiers& m = ((ModifiersDeclaration&) e).fModifiers;
|
||||
@ -2724,17 +2726,17 @@ SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf, bool a
|
||||
} else {
|
||||
typeId = this->getType(*type, memoryLayout);
|
||||
}
|
||||
if (intf.fVariable.fModifiers.fFlags & Modifiers::kBuffer_Flag) {
|
||||
if (intfModifiers.fFlags & Modifiers::kBuffer_Flag) {
|
||||
this->writeInstruction(SpvOpDecorate, typeId, SpvDecorationBufferBlock, fDecorationBuffer);
|
||||
} else if (intf.fVariable.fModifiers.fLayout.fBuiltin == -1) {
|
||||
} else if (intfModifiers.fLayout.fBuiltin == -1) {
|
||||
this->writeInstruction(SpvOpDecorate, typeId, SpvDecorationBlock, fDecorationBuffer);
|
||||
}
|
||||
SpvStorageClass_ storageClass = get_storage_class(intf.fVariable.fModifiers);
|
||||
SpvStorageClass_ storageClass = get_storage_class(intfModifiers);
|
||||
SpvId ptrType = this->nextId();
|
||||
this->writeInstruction(SpvOpTypePointer, ptrType, storageClass, typeId, fConstantBuffer);
|
||||
this->writeInstruction(SpvOpVariable, ptrType, result, storageClass, fConstantBuffer);
|
||||
Layout layout = intf.fVariable.fModifiers.fLayout;
|
||||
if (intf.fVariable.fModifiers.fFlags & Modifiers::kUniform_Flag && layout.fSet == -1) {
|
||||
Layout layout = intfModifiers.fLayout;
|
||||
if (intfModifiers.fFlags & Modifiers::kUniform_Flag && layout.fSet == -1) {
|
||||
layout.fSet = 0;
|
||||
}
|
||||
this->writeLayout(layout, result);
|
||||
@ -2756,19 +2758,19 @@ void SPIRVCodeGenerator::writePrecisionModifier(Precision precision, SpvId id) {
|
||||
}
|
||||
|
||||
bool is_dead(const Variable& var) {
|
||||
if (var.fReadCount || var.fWriteCount) {
|
||||
if (var.readCount() || var.writeCount()) {
|
||||
return false;
|
||||
}
|
||||
// not entirely sure what the rules are for when it's safe to elide interface variables, but it
|
||||
// causes various problems to elide some of them even when dead. But it also causes problems
|
||||
// *not* to elide sk_SampleMask when it's not being used.
|
||||
if (!(var.fModifiers.fFlags & (Modifiers::kIn_Flag |
|
||||
Modifiers::kOut_Flag |
|
||||
Modifiers::kUniform_Flag |
|
||||
Modifiers::kBuffer_Flag))) {
|
||||
if (!(var.modifiers().fFlags & (Modifiers::kIn_Flag |
|
||||
Modifiers::kOut_Flag |
|
||||
Modifiers::kUniform_Flag |
|
||||
Modifiers::kBuffer_Flag))) {
|
||||
return true;
|
||||
}
|
||||
return var.fModifiers.fLayout.fBuiltin == SK_SAMPLEMASK_BUILTIN;
|
||||
return var.modifiers().fLayout.fBuiltin == SK_SAMPLEMASK_BUILTIN;
|
||||
}
|
||||
|
||||
#define BUILTIN_IGNORE 9999
|
||||
@ -2777,15 +2779,15 @@ void SPIRVCodeGenerator::writeGlobalVar(Program::Kind kind, const VarDeclaration
|
||||
const Variable* var = varDecl.fVar;
|
||||
// These haven't been implemented in our SPIR-V generator yet and we only currently use them
|
||||
// in the OpenGL backend.
|
||||
SkASSERT(!(var->fModifiers.fFlags & (Modifiers::kReadOnly_Flag |
|
||||
Modifiers::kWriteOnly_Flag |
|
||||
Modifiers::kCoherent_Flag |
|
||||
Modifiers::kVolatile_Flag |
|
||||
Modifiers::kRestrict_Flag)));
|
||||
if (var->fModifiers.fLayout.fBuiltin == BUILTIN_IGNORE) {
|
||||
SkASSERT(!(var->modifiers().fFlags & (Modifiers::kReadOnly_Flag |
|
||||
Modifiers::kWriteOnly_Flag |
|
||||
Modifiers::kCoherent_Flag |
|
||||
Modifiers::kVolatile_Flag |
|
||||
Modifiers::kRestrict_Flag)));
|
||||
if (var->modifiers().fLayout.fBuiltin == BUILTIN_IGNORE) {
|
||||
return;
|
||||
}
|
||||
if (var->fModifiers.fLayout.fBuiltin == SK_FRAGCOLOR_BUILTIN &&
|
||||
if (var->modifiers().fLayout.fBuiltin == SK_FRAGCOLOR_BUILTIN &&
|
||||
kind != Program::kFragment_Kind) {
|
||||
SkASSERT(!fProgram.fSettings.fFragColorIsInOut);
|
||||
return;
|
||||
@ -2795,11 +2797,11 @@ void SPIRVCodeGenerator::writeGlobalVar(Program::Kind kind, const VarDeclaration
|
||||
}
|
||||
const Type& type = var->type();
|
||||
SpvStorageClass_ storageClass;
|
||||
if (var->fModifiers.fFlags & Modifiers::kIn_Flag) {
|
||||
if (var->modifiers().fFlags & Modifiers::kIn_Flag) {
|
||||
storageClass = SpvStorageClassInput;
|
||||
} else if (var->fModifiers.fFlags & Modifiers::kOut_Flag) {
|
||||
} else if (var->modifiers().fFlags & Modifiers::kOut_Flag) {
|
||||
storageClass = SpvStorageClassOutput;
|
||||
} else if (var->fModifiers.fFlags & Modifiers::kUniform_Flag) {
|
||||
} else if (var->modifiers().fFlags & Modifiers::kUniform_Flag) {
|
||||
if (type.typeKind() == Type::TypeKind::kSampler ||
|
||||
type.typeKind() == Type::TypeKind::kSeparateSampler ||
|
||||
type.typeKind() == Type::TypeKind::kTexture) {
|
||||
@ -2813,7 +2815,7 @@ void SPIRVCodeGenerator::writeGlobalVar(Program::Kind kind, const VarDeclaration
|
||||
SpvId id = this->nextId();
|
||||
fVariableMap[var] = id;
|
||||
SpvId typeId;
|
||||
if (var->fModifiers.fLayout.fBuiltin == SK_IN_BUILTIN) {
|
||||
if (var->modifiers().fLayout.fBuiltin == SK_IN_BUILTIN) {
|
||||
typeId = this->getPointerType(
|
||||
Type("sk_in", Type::TypeKind::kArray, type.componentType(), fSkInCount),
|
||||
storageClass);
|
||||
@ -2830,11 +2832,11 @@ void SPIRVCodeGenerator::writeGlobalVar(Program::Kind kind, const VarDeclaration
|
||||
this->writeInstruction(SpvOpStore, id, value, fGlobalInitializersBuffer);
|
||||
fCurrentBlock = 0;
|
||||
}
|
||||
this->writeLayout(var->fModifiers.fLayout, id);
|
||||
if (var->fModifiers.fFlags & Modifiers::kFlat_Flag) {
|
||||
this->writeLayout(var->modifiers().fLayout, id);
|
||||
if (var->modifiers().fFlags & Modifiers::kFlat_Flag) {
|
||||
this->writeInstruction(SpvOpDecorate, id, SpvDecorationFlat, fDecorationBuffer);
|
||||
}
|
||||
if (var->fModifiers.fFlags & Modifiers::kNoPerspective_Flag) {
|
||||
if (var->modifiers().fFlags & Modifiers::kNoPerspective_Flag) {
|
||||
this->writeInstruction(SpvOpDecorate, id, SpvDecorationNoPerspective,
|
||||
fDecorationBuffer);
|
||||
}
|
||||
@ -2844,11 +2846,11 @@ void SPIRVCodeGenerator::writeVarDeclaration(const VarDeclaration& varDecl, Outp
|
||||
const Variable* var = varDecl.fVar;
|
||||
// These haven't been implemented in our SPIR-V generator yet and we only currently use them
|
||||
// in the OpenGL backend.
|
||||
SkASSERT(!(var->fModifiers.fFlags & (Modifiers::kReadOnly_Flag |
|
||||
Modifiers::kWriteOnly_Flag |
|
||||
Modifiers::kCoherent_Flag |
|
||||
Modifiers::kVolatile_Flag |
|
||||
Modifiers::kRestrict_Flag)));
|
||||
SkASSERT(!(var->modifiers().fFlags & (Modifiers::kReadOnly_Flag |
|
||||
Modifiers::kWriteOnly_Flag |
|
||||
Modifiers::kCoherent_Flag |
|
||||
Modifiers::kVolatile_Flag |
|
||||
Modifiers::kRestrict_Flag)));
|
||||
SpvId id = this->nextId();
|
||||
fVariableMap[var] = id;
|
||||
SpvId type = this->getPointerType(var->type(), SpvStorageClassFunction);
|
||||
@ -3192,14 +3194,15 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
|
||||
for (const auto& e : program) {
|
||||
if (e.kind() == ProgramElement::Kind::kInterfaceBlock) {
|
||||
InterfaceBlock& intf = (InterfaceBlock&) e;
|
||||
if (SK_IN_BUILTIN == intf.fVariable.fModifiers.fLayout.fBuiltin) {
|
||||
const Modifiers& modifiers = intf.fVariable.modifiers();
|
||||
if (SK_IN_BUILTIN == modifiers.fLayout.fBuiltin) {
|
||||
SkASSERT(skInSize != -1);
|
||||
intf.fSizes.emplace_back(new IntLiteral(fContext, -1, skInSize));
|
||||
}
|
||||
SpvId id = this->writeInterfaceBlock(intf);
|
||||
if (((intf.fVariable.fModifiers.fFlags & Modifiers::kIn_Flag) ||
|
||||
(intf.fVariable.fModifiers.fFlags & Modifiers::kOut_Flag)) &&
|
||||
intf.fVariable.fModifiers.fLayout.fBuiltin == -1 &&
|
||||
if (((modifiers.fFlags & Modifiers::kIn_Flag) ||
|
||||
(modifiers.fFlags & Modifiers::kOut_Flag)) &&
|
||||
modifiers.fLayout.fBuiltin == -1 &&
|
||||
!is_dead(intf.fVariable)) {
|
||||
interfaceVars.insert(id);
|
||||
}
|
||||
@ -3227,9 +3230,9 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
|
||||
}
|
||||
for (auto entry : fVariableMap) {
|
||||
const Variable* var = entry.first;
|
||||
if (var->fStorage == Variable::kGlobal_Storage &&
|
||||
((var->fModifiers.fFlags & Modifiers::kIn_Flag) ||
|
||||
(var->fModifiers.fFlags & Modifiers::kOut_Flag)) && !is_dead(*var)) {
|
||||
if (var->storage() == Variable::kGlobal_Storage &&
|
||||
((var->modifiers().fFlags & Modifiers::kIn_Flag) ||
|
||||
(var->modifiers().fFlags & Modifiers::kOut_Flag)) && !is_dead(*var)) {
|
||||
interfaceVars.insert(entry.second);
|
||||
}
|
||||
}
|
||||
|
@ -104,10 +104,11 @@ public:
|
||||
virtual void store(SpvId value, OutputStream& out) = 0;
|
||||
};
|
||||
|
||||
SPIRVCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
|
||||
OutputStream* out)
|
||||
SPIRVCodeGenerator(const Context* context, ModifiersPool* modifiers,
|
||||
const Program* program, ErrorReporter* errors, OutputStream* out)
|
||||
: INHERITED(program, errors, out)
|
||||
, fContext(*context)
|
||||
, fModifiers(*modifiers)
|
||||
, fDefaultLayout(MemoryLayout::k140_Standard)
|
||||
, fCapabilities(0)
|
||||
, fIdCount(1)
|
||||
@ -366,6 +367,7 @@ private:
|
||||
void writeGeometryShaderExecutionMode(SpvId entryPoint, OutputStream& out);
|
||||
|
||||
const Context& fContext;
|
||||
ModifiersPool& fModifiers;
|
||||
const MemoryLayout fDefaultLayout;
|
||||
|
||||
uint64_t fCapabilities;
|
||||
|
@ -63,8 +63,8 @@ public:
|
||||
}
|
||||
|
||||
static bool IsParameter(const Variable& var) {
|
||||
return (var.fModifiers.fFlags & Modifiers::kIn_Flag) &&
|
||||
-1 == var.fModifiers.fLayout.fBuiltin;
|
||||
return (var.modifiers().fFlags & Modifiers::kIn_Flag) &&
|
||||
-1 == var.modifiers().fLayout.fBuiltin;
|
||||
}
|
||||
|
||||
static bool IsSupportedSection(const char* name) {
|
||||
|
@ -55,7 +55,7 @@ public:
|
||||
std::sort(sortedSymbols.begin(), sortedSymbols.end(),
|
||||
[](const Symbol* a, const Symbol* b) { return a->name() < b->name(); });
|
||||
for (const auto& s : sortedSymbols) {
|
||||
const Expression& initialValue = *s->as<Variable>().fInitialValue;
|
||||
const Expression& initialValue = *s->as<Variable>().initialValue();
|
||||
result += separator + " " + s->name() + " = " +
|
||||
to_string(initialValue.as<IntLiteral>().value());
|
||||
separator = ",\n";
|
||||
|
@ -18,7 +18,7 @@ namespace SkSL {
|
||||
|
||||
struct Expression;
|
||||
class IRGenerator;
|
||||
struct Variable;
|
||||
class Variable;
|
||||
|
||||
using DefinitionMap = TinyUnorderedMap<const Variable*, std::unique_ptr<Expression>*>;
|
||||
|
||||
|
@ -28,7 +28,7 @@ struct FunctionDeclaration : public Symbol {
|
||||
static constexpr Kind kSymbolKind = Kind::kFunctionDeclaration;
|
||||
|
||||
FunctionDeclaration(int offset, Modifiers modifiers, StringFragment name,
|
||||
std::vector<const Variable*> parameters, const Type& returnType,
|
||||
std::vector<Variable*> parameters, const Type& returnType,
|
||||
bool builtin)
|
||||
: INHERITED(offset, kSymbolKind, std::move(name))
|
||||
, fDefinition(nullptr)
|
||||
@ -118,7 +118,7 @@ struct FunctionDeclaration : public Symbol {
|
||||
mutable FunctionDefinition* fDefinition;
|
||||
bool fBuiltin;
|
||||
Modifiers fModifiers;
|
||||
const std::vector<const Variable*> fParameters;
|
||||
const std::vector<Variable*> fParameters;
|
||||
const Type& fReturnType;
|
||||
mutable std::atomic<int> fCallCount = 0;
|
||||
|
||||
|
@ -83,15 +83,10 @@ IRNode::IRNode(int offset, int kind, const TypeTokenData& data)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::IRNode(const IRNode& other)
|
||||
: fOffset(other.fOffset)
|
||||
, fKind(other.fKind)
|
||||
, fData(other.fData) {
|
||||
// For now, we can't use a default copy constructor because of the std::unique_ptr children.
|
||||
// Since we never copy nodes containing children, it's easiest just to assert we don't have any
|
||||
// than bother with cloning them.
|
||||
SkASSERT(other.fExpressionChildren.empty());
|
||||
}
|
||||
IRNode::IRNode(int offset, int kind, const VariableData& data)
|
||||
: fOffset(offset)
|
||||
, fKind(kind)
|
||||
, fData(data) {}
|
||||
|
||||
IRNode::~IRNode() {}
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include "src/sksl/SkSLASTNode.h"
|
||||
#include "src/sksl/SkSLLexer.h"
|
||||
#include "src/sksl/SkSLModifiersPool.h"
|
||||
#include "src/sksl/SkSLString.h"
|
||||
|
||||
#include <algorithm>
|
||||
@ -24,7 +25,7 @@ struct Statement;
|
||||
class Symbol;
|
||||
class SymbolTable;
|
||||
class Type;
|
||||
struct Variable;
|
||||
class Variable;
|
||||
|
||||
/**
|
||||
* Represents a node in the intermediate representation (IR) tree. The IR is a fully-resolved
|
||||
@ -72,6 +73,8 @@ public:
|
||||
return *this->typeData();
|
||||
case NodeData::Kind::kTypeToken:
|
||||
return *this->typeTokenData().fType;
|
||||
case NodeData::Kind::kVariable:
|
||||
return *this->variableData().fType;
|
||||
default:
|
||||
SkUNREACHABLE;
|
||||
}
|
||||
@ -135,7 +138,7 @@ protected:
|
||||
|
||||
struct SymbolAliasData {
|
||||
StringFragment fName;
|
||||
const Symbol* fOrigSymbol;
|
||||
Symbol* fOrigSymbol;
|
||||
};
|
||||
|
||||
struct TypeTokenData {
|
||||
@ -143,6 +146,21 @@ protected:
|
||||
Token::Kind fToken;
|
||||
};
|
||||
|
||||
struct VariableData {
|
||||
StringFragment fName;
|
||||
const Type* fType;
|
||||
const Expression* fInitialValue = nullptr;
|
||||
ModifiersPool::Handle fModifiersHandle;
|
||||
// Tracks how many sites read from the variable. If this is zero for a non-out variable (or
|
||||
// becomes zero during optimization), the variable is dead and may be eliminated.
|
||||
mutable int16_t fReadCount;
|
||||
// Tracks how many sites write to the variable. If this is zero, the variable is dead and
|
||||
// may be eliminated.
|
||||
mutable int16_t fWriteCount;
|
||||
/*Variable::Storage*/int8_t fStorage;
|
||||
bool fBuiltin;
|
||||
};
|
||||
|
||||
struct NodeData {
|
||||
enum class Kind {
|
||||
kBlock,
|
||||
@ -159,6 +177,7 @@ protected:
|
||||
kSymbolAlias,
|
||||
kType,
|
||||
kTypeToken,
|
||||
kVariable,
|
||||
} fKind = Kind::kType;
|
||||
// it doesn't really matter what kind we default to, as long as it's a POD type
|
||||
|
||||
@ -177,6 +196,7 @@ protected:
|
||||
SymbolAliasData fSymbolAlias;
|
||||
const Type* fType;
|
||||
TypeTokenData fTypeToken;
|
||||
VariableData fVariable;
|
||||
|
||||
Contents() {}
|
||||
|
||||
@ -253,6 +273,11 @@ protected:
|
||||
*(new(&fContents) TypeTokenData) = data;
|
||||
}
|
||||
|
||||
NodeData(const VariableData& data)
|
||||
: fKind(Kind::kVariable) {
|
||||
*(new(&fContents) VariableData) = data;
|
||||
}
|
||||
|
||||
NodeData(const NodeData& other) {
|
||||
*this = other;
|
||||
}
|
||||
@ -303,6 +328,9 @@ protected:
|
||||
case Kind::kTypeToken:
|
||||
*(new(&fContents) TypeTokenData) = other.fContents.fTypeToken;
|
||||
break;
|
||||
case Kind::kVariable:
|
||||
*(new(&fContents) VariableData) = other.fContents.fVariable;
|
||||
break;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@ -355,6 +383,9 @@ protected:
|
||||
case Kind::kTypeToken:
|
||||
fContents.fTypeToken.~TypeTokenData();
|
||||
break;
|
||||
case Kind::kVariable:
|
||||
fContents.fVariable.~VariableData();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -388,7 +419,7 @@ protected:
|
||||
|
||||
IRNode(int offset, int kind, const TypeTokenData& data);
|
||||
|
||||
IRNode(const IRNode& other);
|
||||
IRNode(int offset, int kind, const VariableData& data);
|
||||
|
||||
Expression& expressionChild(int index) const {
|
||||
SkASSERT(index >= 0 && index < (int) fExpressionChildren.size());
|
||||
@ -509,6 +540,16 @@ protected:
|
||||
return fData.fContents.fTypeToken;
|
||||
}
|
||||
|
||||
VariableData& variableData() {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kVariable);
|
||||
return fData.fContents.fVariable;
|
||||
}
|
||||
|
||||
const VariableData& variableData() const {
|
||||
SkASSERT(fData.fKind == NodeData::Kind::kVariable);
|
||||
return fData.fContents.fVariable;
|
||||
}
|
||||
|
||||
int fKind;
|
||||
|
||||
NodeData fData;
|
||||
|
@ -49,7 +49,7 @@ struct InterfaceBlock : public ProgramElement {
|
||||
}
|
||||
|
||||
String description() const override {
|
||||
String result = fVariable.fModifiers.description() + fTypeName + " {\n";
|
||||
String result = fVariable.modifiers().description() + fTypeName + " {\n";
|
||||
const Type* structType = &fVariable.type();
|
||||
while (structType->typeKind() == Type::TypeKind::kArray) {
|
||||
structType = &structType->componentType();
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
#include "src/sksl/ir/SkSLLayout.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
/**
|
||||
@ -116,6 +118,17 @@ struct Modifiers {
|
||||
int fFlags;
|
||||
};
|
||||
|
||||
} // namespace SkSL
|
||||
} // namespace SkSL
|
||||
|
||||
namespace std {
|
||||
|
||||
template <>
|
||||
struct hash<SkSL::Modifiers> {
|
||||
size_t operator()(const SkSL::Modifiers& key) const {
|
||||
return key.fFlags ^ (key.fLayout.fFlags << 8) ^ ((unsigned) key.fLayout.fBuiltin << 16);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif
|
||||
|
@ -250,6 +250,7 @@ struct Program {
|
||||
std::shared_ptr<Context> context,
|
||||
std::vector<std::unique_ptr<ProgramElement>>* inheritedElements,
|
||||
std::vector<std::unique_ptr<ProgramElement>> elements,
|
||||
std::unique_ptr<ModifiersPool> modifiers,
|
||||
std::shared_ptr<SymbolTable> symbols,
|
||||
Inputs inputs)
|
||||
: fKind(kind)
|
||||
@ -259,7 +260,8 @@ struct Program {
|
||||
, fSymbols(symbols)
|
||||
, fInputs(inputs)
|
||||
, fInheritedElements(inheritedElements)
|
||||
, fElements(std::move(elements)) {}
|
||||
, fElements(std::move(elements))
|
||||
, fModifiers(std::move(modifiers)) {}
|
||||
|
||||
iterator begin() {
|
||||
if (fInheritedElements) {
|
||||
@ -293,6 +295,10 @@ struct Program {
|
||||
return const_iterator(fElements.end(), fElements.end(), fElements.end(), fElements.end());
|
||||
}
|
||||
|
||||
void finish() {
|
||||
fModifiers->finish();
|
||||
}
|
||||
|
||||
Kind fKind;
|
||||
std::unique_ptr<String> fSource;
|
||||
Settings fSettings;
|
||||
@ -305,6 +311,7 @@ struct Program {
|
||||
private:
|
||||
std::vector<std::unique_ptr<ProgramElement>>* fInheritedElements;
|
||||
std::vector<std::unique_ptr<ProgramElement>> fElements;
|
||||
std::unique_ptr<ModifiersPool> fModifiers;
|
||||
|
||||
friend class Compiler;
|
||||
};
|
||||
|
@ -42,7 +42,9 @@ public:
|
||||
Symbol(int offset, const SymbolAliasData& data)
|
||||
: INHERITED(offset, (int) Kind::kSymbolAlias, data) {}
|
||||
|
||||
Symbol(const Symbol&) = default;
|
||||
Symbol(int offset, const VariableData& data)
|
||||
: INHERITED(offset, (int) Kind::kVariable, data) {}
|
||||
|
||||
Symbol& operator=(const Symbol&) = default;
|
||||
|
||||
~Symbol() override {}
|
||||
|
@ -19,14 +19,14 @@ class SymbolAlias : public Symbol {
|
||||
public:
|
||||
static constexpr Kind kSymbolKind = Kind::kSymbolAlias;
|
||||
|
||||
SymbolAlias(int offset, StringFragment name, const Symbol* origSymbol)
|
||||
SymbolAlias(int offset, StringFragment name, Symbol* origSymbol)
|
||||
: INHERITED(offset, SymbolAliasData{name, origSymbol}) {}
|
||||
|
||||
StringFragment name() const override {
|
||||
return this->symbolAliasData().fName;
|
||||
}
|
||||
|
||||
const Symbol* origSymbol() const {
|
||||
Symbol* origSymbol() const {
|
||||
return this->symbolAliasData().fOrigSymbol;
|
||||
}
|
||||
|
||||
|
@ -23,8 +23,8 @@ std::vector<const FunctionDeclaration*> SymbolTable::GetFunctions(const Symbol&
|
||||
}
|
||||
}
|
||||
|
||||
const Symbol* SymbolTable::operator[](StringFragment name) {
|
||||
const auto& entry = fSymbols.find(name);
|
||||
Symbol* SymbolTable::operator[](StringFragment name) {
|
||||
auto entry = fSymbols.find(name);
|
||||
if (entry == fSymbols.end()) {
|
||||
if (fParent) {
|
||||
return (*fParent)[name];
|
||||
@ -59,7 +59,7 @@ const Symbol* SymbolTable::operator[](StringFragment name) {
|
||||
}
|
||||
}
|
||||
}
|
||||
const Symbol* symbol = entry->second;
|
||||
Symbol* symbol = entry->second;
|
||||
while (symbol && symbol->is<SymbolAlias>()) {
|
||||
symbol = symbol->as<SymbolAlias>().origSymbol();
|
||||
}
|
||||
@ -72,14 +72,14 @@ const String* SymbolTable::takeOwnershipOfString(std::unique_ptr<String> n) {
|
||||
return result;
|
||||
}
|
||||
|
||||
void SymbolTable::addAlias(StringFragment name, const Symbol* symbol) {
|
||||
void SymbolTable::addAlias(StringFragment name, Symbol* symbol) {
|
||||
this->add(name, std::make_unique<SymbolAlias>(symbol->fOffset, name, symbol));
|
||||
}
|
||||
|
||||
void SymbolTable::addWithoutOwnership(StringFragment name, const Symbol* symbol) {
|
||||
void SymbolTable::addWithoutOwnership(StringFragment name, Symbol* symbol) {
|
||||
SkASSERT(symbol->name() == name);
|
||||
|
||||
const Symbol*& refInSymbolTable = fSymbols[name];
|
||||
Symbol*& refInSymbolTable = fSymbols[name];
|
||||
if (refInSymbolTable == nullptr) {
|
||||
refInSymbolTable = symbol;
|
||||
return;
|
||||
@ -106,11 +106,11 @@ void SymbolTable::addWithoutOwnership(StringFragment name, const Symbol* symbol)
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_map<StringFragment, const Symbol*>::iterator SymbolTable::begin() {
|
||||
std::unordered_map<StringFragment, Symbol*>::iterator SymbolTable::begin() {
|
||||
return fSymbols.begin();
|
||||
}
|
||||
|
||||
std::unordered_map<StringFragment, const Symbol*>::iterator SymbolTable::end() {
|
||||
std::unordered_map<StringFragment, Symbol*>::iterator SymbolTable::end() {
|
||||
return fSymbols.end();
|
||||
}
|
||||
|
||||
|
@ -31,38 +31,38 @@ public:
|
||||
: fParent(parent)
|
||||
, fErrorReporter(parent->fErrorReporter) {}
|
||||
|
||||
const Symbol* operator[](StringFragment name);
|
||||
Symbol* operator[](StringFragment name);
|
||||
|
||||
void addAlias(StringFragment name, const Symbol* symbol);
|
||||
void addWithoutOwnership(StringFragment name, const Symbol* symbol);
|
||||
void addAlias(StringFragment name, Symbol* symbol);
|
||||
void addWithoutOwnership(StringFragment name, Symbol* symbol);
|
||||
|
||||
template <typename T>
|
||||
const T* add(StringFragment name, std::unique_ptr<T> symbol) {
|
||||
const T* ptr = symbol.get();
|
||||
T* ptr = symbol.get();
|
||||
this->addWithoutOwnership(name, ptr);
|
||||
this->takeOwnershipOfSymbol(std::move(symbol));
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const T* takeOwnershipOfSymbol(std::unique_ptr<T> symbol) {
|
||||
const T* ptr = symbol.get();
|
||||
T* takeOwnershipOfSymbol(std::unique_ptr<T> symbol) {
|
||||
T* ptr = symbol.get();
|
||||
fOwnedSymbols.push_back(std::move(symbol));
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const T* takeOwnershipOfIRNode(std::unique_ptr<T> node) {
|
||||
const T* ptr = node.get();
|
||||
T* takeOwnershipOfIRNode(std::unique_ptr<T> node) {
|
||||
T* ptr = node.get();
|
||||
fOwnedNodes.push_back(std::move(node));
|
||||
return ptr;
|
||||
}
|
||||
|
||||
const String* takeOwnershipOfString(std::unique_ptr<String> n);
|
||||
|
||||
std::unordered_map<StringFragment, const Symbol*>::iterator begin();
|
||||
std::unordered_map<StringFragment, Symbol*>::iterator begin();
|
||||
|
||||
std::unordered_map<StringFragment, const Symbol*>::iterator end();
|
||||
std::unordered_map<StringFragment, Symbol*>::iterator end();
|
||||
|
||||
std::shared_ptr<SymbolTable> fParent;
|
||||
|
||||
@ -75,7 +75,7 @@ private:
|
||||
|
||||
std::vector<std::unique_ptr<String>> fOwnedStrings;
|
||||
|
||||
std::unordered_map<StringFragment, const Symbol*> fSymbols;
|
||||
std::unordered_map<StringFragment, Symbol*> fSymbols;
|
||||
|
||||
ErrorReporter& fErrorReporter;
|
||||
|
||||
|
@ -47,8 +47,8 @@ struct VarDeclaration : public Statement {
|
||||
}
|
||||
|
||||
String description() const override {
|
||||
String result =
|
||||
fVar->fModifiers.description() + fBaseType.description() + " " + fVar->name();
|
||||
String result = fVar->modifiers().description() + fBaseType.description() + " " +
|
||||
fVar->name();
|
||||
for (const auto& size : fSizes) {
|
||||
if (size) {
|
||||
result += "[" + size->description() + "]";
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "src/sksl/ir/SkSLModifiers.h"
|
||||
#include "src/sksl/ir/SkSLSymbol.h"
|
||||
#include "src/sksl/ir/SkSLType.h"
|
||||
#include "src/sksl/ir/SkSLVariableReference.h"
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
@ -22,7 +23,8 @@ struct Expression;
|
||||
* variable itself (the storage location), which is shared between all VariableReferences which
|
||||
* read or write that storage location.
|
||||
*/
|
||||
struct Variable : public Symbol {
|
||||
class Variable : public Symbol {
|
||||
public:
|
||||
static constexpr Kind kSymbolKind = Kind::kVariable;
|
||||
|
||||
enum Storage {
|
||||
@ -32,53 +34,102 @@ struct Variable : public Symbol {
|
||||
kParameter_Storage
|
||||
};
|
||||
|
||||
Variable(int offset, Modifiers modifiers, StringFragment name, const Type* type,
|
||||
Variable(int offset, ModifiersPool::Handle modifiers, StringFragment name, const Type* type,
|
||||
bool builtin, Storage storage, Expression* initialValue = nullptr)
|
||||
: INHERITED(offset, kSymbolKind, name, type)
|
||||
, fModifiers(modifiers)
|
||||
, fStorage(storage)
|
||||
, fInitialValue(initialValue)
|
||||
, fBuiltin(builtin)
|
||||
, fReadCount(0)
|
||||
, fWriteCount(initialValue ? 1 : 0) {}
|
||||
: INHERITED(offset, VariableData{name, type, initialValue, modifiers, /*readCount=*/0,
|
||||
/*writeCount=*/(int16_t) (initialValue ? 1 : 0),
|
||||
(int8_t) storage, builtin}) {}
|
||||
|
||||
~Variable() override {
|
||||
// can't destroy a variable while there are remaining references to it
|
||||
if (fInitialValue) {
|
||||
--fWriteCount;
|
||||
if (this->initialValue()) {
|
||||
--this->variableData().fWriteCount;
|
||||
}
|
||||
SkASSERT(!fReadCount && !fWriteCount);
|
||||
SkASSERT(!this->variableData().fReadCount && !this->variableData().fWriteCount);
|
||||
}
|
||||
|
||||
const Modifiers& modifiers() const {
|
||||
return *this->variableData().fModifiersHandle;
|
||||
}
|
||||
|
||||
const ModifiersPool::Handle& modifiersHandle() const {
|
||||
return this->variableData().fModifiersHandle;
|
||||
}
|
||||
|
||||
void setModifiersHandle(const ModifiersPool::Handle& handle) {
|
||||
this->variableData().fModifiersHandle = handle;
|
||||
}
|
||||
|
||||
bool isBuiltin() const {
|
||||
return this->variableData().fBuiltin;
|
||||
}
|
||||
|
||||
Storage storage() const {
|
||||
return (Storage) this->variableData().fStorage;
|
||||
}
|
||||
|
||||
const Expression* initialValue() const {
|
||||
return this->variableData().fInitialValue;
|
||||
}
|
||||
|
||||
void setInitialValue(const Expression* initialValue) {
|
||||
SkASSERT(!this->initialValue());
|
||||
SkASSERT(this->variableData().fWriteCount == 0);
|
||||
this->variableData().fInitialValue = initialValue;
|
||||
++this->variableData().fWriteCount;
|
||||
}
|
||||
|
||||
int readCount() const {
|
||||
return this->variableData().fReadCount;
|
||||
}
|
||||
|
||||
int writeCount() const {
|
||||
return this->variableData().fWriteCount;
|
||||
}
|
||||
|
||||
StringFragment name() const override {
|
||||
return this->variableData().fName;
|
||||
}
|
||||
|
||||
String description() const override {
|
||||
return fModifiers.description() + this->type().name() + " " + this->name();
|
||||
return this->modifiers().description() + this->type().name() + " " + this->name();
|
||||
}
|
||||
|
||||
bool dead() const {
|
||||
if ((fStorage != kLocal_Storage && fReadCount) ||
|
||||
(fModifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kOut_Flag |
|
||||
const VariableData& data = this->variableData();
|
||||
const Modifiers& modifiers = this->modifiers();
|
||||
if ((data.fStorage != kLocal_Storage && this->variableData().fReadCount) ||
|
||||
(modifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kOut_Flag |
|
||||
Modifiers::kUniform_Flag | Modifiers::kVarying_Flag))) {
|
||||
return false;
|
||||
}
|
||||
return !fWriteCount ||
|
||||
(!fReadCount && !(fModifiers.fFlags & (Modifiers::kPLS_Flag |
|
||||
Modifiers::kPLSOut_Flag)));
|
||||
return !data.fWriteCount ||
|
||||
(!data.fReadCount && !(modifiers.fFlags & (Modifiers::kPLS_Flag |
|
||||
Modifiers::kPLSOut_Flag)));
|
||||
}
|
||||
|
||||
mutable Modifiers fModifiers;
|
||||
const Storage fStorage;
|
||||
private:
|
||||
void referenceCreated(VariableReference::RefKind refKind) const {
|
||||
if (refKind != VariableReference::kRead_RefKind) {
|
||||
++this->variableData().fWriteCount;
|
||||
}
|
||||
if (refKind != VariableReference::kWrite_RefKind) {
|
||||
++this->variableData().fReadCount;
|
||||
}
|
||||
}
|
||||
|
||||
const Expression* fInitialValue = nullptr;
|
||||
bool fBuiltin;
|
||||
|
||||
// Tracks how many sites read from the variable. If this is zero for a non-out variable (or
|
||||
// becomes zero during optimization), the variable is dead and may be eliminated.
|
||||
mutable int fReadCount;
|
||||
// Tracks how many sites write to the variable. If this is zero, the variable is dead and may be
|
||||
// eliminated.
|
||||
mutable int fWriteCount;
|
||||
void referenceDestroyed(VariableReference::RefKind refKind) const {
|
||||
if (refKind != VariableReference::kRead_RefKind) {
|
||||
--this->variableData().fWriteCount;
|
||||
}
|
||||
if (refKind != VariableReference::kWrite_RefKind) {
|
||||
--this->variableData().fReadCount;
|
||||
}
|
||||
}
|
||||
|
||||
using INHERITED = Symbol;
|
||||
|
||||
friend struct VariableReference;
|
||||
};
|
||||
|
||||
} // namespace SkSL
|
||||
|
@ -19,41 +19,41 @@ VariableReference::VariableReference(int offset, const Variable* variable, RefKi
|
||||
, fVariable(variable)
|
||||
, fRefKind(refKind) {
|
||||
SkASSERT(fVariable);
|
||||
this->incrementRefs();
|
||||
fVariable->referenceCreated(fRefKind);
|
||||
}
|
||||
|
||||
VariableReference::~VariableReference() {
|
||||
this->decrementRefs();
|
||||
fVariable->referenceDestroyed(fRefKind);
|
||||
}
|
||||
|
||||
void VariableReference::incrementRefs() const {
|
||||
if (fRefKind != kRead_RefKind) {
|
||||
fVariable->fWriteCount++;
|
||||
}
|
||||
if (fRefKind != kWrite_RefKind) {
|
||||
fVariable->fReadCount++;
|
||||
bool VariableReference::hasProperty(Property property) const {
|
||||
switch (property) {
|
||||
case Property::kSideEffects: return false;
|
||||
case Property::kContainsRTAdjust: return fVariable->name() == "sk_RTAdjust";
|
||||
default:
|
||||
SkASSERT(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void VariableReference::decrementRefs() const {
|
||||
if (fRefKind != kRead_RefKind) {
|
||||
fVariable->fWriteCount--;
|
||||
}
|
||||
if (fRefKind != kWrite_RefKind) {
|
||||
fVariable->fReadCount--;
|
||||
}
|
||||
bool VariableReference::isConstantOrUniform() const {
|
||||
return (fVariable->modifiers().fFlags & Modifiers::kUniform_Flag) != 0;
|
||||
}
|
||||
|
||||
String VariableReference::description() const {
|
||||
return fVariable->name();
|
||||
}
|
||||
|
||||
void VariableReference::setRefKind(RefKind refKind) {
|
||||
this->decrementRefs();
|
||||
fVariable->referenceDestroyed(fRefKind);
|
||||
fRefKind = refKind;
|
||||
this->incrementRefs();
|
||||
fVariable->referenceCreated(fRefKind);
|
||||
}
|
||||
|
||||
void VariableReference::setVariable(const Variable* variable) {
|
||||
this->decrementRefs();
|
||||
fVariable->referenceDestroyed(fRefKind);
|
||||
fVariable = variable;
|
||||
this->incrementRefs();
|
||||
fVariable->referenceCreated(fRefKind);
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression> VariableReference::constantPropagate(const IRGenerator& irGenerator,
|
||||
@ -61,10 +61,11 @@ std::unique_ptr<Expression> VariableReference::constantPropagate(const IRGenerat
|
||||
if (fRefKind != kRead_RefKind) {
|
||||
return nullptr;
|
||||
}
|
||||
if ((fVariable->fModifiers.fFlags & Modifiers::kConst_Flag) && fVariable->fInitialValue &&
|
||||
fVariable->fInitialValue->isCompileTimeConstant() &&
|
||||
const Expression* initialValue = fVariable->initialValue();
|
||||
if ((fVariable->modifiers().fFlags & Modifiers::kConst_Flag) && initialValue &&
|
||||
initialValue->isCompileTimeConstant() &&
|
||||
this->type().typeKind() != Type::TypeKind::kArray) {
|
||||
return fVariable->fInitialValue->clone();
|
||||
return initialValue->clone();
|
||||
}
|
||||
auto exprIter = definitions.find(fVariable);
|
||||
if (exprIter != definitions.end() && exprIter->second &&
|
||||
|
@ -9,11 +9,11 @@
|
||||
#define SKSL_VARIABLEREFERENCE
|
||||
|
||||
#include "src/sksl/ir/SkSLExpression.h"
|
||||
#include "src/sksl/ir/SkSLVariable.h"
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
class IRGenerator;
|
||||
class Variable;
|
||||
|
||||
/**
|
||||
* A reference to a variable, through which it can be read or written. In the statement:
|
||||
@ -48,27 +48,15 @@ struct VariableReference : public Expression {
|
||||
void setRefKind(RefKind refKind);
|
||||
void setVariable(const Variable* variable);
|
||||
|
||||
bool hasProperty(Property property) const override {
|
||||
switch (property) {
|
||||
case Property::kSideEffects: return false;
|
||||
case Property::kContainsRTAdjust: return fVariable->name() == "sk_RTAdjust";
|
||||
default:
|
||||
SkASSERT(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool hasProperty(Property property) const override;
|
||||
|
||||
bool isConstantOrUniform() const override {
|
||||
return (fVariable->fModifiers.fFlags & Modifiers::kUniform_Flag) != 0;
|
||||
}
|
||||
bool isConstantOrUniform() const override;
|
||||
|
||||
std::unique_ptr<Expression> clone() const override {
|
||||
return std::unique_ptr<Expression>(new VariableReference(fOffset, fVariable, fRefKind));
|
||||
}
|
||||
|
||||
String description() const override {
|
||||
return fVariable->name();
|
||||
}
|
||||
String description() const override;
|
||||
|
||||
std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
|
||||
const DefinitionMap& definitions) override;
|
||||
@ -77,9 +65,6 @@ struct VariableReference : public Expression {
|
||||
RefKind fRefKind;
|
||||
|
||||
private:
|
||||
void incrementRefs() const;
|
||||
void decrementRefs() const;
|
||||
|
||||
using INHERITED = Expression;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user