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.
This commit is contained in:
+25
-11
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user