SkSL::Program: Maintain a separate list of shared program elements
Change program iteration so that default iteration (over owned & shared elements) only permits const access. Add a separate non-const iterator that only visits owned elements. Initially, nothing is being placed in the shared list. Follow-up CLs will move builtin variable declarations, builtin functions, etc. Bug: skia:10905 Change-Id: I9a5b11170117bad3ff6a43aab780c1189904417c Reviewed-on: https://skia-review.googlesource.com/c/skia/+/330477 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: John Stiles <johnstiles@google.com>
This commit is contained in:
parent
1c49494d71
commit
133724cc02
@ -187,7 +187,7 @@ SkRuntimeEffect::EffectResult SkRuntimeEffect::Make(SkString sksl) {
|
||||
const SkSL::Context& ctx(compiler->context());
|
||||
|
||||
// Go through program elements, pulling out information that we need
|
||||
for (const auto& elem : program->elements()) {
|
||||
for (const SkSL::ProgramElement* elem : program->elements()) {
|
||||
// Variables (uniform, varying, etc.)
|
||||
if (elem->is<SkSL::GlobalVarDeclaration>()) {
|
||||
const SkSL::GlobalVarDeclaration& global = elem->as<SkSL::GlobalVarDeclaration>();
|
||||
|
@ -442,9 +442,8 @@ bool Analysis::IsAssignable(Expression& expr, VariableReference** assignableVar,
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// ProgramVisitor
|
||||
|
||||
template <typename PROG, typename EXPR, typename STMT, typename ELEM>
|
||||
bool TProgramVisitor<PROG, EXPR, STMT, ELEM>::visit(PROG program) {
|
||||
for (const auto& pe : program.elements()) {
|
||||
bool ProgramVisitor::visit(const Program& program) {
|
||||
for (const ProgramElement* pe : program.elements()) {
|
||||
if (this->visitProgramElement(*pe)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -66,8 +66,6 @@ class TProgramVisitor {
|
||||
public:
|
||||
virtual ~TProgramVisitor() = default;
|
||||
|
||||
bool visit(PROG program);
|
||||
|
||||
protected:
|
||||
virtual bool visitExpression(EXPR expression);
|
||||
virtual bool visitStatement(STMT statement);
|
||||
@ -86,8 +84,14 @@ extern template class TProgramVisitor<Program&, Expression&, Statement&, Program
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
using ProgramVisitor = TProgramVisitor<const Program&, const Expression&,
|
||||
const Statement&, const ProgramElement&>;
|
||||
class ProgramVisitor : public TProgramVisitor<const Program&,
|
||||
const Expression&,
|
||||
const Statement&,
|
||||
const ProgramElement&> {
|
||||
public:
|
||||
bool visit(const Program& program);
|
||||
};
|
||||
|
||||
using ProgramWriter = TProgramVisitor<Program&, Expression&, Statement&, ProgramElement&>;
|
||||
|
||||
} // namespace SkSL
|
||||
|
@ -160,7 +160,7 @@ void ByteCodeGenerator::gatherUniforms(const Type& type, const String& name) {
|
||||
}
|
||||
|
||||
bool ByteCodeGenerator::generateCode() {
|
||||
for (const auto& e : fProgram.elements()) {
|
||||
for (const ProgramElement* e : fProgram.elements()) {
|
||||
switch (e->kind()) {
|
||||
case ProgramElement::Kind::kFunction: {
|
||||
std::unique_ptr<ByteCodeFunction> f =
|
||||
@ -480,7 +480,7 @@ ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var)
|
||||
case Variable::Storage::kGlobal: {
|
||||
if (var.type() == *fContext.fFragmentProcessor_Type) {
|
||||
int offset = 0;
|
||||
for (const auto& e : fProgram.elements()) {
|
||||
for (const ProgramElement* e : fProgram.elements()) {
|
||||
if (e->is<GlobalVarDeclaration>()) {
|
||||
const GlobalVarDeclaration& decl = e->as<GlobalVarDeclaration>();
|
||||
const Variable& declVar = decl.declaration()->as<VarDeclaration>().var();
|
||||
@ -508,7 +508,7 @@ ByteCodeGenerator::Location ByteCodeGenerator::getLocation(const Variable& var)
|
||||
}
|
||||
int offset = 0;
|
||||
bool isUniform = is_uniform(var);
|
||||
for (const auto& e : fProgram.elements()) {
|
||||
for (const ProgramElement* e : fProgram.elements()) {
|
||||
if (e->is<GlobalVarDeclaration>()) {
|
||||
const GlobalVarDeclaration& decl = e->as<GlobalVarDeclaration>();
|
||||
const Variable& declVar = decl.declaration()->as<VarDeclaration>().var();
|
||||
|
@ -413,7 +413,7 @@ void CPPCodeGenerator::writeFieldAccess(const FieldAccess& access) {
|
||||
|
||||
int CPPCodeGenerator::getChildFPIndex(const Variable& var) const {
|
||||
int index = 0;
|
||||
for (const auto& p : fProgram.elements()) {
|
||||
for (const ProgramElement* p : fProgram.elements()) {
|
||||
if (p->is<GlobalVarDeclaration>()) {
|
||||
const VarDeclaration& decl =
|
||||
p->as<GlobalVarDeclaration>().declaration()->as<VarDeclaration>();
|
||||
@ -750,7 +750,7 @@ void CPPCodeGenerator::writeInputVars() {
|
||||
}
|
||||
|
||||
void CPPCodeGenerator::writePrivateVars() {
|
||||
for (const auto& p : fProgram.elements()) {
|
||||
for (const ProgramElement* p : fProgram.elements()) {
|
||||
if (p->is<GlobalVarDeclaration>()) {
|
||||
const GlobalVarDeclaration& global = p->as<GlobalVarDeclaration>();
|
||||
const Variable& var = global.declaration()->as<VarDeclaration>().var();
|
||||
@ -788,7 +788,7 @@ void CPPCodeGenerator::writePrivateVars() {
|
||||
}
|
||||
|
||||
void CPPCodeGenerator::writePrivateVarValues() {
|
||||
for (const auto& p : fProgram.elements()) {
|
||||
for (const ProgramElement* p : fProgram.elements()) {
|
||||
if (p->is<GlobalVarDeclaration>()) {
|
||||
const GlobalVarDeclaration& global = p->as<GlobalVarDeclaration>();
|
||||
const VarDeclaration& decl = global.declaration()->as<VarDeclaration>();
|
||||
@ -1016,7 +1016,7 @@ bool CPPCodeGenerator::writeEmitCode(std::vector<const Variable*>& uniforms) {
|
||||
this->writef(" const %s& _outer = args.fFp.cast<%s>();\n"
|
||||
" (void) _outer;\n",
|
||||
fFullName.c_str(), fFullName.c_str());
|
||||
for (const auto& p : fProgram.elements()) {
|
||||
for (const ProgramElement* p : fProgram.elements()) {
|
||||
if (p->is<GlobalVarDeclaration>()) {
|
||||
const GlobalVarDeclaration& global = p->as<GlobalVarDeclaration>();
|
||||
const VarDeclaration& decl = global.declaration()->as<VarDeclaration>();
|
||||
@ -1045,7 +1045,7 @@ bool CPPCodeGenerator::writeEmitCode(std::vector<const Variable*>& uniforms) {
|
||||
|
||||
// Generate mangled names and argument lists for helper functions.
|
||||
std::unordered_set<const FunctionDeclaration*> definedHelpers;
|
||||
for (const auto& p : fProgram.elements()) {
|
||||
for (const ProgramElement* p : fProgram.elements()) {
|
||||
if (p->is<FunctionDefinition>()) {
|
||||
const FunctionDeclaration* decl = &p->as<FunctionDefinition>().declaration();
|
||||
definedHelpers.insert(decl);
|
||||
@ -1055,7 +1055,7 @@ bool CPPCodeGenerator::writeEmitCode(std::vector<const Variable*>& uniforms) {
|
||||
|
||||
// Emit prototypes for defined helper functions that originally had prototypes in the FP file.
|
||||
// (If a function was prototyped but never defined, we skip it, since it wasn't prepared above.)
|
||||
for (const auto& p : fProgram.elements()) {
|
||||
for (const ProgramElement* p : fProgram.elements()) {
|
||||
if (p->is<FunctionPrototype>()) {
|
||||
const FunctionDeclaration* decl = &p->as<FunctionPrototype>().declaration();
|
||||
if (definedHelpers.find(decl) != definedHelpers.end()) {
|
||||
@ -1152,7 +1152,7 @@ void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) {
|
||||
}
|
||||
if (section) {
|
||||
int samplerIndex = 0;
|
||||
for (const auto& p : fProgram.elements()) {
|
||||
for (const ProgramElement* p : fProgram.elements()) {
|
||||
if (p->is<GlobalVarDeclaration>()) {
|
||||
const GlobalVarDeclaration& global = p->as<GlobalVarDeclaration>();
|
||||
const VarDeclaration& decl = global.declaration()->as<VarDeclaration>();
|
||||
@ -1326,7 +1326,7 @@ void CPPCodeGenerator::writeGetKey() {
|
||||
this->writef("void %s::onGetGLSLProcessorKey(const GrShaderCaps& caps, "
|
||||
"GrProcessorKeyBuilder* b) const {\n",
|
||||
fFullName.c_str());
|
||||
for (const auto& p : fProgram.elements()) {
|
||||
for (const ProgramElement* p : fProgram.elements()) {
|
||||
if (p->is<GlobalVarDeclaration>()) {
|
||||
const GlobalVarDeclaration& global = p->as<GlobalVarDeclaration>();
|
||||
const VarDeclaration& decl = global.declaration()->as<VarDeclaration>();
|
||||
@ -1401,7 +1401,7 @@ void CPPCodeGenerator::writeGetKey() {
|
||||
|
||||
bool CPPCodeGenerator::generateCode() {
|
||||
std::vector<const Variable*> uniforms;
|
||||
for (const auto& p : fProgram.elements()) {
|
||||
for (const ProgramElement* p : fProgram.elements()) {
|
||||
if (p->is<GlobalVarDeclaration>()) {
|
||||
const GlobalVarDeclaration& global = p->as<GlobalVarDeclaration>();
|
||||
const VarDeclaration& decl = global.declaration()->as<VarDeclaration>();
|
||||
|
@ -292,6 +292,7 @@ LoadedModule Compiler::loadModule(Program::Kind kind,
|
||||
fIRGenerator->convertProgram(kind, &settings, &standaloneCaps, baseModule,
|
||||
/*isBuiltinCode=*/true, source->c_str(), source->length(),
|
||||
/*externalValues=*/nullptr);
|
||||
SkASSERT(ir.fSharedElements.empty());
|
||||
LoadedModule module = {std::move(ir.fSymbolTable), std::move(ir.fElements)};
|
||||
fIRGenerator->fCanInline = true;
|
||||
if (this->fErrorCount) {
|
||||
@ -1724,6 +1725,7 @@ std::unique_ptr<Program> Compiler::convertProgram(
|
||||
fCaps,
|
||||
fContext,
|
||||
std::move(ir.fElements),
|
||||
std::move(ir.fSharedElements),
|
||||
std::move(ir.fModifiers),
|
||||
std::move(ir.fSymbolTable),
|
||||
std::move(pool),
|
||||
@ -1752,7 +1754,7 @@ bool Compiler::optimize(Program& program) {
|
||||
bool madeChanges = false;
|
||||
|
||||
// Scan and optimize based on the control-flow graph for each function.
|
||||
for (const auto& element : program.elements()) {
|
||||
for (const auto& element : program.ownedElements()) {
|
||||
if (element->is<FunctionDefinition>()) {
|
||||
madeChanges |= this->scanCFG(element->as<FunctionDefinition>(), usage);
|
||||
}
|
||||
@ -1764,41 +1766,54 @@ bool Compiler::optimize(Program& program) {
|
||||
// Remove dead functions. We wait until after analysis so that we still report errors,
|
||||
// even in unused code.
|
||||
if (program.fSettings.fRemoveDeadFunctions) {
|
||||
auto isDeadFunction = [&](const ProgramElement* element) {
|
||||
if (!element->is<FunctionDefinition>()) {
|
||||
return false;
|
||||
}
|
||||
const FunctionDefinition& fn = element->as<FunctionDefinition>();
|
||||
if (fn.declaration().name() != "main" && usage->get(fn.declaration()) == 0) {
|
||||
usage->remove(*element);
|
||||
madeChanges = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
program.fElements.erase(
|
||||
std::remove_if(program.fElements.begin(),
|
||||
program.fElements.end(),
|
||||
std::remove_if(program.fElements.begin(), program.fElements.end(),
|
||||
[&](const std::unique_ptr<ProgramElement>& element) {
|
||||
if (!element->is<FunctionDefinition>()) {
|
||||
return false;
|
||||
}
|
||||
const auto& fn = element->as<FunctionDefinition>();
|
||||
bool dead = fn.declaration().name() != "main" &&
|
||||
usage->get(fn.declaration()) == 0;
|
||||
if (dead) {
|
||||
madeChanges = true;
|
||||
usage->remove(*element);
|
||||
}
|
||||
return dead;
|
||||
return isDeadFunction(element.get());
|
||||
}),
|
||||
program.fElements.end());
|
||||
program.fSharedElements.erase(
|
||||
std::remove_if(program.fSharedElements.begin(), program.fSharedElements.end(),
|
||||
isDeadFunction),
|
||||
program.fSharedElements.end());
|
||||
}
|
||||
|
||||
if (program.fKind != Program::kFragmentProcessor_Kind) {
|
||||
// Remove declarations of dead global variables
|
||||
auto isDeadVariable = [&](const ProgramElement* element) {
|
||||
if (!element->is<GlobalVarDeclaration>()) {
|
||||
return false;
|
||||
}
|
||||
const GlobalVarDeclaration& global = element->as<GlobalVarDeclaration>();
|
||||
const VarDeclaration& varDecl = global.declaration()->as<VarDeclaration>();
|
||||
if (usage->isDead(varDecl.var())) {
|
||||
madeChanges = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
program.fElements.erase(
|
||||
std::remove_if(program.fElements.begin(), program.fElements.end(),
|
||||
[&](const std::unique_ptr<ProgramElement>& element) {
|
||||
if (!element->is<GlobalVarDeclaration>()) {
|
||||
return false;
|
||||
}
|
||||
const auto& global = element->as<GlobalVarDeclaration>();
|
||||
const auto& varDecl =
|
||||
global.declaration()->as<VarDeclaration>();
|
||||
bool dead = usage->isDead(varDecl.var());
|
||||
madeChanges |= dead;
|
||||
return dead;
|
||||
return isDeadVariable(element.get());
|
||||
}),
|
||||
program.fElements.end());
|
||||
program.fSharedElements.erase(
|
||||
std::remove_if(program.fSharedElements.begin(), program.fSharedElements.end(),
|
||||
isDeadVariable),
|
||||
program.fSharedElements.end());
|
||||
}
|
||||
|
||||
if (!madeChanges) {
|
||||
|
@ -1570,7 +1570,7 @@ bool GLSLCodeGenerator::generateCode() {
|
||||
OutputStream* rawOut = fOut;
|
||||
StringStream body;
|
||||
fOut = &body;
|
||||
for (const auto& e : fProgram.elements()) {
|
||||
for (const ProgramElement* e : fProgram.elements()) {
|
||||
this->writeProgramElement(*e);
|
||||
}
|
||||
fOut = rawOut;
|
||||
|
@ -355,7 +355,7 @@ bool HCodeGenerator::generateCode() {
|
||||
"class %s : public GrFragmentProcessor {\n"
|
||||
"public:\n",
|
||||
fFullName.c_str());
|
||||
for (const auto& p : fProgram.elements()) {
|
||||
for (const ProgramElement* p : fProgram.elements()) {
|
||||
if (p->is<Enum>() && !p->as<Enum>().isSharedWithCpp()) {
|
||||
this->writef("%s\n", p->as<Enum>().code().c_str());
|
||||
}
|
||||
|
@ -3011,7 +3011,10 @@ IRGenerator::IRBundle IRGenerator::convertProgram(
|
||||
fIsBuiltinCode = isBuiltinCode;
|
||||
|
||||
std::vector<std::unique_ptr<ProgramElement>> elements;
|
||||
std::vector<const ProgramElement*> sharedElements;
|
||||
|
||||
fProgramElements = &elements;
|
||||
fSharedElements = &sharedElements;
|
||||
|
||||
fInputs.reset();
|
||||
fInvocations = -1;
|
||||
@ -3141,7 +3144,8 @@ IRGenerator::IRBundle IRGenerator::convertProgram(
|
||||
|
||||
fSettings = nullptr;
|
||||
|
||||
return IRBundle{std::move(elements), this->releaseModifiers(), fSymbolTable, fInputs};
|
||||
return IRBundle{std::move(elements), std::move(sharedElements), this->releaseModifiers(),
|
||||
fSymbolTable, fInputs};
|
||||
}
|
||||
|
||||
} // namespace SkSL
|
||||
|
@ -100,6 +100,7 @@ public:
|
||||
|
||||
struct IRBundle {
|
||||
std::vector<std::unique_ptr<ProgramElement>> fElements;
|
||||
std::vector<const ProgramElement*> fSharedElements;
|
||||
std::unique_ptr<ModifiersPool> fModifiers;
|
||||
std::shared_ptr<SymbolTable> fSymbolTable;
|
||||
Program::Inputs fInputs;
|
||||
@ -250,6 +251,7 @@ private:
|
||||
ErrorReporter& fErrors;
|
||||
int fInvocations;
|
||||
std::vector<std::unique_ptr<ProgramElement>>* fProgramElements = nullptr;
|
||||
std::vector<const ProgramElement*>* fSharedElements = nullptr;
|
||||
const Variable* fRTAdjust = nullptr;
|
||||
const Variable* fRTAdjustInterfaceBlock = nullptr;
|
||||
int fRTAdjustFieldIndex;
|
||||
|
@ -828,7 +828,7 @@ public:
|
||||
fCandidateList = candidateList;
|
||||
fSymbolTableStack.push_back(program.fSymbols.get());
|
||||
|
||||
for (const auto& pe : program.elements()) {
|
||||
for (const std::unique_ptr<ProgramElement>& pe : program.ownedElements()) {
|
||||
this->visitProgramElement(pe.get());
|
||||
}
|
||||
|
||||
|
@ -965,7 +965,7 @@ bool MetalCodeGenerator::writeFunctionDeclaration(const FunctionDeclaration& f)
|
||||
this->write(", constant Uniforms& _uniforms [[buffer(" +
|
||||
to_string(fUniformBuffer) + ")]]");
|
||||
}
|
||||
for (const auto& e : fProgram.elements()) {
|
||||
for (const ProgramElement* e : fProgram.elements()) {
|
||||
if (e->is<GlobalVarDeclaration>()) {
|
||||
const GlobalVarDeclaration& decls = e->as<GlobalVarDeclaration>();
|
||||
const VarDeclaration& var = decls.declaration()->as<VarDeclaration>();
|
||||
@ -1422,7 +1422,7 @@ void MetalCodeGenerator::writeHeader() {
|
||||
}
|
||||
|
||||
void MetalCodeGenerator::writeUniformStruct() {
|
||||
for (const auto& e : fProgram.elements()) {
|
||||
for (const ProgramElement* e : fProgram.elements()) {
|
||||
if (e->is<GlobalVarDeclaration>()) {
|
||||
const GlobalVarDeclaration& decls = e->as<GlobalVarDeclaration>();
|
||||
const Variable& var = decls.declaration()->as<VarDeclaration>().var();
|
||||
@ -1455,7 +1455,7 @@ void MetalCodeGenerator::writeUniformStruct() {
|
||||
|
||||
void MetalCodeGenerator::writeInputStruct() {
|
||||
this->write("struct Inputs {\n");
|
||||
for (const auto& e : fProgram.elements()) {
|
||||
for (const ProgramElement* e : fProgram.elements()) {
|
||||
if (e->is<GlobalVarDeclaration>()) {
|
||||
const GlobalVarDeclaration& decls = e->as<GlobalVarDeclaration>();
|
||||
const Variable& var = decls.declaration()->as<VarDeclaration>().var();
|
||||
@ -1488,7 +1488,7 @@ void MetalCodeGenerator::writeOutputStruct() {
|
||||
} else if (fProgram.fKind == Program::kFragment_Kind) {
|
||||
this->write(" float4 sk_FragColor [[color(0)]];\n");
|
||||
}
|
||||
for (const auto& e : fProgram.elements()) {
|
||||
for (const ProgramElement* e : fProgram.elements()) {
|
||||
if (e->is<GlobalVarDeclaration>()) {
|
||||
const GlobalVarDeclaration& decls = e->as<GlobalVarDeclaration>();
|
||||
const Variable& var = decls.declaration()->as<VarDeclaration>().var();
|
||||
@ -1522,7 +1522,7 @@ void MetalCodeGenerator::writeOutputStruct() {
|
||||
|
||||
void MetalCodeGenerator::writeInterfaceBlocks() {
|
||||
bool wroteInterfaceBlock = false;
|
||||
for (const auto& e : fProgram.elements()) {
|
||||
for (const ProgramElement* e : fProgram.elements()) {
|
||||
if (e->is<InterfaceBlock>()) {
|
||||
this->writeInterfaceBlock(e->as<InterfaceBlock>());
|
||||
wroteInterfaceBlock = true;
|
||||
@ -1540,7 +1540,7 @@ void MetalCodeGenerator::visitGlobalStruct(GlobalStructVisitor* visitor) {
|
||||
for (const auto& [interfaceType, interfaceName] : fInterfaceBlockNameMap) {
|
||||
visitor->VisitInterfaceBlock(*interfaceType, interfaceName);
|
||||
}
|
||||
for (const auto& element : fProgram.elements()) {
|
||||
for (const ProgramElement* element : fProgram.elements()) {
|
||||
if (!element->is<GlobalVarDeclaration>()) {
|
||||
continue;
|
||||
}
|
||||
@ -1843,7 +1843,7 @@ MetalCodeGenerator::Requirements MetalCodeGenerator::requirements(const Function
|
||||
auto found = fRequirements.find(&f);
|
||||
if (found == fRequirements.end()) {
|
||||
fRequirements[&f] = kNo_Requirements;
|
||||
for (const auto& e : fProgram.elements()) {
|
||||
for (const ProgramElement* e : fProgram.elements()) {
|
||||
if (e->is<FunctionDefinition>()) {
|
||||
const FunctionDefinition& def = e->as<FunctionDefinition>();
|
||||
if (&def.declaration() == &f) {
|
||||
@ -1872,7 +1872,7 @@ bool MetalCodeGenerator::generateCode() {
|
||||
this->writeGlobalStruct();
|
||||
StringStream body;
|
||||
fOut = &body;
|
||||
for (const auto& e : fProgram.elements()) {
|
||||
for (const ProgramElement* e : fProgram.elements()) {
|
||||
this->writeProgramElement(*e);
|
||||
}
|
||||
fOut = rawOut;
|
||||
|
@ -44,7 +44,7 @@ void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) {
|
||||
SkASSERT(arguments[0]->is<VariableReference>());
|
||||
int index = 0;
|
||||
bool found = false;
|
||||
for (const auto& p : fProgram.elements()) {
|
||||
for (const ProgramElement* p : fProgram.elements()) {
|
||||
if (p->is<GlobalVarDeclaration>()) {
|
||||
const GlobalVarDeclaration& global = p->as<GlobalVarDeclaration>();
|
||||
const VarDeclaration& decl = global.declaration()->as<VarDeclaration>();
|
||||
@ -81,7 +81,7 @@ void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) {
|
||||
INHERITED::writeFunctionCall(c);
|
||||
} else {
|
||||
int index = 0;
|
||||
for (const auto& e : fProgram.elements()) {
|
||||
for (const ProgramElement* e : fProgram.elements()) {
|
||||
if (e->is<FunctionDefinition>()) {
|
||||
if (&e->as<FunctionDefinition>().declaration() == &function) {
|
||||
break;
|
||||
@ -117,7 +117,7 @@ void PipelineStageCodeGenerator::writeVariableReference(const VariableReference&
|
||||
auto varIndexByFlag = [this, &ref](uint32_t flag) {
|
||||
int index = 0;
|
||||
bool found = false;
|
||||
for (const auto& e : fProgram.elements()) {
|
||||
for (const ProgramElement* e : fProgram.elements()) {
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
|
@ -2744,7 +2744,7 @@ SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf, bool a
|
||||
}
|
||||
SpvId typeId;
|
||||
if (intfModifiers.fLayout.fBuiltin == SK_IN_BUILTIN) {
|
||||
for (const auto& e : fProgram.elements()) {
|
||||
for (const ProgramElement* e : fProgram.elements()) {
|
||||
if (e->is<ModifiersDeclaration>()) {
|
||||
const Modifiers& m = e->as<ModifiersDeclaration>().modifiers();
|
||||
update_sk_in_count(m, &fSkInCount);
|
||||
@ -3122,7 +3122,7 @@ void SPIRVCodeGenerator::writeReturnStatement(const ReturnStatement& r, OutputSt
|
||||
void SPIRVCodeGenerator::writeGeometryShaderExecutionMode(SpvId entryPoint, OutputStream& out) {
|
||||
SkASSERT(fProgram.fKind == Program::kGeometry_Kind);
|
||||
int invocations = 1;
|
||||
for (const auto& e : fProgram.elements()) {
|
||||
for (const ProgramElement* e : fProgram.elements()) {
|
||||
if (e->is<ModifiersDeclaration>()) {
|
||||
const Modifiers& m = e->as<ModifiersDeclaration>().modifiers();
|
||||
if (m.fFlags & Modifiers::kIn_Flag) {
|
||||
@ -3190,7 +3190,7 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
|
||||
StringStream body;
|
||||
std::set<SpvId> interfaceVars;
|
||||
// assign IDs to functions
|
||||
for (const auto& e : program.elements()) {
|
||||
for (const ProgramElement* e : program.elements()) {
|
||||
switch (e->kind()) {
|
||||
case ProgramElement::Kind::kFunction: {
|
||||
const FunctionDefinition& f = e->as<FunctionDefinition>();
|
||||
@ -3201,7 +3201,7 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (const auto& e : program.elements()) {
|
||||
for (const ProgramElement* e : program.elements()) {
|
||||
if (e->is<InterfaceBlock>()) {
|
||||
const InterfaceBlock& intf = e->as<InterfaceBlock>();
|
||||
SpvId id = this->writeInterfaceBlock(intf);
|
||||
@ -3215,14 +3215,14 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const auto& e : program.elements()) {
|
||||
for (const ProgramElement* e : program.elements()) {
|
||||
if (e->is<GlobalVarDeclaration>()) {
|
||||
this->writeGlobalVar(program.fKind,
|
||||
e->as<GlobalVarDeclaration>().declaration()->as<VarDeclaration>(),
|
||||
body);
|
||||
}
|
||||
}
|
||||
for (const auto& e : program.elements()) {
|
||||
for (const ProgramElement* e : program.elements()) {
|
||||
if (e->is<FunctionDefinition>()) {
|
||||
this->writeFunction(e->as<FunctionDefinition>(), body);
|
||||
}
|
||||
@ -3279,7 +3279,7 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
|
||||
SpvExecutionModeOriginUpperLeft,
|
||||
out);
|
||||
}
|
||||
for (const auto& e : program.elements()) {
|
||||
for (const ProgramElement* e : program.elements()) {
|
||||
if (e->is<Extension>()) {
|
||||
this->writeInstruction(SpvOpSourceExtension, e->as<Extension>().name().c_str(), out);
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ namespace SkSL {
|
||||
|
||||
SectionAndParameterHelper::SectionAndParameterHelper(const Program* program, ErrorReporter& errors)
|
||||
: fProgram(*program) {
|
||||
for (const auto& p : fProgram.elements()) {
|
||||
for (const ProgramElement* p : fProgram.elements()) {
|
||||
switch (p->kind()) {
|
||||
case ProgramElement::Kind::kGlobalVar: {
|
||||
const VarDeclaration& decl =
|
||||
|
@ -186,6 +186,7 @@ struct Program {
|
||||
const ShaderCapsClass* caps,
|
||||
std::shared_ptr<Context> context,
|
||||
std::vector<std::unique_ptr<ProgramElement>> elements,
|
||||
std::vector<const ProgramElement*> sharedElements,
|
||||
std::unique_ptr<ModifiersPool> modifiers,
|
||||
std::shared_ptr<SymbolTable> symbols,
|
||||
std::unique_ptr<Pool> pool,
|
||||
@ -199,6 +200,7 @@ struct Program {
|
||||
, fPool(std::move(pool))
|
||||
, fInputs(inputs)
|
||||
, fElements(std::move(elements))
|
||||
, fSharedElements(std::move(sharedElements))
|
||||
, fModifiers(std::move(modifiers)) {
|
||||
fUsage = Analysis::GetUsage(*this);
|
||||
}
|
||||
@ -215,7 +217,74 @@ struct Program {
|
||||
fPool->detachFromThread();
|
||||
}
|
||||
|
||||
const std::vector<std::unique_ptr<ProgramElement>>& elements() const { return fElements; }
|
||||
class ElementsCollection {
|
||||
public:
|
||||
class iterator {
|
||||
public:
|
||||
const ProgramElement* operator*() {
|
||||
if (fShared != fSharedEnd) {
|
||||
return *fShared;
|
||||
} else {
|
||||
return fOwned->get();
|
||||
}
|
||||
}
|
||||
|
||||
iterator& operator++() {
|
||||
if (fShared != fSharedEnd) {
|
||||
++fShared;
|
||||
} else {
|
||||
++fOwned;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const iterator& other) const {
|
||||
return fOwned == other.fOwned && fShared == other.fShared;
|
||||
}
|
||||
|
||||
bool operator!=(const iterator& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
private:
|
||||
using Owned = std::vector<std::unique_ptr<ProgramElement>>::const_iterator;
|
||||
using Shared = std::vector<const ProgramElement*>::const_iterator;
|
||||
friend class ElementsCollection;
|
||||
|
||||
iterator(Owned owned, Owned ownedEnd, Shared shared, Shared sharedEnd)
|
||||
: fOwned(owned), fOwnedEnd(ownedEnd), fShared(shared), fSharedEnd(sharedEnd) {}
|
||||
|
||||
Owned fOwned;
|
||||
Owned fOwnedEnd;
|
||||
Shared fShared;
|
||||
Shared fSharedEnd;
|
||||
};
|
||||
|
||||
iterator begin() const {
|
||||
return iterator(fProgram.fElements.begin(), fProgram.fElements.end(),
|
||||
fProgram.fSharedElements.begin(), fProgram.fSharedElements.end());
|
||||
}
|
||||
|
||||
iterator end() const {
|
||||
return iterator(fProgram.fElements.end(), fProgram.fElements.end(),
|
||||
fProgram.fSharedElements.end(), fProgram.fSharedElements.end());
|
||||
}
|
||||
|
||||
private:
|
||||
friend struct Program;
|
||||
|
||||
ElementsCollection(const Program& program) : fProgram(program) {}
|
||||
const Program& fProgram;
|
||||
};
|
||||
|
||||
// Can be used to iterate over *all* elements in this Program, both owned and shared (builtin).
|
||||
// The iterator's value type is 'const ProgramElement*', so it's clear that you *must not*
|
||||
// modify anything (as you might be mutating shared data).
|
||||
ElementsCollection elements() const { return ElementsCollection(*this); }
|
||||
|
||||
// Can be used to iterate over *just* the elements owned by the Program, not shared builtins.
|
||||
// The iterator's value type is 'std::unique_ptr<ProgramElement>', and mutation is allowed.
|
||||
const std::vector<std::unique_ptr<ProgramElement>>& ownedElements() { return fElements; }
|
||||
|
||||
Kind fKind;
|
||||
std::unique_ptr<String> fSource;
|
||||
@ -230,6 +299,7 @@ struct Program {
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<ProgramElement>> fElements;
|
||||
std::vector<const ProgramElement*> fSharedElements;
|
||||
std::unique_ptr<ModifiersPool> fModifiers;
|
||||
std::unique_ptr<ProgramUsage> fUsage;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user