[Mesa-dev] [PATCH 8/8] i965: make use of nir linking
Timothy Arceri
tarceri at itsqueeze.com
Mon Sep 25 23:06:03 UTC 2017
On 26/09/17 08:47, Kenneth Graunke wrote:
> On Tuesday, September 12, 2017 4:37:35 PM PDT Timothy Arceri wrote:
>> 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
>> ---
>> src/mesa/drivers/dri/i965/brw_link.cpp | 48 ++++++++++++++++++++++++++++++++++
>> 1 file changed, 48 insertions(+)
>>
>> diff --git a/src/mesa/drivers/dri/i965/brw_link.cpp b/src/mesa/drivers/dri/i965/brw_link.cpp
>> index 9f1634a5459..c4c89a0686e 100644
>> --- a/src/mesa/drivers/dri/i965/brw_link.cpp
>> +++ b/src/mesa/drivers/dri/i965/brw_link.cpp
>> @@ -252,6 +252,54 @@ 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(shProg->_LinkedShaders[next]->Program->nir,
>> + nir_var_shader_in);
>> + nir_remove_dead_variables(shProg->_LinkedShaders[i]->Program->nir,
>> + nir_var_shader_out);
>> + 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;
>> +
>> + nir_lower_indirect_derefs(producer, indirect_mask);
>
> Ugh, good catch...by demoting inputs/outputs to globals, we might end up
> with indirects on temporaries, so we do need to lower them here. (It's
> a bit annoying that we don't handle indirects on temporaries in the FS
> backend in 2017...I asked krh to implement that in review feedback for
> his 2014-era SIMD8 VS series, and then jekstrand actually implemented it
> in 2015, and it never landed for some reason...but...I digress...)
>
>> +
>> + const bool is_scalar = compiler->scalar_stage[producer->stage];
>> + shProg->_LinkedShaders[i]->Program->nir =
>> + brw_nir_optimize(producer, compiler, is_scalar);
>
> I'm a little lost why you only lower indirect derefs and optimize for
> the producer stage. nir_remove_unused_varyings can demote variables in
> either stage. For example, if the consumer reads a variable, but the
> producer doesn't write it, then we'll have a consumer-only variable get
> demoted.
>
> It seems like the consumer is the more important one, too, because
> you're walking backwards, so the current producer may get hit by the
> next pass...unless it's the first stage...so...don't we need to do both?
Yeah I think your right.
>
>> + }
>> +
>> + next = i;
>> + }
>> + }
>> +
>> for (stage = 0; stage < ARRAY_SIZE(shProg->_LinkedShaders); stage++) {
>> struct gl_linked_shader *shader = shProg->_LinkedShaders[stage];
>> if (!shader)
>>
>
More information about the mesa-dev
mailing list