From: Mikko Rasa Date: Thu, 25 Feb 2021 22:38:10 +0000 (+0200) Subject: Support automatic generation of interface blocks X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=commitdiff_plain;h=64d98b0b4fb3214a3ca67ab1b239c120748e8e35 Support automatic generation of interface blocks --- diff --git a/source/glsl/generate.cpp b/source/glsl/generate.cpp index 434dbe7a..e037e0a5 100644 --- a/source/glsl/generate.cpp +++ b/source/glsl/generate.cpp @@ -304,7 +304,9 @@ void FunctionResolver::visit(FunctionDeclaration &func) InterfaceGenerator::InterfaceGenerator(): stage(0), function_scope(false), - iface_block(0) + iface_block(0), + copy_block(false), + iface_target_block(0) { } string InterfaceGenerator::get_out_prefix(Stage::Type type) @@ -320,6 +322,7 @@ string InterfaceGenerator::get_out_prefix(Stage::Type type) void InterfaceGenerator::apply(Stage &s) { stage = &s; + iface_target_block = &stage->content; if(stage->previous) in_prefix = get_out_prefix(stage->previous->type); out_prefix = get_out_prefix(stage->type); @@ -357,7 +360,7 @@ bool InterfaceGenerator::generate_interface(VariableDeclaration &var, const stri iface_var->type = var.type; iface_var->type_declaration = var.type_declaration; iface_var->name = name; - if(stage->type==Stage::GEOMETRY) + if(stage->type==Stage::GEOMETRY && !copy_block) iface_var->array = ((var.array && var.interface!="in") || iface=="in"); else iface_var->array = var.array; @@ -368,8 +371,44 @@ bool InterfaceGenerator::generate_interface(VariableDeclaration &var, const stri iface_var->linked_declaration = &var; var.linked_declaration = iface_var; } - stage->content.body.insert(iface_insert_point, iface_var); - stage->content.variables[name] = iface_var; + + iface_target_block->body.insert(iface_insert_point, iface_var); + iface_target_block->variables[name] = iface_var; + + return true; +} + +bool InterfaceGenerator::generate_interface(InterfaceBlock &out_block) +{ + if(stage->content.interfaces.count(out_block.name)) + return false; + + InterfaceBlock *in_block = new InterfaceBlock; + in_block->interface = "in"; + in_block->name = out_block.name; + in_block->instance_name = out_block.instance_name; + if(stage->type==Stage::GEOMETRY) + in_block->array = true; + else + in_block->array = out_block.array; + in_block->linked_block = &out_block; + out_block.linked_block = in_block; + + { + SetFlag set_copy(copy_block, true); + SetForScope set_target(iface_target_block, &in_block->members); + SetForScope::iterator> set_ins_pt(iface_insert_point, in_block->members.body.end()); + out_block.members.visit(*this); + } + + iface_target_block->body.insert(iface_insert_point, in_block); + iface_target_block->interfaces[in_block->name] = in_block; + if(!in_block->instance_name.empty()) + stage->content.interfaces[in_block->instance_name] = in_block; + + SetFlag set_scope(function_scope, false); + SetForScope set_block(current_block, &stage->content); + in_block->visit(*this); return true; } @@ -408,11 +447,37 @@ void InterfaceGenerator::visit(VariableReference &var) { generate_interface(*i->second, "in", i->second->name); var.name = i->second->name; + return; + } + + const map &prev_blocks = stage->previous->content.interfaces; + map::const_iterator j = prev_blocks.find(var.name); + if(j!=prev_blocks.end() && j->second->interface=="out" && j->second->instance_name==var.name) + { + generate_interface(*j->second); + return; } + + for(j=prev_blocks.begin(); j!=prev_blocks.end(); ++j) + if(j->second->instance_name.empty()) + { + i = j->second->members.variables.find(var.name); + if(i!=j->second->members.variables.end()) + { + generate_interface(*j->second); + return; + } + } } void InterfaceGenerator::visit(VariableDeclaration &var) { + if(copy_block) + { + generate_interface(var, "in", var.name); + return; + } + if(iface_block) { if(iface_block->linked_block) diff --git a/source/glsl/generate.h b/source/glsl/generate.h index 49682976..2a36f704 100644 --- a/source/glsl/generate.h +++ b/source/glsl/generate.h @@ -88,6 +88,8 @@ private: std::string out_prefix; bool function_scope; InterfaceBlock *iface_block; + bool copy_block; + Block *iface_target_block; NodeList::iterator iface_insert_point; NodeList::iterator assignment_insert_point; std::set nodes_to_remove; @@ -102,6 +104,7 @@ private: std::string change_prefix(const std::string &, const std::string &) const; virtual void visit(Block &); bool generate_interface(VariableDeclaration &, const std::string &, const std::string &); + bool generate_interface(InterfaceBlock &); ExpressionStatement &insert_assignment(const std::string &, Expression *); virtual void visit(VariableReference &); virtual void visit(VariableDeclaration &);