summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/glsl/link_varyings.cpp45
-rw-r--r--src/glsl/link_varyings.h5
-rw-r--r--src/glsl/linker.cpp52
3 files changed, 54 insertions, 48 deletions
diff --git a/src/glsl/link_varyings.cpp b/src/glsl/link_varyings.cpp
index c43abbcc6a5..a80a1b5660d 100644
--- a/src/glsl/link_varyings.cpp
+++ b/src/glsl/link_varyings.cpp
@@ -309,6 +309,41 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
}
}
+/**
+ * Demote shader inputs and outputs that are not used in other stages, and
+ * remove them via dead code elimination.
+ */
+void
+remove_unused_shader_inputs_and_outputs(bool is_separate_shader_object,
+ gl_shader *sh,
+ enum ir_variable_mode mode)
+{
+ if (is_separate_shader_object)
+ return;
+
+ foreach_in_list(ir_instruction, node, sh->ir) {
+ ir_variable *const var = node->as_variable();
+
+ if ((var == NULL) || (var->data.mode != int(mode)))
+ continue;
+
+ /* 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->data.is_unmatched_generic_inout) {
+ assert(var->data.mode != ir_var_temporary);
+ var->data.mode = ir_var_auto;
+ }
+ }
+
+ /* Eliminate code that is now dead due to unused inputs/outputs being
+ * demoted.
+ */
+ while (do_dead_code(sh->ir, false))
+ ;
+
+}
/**
* Initialize this object based on a string that was passed to
@@ -1671,6 +1706,16 @@ assign_varying_locations(struct gl_context *ctx,
}
}
}
+
+ /* Now that validation is done its safe to remove unused varyings. As
+ * we have both a producer and consumer its safe to remove unused
+ * varyings even if the program is a SSO because the stages are being
+ * linked together i.e. we have a multi-stage SSO.
+ */
+ remove_unused_shader_inputs_and_outputs(false, producer,
+ ir_var_shader_out);
+ remove_unused_shader_inputs_and_outputs(false, consumer,
+ ir_var_shader_in);
}
if (!disable_varying_packing) {
diff --git a/src/glsl/link_varyings.h b/src/glsl/link_varyings.h
index 1d12978fa30..b2812614ecc 100644
--- a/src/glsl/link_varyings.h
+++ b/src/glsl/link_varyings.h
@@ -268,6 +268,11 @@ parse_tfeedback_decls(struct gl_context *ctx, struct gl_shader_program *prog,
const void *mem_ctx, unsigned num_names,
char **varying_names, tfeedback_decl *decls);
+void
+remove_unused_shader_inputs_and_outputs(bool is_separate_shader_object,
+ gl_shader *sh,
+ enum ir_variable_mode mode);
+
bool
store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,
unsigned num_tfeedback_decls,
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index acc63ae8cf6..7a18523fe23 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -2723,30 +2723,6 @@ match_explicit_outputs_to_inputs(struct gl_shader_program *prog,
}
/**
- * Demote shader inputs and outputs that are not used in other stages
- */
-void
-demote_shader_inputs_and_outputs(gl_shader *sh, enum ir_variable_mode mode)
-{
- foreach_in_list(ir_instruction, node, sh->ir) {
- ir_variable *const var = node->as_variable();
-
- if ((var == NULL) || (var->data.mode != int(mode)))
- continue;
-
- /* 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->data.is_unmatched_generic_inout) {
- assert(var->data.mode != ir_var_temporary);
- var->data.mode = ir_var_auto;
- }
- }
-}
-
-
-/**
* Store the gl_FragDepth layout in the gl_shader_program struct.
*/
static void
@@ -4446,14 +4422,8 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
do_dead_builtin_varyings(ctx, sh, NULL,
num_tfeedback_decls, tfeedback_decls);
- if (!prog->SeparateShader) {
- demote_shader_inputs_and_outputs(sh, ir_var_shader_out);
- /* Eliminate code that is now dead due to unused outputs being
- * demoted.
- */
- while (do_dead_code(sh->ir, false))
- ;
- }
+ remove_unused_shader_inputs_and_outputs(prog->SeparateShader, sh,
+ ir_var_shader_out);
}
else if (first == MESA_SHADER_FRAGMENT) {
/* If the program only contains a fragment shader...
@@ -4471,12 +4441,8 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
NULL /* tfeedback_decls */))
goto done;
} else {
- demote_shader_inputs_and_outputs(sh, ir_var_shader_in);
- /* Eliminate code that is now dead due to unused inputs being
- * demoted.
- */
- while (do_dead_code(sh->ir, false))
- ;
+ remove_unused_shader_inputs_and_outputs(false, sh,
+ ir_var_shader_in);
}
}
@@ -4497,16 +4463,6 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
next == MESA_SHADER_FRAGMENT ? num_tfeedback_decls : 0,
tfeedback_decls);
- demote_shader_inputs_and_outputs(sh_i, ir_var_shader_out);
- demote_shader_inputs_and_outputs(sh_next, ir_var_shader_in);
-
- /* Eliminate code that is now dead due to unused outputs being demoted.
- */
- while (do_dead_code(sh_i->ir, false))
- ;
- while (do_dead_code(sh_next->ir, false))
- ;
-
/* This must be done after all dead varyings are eliminated. */
if (!check_against_output_limit(ctx, prog, sh_i))
goto done;