X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Fgenerate.cpp;h=434dbe7a8486e0d73104c9a2c0e0ad451c67d39a;hb=bd8816692056230c36504dcccd76c6946dff47b1;hp=62c879c88a2d56c1ca99c9ef3daa2de20e69c50a;hpb=90c89817585b41fdd1ab24153fec41d28d56cab0;p=libs%2Fgl.git diff --git a/source/glsl/generate.cpp b/source/glsl/generate.cpp index 62c879c8..434dbe7a 100644 --- a/source/glsl/generate.cpp +++ b/source/glsl/generate.cpp @@ -80,12 +80,18 @@ void BlockResolver::enter(Block &block) void BlockResolver::visit(InterfaceBlock &iface) { - iface.members.anonymous = true; + /* Block names can't be used for any other identifiers so we can put them + in the same map with instance names. */ + current_block->interfaces[iface.name] = &iface; + if(!iface.instance_name.empty()) + current_block->interfaces[iface.instance_name] = &iface; TraversingVisitor::visit(iface); } VariableResolver::VariableResolver(): + builtins(0), + members(0), record_target(false), assignment_target(0), self_referencing(false) @@ -111,14 +117,38 @@ void VariableResolver::enter(Block &block) void VariableResolver::visit(VariableReference &var) { var.declaration = 0; - type = 0; + members = 0; for(Block *block=current_block; block; block=next_block(*block)) { - map::iterator j = block->variables.find(var.name); - if(j!=block->variables.end()) + map::iterator i = block->variables.find(var.name); + if(i!=block->variables.end()) + var.declaration = i->second; + else + { + const map &ifaces = block->interfaces; + for(map::const_iterator j=ifaces.begin(); (!var.declaration && j!=ifaces.end()); ++j) + if(j->second->instance_name.empty()) + { + i = j->second->members.variables.find(var.name); + if(i!=j->second->members.variables.end()) + var.declaration = i->second; + } + } + + if(var.declaration) { - var.declaration = j->second; - type = j->second->type_declaration; + if(var.declaration->type_declaration) + members = &var.declaration->type_declaration->members.variables; + break; + } + + map::iterator j = block->interfaces.find(var.name); + if(j!=block->interfaces.end() && j->second->instance_name==var.name) + { + iface_ref = new InterfaceBlockReference; + iface_ref->name = var.name; + iface_ref->declaration = j->second; + members = &j->second->members.variables; break; } } @@ -137,21 +167,43 @@ void VariableResolver::visit(VariableReference &var) self_referencing = true; } +void VariableResolver::visit(InterfaceBlockReference &iface) +{ + iface.declaration = 0; + for(Block *block=current_block; block; block=next_block(*block)) + { + map::iterator j = block->interfaces.find(iface.name); + if(j!=block->interfaces.end()) + { + iface.declaration = j->second; + members = &j->second->members.variables; + break; + } + } +} + void VariableResolver::visit(MemberAccess &memacc) { - type = 0; - TraversingVisitor::visit(memacc); + members = 0; + iface_ref = 0; + memacc.left->visit(*this); + + if(iface_ref) + memacc.left = iface_ref; + iface_ref = 0; + memacc.declaration = 0; - if(type) + if(members) { - map::iterator i = type->members.variables.find(memacc.member); - if(i!=type->members.variables.end()) + map::iterator i = members->find(memacc.member); + if(i!=members->end()) { memacc.declaration = i->second; - type = i->second->type_declaration; + if(i->second->type_declaration) + members = &i->second->type_declaration->members.variables; } else - type = 0; + members = 0; } } @@ -163,13 +215,17 @@ void VariableResolver::visit(BinaryExpression &binary) SetForScope set(record_target, false); binary.right->visit(*this); } - type = 0; + members = 0; + iface_ref = 0; binary.left->visit(*this); + if(iface_ref) + binary.left = iface_ref; + iface_ref = 0; } else { TraversingVisitor::visit(binary); - type = 0; + members = 0; } } @@ -208,8 +264,6 @@ void VariableResolver::visit(VariableDeclaration &var) TraversingVisitor::visit(var); current_block->variables[var.name] = &var; - if(current_block->anonymous && current_block->parent) - current_block->parent->variables[var.name] = &var; } void VariableResolver::visit(InterfaceBlock &iface) @@ -248,7 +302,9 @@ void FunctionResolver::visit(FunctionDeclaration &func) InterfaceGenerator::InterfaceGenerator(): - stage(0) + stage(0), + function_scope(false), + iface_block(0) { } string InterfaceGenerator::get_out_prefix(Stage::Type type) @@ -292,8 +348,7 @@ string InterfaceGenerator::change_prefix(const string &name, const string &prefi bool InterfaceGenerator::generate_interface(VariableDeclaration &var, const string &iface, const string &name) { - const map &stage_vars = (iface=="in" ? stage->in_variables : stage->out_variables); - if(stage_vars.count(name)) + if(stage->content.variables.count(name)) return false; VariableDeclaration* iface_var = new VariableDeclaration; @@ -309,12 +364,12 @@ bool InterfaceGenerator::generate_interface(VariableDeclaration &var, const stri if(iface_var->array) iface_var->array_size = var.array_size; if(iface=="in") - iface_var->linked_declaration = &var; - stage->content.body.insert(iface_insert_point, iface_var); { - SetForScope set_block(current_block, &stage->content); - iface_var->visit(*this); + 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; return true; } @@ -342,14 +397,14 @@ void InterfaceGenerator::visit(VariableReference &var) return; /* Don't pull a variable from previous stage if we just generated an out interface in this stage */ - if(stage->out_variables.count(var.name)) + if(stage->content.variables.count(var.name)) return; - const map &prev_out = stage->previous->out_variables; - map::const_iterator i = prev_out.find(var.name); - if(i==prev_out.end()) - i = prev_out.find(in_prefix+var.name); - if(i!=prev_out.end()) + const map &prev_vars = stage->previous->content.variables; + map::const_iterator i = prev_vars.find(var.name); + if(i==prev_vars.end() || i->second->interface!="out") + i = prev_vars.find(in_prefix+var.name); + if(i!=prev_vars.end() && i->second->interface=="out") { generate_interface(*i->second, "in", i->second->name); var.name = i->second->name; @@ -358,11 +413,23 @@ void InterfaceGenerator::visit(VariableReference &var) void InterfaceGenerator::visit(VariableDeclaration &var) { + if(iface_block) + { + if(iface_block->linked_block) + { + const map &linked_vars = iface_block->linked_block->members.variables; + map::const_iterator i = linked_vars.find(var.name); + if(i!=linked_vars.end()) + var.linked_declaration = i->second; + } + return; + } + if(var.interface=="out") { - if(current_block==&stage->content) - stage->out_variables[var.name] = &var; - else if(generate_interface(var, "out", change_prefix(var.name, string()))) + /* For out variables in function scope, generate a global interface and + replace the local declaration with an assignment. */ + if(function_scope && generate_interface(var, "out", var.name)) { nodes_to_remove.insert(&var); if(var.init_expression) @@ -376,14 +443,13 @@ void InterfaceGenerator::visit(VariableDeclaration &var) } else if(var.interface=="in") { - stage->in_variables[var.name] = &var; - if(var.linked_declaration) - var.linked_declaration->linked_declaration = &var; - else if(stage->previous) + /* Try to link in variables in global scope with out variables from + previous stage */ + if(current_block==&stage->content && !var.linked_declaration && stage->previous) { - const map &prev_out = stage->previous->out_variables; - map::const_iterator i = prev_out.find(var.name); - if(i!=prev_out.end()) + const map &prev_vars = stage->previous->content.variables; + map::const_iterator i = prev_vars.find(var.name); + if(i!=prev_vars.end() && i->second->interface=="out") { var.linked_declaration = i->second; i->second->linked_declaration = &var; @@ -394,8 +460,29 @@ void InterfaceGenerator::visit(VariableDeclaration &var) TraversingVisitor::visit(var); } +void InterfaceGenerator::visit(InterfaceBlock &iface) +{ + if(iface.interface=="in") + { + if(!iface.linked_block && stage->previous) + { + const map &prev_blocks = stage->previous->content.interfaces; + map::const_iterator i = prev_blocks.find(iface.name); + if(i!=prev_blocks.end() && i->second->interface=="out" && i->second->name==iface.name) + { + iface.linked_block = i->second; + i->second->linked_block = &iface; + } + } + } + + SetForScope set_iface(iface_block, &iface); + TraversingVisitor::visit(iface); +} + void InterfaceGenerator::visit(FunctionDeclaration &func) { + SetFlag set_scope(function_scope, true); // Skip parameters because they're not useful here func.body.visit(*this); } @@ -404,13 +491,14 @@ void InterfaceGenerator::visit(Passthrough &pass) { vector pass_vars; - for(map::const_iterator i=stage->in_variables.begin(); i!=stage->in_variables.end(); ++i) - pass_vars.push_back(i->second); + for(map::const_iterator i=stage->content.variables.begin(); i!=stage->content.variables.end(); ++i) + if(i->second->interface=="in") + pass_vars.push_back(i->second); if(stage->previous) { - const map &prev_out = stage->previous->out_variables; - for(map::const_iterator i=prev_out.begin(); i!=prev_out.end(); ++i) + const map &prev_vars = stage->previous->content.variables; + for(map::const_iterator i=prev_vars.begin(); i!=prev_vars.end(); ++i) { bool linked = false; for(vector::const_iterator j=pass_vars.begin(); (!linked && j!=pass_vars.end()); ++j) @@ -423,7 +511,7 @@ void InterfaceGenerator::visit(Passthrough &pass) if(stage->type==Stage::GEOMETRY) { - VariableReference *ref = new VariableReference; + InterfaceBlockReference *ref = new InterfaceBlockReference; ref->name = "gl_in"; BinaryExpression *subscript = new BinaryExpression;