glsl/linker: Always invalidate shader ins/outs, even in corner cases.
authorPaul Berry <stereotype441@gmail.com>
Wed, 5 Dec 2012 15:17:07 +0000 (07:17 -0800)
committerPaul Berry <stereotype441@gmail.com>
Fri, 14 Dec 2012 18:48:35 +0000 (10:48 -0800)
Previously, link_invalidate_variable_locations() was only called
during assign_attribute_or_color_locations() and
assign_varying_locations().  This meant that in the corner case when
there was only a vertex shader, and varyings were being captured by
transform feedback, link_invalidate_variable_locations() wasn't being
called for the varyings.

This patch migrates the calls to link_invalidate_variable_locations()
to link_shaders(), so that they will be called in all circumstances.
In addition, it modifies the call semantics so that
link_invalidate_variable_locations() need only be called once per
shader stage (rather than once for inputs and once for outputs).

Reviewed-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
src/glsl/linker.cpp

index 802323e32f013bd6ecaf57c6b84a7bd7359d99a1..2523dc99d6ff97fe2bc295957af6d702d1feee9c 100644 (file)
@@ -200,19 +200,31 @@ linker_warning(gl_shader_program *prog, const char *fmt, ...)
 
 
 void
-link_invalidate_variable_locations(gl_shader *sh, enum ir_variable_mode mode,
-                                  int generic_base)
+link_invalidate_variable_locations(gl_shader *sh, int input_base,
+                                   int output_base)
 {
    foreach_list(node, sh->ir) {
       ir_variable *const var = ((ir_instruction *) node)->as_variable();
 
-      if ((var == NULL) || (var->mode != (unsigned) mode))
-        continue;
+      if (var == NULL)
+         continue;
+
+      int base;
+      switch (var->mode) {
+      case ir_var_in:
+         base = input_base;
+         break;
+      case ir_var_out:
+         base = output_base;
+         break;
+      default:
+         continue;
+      }
 
       /* Only assign locations for generic attributes / varyings / etc.
        */
-      if ((var->location >= generic_base) && !var->explicit_location)
-         var->location = -1;
+      if ((var->location >= base) && !var->explicit_location)
+         var->location = -1;
    }
 }
 
@@ -1309,8 +1321,6 @@ assign_attribute_or_color_locations(gl_shader_program *prog,
       (target_index == MESA_SHADER_VERTEX) ? ir_var_in : ir_var_out;
 
 
-   link_invalidate_variable_locations(sh, direction, generic_base);
-
    /* Temporary storage for the set of attributes that need locations assigned.
     */
    struct temp_attr {
@@ -2072,10 +2082,6 @@ assign_varying_locations(struct gl_context *ctx,
     *    not being inputs.  This lets the optimizer eliminate them.
     */
 
-   link_invalidate_variable_locations(producer, ir_var_out, VERT_RESULT_VAR0);
-   if (consumer)
-      link_invalidate_variable_locations(consumer, ir_var_in, FRAG_ATTRIB_VAR0);
-
    foreach_list(node, producer->ir) {
       ir_variable *const output_var = ((ir_instruction *) node)->as_variable();
 
@@ -2578,6 +2584,19 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
         ;
    }
 
+   /* Mark all generic shader inputs and outputs as unpaired. */
+   if (prog->_LinkedShaders[MESA_SHADER_VERTEX] != NULL) {
+      link_invalidate_variable_locations(
+            prog->_LinkedShaders[MESA_SHADER_VERTEX],
+            VERT_ATTRIB_GENERIC0, VERT_RESULT_VAR0);
+   }
+   /* FINISHME: Geometry shaders not implemented yet */
+   if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] != NULL) {
+      link_invalidate_variable_locations(
+            prog->_LinkedShaders[MESA_SHADER_FRAGMENT],
+            FRAG_ATTRIB_VAR0, FRAG_RESULT_DATA0);
+   }
+
    /* FINISHME: The value of the max_attribute_index parameter is
     * FINISHME: implementation dependent based on the value of
     * FINISHME: GL_MAX_VERTEX_ATTRIBS.  GL_MAX_VERTEX_ATTRIBS must be