From a29cc14162e911b36d18d1d1896216697c7dc0c1 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 11 Nov 2016 18:39:57 +0200 Subject: [PATCH] Refactor module and stage management Originally I envisioned that ProgramParser would handle imports, but it's non-trivial to make re-entrant. The parser will now only hold one module at a time and ProgramCompiler will handle combining them. --- source/programcompiler.cpp | 34 ++++++++++++++------------------- source/programcompiler.h | 2 +- source/programparser.cpp | 39 +++++++++++++++++++++++--------------- source/programparser.h | 8 +++++--- source/programsyntax.cpp | 6 +----- source/programsyntax.h | 5 +---- 6 files changed, 46 insertions(+), 48 deletions(-) diff --git a/source/programcompiler.cpp b/source/programcompiler.cpp index 2dae07c8..bc021c97 100644 --- a/source/programcompiler.cpp +++ b/source/programcompiler.cpp @@ -35,12 +35,15 @@ void ProgramCompiler::add_shaders(Program &program) throw invalid_operation("ProgramCompiler::add_shaders"); string head = "#version 150\n"; - if(module->vertex_stage.present) - program.attach_shader_owned(new VertexShader(head+format_stage(module->vertex_stage))); - if(module->geometry_stage.present) - program.attach_shader_owned(new GeometryShader(head+format_stage(module->geometry_stage))); - if(module->fragment_stage.present) - program.attach_shader_owned(new FragmentShader(head+format_stage(module->fragment_stage))); + for(list::iterator i=module->stages.begin(); i!=module->stages.end(); ++i) + { + if(i->type==VERTEX) + program.attach_shader_owned(new VertexShader(head+create_source(*i))); + else if(i->type==GEOMETRY) + program.attach_shader_owned(new GeometryShader(head+create_source(*i))); + else if(i->type==FRAGMENT) + program.attach_shader_owned(new FragmentShader(head+create_source(*i))); + } program.bind_attribute(VERTEX4, "vertex"); program.bind_attribute(NORMAL3, "normal"); @@ -50,19 +53,10 @@ void ProgramCompiler::add_shaders(Program &program) void ProgramCompiler::process() { - if(module->vertex_stage.present) - generate(module->vertex_stage); - if(module->geometry_stage.present) - generate(module->geometry_stage); - if(module->fragment_stage.present) - generate(module->fragment_stage); - - if(module->vertex_stage.present) - optimize(module->vertex_stage); - if(module->geometry_stage.present) - optimize(module->geometry_stage); - if(module->fragment_stage.present) - optimize(module->fragment_stage); + for(list::iterator i=module->stages.begin(); i!=module->stages.end(); ++i) + generate(*i); + for(list::iterator i=module->stages.begin(); i!=module->stages.end(); ++i) + optimize(*i); } void ProgramCompiler::generate(Stage &stage) @@ -109,7 +103,7 @@ void ProgramCompiler::resolve_variables(Stage &stage) stage.content.visit(resolver); } -string ProgramCompiler::format_stage(Stage &stage) +string ProgramCompiler::create_source(Stage &stage) { Formatter formatter; stage.content.visit(formatter); diff --git a/source/programcompiler.h b/source/programcompiler.h index ecae3dc1..7200679e 100644 --- a/source/programcompiler.h +++ b/source/programcompiler.h @@ -139,7 +139,7 @@ private: void optimize(ProgramSyntax::Stage &); static void inject_block(ProgramSyntax::Block &, const ProgramSyntax::Block &); static void resolve_variables(ProgramSyntax::Stage &); - std::string format_stage(ProgramSyntax::Stage &); + std::string create_source(ProgramSyntax::Stage &); }; } // namespace GL diff --git a/source/programparser.cpp b/source/programparser.cpp index d1826ad6..16299d20 100644 --- a/source/programparser.cpp +++ b/source/programparser.cpp @@ -58,11 +58,20 @@ ProgramParser::Operator ProgramParser::operators[] = { { 0 }, 18, NO_OPERATOR, LEFT_TO_RIGHT } }; +ProgramParser::ProgramParser(): + module(0) +{ } + +ProgramParser::~ProgramParser() +{ + delete module; +} + Module &ProgramParser::parse(const string &s) { source = s; - parse_source(main_module); - return main_module; + parse_source(); + return *module; } Module &ProgramParser::parse(IO::Base &io) @@ -74,37 +83,37 @@ Module &ProgramParser::parse(IO::Base &io) unsigned len = io.read(buffer, sizeof(buffer)); source.append(buffer, len); } - parse_source(main_module); - return main_module; + parse_source(); + return *module; } -void ProgramParser::parse_source(Module &module) +void ProgramParser::parse_source() { - cur_module = &module; - cur_stage = &module.shared; + delete module; + module = new Module; + cur_stage = &module->shared; iter = source.begin(); while(1) { while(Node *statement = parse_global_declaration()) cur_stage->content.body.push_back(statement); - cur_stage->present = !cur_stage->content.body.empty(); - Stage *prev_stage = cur_stage; parse_token(); string token = parse_token(); if(token.empty()) break; - else if(token=="global") - cur_stage = &module.shared; else if(token=="vertex") - cur_stage = &module.vertex_stage; + module->stages.push_back(VERTEX); else if(token=="geometry") - cur_stage = &module.geometry_stage; + module->stages.push_back(GEOMETRY); else if(token=="fragment") - cur_stage = &module.fragment_stage; + module->stages.push_back(FRAGMENT); else throw runtime_error(format("Parse error at '%s': expected stage identifier", token)); - cur_stage->previous = prev_stage; + + if(cur_stage->type!=SHARED) + module->stages.back().previous = cur_stage; + cur_stage = &module->stages.back(); for(; (iter!=source.end() && *iter!='\n'); ++iter) ; } diff --git a/source/programparser.h b/source/programparser.h index 1ca1a44c..4c2d7b7e 100644 --- a/source/programparser.h +++ b/source/programparser.h @@ -39,19 +39,21 @@ private: std::string source; std::string::const_iterator iter; std::deque next_tokens; - ProgramSyntax::Module main_module; - ProgramSyntax::Module *cur_module; + ProgramSyntax::Module *module; ProgramSyntax::Stage *cur_stage; std::set declared_types; static Operator operators[]; public: + ProgramParser(); + ~ProgramParser(); + ProgramSyntax::Module &parse(const std::string &); ProgramSyntax::Module &parse(IO::Base &); private: - void parse_source(ProgramSyntax::Module &); + void parse_source(); const std::string &peek_token(unsigned = 0); std::string parse_token(); diff --git a/source/programsyntax.cpp b/source/programsyntax.cpp index 7ca71d57..6e4d070e 100644 --- a/source/programsyntax.cpp +++ b/source/programsyntax.cpp @@ -250,16 +250,12 @@ void TraversingVisitor::visit(Return &ret) Stage::Stage(StageType t): type(t), - present(false), previous(0) { } Module::Module(): - shared(SHARED), - vertex_stage(VERTEX), - geometry_stage(GEOMETRY), - fragment_stage(FRAGMENT) + shared(SHARED) { } } // namespace ProgramSyntax diff --git a/source/programsyntax.h b/source/programsyntax.h index 86cb6b90..c645a60a 100644 --- a/source/programsyntax.h +++ b/source/programsyntax.h @@ -312,7 +312,6 @@ enum StageType struct Stage { StageType type; - bool present; Stage *previous; ProgramSyntax::Block content; std::map in_variables; @@ -324,9 +323,7 @@ struct Stage struct Module { Stage shared; - Stage vertex_stage; - Stage geometry_stage; - Stage fragment_stage; + std::list stages; Module(); }; -- 2.43.0