}
}
+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);
{
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);
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<string, VariableDeclaration *> &vars = iface.struct_declaration->members.variables;
+ const map<string, VariableDeclaration *> &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);
}
--- /dev/null
+#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;
+}
+*/