From: Mikko Rasa Date: Thu, 25 Feb 2021 19:30:36 +0000 (+0200) Subject: Improve support for interface blocks X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=bd8816692056230c36504dcccd76c6946dff47b1;p=libs%2Fgl.git Improve support for interface blocks Blocks with instance names are now properly supported in the syntax tree. --- diff --git a/source/glsl/debug.cpp b/source/glsl/debug.cpp index 018408c7..62cf7a94 100644 --- a/source/glsl/debug.cpp +++ b/source/glsl/debug.cpp @@ -85,8 +85,15 @@ void DumpTree::visit(Block &block) for(std::map::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::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 seen_interfaces; + for(std::map::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) diff --git a/source/glsl/debug.h b/source/glsl/debug.h index 66f2b067..6aca7af0 100644 --- a/source/glsl/debug.h +++ b/source/glsl/debug.h @@ -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 &); diff --git a/source/glsl/generate.cpp b/source/glsl/generate.cpp index 3ff04eb9..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) { - 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::iterator i = block->variables.find(var.name); @@ -119,18 +125,30 @@ void VariableResolver::visit(VariableReference &var) var.declaration = i->second; else { - const set &ifaces = block->interfaces; - for(set::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 &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) { - type = var.declaration->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; } } @@ -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::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; } } @@ -175,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; } } @@ -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 &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") { /* 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 &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); @@ -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; diff --git a/source/glsl/generate.h b/source/glsl/generate.h index 72035b2c..49682976 100644 --- a/source/glsl/generate.h +++ b/source/glsl/generate.h @@ -41,7 +41,8 @@ class VariableResolver: private TraversingVisitor { private: Block *builtins; - StructDeclaration *type; + std::map *members; + RefPtr 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::iterator iface_insert_point; NodeList::iterator assignment_insert_point; std::set 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 &); }; diff --git a/source/glsl/optimize.cpp b/source/glsl/optimize.cpp index fcb1075e..1ebb87c5 100644 --- a/source/glsl/optimize.cpp +++ b/source/glsl/optimize.cpp @@ -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); diff --git a/source/glsl/optimize.h b/source/glsl/optimize.h index c412433e..38218966 100644 --- a/source/glsl/optimize.h +++ b/source/glsl/optimize.h @@ -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 &); diff --git a/source/glsl/output.cpp b/source/glsl/output.cpp index ef7910f1..44acd634 100644 --- a/source/glsl/output.cpp +++ b/source/glsl/output.cpp @@ -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 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(';'); } diff --git a/source/glsl/output.h b/source/glsl/output.h index b8554b7d..66b77bba 100644 --- a/source/glsl/output.h +++ b/source/glsl/output.h @@ -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 &); diff --git a/source/glsl/syntax.cpp b/source/glsl/syntax.cpp index b20f63ca..6c766fd7 100644 --- a/source/glsl/syntax.cpp +++ b/source/glsl/syntax.cpp @@ -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); diff --git a/source/glsl/syntax.h b/source/glsl/syntax.h index 4ff05fa1..f7e778b8 100644 --- a/source/glsl/syntax.h +++ b/source/glsl/syntax.h @@ -110,7 +110,7 @@ struct Block: Node bool use_braces; std::map types; std::map variables; - std::set interfaces; + std::map 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 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 &); diff --git a/source/glsl/visitor.cpp b/source/glsl/visitor.cpp index c27de118..051d92f6 100644 --- a/source/glsl/visitor.cpp +++ b/source/glsl/visitor.cpp @@ -134,10 +134,11 @@ void NodeRemover::apply(Stage &s, const set &tr) s.content.visit(*this); } -void NodeRemover::remove_variable(map &vars, VariableDeclaration &decl) +template +void NodeRemover::remove_from_map(map &vars, const string &key, T &node) { - map::iterator i = vars.find(decl.name); - if(i!=vars.end() && i->second==&decl) + typename map::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); } diff --git a/source/glsl/visitor.h b/source/glsl/visitor.h index 2a4ef549..a26e785c 100644 --- a/source/glsl/visitor.h +++ b/source/glsl/visitor.h @@ -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 &); private: - void remove_variable(std::map &, VariableDeclaration &); + template + void remove_from_map(std::map &, const std::string &, T &); virtual void visit(Block &); virtual void visit(StructDeclaration &);