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