]> git.tdb.fi Git - libs/gl.git/commitdiff
Improve support for interface blocks
authorMikko Rasa <tdb@tdb.fi>
Thu, 25 Feb 2021 19:30:36 +0000 (21:30 +0200)
committerMikko Rasa <tdb@tdb.fi>
Thu, 25 Feb 2021 22:33:59 +0000 (00:33 +0200)
Blocks with instance names are now properly supported in the syntax tree.

12 files changed:
source/glsl/debug.cpp
source/glsl/debug.h
source/glsl/generate.cpp
source/glsl/generate.h
source/glsl/optimize.cpp
source/glsl/optimize.h
source/glsl/output.cpp
source/glsl/output.h
source/glsl/syntax.cpp
source/glsl/syntax.h
source/glsl/visitor.cpp
source/glsl/visitor.h

index 018408c7a74d83b8974a7252061b40ab72695eb6..62cf7a94701ec04169c39748fbad6c84b46d58d2 100644 (file)
@@ -85,8 +85,15 @@ void DumpTree::visit(Block &block)
        for(std::map<string, VariableDeclaration *>::const_iterator i=block.variables.begin(); i!=block.variables.end(); ++i)
                append(format("Variable: %%%d %s %s", get_label(*i->second), i->second->type, i->first));
 
-       for(std::set<InterfaceBlock *>::const_iterator i=block.interfaces.begin(); i!=block.interfaces.end(); ++i)
-               append(format("Interface: %%%d %s %s", get_label(*i->second), i->second->interface, i->second->name));
+       set<InterfaceBlock *> seen_interfaces;
+       for(std::map<string, InterfaceBlock *>::const_iterator i=block.interfaces.begin(); i!=block.interfaces.end(); ++i)
+               if(seen_interfaces.insert(i->second).second)
+               {
+                       string text = format("Interface: %%%d %s %s", get_label(*i->second), i->second->interface, i->second->name);
+                       if(!i->second->instance_name.empty())
+                               text += format(" %s", i->second->instance_name);
+                       append(text);
+               }
 
        bool labeled_body = (!block.types.empty() || !block.variables.empty());
        if(labeled_body)
@@ -121,7 +128,16 @@ void DumpTree::visit(VariableReference &var)
        string text;
        if(var.declaration)
                text += format("%%%d ", get_label(*var.declaration));
-       text += var.name;
+       text += format("%s (var)", var.name);
+       append(text);
+}
+
+void DumpTree::visit(InterfaceBlockReference &iface)
+{
+       string text;
+       if(iface.declaration)
+               text += format("%%%d ", get_label(*iface.declaration));
+       text += format("%s (iface)", iface.name);
        append(text);
 }
 
@@ -264,7 +280,17 @@ void DumpTree::visit(VariableDeclaration &var)
 
 void DumpTree::visit(InterfaceBlock &block)
 {
-       annotated_branch(format("%s %s", block.interface, block.name), block.members);
+       string head;
+       if(!block.instance_name.empty())
+               head += format("%%%d ", get_label(block));
+       head += format("%s %s", block.interface, block.name);
+       if(!block.instance_name.empty())
+               head += format(" %s", block.instance_name);
+       if(block.array)
+               head += "[]";
+       if(block.linked_block)
+               head += " (linked)";
+       annotated_branch(head, block.members);
 }
 
 void DumpTree::visit(FunctionDeclaration &func)
index 66f2b067c15776cf5806453c1e0548ec00365734..6aca7af0fb2a94b0aab0b8936f1c9ea902021d2a 100644 (file)
@@ -42,6 +42,7 @@ private:
        virtual void visit(Literal &);
        virtual void visit(ParenthesizedExpression &);
        virtual void visit(VariableReference &);
+       virtual void visit(InterfaceBlockReference &);
        virtual void visit(MemberAccess &);
        virtual void visit(UnaryExpression &);
        virtual void visit(BinaryExpression &);
index 3ff04eb9890124f7098c015dafe1099d77d7d34e..434dbe7a8486e0d73104c9a2c0e0ad451c67d39a 100644 (file)
@@ -80,12 +80,18 @@ void BlockResolver::enter(Block &block)
 
 void BlockResolver::visit(InterfaceBlock &iface)
 {
-       current_block->interfaces.insert(&iface);
+       /* 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,7 +117,7 @@ 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<string, VariableDeclaration *>::iterator i = block->variables.find(var.name);
@@ -119,18 +125,30 @@ void VariableResolver::visit(VariableReference &var)
                        var.declaration = i->second;
                else
                {
-                       const set<InterfaceBlock *> &ifaces = block->interfaces;
-                       for(set<InterfaceBlock *>::const_iterator j=ifaces.begin(); (!var.declaration && j!=ifaces.end()); ++j)
-                       {
-                               i = (*j)->members.variables.find(var.name);
-                               if(i!=(*j)->members.variables.end())
-                                       var.declaration = i->second;
-                       }
+                       const map<string, InterfaceBlock *> &ifaces = block->interfaces;
+                       for(map<string, InterfaceBlock *>::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)
                {
-                       type = var.declaration->type_declaration;
+                       if(var.declaration->type_declaration)
+                               members = &var.declaration->type_declaration->members.variables;
+                       break;
+               }
+
+               map<string, InterfaceBlock *>::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;
                }
        }
@@ -149,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<string, InterfaceBlock *>::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<string, VariableDeclaration *>::iterator i = type->members.variables.find(memacc.member);
-               if(i!=type->members.variables.end())
+               map<string, VariableDeclaration *>::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;
        }
 }
 
@@ -175,13 +215,17 @@ void VariableResolver::visit(BinaryExpression &binary)
                        SetForScope<bool> 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;
        }
 }
 
@@ -259,7 +303,8 @@ void FunctionResolver::visit(FunctionDeclaration &func)
 
 InterfaceGenerator::InterfaceGenerator():
        stage(0),
-       function_scope(false)
+       function_scope(false),
+       iface_block(0)
 { }
 
 string InterfaceGenerator::get_out_prefix(Stage::Type type)
@@ -368,6 +413,18 @@ void InterfaceGenerator::visit(VariableReference &var)
 
 void InterfaceGenerator::visit(VariableDeclaration &var)
 {
+       if(iface_block)
+       {
+               if(iface_block->linked_block)
+               {
+                       const map<string, VariableDeclaration *> &linked_vars = iface_block->linked_block->members.variables;
+                       map<string, VariableDeclaration *>::const_iterator i = linked_vars.find(var.name);
+                       if(i!=linked_vars.end())
+                               var.linked_declaration = i->second;
+               }
+               return;
+       }
+
        if(var.interface=="out")
        {
                /* For out variables in function scope, generate a global interface and
@@ -403,6 +460,26 @@ 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<string, InterfaceBlock *> &prev_blocks = stage->previous->content.interfaces;
+                       map<string, InterfaceBlock *>::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<InterfaceBlock *> set_iface(iface_block, &iface);
+       TraversingVisitor::visit(iface);
+}
+
 void InterfaceGenerator::visit(FunctionDeclaration &func)
 {
        SetFlag set_scope(function_scope, true);
@@ -434,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;
index 72035b2c4869504199edda4df59e46958b41fed1..4968297635c074e975af19e42934c57fe1da78a7 100644 (file)
@@ -41,7 +41,8 @@ class VariableResolver: private TraversingVisitor
 {
 private:
        Block *builtins;
-       StructDeclaration *type;
+       std::map<std::string, VariableDeclaration *> *members;
+       RefPtr<InterfaceBlockReference> iface_ref;
        std::string block_interface;
        bool record_target;
        VariableDeclaration *assignment_target;
@@ -57,6 +58,7 @@ private:
 
        virtual void enter(Block &);
        virtual void visit(VariableReference &);
+       virtual void visit(InterfaceBlockReference &);
        virtual void visit(MemberAccess &);
        virtual void visit(BinaryExpression &);
        virtual void visit(Assignment &);
@@ -85,6 +87,7 @@ private:
        std::string in_prefix;
        std::string out_prefix;
        bool function_scope;
+       InterfaceBlock *iface_block;
        NodeList<Statement>::iterator iface_insert_point;
        NodeList<Statement>::iterator assignment_insert_point;
        std::set<Node *> nodes_to_remove;
@@ -102,6 +105,7 @@ private:
        ExpressionStatement &insert_assignment(const std::string &, Expression *);
        virtual void visit(VariableReference &);
        virtual void visit(VariableDeclaration &);
+       virtual void visit(InterfaceBlock &);
        virtual void visit(FunctionDeclaration &);
        virtual void visit(Passthrough &);
 };
index fcb1075ecbadc6a1d412142dc8191a83587ff917..1ebb87c5c2ea23360c33917104745273de6d8da0 100644 (file)
@@ -264,6 +264,11 @@ void UnusedVariableRemover::visit(VariableReference &var)
        }
 }
 
+void UnusedVariableRemover::visit(InterfaceBlockReference &iface)
+{
+       unused_nodes.erase(iface.declaration);
+}
+
 void UnusedVariableRemover::visit(MemberAccess &memacc)
 {
        TraversingVisitor::visit(memacc);
index c412433e0a222337ffcd4752fa11540f8514e936..38218966369213c5fbc8ba802d38bbf1e8bda420 100644 (file)
@@ -103,6 +103,7 @@ public:
 
 private:
        virtual void visit(VariableReference &);
+       virtual void visit(InterfaceBlockReference &);
        virtual void visit(MemberAccess &);
        virtual void visit(BinaryExpression &);
        virtual void visit(Assignment &);
index ef7910f17bd2de93e8de4cc742ff68ee90c1e2b4..44acd634d388e1d3f9c7ab86081e43e4368f01ee 100644 (file)
@@ -99,6 +99,11 @@ void Formatter::visit(VariableReference &var)
        append(var.name);
 }
 
+void Formatter::visit(InterfaceBlockReference &iface)
+{
+       append(iface.name);
+}
+
 void Formatter::visit(MemberAccess &memacc)
 {
        memacc.left->visit(*this);
@@ -255,6 +260,13 @@ void Formatter::visit(InterfaceBlock &iface)
        SetForScope<string> set(block_interface, iface.interface);
        append(format("%s %s\n", iface.interface, iface.name));
        iface.members.visit(*this);
+       if(!iface.instance_name.empty())
+       {
+               append(' ');
+               append(iface.instance_name);
+               if(iface.array)
+                       append("[]");
+       }
        append(';');
 }
 
index b8554b7d1aa83eb95f89e1647a280492883065e3..66b77bbaaca62a391cce7b022b68473a2f9595e5 100644 (file)
@@ -36,6 +36,7 @@ private:
        virtual void visit(Literal &);
        virtual void visit(ParenthesizedExpression &);
        virtual void visit(VariableReference &);
+       virtual void visit(InterfaceBlockReference &);
        virtual void visit(MemberAccess &);
        virtual void visit(UnaryExpression &);
        virtual void visit(BinaryExpression &);
index b20f63caf2030887a5a4ea6203346f401253e36b..6c766fd758161283006de48f0cdbc09666e8d305 100644 (file)
@@ -117,6 +117,21 @@ void VariableReference::visit(NodeVisitor &visitor)
 }
 
 
+InterfaceBlockReference::InterfaceBlockReference():
+       declaration(0)
+{ }
+
+InterfaceBlockReference::InterfaceBlockReference(const InterfaceBlockReference &other):
+       name(other.name),
+       declaration(0)
+{ }
+
+void InterfaceBlockReference::visit(NodeVisitor &visitor)
+{
+       visitor.visit(*this);
+}
+
+
 MemberAccess::MemberAccess():
        declaration(0)
 { }
@@ -254,11 +269,21 @@ void VariableDeclaration::visit(NodeVisitor &visitor)
 
 
 InterfaceBlock::InterfaceBlock():
-       array(false)
+       array(false),
+       linked_block(0)
 {
        members.use_braces = true;
 }
 
+InterfaceBlock::InterfaceBlock(const InterfaceBlock &other):
+       interface(other.interface),
+       name(other.name),
+       members(other.members),
+       instance_name(other.instance_name),
+       array(other.array),
+       linked_block(0)
+{ }
+
 void InterfaceBlock::visit(NodeVisitor &visitor)
 {
        visitor.visit(*this);
index 4ff05fa1a09f9275760dcbfe617610dc6d21a2e3..f7e778b89ef65d417afd1f44751930311c5e94ed 100644 (file)
@@ -110,7 +110,7 @@ struct Block: Node
        bool use_braces;
        std::map<std::string, StructDeclaration *> types;
        std::map<std::string, VariableDeclaration *> variables;
-       std::set<InterfaceBlock *> interfaces;
+       std::map<std::string, InterfaceBlock *> interfaces;
        Block *parent;
 
        Block();
@@ -153,6 +153,18 @@ struct VariableReference: Expression
        virtual void visit(NodeVisitor &);
 };
 
+struct InterfaceBlockReference: Expression
+{
+       std::string name;
+       InterfaceBlock *declaration;
+
+       InterfaceBlockReference();
+       InterfaceBlockReference(const InterfaceBlockReference &);
+
+       virtual InterfaceBlockReference *clone() const { return new InterfaceBlockReference(*this); }
+       virtual void visit(NodeVisitor &);
+};
+
 struct MemberAccess: Expression
 {
        NodePtr<Expression> left;
@@ -305,8 +317,10 @@ struct InterfaceBlock: Statement
        Block members;
        std::string instance_name;
        bool array;
+       InterfaceBlock *linked_block;
 
        InterfaceBlock();
+       InterfaceBlock(const InterfaceBlock &);
 
        virtual InterfaceBlock *clone() const { return new InterfaceBlock(*this); }
        virtual void visit(NodeVisitor &);
index c27de11892607ec627e1a6bf7022e2aa267e0023..051d92f6adfc1e48f9117a32797d3004f9759e10 100644 (file)
@@ -134,10 +134,11 @@ void NodeRemover::apply(Stage &s, const set<Node *> &tr)
        s.content.visit(*this);
 }
 
-void NodeRemover::remove_variable(map<string, VariableDeclaration *> &vars, VariableDeclaration &decl)
+template<typename T>
+void NodeRemover::remove_from_map(map<string, T *> &vars, const string &key, T &node)
 {
-       map<string, VariableDeclaration *>::iterator i = vars.find(decl.name);
-       if(i!=vars.end() && i->second==&decl)
+       typename map<string, T *>::iterator i = vars.find(key);
+       if(i!=vars.end() && i->second==&node)
                vars.erase(i);
 }
 
@@ -157,14 +158,14 @@ void NodeRemover::visit(Block &block)
 void NodeRemover::visit(StructDeclaration &strct)
 {
        if(to_remove->count(&strct))
-               current_block->types.erase(strct.name);
+               remove_from_map(current_block->types, strct.name, strct);
 }
 
 void NodeRemover::visit(VariableDeclaration &var)
 {
        if(recursive_remove || to_remove->count(&var))
        {
-               remove_variable(current_block->variables, var);
+               remove_from_map(current_block->variables, var.name, var);
                stage->locations.erase(var.name);
                if(var.linked_declaration)
                        var.linked_declaration->linked_declaration = 0;
@@ -176,7 +177,11 @@ void NodeRemover::visit(VariableDeclaration &var)
 void NodeRemover::visit(InterfaceBlock &iface)
 {
        if(to_remove->count(&iface))
-               current_block->interfaces.erase(&iface);
+       {
+               remove_from_map(current_block->interfaces, iface.name, iface);
+               if(!iface.instance_name.empty())
+                       remove_from_map(current_block->interfaces, iface.instance_name, iface);
+       }
        SetFlag set_recursive(recursive_remove, recursive_remove || to_remove->count(&iface));
        TraversingVisitor::visit(iface);
 }
index 2a4ef549b827b4f9b42fb1c7db411770dc92ff21..a26e785c741e3b97e643d78f6353742feca04dd2 100644 (file)
@@ -20,6 +20,7 @@ public:
        virtual void visit(Literal &) { }
        virtual void visit(ParenthesizedExpression &) { }
        virtual void visit(VariableReference &) { }
+       virtual void visit(InterfaceBlockReference &) { }
        virtual void visit(MemberAccess &) { }
        virtual void visit(UnaryExpression &) { }
        virtual void visit(BinaryExpression &) { }
@@ -94,7 +95,8 @@ public:
        void apply(Stage &, const std::set<Node *> &);
 
 private:
-       void remove_variable(std::map<std::string, VariableDeclaration *> &, VariableDeclaration &);
+       template<typename T>
+       void remove_from_map(std::map<std::string, T *> &, const std::string &, T &);
 
        virtual void visit(Block &);
        virtual void visit(StructDeclaration &);