diff options
author | Ian Romanick <[email protected]> | 2010-10-19 17:59:10 -0700 |
---|---|---|
committer | Ian Romanick <[email protected]> | 2010-10-19 18:12:32 -0700 |
commit | cc90e62d70d91fb16abcd66c61c211c0fd573339 (patch) | |
tree | 939bbededa4fa2698bd96a6ae9578dcadac22f22 /src/glsl/linker.cpp | |
parent | 974fb466f299fc569a86097936ab89c8c369f6d2 (diff) |
linker: Improve handling of unread/unwritten shader inputs/outputs
Previously some shader input or outputs that hadn't received location
assignments could slip through. This could happen when a shader
contained user-defined varyings and was used with either
fixed-function or assembly shaders.
See the piglit tests glsl-[fv]s-user-varying-ff and
sso-user-varying-0[12].
NOTE: this is a candidate for the 7.9 branch.
Diffstat (limited to 'src/glsl/linker.cpp')
-rw-r--r-- | src/glsl/linker.cpp | 36 |
1 files changed, 25 insertions, 11 deletions
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 64827da2f8e..616ec780071 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -1290,19 +1290,20 @@ assign_attribute_locations(gl_shader_program *prog, unsigned max_attribute_index /** - * Demote shader outputs that are not read to being just plain global variables + * Demote shader inputs and outputs that are not used in other stages */ void -demote_unread_shader_outputs(gl_shader *sh) +demote_shader_inputs_and_outputs(gl_shader *sh, enum ir_variable_mode mode) { foreach_list(node, sh->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if ((var == NULL) || (var->mode != ir_var_out)) + if ((var == NULL) || (var->mode != int(mode))) continue; - /* An 'out' variable is only really a shader output if its value is read - * by the following stage. + /* A shader 'in' or 'out' variable is only really an input or output if + * its value is used by other shader stages. This will cause the variable + * to have a location assigned. */ if (var->location == -1) { var->mode = ir_var_auto; @@ -1368,8 +1369,6 @@ assign_varying_locations(struct gl_shader_program *prog, } } - demote_unread_shader_outputs(producer); - foreach_list(node, consumer->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); @@ -1558,10 +1557,6 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) prog->LinkStatus = false; goto done; } - - if ((prog->_LinkedShaders[MESA_SHADER_GEOMETRY] == NULL) - && (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)) - demote_unread_shader_outputs(prog->_LinkedShaders[MESA_SHADER_VERTEX]); } unsigned prev; @@ -1580,6 +1575,25 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) prev = i; } + if (prog->_LinkedShaders[MESA_SHADER_VERTEX] != NULL) { + demote_shader_inputs_and_outputs(prog->_LinkedShaders[MESA_SHADER_VERTEX], + ir_var_out); + } + + if (prog->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL) { + gl_shader *const sh = prog->_LinkedShaders[MESA_SHADER_GEOMETRY]; + + demote_shader_inputs_and_outputs(sh, ir_var_in); + demote_shader_inputs_and_outputs(sh, ir_var_inout); + demote_shader_inputs_and_outputs(sh, ir_var_out); + } + + if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] != NULL) { + gl_shader *const sh = prog->_LinkedShaders[MESA_SHADER_FRAGMENT]; + + demote_shader_inputs_and_outputs(sh, ir_var_in); + } + /* FINISHME: Assign fragment shader output locations. */ done: |