diff --git a/src/core/SkRuntimeEffect.cpp b/src/core/SkRuntimeEffect.cpp index 5277aa24c3..5e57629a9a 100644 --- a/src/core/SkRuntimeEffect.cpp +++ b/src/core/SkRuntimeEffect.cpp @@ -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; } diff --git a/src/sksl/SkSLAnalysis.cpp b/src/sksl/SkSLAnalysis.cpp index 9804945841..857bdc3e14 100644 --- a/src/sksl/SkSLAnalysis.cpp +++ b/src/sksl/SkSLAnalysis.cpp @@ -139,7 +139,7 @@ public: bool visitExpression(const Expression& e) override { if (e.is()) { const VariableReference& var = e.as(); - 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(); 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) { diff --git a/src/sksl/SkSLAnalysis.h b/src/sksl/SkSLAnalysis.h index c606dc0b63..c6ce66fecb 100644 --- a/src/sksl/SkSLAnalysis.h +++ b/src/sksl/SkSLAnalysis.h @@ -21,7 +21,7 @@ struct FunctionDefinition; struct Program; struct ProgramElement; struct Statement; -struct Variable; +class Variable; struct VariableReference; /** diff --git a/src/sksl/SkSLByteCodeGenerator.cpp b/src/sksl/SkSLByteCodeGenerator.cpp index f71328df11..dc5a40684e 100644 --- a/src/sksl/SkSLByteCodeGenerator.cpp +++ b/src/sksl/SkSLByteCodeGenerator.cpp @@ -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 ByteCodeGenerator::writeFunction(const Functio static int expression_as_builtin(const Expression& e) { if (e.is()) { const Variable& var(*e.as().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()) { const GlobalVarDeclaration& decl = e.as(); 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; } } diff --git a/src/sksl/SkSLCPPCodeGenerator.cpp b/src/sksl/SkSLCPPCodeGenerator.cpp index 77a393309b..dd719735f8 100644 --- a/src/sksl/SkSLCPPCodeGenerator.cpp +++ b/src/sksl/SkSLCPPCodeGenerator.cpp @@ -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(); 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& 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& 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()) { const VarDeclaration& decl = *p.as().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()); } diff --git a/src/sksl/SkSLCPPUniformCTypes.h b/src/sksl/SkSLCPPUniformCTypes.h index f3455e9dd0..1db23ac3c5 100644 --- a/src/sksl/SkSLCPPUniformCTypes.h +++ b/src/sksl/SkSLCPPUniformCTypes.h @@ -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 diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp index 55f5c25359..de6a241e1e 100644 --- a/src/sksl/SkSLCompiler.cpp +++ b/src/sksl/SkSLCompiler.cpp @@ -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(/*offset=*/-1, Modifiers(), skCapsName, - fContext->fSkCaps_Type.get(), + std::make_unique(/*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> 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> 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> 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_ptrkind()) { case Expression::Kind::kVariableReference: { const Variable& var = *lvalue->as().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(); 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*) &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 Compiler::convertProgram( fErrorText = ""; fErrorCount = 0; - fInliner.reset(context(), settings); + fInliner.reset(&fIRGenerator->fContext, fIRGenerator->fModifiers.get(), &settings); std::vector>* inherited; std::vector> elements; switch (kind) { @@ -1627,6 +1640,7 @@ std::unique_ptr 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 diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h index 6de2480dd9..1a18b77632 100644 --- a/src/sksl/SkSLCompiler.h +++ b/src/sksl/SkSLCompiler.h @@ -252,6 +252,9 @@ private: std::shared_ptr fFPSymbolTable; std::unique_ptr fFPIntrinsics; + // holds ModifiersPools belonging to the core includes for lifetime purposes + std::vector> fModifiers; + Inliner fInliner; std::unique_ptr fIRGenerator; int fFlags; diff --git a/src/sksl/SkSLDehydrator.cpp b/src/sksl/SkSLDehydrator.cpp index c2619ecbb1..b67bf65491 100644 --- a/src/sksl/SkSLDehydrator.cpp +++ b/src/sksl/SkSLDehydrator.cpp @@ -216,10 +216,10 @@ void Dehydrator::write(const Symbol& s) { const Variable& v = s.as(); 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& s : en.symbols()->fOwnedSymbols) { SkASSERT(s->kind() == Symbol::Kind::kVariable); Variable& v = (Variable&) *s; - SkASSERT(v.fInitialValue); - const IntLiteral& i = v.fInitialValue->as(); + SkASSERT(v.initialValue()); + const IntLiteral& i = v.initialValue()->as(); this->writeS32(i.value()); } break; diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp index 66452fdacc..9541eb9944 100644 --- a/src/sksl/SkSLGLSLCodeGenerator.cpp +++ b/src/sksl/SkSLGLSLCodeGenerator.cpp @@ -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 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().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 { diff --git a/src/sksl/SkSLHCodeGenerator.cpp b/src/sksl/SkSLHCodeGenerator.cpp index 291b8dcf53..fb4ffe65f3 100644 --- a/src/sksl/SkSLHCodeGenerator.cpp +++ b/src/sksl/SkSLHCodeGenerator.cpp @@ -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()); } } diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp index e883af874e..fc6bd2d841 100644 --- a/src/sksl/SkSLIRGenerator.cpp +++ b/src/sksl/SkSLIRGenerator.cpp @@ -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 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 IRGenerator::releaseModifiers() { + std::unique_ptr result = std::move(fModifiers); + fModifiers = std::make_unique(); + return result; } std::unique_ptr IRGenerator::convertSingleStatement(const ASTNode& statement) { @@ -444,8 +453,8 @@ std::vector> IRGenerator::convertVarDeclarations( sizes.push_back(nullptr); } } - auto var = std::make_unique(varDecl.fOffset, modifiers, varData.fName, type, - fIsBuiltinCode, storage); + auto var = std::make_unique(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> 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().fModifiers.fLayout.fBuiltin >= 0) { + symbol->as().modifiers().fLayout.fBuiltin >= 0) { // Already defined, just update the modifiers. - symbol->as().fModifiers = var->fModifiers; + symbol->as().setModifiersHandle(var->modifiersHandle()); } else { varDecls.emplace_back(std::make_unique( var.get(), baseType, std::move(sizes), std::move(value))); @@ -500,9 +508,11 @@ std::unique_ptr IRGenerator::convertModifiersDeclaration(c fInvocations = modifiers.fLayout.fInvocations; if (fSettings->fCaps && !fSettings->fCaps->gsInvocationsSupport()) { modifiers.fLayout.fInvocations = -1; - const Variable& invocationId = (*fSymbolTable)["sk_InvocationID"]->as(); - invocationId.fModifiers.fFlags = 0; - invocationId.fModifiers.fLayout.fBuiltin = -1; + Variable& invocationId = (*fSymbolTable)["sk_InvocationID"]->as(); + 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 IRGenerator::applyInvocationIDWorkaround(std::unique_ptr< "_invoke", std::make_unique(/*offset=*/-1, invokeModifiers, "_invoke", - std::vector(), + std::vector(), *fContext.fVoid_Type, /*builtin=*/false)); fProgramElements->push_back(std::make_unique(/*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 parameters; + std::vector 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(param.fOffset, pd.fModifiers, name, type, - fIsBuiltinCode, Variable::kParameter_Storage)); + Variable* var = fSymbolTable->takeOwnershipOfSymbol( + std::make_unique(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 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 IRGenerator::convertInterfaceBlock(const ASTNode sizes.push_back(nullptr); } } - const Variable* var = old->takeOwnershipOfSymbol( + Variable* var = old->takeOwnershipOfSymbol( std::make_unique(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().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(e.fOffset, modifiers, child.getString(), type, - fIsBuiltinCode, Variable::kGlobal_Storage, value.get())); + std::make_unique(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 IRGenerator::convertIdentifier(const ASTNode& identi } case Symbol::Kind::kVariable: { const Variable* var = &result->as(); - 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 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
IRGenerator::convertSection(const ASTNode& s) { section.fText); } - std::unique_ptr IRGenerator::coerce(std::unique_ptr expr, const Type& type) { if (!expr) { @@ -2109,7 +2122,7 @@ std::unique_ptr 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 IRGenerator::convertTypeField(int offset, const Type ASTNode(&fFile->fNodes, offset, ASTNode::Kind::kIdentifier, field)); if (result) { const Variable& v = *result->as().fVariable; - SkASSERT(v.fInitialValue); + SkASSERT(v.initialValue()); result = std::make_unique( - offset, v.fInitialValue->as().value(), &type); + offset, v.initialValue()->as().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( - 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() && e.as().fVariable->fBuiltin) { + if (e.is() && e.as().fVariable->isBuiltin()) { const Variable* sharedVar = e.as().fVariable; this->cloneVariable(sharedVar->name()); diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h index 9ba9e77296..5e60f703a3 100644 --- a/src/sksl/SkSLIRGenerator.h +++ b/src/sksl/SkSLIRGenerator.h @@ -123,6 +123,11 @@ private: */ void finish(); + /** + * Relinquishes ownership of the Modifiers that have been collected so far and returns them. + */ + std::unique_ptr 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 fModifiers; friend class AutoSymbolTable; friend class AutoLoopLevel; diff --git a/src/sksl/SkSLInliner.cpp b/src/sksl/SkSLInliner.cpp index 5b3fb4e5ed..1755bdf039 100644 --- a/src/sksl/SkSLInliner.cpp +++ b/src/sksl/SkSLInliner.cpp @@ -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 Inliner::inlineStatement(int offset, const Type* typePtr = copy_if_needed(&old->type(), *symbolTableForStatement); const Variable* clone = symbolTableForStatement->takeOwnershipOfSymbol( std::make_unique(offset, - old->fModifiers, + old->modifiersHandle(), namePtr->c_str(), typePtr, isBuiltinCode, - old->fStorage, + old->storage(), initialValue.get())); (*varMap)[old] = std::make_unique(offset, clone); return std::make_unique(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(/*offset=*/-1, Modifiers(), nameFrag, type, - caller->fBuiltin, Variable::kLocal_Storage, - initialValue->get()); + auto newVar = std::make_unique(/*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 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(); @@ -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(*fContext, offset, + inlinedCall.fReplacementExpr = std::make_unique(*fContext, + offset, /*value=*/false); } diff --git a/src/sksl/SkSLInliner.h b/src/sksl/SkSLInliner.h index 7a723b77a2..8f9d3829d8 100644 --- a/src/sksl/SkSLInliner.h +++ b/src/sksl/SkSLInliner.h @@ -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; }; diff --git a/src/sksl/SkSLMetalCodeGenerator.cpp b/src/sksl/SkSLMetalCodeGenerator.cpp index 2ef54519d2..8dfb0f967c 100644 --- a/src/sksl/SkSLMetalCodeGenerator.cpp +++ b/src/sksl/SkSLMetalCodeGenerator.cpp @@ -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() && - left.as().fVariable->fStorage == Variable::kParameter_Storage && - left.as().fVariable->fModifiers.fFlags & Modifiers::kOut_Flag) { + left.as().fVariable->storage() == Variable::kParameter_Storage && + left.as().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(); 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 "); 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 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()) { const GlobalVarDeclaration& decls = e.as(); 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()) { const GlobalVarDeclaration& decls = e.as(); 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()) { const GlobalVarDeclaration& decls = e.as(); 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(); 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().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(); + 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 { diff --git a/src/sksl/SkSLModifiersPool.h b/src/sksl/SkSLModifiersPool.h new file mode 100644 index 0000000000..31e9bc4939 --- /dev/null +++ b/src/sksl/SkSLModifiersPool.h @@ -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 + +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 fModifiers; + std::unordered_map fModifiersMap; +}; + +} // namespace SkSL + +#endif diff --git a/src/sksl/SkSLPipelineStageCodeGenerator.cpp b/src/sksl/SkSLPipelineStageCodeGenerator.cpp index 35e2aaead0..8b03c5bfe2 100644 --- a/src/sksl/SkSLPipelineStageCodeGenerator.cpp +++ b/src/sksl/SkSLPipelineStageCodeGenerator.cpp @@ -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()) { const Variable& var = *p.as().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; } } diff --git a/src/sksl/SkSLRehydrator.cpp b/src/sksl/SkSLRehydrator.cpp index c778bf4d99..3e9d7bf804 100644 --- a/src/sksl/SkSLRehydrator.cpp +++ b/src/sksl/SkSLRehydrator.cpp @@ -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(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(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 parameters; + std::vector parameters; parameters.reserve(parameterCount); for (int i = 0; i < parameterCount; ++i) { parameters.push_back(this->symbolRef(Symbol::Kind::kVariable)); } const Type* returnType = this->type(); - const FunctionDeclaration* result = + FunctionDeclaration* result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique( /*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(Symbol::Kind::kVariable); uint8_t index = this->readU8(); - const Field* result = fSymbolTable->takeOwnershipOfSymbol( + Field* result = fSymbolTable->takeOwnershipOfSymbol( std::make_unique(/*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(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(/*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(/*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(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* result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique( /*offset=*/-1, m, name, type, /*builtin=*/true, storage)); this->addSymbol(id, result); return result; @@ -285,9 +285,8 @@ std::unique_ptr Rehydrator::element() { SkASSERT(s->kind() == Symbol::Kind::kVariable); Variable& v = (Variable&) *s; int value = this->readS32(); - v.fInitialValue = symbols->takeOwnershipOfIRNode( - std::make_unique(fContext, /*offset=*/-1, value)); - v.fWriteCount = 1; + v.setInitialValue(symbols->takeOwnershipOfIRNode( + std::make_unique(fContext, /*offset=*/-1, value))); } return std::unique_ptr(new Enum(-1, typeName, std::move(symbols))); } @@ -429,9 +428,7 @@ std::unique_ptr Rehydrator::statement() { } std::unique_ptr value = this->expression(); if (value) { - var->fInitialValue = value.get(); - SkASSERT(var->fWriteCount == 0); - ++var->fWriteCount; + var->setInitialValue(value.get()); } return std::unique_ptr( new VarDeclaration(var, baseType, std::move(sizes), std::move(value))); @@ -567,7 +564,7 @@ std::shared_ptr Rehydrator::symbolTable(bool inherit) { std::shared_ptr result = inherit ? std::make_shared(fSymbolTable) : std::make_shared(fErrors); fSymbolTable = result; - std::vector ownedSymbols; + std::vector ownedSymbols; ownedSymbols.reserve(ownedCount); for (int i = 0; i < ownedCount; ++i) { ownedSymbols.push_back(this->symbol()); diff --git a/src/sksl/SkSLRehydrator.h b/src/sksl/SkSLRehydrator.h index 18bdda4185..f254f05562 100644 --- a/src/sksl/SkSLRehydrator.h +++ b/src/sksl/SkSLRehydrator.h @@ -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, - ErrorReporter* errorReporter, const uint8_t* src, size_t length) + Rehydrator(const Context* context, ModifiersPool* modifiers, + std::shared_ptr 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 element(); @@ -228,10 +231,11 @@ private: const Type* type(); - Context& fContext; + const Context& fContext; + ModifiersPool& fModifiers; ErrorReporter* fErrors; std::shared_ptr fSymbolTable; - std::vector fSymbols; + std::vector fSymbols; const uint8_t* fStart; const uint8_t* fIP; diff --git a/src/sksl/SkSLSPIRVCodeGenerator.cpp b/src/sksl/SkSLSPIRVCodeGenerator.cpp index 05cbea6972..5e7dbabb96 100644 --- a/src/sksl/SkSLSPIRVCodeGenerator.cpp +++ b/src/sksl/SkSLSPIRVCodeGenerator.cpp @@ -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 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 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().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::getLValue(const case Expression::Kind::kVariableReference: { SpvId typeId; const Variable& var = *expr.as().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(/*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); } } diff --git a/src/sksl/SkSLSPIRVCodeGenerator.h b/src/sksl/SkSLSPIRVCodeGenerator.h index 2bc8b32468..21f9f4ec03 100644 --- a/src/sksl/SkSLSPIRVCodeGenerator.h +++ b/src/sksl/SkSLSPIRVCodeGenerator.h @@ -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; diff --git a/src/sksl/SkSLSectionAndParameterHelper.h b/src/sksl/SkSLSectionAndParameterHelper.h index e35f27d4cf..6dc7cf4a4c 100644 --- a/src/sksl/SkSLSectionAndParameterHelper.h +++ b/src/sksl/SkSLSectionAndParameterHelper.h @@ -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) { diff --git a/src/sksl/ir/SkSLEnum.h b/src/sksl/ir/SkSLEnum.h index 6859f48e4c..c5bbadd16e 100644 --- a/src/sksl/ir/SkSLEnum.h +++ b/src/sksl/ir/SkSLEnum.h @@ -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().fInitialValue; + const Expression& initialValue = *s->as().initialValue(); result += separator + " " + s->name() + " = " + to_string(initialValue.as().value()); separator = ",\n"; diff --git a/src/sksl/ir/SkSLExpression.h b/src/sksl/ir/SkSLExpression.h index 76462689f2..746f4ce441 100644 --- a/src/sksl/ir/SkSLExpression.h +++ b/src/sksl/ir/SkSLExpression.h @@ -18,7 +18,7 @@ namespace SkSL { struct Expression; class IRGenerator; -struct Variable; +class Variable; using DefinitionMap = TinyUnorderedMap*>; diff --git a/src/sksl/ir/SkSLFunctionDeclaration.h b/src/sksl/ir/SkSLFunctionDeclaration.h index f4bfbd0745..ffbd3d1624 100644 --- a/src/sksl/ir/SkSLFunctionDeclaration.h +++ b/src/sksl/ir/SkSLFunctionDeclaration.h @@ -28,7 +28,7 @@ struct FunctionDeclaration : public Symbol { static constexpr Kind kSymbolKind = Kind::kFunctionDeclaration; FunctionDeclaration(int offset, Modifiers modifiers, StringFragment name, - std::vector parameters, const Type& returnType, + std::vector 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 fParameters; + const std::vector fParameters; const Type& fReturnType; mutable std::atomic fCallCount = 0; diff --git a/src/sksl/ir/SkSLIRNode.cpp b/src/sksl/ir/SkSLIRNode.cpp index 3361ebb390..7fbcd4eb79 100644 --- a/src/sksl/ir/SkSLIRNode.cpp +++ b/src/sksl/ir/SkSLIRNode.cpp @@ -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() {} diff --git a/src/sksl/ir/SkSLIRNode.h b/src/sksl/ir/SkSLIRNode.h index 012d3dce89..18c9b2f71e 100644 --- a/src/sksl/ir/SkSLIRNode.h +++ b/src/sksl/ir/SkSLIRNode.h @@ -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 @@ -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; diff --git a/src/sksl/ir/SkSLInterfaceBlock.h b/src/sksl/ir/SkSLInterfaceBlock.h index 2bc2f79607..cee0a22d61 100644 --- a/src/sksl/ir/SkSLInterfaceBlock.h +++ b/src/sksl/ir/SkSLInterfaceBlock.h @@ -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(); diff --git a/src/sksl/ir/SkSLModifiers.h b/src/sksl/ir/SkSLModifiers.h index f830b0ff09..7030377559 100644 --- a/src/sksl/ir/SkSLModifiers.h +++ b/src/sksl/ir/SkSLModifiers.h @@ -10,6 +10,8 @@ #include "src/sksl/ir/SkSLLayout.h" +#include + namespace SkSL { /** @@ -116,6 +118,17 @@ struct Modifiers { int fFlags; }; -} // namespace SkSL +} // namespace SkSL + +namespace std { + +template <> +struct hash { + size_t operator()(const SkSL::Modifiers& key) const { + return key.fFlags ^ (key.fLayout.fFlags << 8) ^ ((unsigned) key.fLayout.fBuiltin << 16); + } +}; + +} // namespace std #endif diff --git a/src/sksl/ir/SkSLProgram.h b/src/sksl/ir/SkSLProgram.h index bf22189dfe..0a5d667de1 100644 --- a/src/sksl/ir/SkSLProgram.h +++ b/src/sksl/ir/SkSLProgram.h @@ -250,6 +250,7 @@ struct Program { std::shared_ptr context, std::vector>* inheritedElements, std::vector> elements, + std::unique_ptr modifiers, std::shared_ptr 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 fSource; Settings fSettings; @@ -305,6 +311,7 @@ struct Program { private: std::vector>* fInheritedElements; std::vector> fElements; + std::unique_ptr fModifiers; friend class Compiler; }; diff --git a/src/sksl/ir/SkSLSymbol.h b/src/sksl/ir/SkSLSymbol.h index 3d18c1ad4b..76e7c58a19 100644 --- a/src/sksl/ir/SkSLSymbol.h +++ b/src/sksl/ir/SkSLSymbol.h @@ -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 {} diff --git a/src/sksl/ir/SkSLSymbolAlias.h b/src/sksl/ir/SkSLSymbolAlias.h index 109824fb77..a84f25ff2e 100644 --- a/src/sksl/ir/SkSLSymbolAlias.h +++ b/src/sksl/ir/SkSLSymbolAlias.h @@ -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; } diff --git a/src/sksl/ir/SkSLSymbolTable.cpp b/src/sksl/ir/SkSLSymbolTable.cpp index 26a7cb671b..5e9b30ee9f 100644 --- a/src/sksl/ir/SkSLSymbolTable.cpp +++ b/src/sksl/ir/SkSLSymbolTable.cpp @@ -23,8 +23,8 @@ std::vector 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()) { symbol = symbol->as().origSymbol(); } @@ -72,14 +72,14 @@ const String* SymbolTable::takeOwnershipOfString(std::unique_ptr n) { return result; } -void SymbolTable::addAlias(StringFragment name, const Symbol* symbol) { +void SymbolTable::addAlias(StringFragment name, Symbol* symbol) { this->add(name, std::make_unique(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::iterator SymbolTable::begin() { +std::unordered_map::iterator SymbolTable::begin() { return fSymbols.begin(); } -std::unordered_map::iterator SymbolTable::end() { +std::unordered_map::iterator SymbolTable::end() { return fSymbols.end(); } diff --git a/src/sksl/ir/SkSLSymbolTable.h b/src/sksl/ir/SkSLSymbolTable.h index b10341c102..1c36de0f29 100644 --- a/src/sksl/ir/SkSLSymbolTable.h +++ b/src/sksl/ir/SkSLSymbolTable.h @@ -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 const T* add(StringFragment name, std::unique_ptr symbol) { - const T* ptr = symbol.get(); + T* ptr = symbol.get(); this->addWithoutOwnership(name, ptr); this->takeOwnershipOfSymbol(std::move(symbol)); return ptr; } template - const T* takeOwnershipOfSymbol(std::unique_ptr symbol) { - const T* ptr = symbol.get(); + T* takeOwnershipOfSymbol(std::unique_ptr symbol) { + T* ptr = symbol.get(); fOwnedSymbols.push_back(std::move(symbol)); return ptr; } template - const T* takeOwnershipOfIRNode(std::unique_ptr node) { - const T* ptr = node.get(); + T* takeOwnershipOfIRNode(std::unique_ptr node) { + T* ptr = node.get(); fOwnedNodes.push_back(std::move(node)); return ptr; } const String* takeOwnershipOfString(std::unique_ptr n); - std::unordered_map::iterator begin(); + std::unordered_map::iterator begin(); - std::unordered_map::iterator end(); + std::unordered_map::iterator end(); std::shared_ptr fParent; @@ -75,7 +75,7 @@ private: std::vector> fOwnedStrings; - std::unordered_map fSymbols; + std::unordered_map fSymbols; ErrorReporter& fErrorReporter; diff --git a/src/sksl/ir/SkSLVarDeclarations.h b/src/sksl/ir/SkSLVarDeclarations.h index 21883f5d24..5ddb4b635b 100644 --- a/src/sksl/ir/SkSLVarDeclarations.h +++ b/src/sksl/ir/SkSLVarDeclarations.h @@ -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() + "]"; diff --git a/src/sksl/ir/SkSLVariable.h b/src/sksl/ir/SkSLVariable.h index e1a21c8966..e5a39dd222 100644 --- a/src/sksl/ir/SkSLVariable.h +++ b/src/sksl/ir/SkSLVariable.h @@ -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 diff --git a/src/sksl/ir/SkSLVariableReference.cpp b/src/sksl/ir/SkSLVariableReference.cpp index 13872877c0..376036a4b2 100644 --- a/src/sksl/ir/SkSLVariableReference.cpp +++ b/src/sksl/ir/SkSLVariableReference.cpp @@ -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 VariableReference::constantPropagate(const IRGenerator& irGenerator, @@ -61,10 +61,11 @@ std::unique_ptr 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 && diff --git a/src/sksl/ir/SkSLVariableReference.h b/src/sksl/ir/SkSLVariableReference.h index 6f38b9c6c4..7b98ed55d2 100644 --- a/src/sksl/ir/SkSLVariableReference.h +++ b/src/sksl/ir/SkSLVariableReference.h @@ -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 clone() const override { return std::unique_ptr(new VariableReference(fOffset, fVariable, fRefKind)); } - String description() const override { - return fVariable->name(); - } + String description() const override; std::unique_ptr 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; };