From: Ian Romanick <ian.d.roman...@intel.com>

Outputs that go from one shader stage to the next need slightly
different treatment than outputs from the fragement shader.  Likewise
for inputs.  If an output (or input) is intrastage and not a built-in,
smash its location to 0, and set explicit_location to false.  The
location set in the shader test is still tracked by user_location.

This could probably be done elsewhere before linking, but this seems the
most reasonable place.

Signed-off-by: Ian Romanick <ian.d.roman...@intel.com>
---
 src/glsl/linker.cpp                          | 37 ++++++++++++++++++++++------
 src/glsl/linker.h                            |  2 +-
 src/glsl/tests/invalidate_locations_test.cpp | 12 ++++-----
 3 files changed, 36 insertions(+), 15 deletions(-)

diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index e02ce87..5e495d5 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -365,7 +365,7 @@ parse_program_resource_name(const GLchar *name,
 
 
 void
-link_invalidate_variable_locations(exec_list *ir)
+link_invalidate_variable_locations(exec_list *ir, unsigned stage)
 {
    foreach_list(node, ir) {
       ir_variable *const var = ((ir_instruction *) node)->as_variable();
@@ -373,16 +373,34 @@ link_invalidate_variable_locations(exec_list *ir)
       if (var == NULL)
          continue;
 
+      bool intrastage_io = false;
+      switch (stage) {
+      case MESA_SHADER_VERTEX:
+         intrastage_io = (var->data.mode == ir_var_shader_out)
+            && var->data.location >= VARYING_SLOT_VAR0;
+         break;
+
+      case MESA_SHADER_GEOMETRY:
+         intrastage_io = ((var->data.mode == ir_var_shader_in)
+                          || (var->data.mode == ir_var_shader_out))
+            && var->data.location >= VARYING_SLOT_VAR0;
+         break;
+
+      case MESA_SHADER_FRAGMENT:
+         intrastage_io = (var->data.mode == ir_var_shader_in)
+            && var->data.location >= VARYING_SLOT_VAR0;
+         break;
+
+      default:
+         assert(!"Should not get here.");
+         unreachable();
+      }
+
       /* Only assign locations for variables that lack an explicit location.
        * Explicit locations are set for all built-in variables, generic vertex
        * shader inputs (via layout(location=...)), and generic fragment shader
        * outputs (also via layout(location=...)).
        */
-      if (!var->data.explicit_location) {
-         var->data.location = -1;
-         var->data.location_frac = 0;
-      }
-
       /* ir_variable::is_unmatched_generic_inout is used by the linker while
        * connecting outputs from one stage to inputs of the next stage.
        *
@@ -395,8 +413,11 @@ link_invalidate_variable_locations(exec_list *ir)
        * GL_ARB_separate_shader_objects is supported.  When that extension is
        * implemented, this function will need some modifications.
        */
-      if (!var->data.explicit_location) {
+      if (!var->data.explicit_location || intrastage_io) {
+         var->data.location = -1;
+         var->data.location_frac = 0;
          var->data.is_unmatched_generic_inout = 1;
+         var->data.explicit_location = false;
       } else {
          var->data.is_unmatched_generic_inout = 0;
       }
@@ -2306,7 +2327,7 @@ link_shaders(struct gl_context *ctx, struct 
gl_shader_program *prog)
    /* Mark all generic shader inputs and outputs as unpaired. */
    for (unsigned i = MESA_SHADER_VERTEX; i <= MESA_SHADER_FRAGMENT; i++) {
       if (prog->_LinkedShaders[i] != NULL) {
-         link_invalidate_variable_locations(prog->_LinkedShaders[i]->ir);
+         link_invalidate_variable_locations(prog->_LinkedShaders[i]->ir, i);
       }
    }
 
diff --git a/src/glsl/linker.h b/src/glsl/linker.h
index 130915d..43283b9 100644
--- a/src/glsl/linker.h
+++ b/src/glsl/linker.h
@@ -31,7 +31,7 @@ link_function_calls(gl_shader_program *prog, gl_shader *main,
                    gl_shader **shader_list, unsigned num_shaders);
 
 extern void
-link_invalidate_variable_locations(exec_list *ir);
+link_invalidate_variable_locations(exec_list *ir, unsigned stage);
 
 extern void
 link_assign_uniform_locations(struct gl_shader_program *prog);
diff --git a/src/glsl/tests/invalidate_locations_test.cpp 
b/src/glsl/tests/invalidate_locations_test.cpp
index 997592f..10526a0 100644
--- a/src/glsl/tests/invalidate_locations_test.cpp
+++ b/src/glsl/tests/invalidate_locations_test.cpp
@@ -72,7 +72,7 @@ TEST_F(invalidate_locations, simple_vertex_in_generic)
 
    ir.push_tail(var);
 
-   link_invalidate_variable_locations(&ir);
+   link_invalidate_variable_locations(&ir, MESA_SHADER_VERTEX);
 
    EXPECT_EQ(-1, var->data.location);
    EXPECT_EQ(0u, var->data.location_frac);
@@ -95,7 +95,7 @@ TEST_F(invalidate_locations, 
explicit_location_vertex_in_generic)
 
    ir.push_tail(var);
 
-   link_invalidate_variable_locations(&ir);
+   link_invalidate_variable_locations(&ir, MESA_SHADER_VERTEX);
 
    EXPECT_EQ(VERT_ATTRIB_GENERIC0, var->data.location);
    EXPECT_EQ(0u, var->data.location_frac);
@@ -119,7 +119,7 @@ TEST_F(invalidate_locations, 
explicit_location_frac_vertex_in_generic)
 
    ir.push_tail(var);
 
-   link_invalidate_variable_locations(&ir);
+   link_invalidate_variable_locations(&ir, MESA_SHADER_VERTEX);
 
    EXPECT_EQ(VERT_ATTRIB_GENERIC0, var->data.location);
    EXPECT_EQ(2u, var->data.location_frac);
@@ -142,7 +142,7 @@ TEST_F(invalidate_locations, vertex_in_builtin)
 
    ir.push_tail(var);
 
-   link_invalidate_variable_locations(&ir);
+   link_invalidate_variable_locations(&ir, MESA_SHADER_VERTEX);
 
    EXPECT_EQ(VERT_ATTRIB_POS, var->data.location);
    EXPECT_EQ(0u, var->data.location_frac);
@@ -164,7 +164,7 @@ TEST_F(invalidate_locations, simple_vertex_out_generic)
 
    ir.push_tail(var);
 
-   link_invalidate_variable_locations(&ir);
+   link_invalidate_variable_locations(&ir, MESA_SHADER_VERTEX);
 
    EXPECT_EQ(-1, var->data.location);
    EXPECT_EQ(0u, var->data.location_frac);
@@ -187,7 +187,7 @@ TEST_F(invalidate_locations, vertex_out_builtin)
 
    ir.push_tail(var);
 
-   link_invalidate_variable_locations(&ir);
+   link_invalidate_variable_locations(&ir, MESA_SHADER_VERTEX);
 
    EXPECT_EQ(VARYING_SLOT_COL0, var->data.location);
    EXPECT_EQ(0u, var->data.location_frac);
-- 
1.8.1.4

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to