From 806dcf9db7c03996794b52e833be86c77ce3d36f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Ondra=C4=8Dka?= Date: Sat, 19 Mar 2022 21:34:07 +0100 Subject: [PATCH] r300: only output wpos in vertex shaders when needed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Part-of: --- src/gallium/drivers/r300/r300_state_derived.c | 37 +++++++++++++++++++ src/gallium/drivers/r300/r300_vs.c | 10 +++-- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index 6bcdb26780b..2e45fb0c7d2 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -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); diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c index 22dfe68e1c5..365ae218869 100644 --- a/src/gallium/drivers/r300/r300_vs.c +++ b/src/gallium/drivers/r300/r300_vs.c @@ -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);