diff options
| author | Ian Romanick <ian.d.romanick@intel.com> | 2010-10-19 17:59:10 -0700 | 
|---|---|---|
| committer | Ian Romanick <ian.d.romanick@intel.com> | 2010-10-19 18:12:32 -0700 | 
| commit | cc90e62d70d91fb16abcd66c61c211c0fd573339 (patch) | |
| tree | 939bbededa4fa2698bd96a6ae9578dcadac22f22 /src | |
| 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')
| -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 64827da2f8..616ec78007 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: | 
