From f438142c7589df7480aa640cf62b7a2c3d48bab2 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sun, 10 Oct 2021 18:35:43 +0300 Subject: [PATCH] Allow redeclaring entire builtin interface blocks --- source/glsl/resolve.cpp | 66 ++++++++++++++++++++++++------- source/glsl/resolve.h | 1 + tests/glsl/redeclare_builtin.glsl | 23 +++++++++++ 3 files changed, 75 insertions(+), 15 deletions(-) create mode 100644 tests/glsl/redeclare_builtin.glsl diff --git a/source/glsl/resolve.cpp b/source/glsl/resolve.cpp index f72dedfd..b80ae217 100644 --- a/source/glsl/resolve.cpp +++ b/source/glsl/resolve.cpp @@ -390,6 +390,21 @@ void VariableResolver::merge_layouts(Layout &to_layout, const Layout &from_layou } } +void VariableResolver::redeclare_builtin(VariableDeclaration &existing, VariableDeclaration &var) +{ + if(var.layout) + { + if(existing.layout) + merge_layouts(*existing.layout, *var.layout); + else + existing.layout = var.layout; + } + if(var.array_size) + existing.array_size = var.array_size; + + redeclared_builtins.push_back(&existing); +} + void VariableResolver::visit(VariableDeclaration &var) { TraversingVisitor::visit(var); @@ -422,17 +437,8 @@ void VariableResolver::visit(VariableDeclaration &var) { if(existing->source==BUILTIN_SOURCE) { - if(var.layout) - { - if(existing->layout) - merge_layouts(*existing->layout, *var.layout); - else - existing->layout = var.layout; - } - if(var.array_size) - existing->array_size = var.array_size; + redeclare_builtin(*existing, var); - redeclared_builtins.push_back(existing); if(block) { redeclared_builtins.push_back(block); @@ -454,11 +460,41 @@ void VariableResolver::visit(VariableDeclaration &var) 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(format("%s %s", iface.interface, iface.block_name), &iface)); - if(!iface.instance_name.empty()) - stage->interface_blocks.insert(make_pair(iface.instance_name, &iface)); + string key = format("%s %s", iface.interface, iface.block_name); + auto i = stage->interface_blocks.find(key); + if(i!=stage->interface_blocks.end()) + { + if(i->second->source==BUILTIN_SOURCE && iface.struct_declaration && i->second->struct_declaration) + { + const map &vars = iface.struct_declaration->members.variables; + const map &existing_vars = i->second->struct_declaration->members.variables; + + bool found_all = true; + for(const auto &kvp: vars) + { + auto j = existing_vars.find(kvp.first); + if(j!=existing_vars.end() && j->second->type==kvp.second->type && j->second->array==kvp.second->array) + redeclare_builtin(*j->second, *kvp.second); + else + found_all = false; + } + + if(found_all) + { + redeclared_builtins.push_back(i->second); + nodes_to_remove.insert(&iface); + nodes_to_remove.insert(iface.struct_declaration); + } + } + } + else + { + /* Block names can be reused in different interfaces. Prepend the interface + to the name to avoid conflicts. */ + stage->interface_blocks.insert(make_pair(key, &iface)); + if(!iface.instance_name.empty()) + stage->interface_blocks.insert(make_pair(iface.instance_name, &iface)); + } TraversingVisitor::visit(iface); } diff --git a/source/glsl/resolve.h b/source/glsl/resolve.h index 85611727..10322d49 100644 --- a/source/glsl/resolve.h +++ b/source/glsl/resolve.h @@ -78,6 +78,7 @@ private: virtual void visit(BinaryExpression &); virtual void visit(Assignment &); void merge_layouts(Layout &, const Layout &); + void redeclare_builtin(VariableDeclaration &, VariableDeclaration &); virtual void visit(VariableDeclaration &); virtual void visit(InterfaceBlock &); }; diff --git a/tests/glsl/redeclare_builtin.glsl b/tests/glsl/redeclare_builtin.glsl new file mode 100644 index 00000000..c0b84c42 --- /dev/null +++ b/tests/glsl/redeclare_builtin.glsl @@ -0,0 +1,23 @@ +#pragma MSP stage(vertex) +layout(location=0) in vec4 position; +out float gl_ClipDistance[1]; +void main() +{ + gl_ClipDistance[0] = dot(position.xyz, vec3(0.0, 0.0, 1.0)); + gl_Position = position; +} + +/* Expected output: vertex +out gl_PerVertex +{ + vec4 gl_Position; + float gl_PointSize; + float gl_ClipDistance[1]; +}; +layout(location=0) in vec4 position; +void main() +{ + gl_ClipDistance[0] = dot(position.xyz, vec3(0.0, 0.0, 1.0)); + gl_Position = position; +} +*/ -- 2.43.0