]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/resolve.cpp
Support redeclaring builtins defined in an interface block
[libs/gl.git] / source / glsl / resolve.cpp
index c03ecae08c80d5bbe9be4c942a8379482b2bbe14..f72dedfd2aa006fe71409fad62c559908be118bd 100644 (file)
@@ -151,8 +151,8 @@ bool VariableResolver::apply(Stage &s)
        s.interface_blocks.clear();
        r_any_resolved = false;
        s.content.visit(*this);
-       for(VariableDeclaration *v: redeclared_builtins)
-               v->source = GENERATED_SOURCE;
+       for(Statement *b: redeclared_builtins)
+               b->source = GENERATED_SOURCE;
        NodeRemover().apply(s, nodes_to_remove);
        return r_any_resolved;
 }
@@ -393,31 +393,59 @@ void VariableResolver::merge_layouts(Layout &to_layout, const Layout &from_layou
 void VariableResolver::visit(VariableDeclaration &var)
 {
        TraversingVisitor::visit(var);
-       VariableDeclaration *&ptr = current_block->variables[var.name];
-       if(!ptr)
-               ptr = &var;
-       else if(!current_block->parent && ptr->interface==var.interface && ptr->type==var.type)
+
+       auto i = current_block->variables.find(var.name);
+       VariableDeclaration *existing = 0;
+       InterfaceBlock *block = 0;
+       if(i!=current_block->variables.end())
+               existing = i->second;
+       else if(!current_block->parent)
        {
-               if(ptr->source==BUILTIN_SOURCE)
-               {
-                       redeclared_builtins.push_back(ptr);
+               const map<string, InterfaceBlock *> &blocks = stage->interface_blocks;
+               for(auto j=blocks.begin(); j!=blocks.end(); ++j)
+                       if(j->second->instance_name.empty() && j->second->struct_declaration)
+                       {
+                               map<string, VariableDeclaration *> &block_vars = j->second->struct_declaration->members.variables;
+                               i = block_vars.find(var.name);
+                               if(i!=block_vars.end())
+                               {
+                                       existing = i->second;
+                                       block = j->second;
+                                       break;
+                               }
+                       }
+       }
 
+       if(!existing)
+               current_block->variables.insert(make_pair(var.name, &var));
+       else if(!current_block->parent && (block ? block->interface : existing->interface)==var.interface && existing->type==var.type && existing->array==var.array)
+       {
+               if(existing->source==BUILTIN_SOURCE)
+               {
                        if(var.layout)
                        {
-                               if(ptr->layout)
-                                       merge_layouts(*ptr->layout, *var.layout);
+                               if(existing->layout)
+                                       merge_layouts(*existing->layout, *var.layout);
                                else
-                                       ptr->layout = var.layout;
+                                       existing->layout = var.layout;
                        }
                        if(var.array_size)
-                               ptr->array_size = var.array_size;
+                               existing->array_size = var.array_size;
+
+                       redeclared_builtins.push_back(existing);
+                       if(block)
+                       {
+                               redeclared_builtins.push_back(block);
+                               for(const auto &kvp: block->struct_declaration->members.variables)
+                                       redeclared_builtins.push_back(kvp.second);
+                       }
 
                        nodes_to_remove.insert(&var);
                        r_any_resolved = true;
                }
-               else if(ptr->array && !ptr->array_size && !var.layout && !var.init_expression)
+               else if(existing->array && !existing->array_size && !var.layout && !var.init_expression)
                {
-                       ptr->array_size = var.array_size;
+                       existing->array_size = var.array_size;
                        nodes_to_remove.insert(&var);
                        r_any_resolved = true;
                }