]> git.tdb.fi Git - libs/gl.git/commitdiff
Limit GLSL passthrough statement to variables declared by that point
authorMikko Rasa <tdb@tdb.fi>
Fri, 12 Mar 2021 09:53:11 +0000 (11:53 +0200)
committerMikko Rasa <tdb@tdb.fi>
Fri, 12 Mar 2021 18:27:38 +0000 (20:27 +0200)
This fixes an issue where a base module's passthrough statement would
generate references to inputs declared in an importing module, resulting
in a compile error.

source/glsl/generate.cpp
source/glsl/generate.h
tests/glsl/passthrough_declaration_order.glsl [new file with mode: 0644]

index 01d34c63cd5f1b0eb99060b59b8abd533f41401f..ab487a44c470bca769af032b9ce2966c7a0df5d2 100644 (file)
@@ -1065,6 +1065,8 @@ VariableDeclaration *InterfaceGenerator::generate_interface(VariableDeclaration
 
        iface_target_block->body.insert(iface_insert_point, iface_var);
        iface_target_block->variables.insert(make_pair(name, iface_var));
+       if(iface_target_block==&stage->content && iface=="in")
+               declared_inputs.push_back(iface_var);
 
        return iface_var;
 }
@@ -1197,11 +1199,13 @@ void InterfaceGenerator::visit(VariableDeclaration &var)
                        }
                }
        }
-       else if(var.interface=="in")
+       else if(var.interface=="in" && current_block==&stage->content)
        {
+               declared_inputs.push_back(&var);
+
                /* Try to link input variables in global scope with output variables from
                previous stage. */
-               if(current_block==&stage->content && !var.linked_declaration && stage->previous)
+               if(!var.linked_declaration && stage->previous)
                {
                        const map<string, VariableDeclaration *> &prev_vars = stage->previous->content.variables;
                        map<string, VariableDeclaration *>::const_iterator i = prev_vars.find(var.name);
@@ -1246,12 +1250,8 @@ void InterfaceGenerator::visit(FunctionDeclaration &func)
 
 void InterfaceGenerator::visit(Passthrough &pass)
 {
-       vector<VariableDeclaration *> pass_vars;
-
-       // Pass through all input variables of this stage.
-       for(map<string, VariableDeclaration *>::const_iterator i=stage->content.variables.begin(); i!=stage->content.variables.end(); ++i)
-               if(i->second->interface=="in")
-                       pass_vars.push_back(i->second);
+       // Pass through all input variables declared so far.
+       vector<VariableDeclaration *> pass_vars = declared_inputs;
 
        if(stage->previous)
        {
index 4e66ef68ed6c75fbda2e360dfe813a1cdda1838e..c7a162e5c6c7e81f81a30d104f0763e81ff8f0ee 100644 (file)
@@ -200,6 +200,7 @@ private:
        std::string out_prefix;
        bool function_scope;
        bool copy_block;
+       std::vector<VariableDeclaration *> declared_inputs;
        Block *iface_target_block;
        NodeList<Statement>::iterator iface_insert_point;
        NodeList<Statement>::iterator assignment_insert_point;
diff --git a/tests/glsl/passthrough_declaration_order.glsl b/tests/glsl/passthrough_declaration_order.glsl
new file mode 100644 (file)
index 0000000..52712d8
--- /dev/null
@@ -0,0 +1,41 @@
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 position;
+void process();
+void main()
+{
+       gl_Position = position;
+       passthrough;
+       process();
+}
+layout(location=1) in vec4 color;
+void process()
+{
+       passthrough;
+}
+
+#pragma MSP stage(fragment)
+layout(location=0) out vec4 frag_color;
+void main()
+{
+       frag_color = color;
+}
+
+/* Expected output: vertex
+layout(location=0) in vec4 position;
+layout(location=1) in vec4 color;
+out vec4 _vs_out_color;
+void main()
+{
+       gl_Position = position;
+       _vs_out_color = color;
+}
+*/
+
+/* Expected output: fragment
+layout(location=0) out vec4 frag_color;
+in vec4 _vs_out_color;
+void main()
+{
+       frag_color = _vs_out_color;
+}
+*/