From 379b24a40d3d34ffdaaeb1b328f50e28ecb01468 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Thu, 7 Sep 2017 23:29:25 +1000 Subject: [PATCH] i965: make use of nir linking For now linking is just removing unused varyings between stages. shader-db results BDW: total instructions in shared programs: 13198288 -> 13191693 (-0.05%) instructions in affected programs: 48325 -> 41730 (-13.65%) helped: 473 HURT: 0 total cycles in shared programs: 541184926 -> 541159260 (-0.00%) cycles in affected programs: 213238 -> 187572 (-12.04%) helped: 435 HURT: 8 V2: - lower indirects on demoted inputs as well as outputs. Reviewed-by: Kenneth Graunke --- src/mesa/drivers/dri/i965/brw_link.cpp | 56 ++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/mesa/drivers/dri/i965/brw_link.cpp b/src/mesa/drivers/dri/i965/brw_link.cpp index b7fab8d7a25..9ddf0230183 100644 --- a/src/mesa/drivers/dri/i965/brw_link.cpp +++ b/src/mesa/drivers/dri/i965/brw_link.cpp @@ -253,6 +253,62 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *shProg) compiler->scalar_stage[stage]); } + /* Determine first and last stage. */ + unsigned first = MESA_SHADER_STAGES; + unsigned last = 0; + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { + if (!shProg->_LinkedShaders[i]) + continue; + if (first == MESA_SHADER_STAGES) + first = i; + last = i; + } + + /* Linking the stages in the opposite order (from fragment to vertex) + * ensures that inter-shader outputs written to in an earlier stage + * are eliminated if they are (transitively) not used in a later + * stage. + */ + if (first != last) { + int next = last; + for (int i = next - 1; i >= 0; i--) { + if (shProg->_LinkedShaders[i] == NULL) + continue; + + nir_shader *producer = shProg->_LinkedShaders[i]->Program->nir; + nir_shader *consumer = shProg->_LinkedShaders[next]->Program->nir; + + nir_remove_dead_variables(producer, nir_var_shader_out); + nir_remove_dead_variables(consumer, nir_var_shader_in); + + if (nir_remove_unused_varyings(producer, consumer)) { + nir_lower_global_vars_to_local(producer); + nir_lower_global_vars_to_local(consumer); + + nir_variable_mode indirect_mask = (nir_variable_mode) 0; + if (compiler->glsl_compiler_options[i].EmitNoIndirectTemp) + indirect_mask = (nir_variable_mode) nir_var_local; + + /* The backend might not be able to handle indirects on + * temporaries so we need to lower indirects on any of the + * varyings we have demoted here. + */ + nir_lower_indirect_derefs(producer, indirect_mask); + nir_lower_indirect_derefs(consumer, indirect_mask); + + const bool p_is_scalar = compiler->scalar_stage[producer->stage]; + shProg->_LinkedShaders[i]->Program->nir = + brw_nir_optimize(producer, compiler, p_is_scalar); + + const bool c_is_scalar = compiler->scalar_stage[producer->stage]; + shProg->_LinkedShaders[next]->Program->nir = + brw_nir_optimize(consumer, compiler, c_is_scalar); + } + + next = i; + } + } + for (stage = 0; stage < ARRAY_SIZE(shProg->_LinkedShaders); stage++) { struct gl_linked_shader *shader = shProg->_LinkedShaders[stage]; if (!shader) -- 2.30.2