r300: only output wpos in vertex shaders when needed

Right now we always copy pos to wpos regardless of if the fragment
shader needs it or not. Instead just do it only for the shaders
that really need it.

Shader-db is not able to measure preciselly the effect as we
build only the non-wpos variants, but given that majority of fragment
shaders don't needs the wpos, the real effect should be close:

total instructions in shared programs: 105427 -> 104313 (-1.06%)
instructions in affected programs: 53098 -> 51984 (-2.10%)
total temps in shared programs: 13991 -> 13958 (-0.24%)
temps in affected programs: 114 -> 81 (-28.95%)

Signed-off-by: Pavel Ondračka <pavel.ondracka@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15321>
This commit is contained in:
Pavel Ondračka 2022-03-19 21:34:07 +01:00 committed by Marge Bot
parent 8c90a5fab7
commit 806dcf9db7
2 changed files with 43 additions and 4 deletions

View file

@ -1061,6 +1061,41 @@ static void r300_validate_fragment_shader(struct r300_context *r300)
}
}
static void r300_pick_vertex_shader(struct r300_context *r300)
{
struct r300_vertex_shader_code *ptr;
struct r300_vertex_shader *vs = r300_vs(r300);
if (r300->vs_state.state) {
bool wpos = r300_fs(r300)->shader->inputs.wpos != ATTR_UNUSED;
if (!vs->first) {
/* Build the vertex shader for the first time. */
vs->first = vs->shader = CALLOC_STRUCT(r300_vertex_shader_code);
vs->first->wpos = wpos;
r300_translate_vertex_shader(r300, vs);
r300_mark_atom_dirty(r300, &r300->rs_block_state);
return;
}
/* Pick the vertex shader based on whether we need wpos */
if (vs->first->wpos != wpos) {
if (vs->first->next && vs->first->next->wpos == wpos) {
ptr = vs->first->next;
vs->first->next = NULL;
ptr->next = vs->first;
vs->first = vs->shader = ptr;
} else {
ptr = CALLOC_STRUCT(r300_vertex_shader_code);
ptr->next = vs->first;
vs->first = vs->shader = ptr;
vs->shader->wpos = wpos;
r300_translate_vertex_shader(r300, vs);
}
r300_mark_atom_dirty(r300, &r300->rs_block_state);
}
}
}
void r300_update_derived_state(struct r300_context* r300)
{
if (r300->textures_state.dirty) {
@ -1069,6 +1104,8 @@ void r300_update_derived_state(struct r300_context* r300)
}
r300_validate_fragment_shader(r300);
if (r300->screen->caps.has_tcl)
r300_pick_vertex_shader(r300);
if (r300->rs_block_state.dirty) {
r300_update_rs_block(r300);

View file

@ -99,7 +99,7 @@ static void r300_shader_read_vs_outputs(
}
}
/* WPOS is a straight copy of POSITION and it's always emitted. */
/* WPOS is a straight copy of POSITION */
vs_outputs->wpos = i;
}
@ -167,7 +167,8 @@ static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c)
}
/* WPOS. */
c->code->outputs[outputs->wpos] = reg++;
if (vs->wpos)
c->code->outputs[outputs->wpos] = reg++;
}
void r300_init_vs_outputs(struct r300_context *r300,
@ -253,11 +254,12 @@ void r300_translate_vertex_shader(struct r300_context *r300,
compiler.Base.remove_unused_constants = TRUE;
}
compiler.RequiredOutputs = ~(~0U << (vs->info.num_outputs + 1));
compiler.RequiredOutputs = ~(~0U << (vs->info.num_outputs + (vs->wpos ? 1 : 0)));
compiler.SetHwInputOutput = &set_vertex_inputs_outputs;
/* Insert the WPOS output. */
rc_copy_output(&compiler.Base, 0, vs->outputs.wpos);
if (vs->wpos)
rc_copy_output(&compiler.Base, 0, vs->outputs.wpos);
/* Invoke the compiler */
r3xx_compile_vertex_program(&compiler);