r300: only output wpos in vertex shaders when needed
authorPavel Ondračka <pavel.ondracka@gmail.com>
Sat, 19 Mar 2022 20:34:07 +0000 (21:34 +0100)
committerMarge Bot <emma+marge@anholt.net>
Tue, 29 Mar 2022 21:37:24 +0000 (21:37 +0000)
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>

src/gallium/drivers/r300/r300_state_derived.c
src/gallium/drivers/r300/r300_vs.c

index 6bcdb26780b8fdf7b7648b96cde9e8957390b48e..2e45fb0c7d25c4b6e929ac2f97e5b523513ae900 100644 (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);
index 22dfe68e1c5b73f9dc9be03be02122bf23380611..365ae218869c3332e5ed0ed437ad8cf26a51a654 100644 (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);