]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/resolve.cpp
Always use member access for interface blocks, even anonymous ones
[libs/gl.git] / source / glsl / resolve.cpp
index 05aead3c5fa369f55529c02c05c34fe7a6997dba..c5a507a222a96558a7582d72b8725216889d9fa7 100644 (file)
@@ -225,29 +225,43 @@ void VariableResolver::visit(VariableReference &var)
        if(!declaration)
        {
                const map<string, InterfaceBlock *> &blocks = stage->interface_blocks;
-               map<string, InterfaceBlock *>::const_iterator i = blocks.find("_"+var.name);
+               map<string, InterfaceBlock *>::const_iterator i = blocks.find(var.name);
+               if(i==blocks.end())
+               {
+                       // Look for the variable in anonymous interface blocks.
+                       for(i=blocks.begin(); i!=blocks.end(); ++i)
+                               if(i->second->instance_name.empty() && i->second->struct_declaration)
+                                       if(i->second->struct_declaration->members.variables.count(var.name))
+                                               break;
+               }
+
                if(i!=blocks.end())
                {
-                       /* The name refers to an interface block with an instance name rather
-                       than a variable.  Prepare a new syntax tree node accordingly. */
+                       /* The name refers to either an interface block with an instance name
+                       or a variable declared inside an anonymous interface block.  Prepare
+                       new syntax tree nodes accordingly. */
                        InterfaceBlockReference *iface_ref = new InterfaceBlockReference;
                        iface_ref->source = var.source;
                        iface_ref->line = var.line;
-                       iface_ref->name = var.name;
                        iface_ref->declaration = i->second;
-                       r_replacement_expr = iface_ref;
-               }
-               else
-               {
-                       // Look for the variable in anonymous interface blocks.
-                       for(i=blocks.begin(); (!declaration && i!=blocks.end()); ++i)
-                               if(i->second->instance_name.empty() && i->second->struct_declaration)
-                               {
-                                       const map<string, VariableDeclaration *> &iface_vars = i->second->struct_declaration->members.variables;
-                                       map<string, VariableDeclaration *>::const_iterator j = iface_vars.find(var.name);
-                                       if(j!=iface_vars.end())
-                                               declaration = j->second;
-                               }
+
+                       if(i->second->instance_name.empty())
+                       {
+                               iface_ref->name = format("%s %s", i->second->interface, i->second->block_name);
+
+                               MemberAccess *memacc = new MemberAccess;
+                               memacc->source = var.source;
+                               memacc->line = var.line;
+                               memacc->left = iface_ref;
+                               memacc->member = var.name;
+
+                               r_replacement_expr = memacc;
+                       }
+                       else
+                       {
+                               iface_ref->name = var.name;
+                               r_replacement_expr = iface_ref;
+                       }
                }
        }
 
@@ -259,7 +273,7 @@ void VariableResolver::visit(VariableReference &var)
 
 void VariableResolver::visit(InterfaceBlockReference &iface)
 {
-       map<string, InterfaceBlock *>::iterator i = stage->interface_blocks.find("_"+iface.name);
+       map<string, InterfaceBlock *>::iterator i = stage->interface_blocks.find(iface.name);
        InterfaceBlock *declaration = (i!=stage->interface_blocks.end() ? i->second : 0);
        r_any_resolved |= (declaration!=iface.declaration);
        iface.declaration = declaration;
@@ -279,21 +293,18 @@ void VariableResolver::visit(MemberAccess &memacc)
        TraversingVisitor::visit(memacc);
 
        VariableDeclaration *declaration = 0;
+       int index = -1;
        if(StructDeclaration *strct = dynamic_cast<StructDeclaration *>(memacc.left->type))
        {
                map<string, VariableDeclaration *>::iterator i = strct->members.variables.find(memacc.member);
                if(i!=strct->members.variables.end())
                {
                        declaration = i->second;
+                       for(NodeList<Statement>::const_iterator j=strct->members.body.begin(); (j!=strct->members.body.end() && j->get()!=i->second); ++j)
+                               ++index;
 
                        if(record_target)
-                       {
-                               unsigned index = 0;
-                               for(NodeList<Statement>::const_iterator j=strct->members.body.begin(); (j!=strct->members.body.end() && j->get()!=i->second); ++j)
-                                       ++index;
-
                                add_to_chain(Assignment::Target::MEMBER, index);
-                       }
                }
        }
        else if(BasicTypeDeclaration *basic = dynamic_cast<BasicTypeDeclaration *>(memacc.left->type))
@@ -324,8 +335,9 @@ void VariableResolver::visit(MemberAccess &memacc)
                }
        }
 
-       r_any_resolved |= (declaration!=memacc.declaration);
+       r_any_resolved |= (declaration!=memacc.declaration || index!=memacc.index);
        memacc.declaration = declaration;
+       memacc.index = index;
 }
 
 void VariableResolver::visit(Swizzle &swizzle)
@@ -432,9 +444,9 @@ void VariableResolver::visit(InterfaceBlock &iface)
 {
        /* Block names can be reused in different interfaces.  Prefix the name with
        the first character of the interface to avoid conflicts. */
-       stage->interface_blocks.insert(make_pair(iface.interface+iface.block_name, &iface));
+       stage->interface_blocks.insert(make_pair(format("%s %s", iface.interface, iface.block_name), &iface));
        if(!iface.instance_name.empty())
-               stage->interface_blocks.insert(make_pair("_"+iface.instance_name, &iface));
+               stage->interface_blocks.insert(make_pair(iface.instance_name, &iface));
 
        TraversingVisitor::visit(iface);
 }