]> git.tdb.fi Git - libs/gl.git/commitdiff
Refactor module and stage management
authorMikko Rasa <tdb@tdb.fi>
Fri, 11 Nov 2016 16:39:57 +0000 (18:39 +0200)
committerMikko Rasa <tdb@tdb.fi>
Fri, 11 Nov 2016 16:39:57 +0000 (18:39 +0200)
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
source/programcompiler.h
source/programparser.cpp
source/programparser.h
source/programsyntax.cpp
source/programsyntax.h

index 2dae07c8f4d3ecc049c153e66de8793d347e3134..bc021c97b04874ccf375d82383218da4d9a4b4d7 100644 (file)
@@ -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<Stage>::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<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
+               generate(*i);
+       for(list<Stage>::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);
index ecae3dc13411273ec80a825b2a79e780712fae34..7200679e1813723aca6857a70889663b096955b1 100644 (file)
@@ -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
index d1826ad69e160a6b7aa30168d1daef3b02a58eb6..16299d20cf157f8281fc2face34d55a21712eee1 100644 (file)
@@ -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) ;
        }
index 1ca1a44c564d7aa8e6e65ed5f37e465b6a3f2340..4c2d7b7ea5bc1049ddacede49a9f6a1cb280d3e7 100644 (file)
@@ -39,19 +39,21 @@ private:
        std::string source;
        std::string::const_iterator iter;
        std::deque<std::string> next_tokens;
-       ProgramSyntax::Module main_module;
-       ProgramSyntax::Module *cur_module;
+       ProgramSyntax::Module *module;
        ProgramSyntax::Stage *cur_stage;
        std::set<std::string> 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();
index 7ca71d5761352997fe8d4df0bce9bed83c868184..6e4d070e2b3e480cd29b09ccabbb7e7ae4194415 100644 (file)
@@ -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
index 86cb6b906181e7686d4230dbbe1b6fbeb9cb1556..c645a60a442ec91a616060f11c55327e9a34d4f6 100644 (file)
@@ -312,7 +312,6 @@ enum StageType
 struct Stage
 {
        StageType type;
-       bool present;
        Stage *previous;
        ProgramSyntax::Block content;
        std::map<std::string, VariableDeclaration *> in_variables;
@@ -324,9 +323,7 @@ struct Stage
 struct Module
 {
        Stage shared;
-       Stage vertex_stage;
-       Stage geometry_stage;
-       Stage fragment_stage;
+       std::list<Stage> stages;
 
        Module();
 };