From dfcf8ebc329b79c369b88bdbeb982480aa5fc12a Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 5 Apr 2021 14:49:41 +0300 Subject: [PATCH] Always use member access for interface blocks, even anonymous ones Having variable references magically refer to variables inside interface blocks causes trouble when generating SPIR-V. This currently breaks one test case because UnusedVariableRemover can't track access chains. --- source/glsl/optimize.cpp | 16 ++------------ source/glsl/output.cpp | 12 ++++++++--- source/glsl/output.h | 1 + source/glsl/resolve.cpp | 46 ++++++++++++++++++++++++++-------------- 4 files changed, 42 insertions(+), 33 deletions(-) diff --git a/source/glsl/optimize.cpp b/source/glsl/optimize.cpp index d7558ebd..475e8b64 100644 --- a/source/glsl/optimize.cpp +++ b/source/glsl/optimize.cpp @@ -997,10 +997,6 @@ bool UnusedVariableRemover::apply(Stage &s) if(i->used_by.empty()) unused_nodes.insert(i->node); - for(map::const_iterator i=s.interface_blocks.begin(); i!=s.interface_blocks.end(); ++i) - if(i->second->instance_name.empty()) - unused_nodes.insert(i->second); - for(BlockVariableMap::const_iterator i=variables.begin(); i!=variables.end(); ++i) { if(i->second.output) @@ -1153,16 +1149,8 @@ void UnusedVariableRemover::visit(VariableDeclaration &var) void UnusedVariableRemover::visit(InterfaceBlock &iface) { - if(iface.instance_name.empty()) - { - SetForScope set_block(interface_block, &iface); - iface.struct_declaration->members.visit(*this); - } - else - { - VariableInfo &var_info = variables[&iface]; - var_info.output = (iface.interface=="out" && (iface.linked_block || !iface.block_name.compare(0, 3, "gl_"))); - } + VariableInfo &var_info = variables[&iface]; + var_info.output = (iface.interface=="out" && (iface.linked_block || !iface.block_name.compare(0, 3, "gl_"))); } void UnusedVariableRemover::merge_variables(const BlockVariableMap &other_vars) diff --git a/source/glsl/output.cpp b/source/glsl/output.cpp index 1d82cae6..38adb5bd 100644 --- a/source/glsl/output.cpp +++ b/source/glsl/output.cpp @@ -14,7 +14,8 @@ Formatter::Formatter(): source_line(1), indent(0), parameter_list(false), - omit_builtin(false) + omit_builtin(false), + r_empty_name(false) { } const string &Formatter::apply(Stage &s) @@ -154,17 +155,22 @@ void Formatter::visit(Literal &literal) void Formatter::visit(VariableReference &var) { append(var.name); + r_empty_name = false; } void Formatter::visit(InterfaceBlockReference &iface) { - append(iface.name); + r_empty_name = iface.declaration->instance_name.empty(); + if(!r_empty_name) + append(iface.declaration->instance_name); } void Formatter::visit(MemberAccess &memacc) { visit_expression(*memacc.left, memacc.oper, false); - append(format(".%s", memacc.member)); + if(!r_empty_name) + append('.'); + append(memacc.member); } void Formatter::visit(Swizzle &swizzle) diff --git a/source/glsl/output.h b/source/glsl/output.h index 6bdb1ab7..ef936987 100644 --- a/source/glsl/output.h +++ b/source/glsl/output.h @@ -20,6 +20,7 @@ private: unsigned indent; bool parameter_list; bool omit_builtin; + bool r_empty_name; public: Formatter(); diff --git a/source/glsl/resolve.cpp b/source/glsl/resolve.cpp index 8bfe635e..c5a507a2 100644 --- a/source/glsl/resolve.cpp +++ b/source/glsl/resolve.cpp @@ -226,28 +226,42 @@ void VariableResolver::visit(VariableReference &var) { const map &blocks = stage->interface_blocks; map::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 &iface_vars = i->second->struct_declaration->members.variables; - map::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; + } } } -- 2.43.0