radeonsi: set GS_STATE_OUTPRIM and PROVOKING_VTX_INDEX only when they change
authorMarek Olšák <marek.olsak@amd.com>
Sun, 14 Aug 2022 12:20:01 +0000 (08:20 -0400)
committerMarge Bot <emma+marge@anholt.net>
Tue, 30 Aug 2022 04:57:43 +0000 (04:57 +0000)
This moves setting those registers from an unconditional place in draw_vbo
into si_set_rasterized_prim (for draw_vbo), si_update_rasterized_prim
(for bind_xx_shader), and si_bind_rs_state.

It's a little more complicated than expected.

Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18195>

src/gallium/drivers/radeonsi/si_pipe.h
src/gallium/drivers/radeonsi/si_state.c
src/gallium/drivers/radeonsi/si_state_draw.cpp
src/gallium/drivers/radeonsi/si_state_shaders.cpp

index 7bafc99..811f340 100644 (file)
@@ -2105,9 +2105,34 @@ void si_check_dirty_buffers_textures(struct si_context *sctx)
    }
 }
 
-/* Set the primitive type seen by the rasterizer. GS and tessellation affect this. */
+/* Update these two GS_STATE fields. They depend on whatever the last shader before PS is
+ * and the rasterizer state.
+ *
+ * It's expected that hw_vs and ngg are inline constants in draw_vbo after optimizations.
+ */
+static inline void
+si_update_ngg_prim_state_sgpr(struct si_context *sctx, struct si_shader *hw_vs, bool ngg)
+{
+   if (!ngg || !hw_vs)
+      return;
+
+   if (hw_vs->uses_vs_state_provoking_vertex) {
+      unsigned vtx_index = sctx->queued.named.rasterizer->flatshade_first ? 0 : sctx->gs_out_prim;
+
+      SET_FIELD(sctx->current_gs_state, GS_STATE_PROVOKING_VTX_INDEX, vtx_index);
+   }
+
+   if (hw_vs->uses_gs_state_outprim) {
+      SET_FIELD(sctx->current_gs_state, GS_STATE_OUTPRIM, sctx->gs_out_prim);
+   }
+}
+
+/* Set the primitive type seen by the rasterizer. GS and tessellation affect this.
+ * It's expected that hw_vs and ngg are inline constants in draw_vbo after optimizations.
+ */
 static inline void
-si_set_rasterized_prim(struct si_context *sctx, enum pipe_prim_type rast_prim)
+si_set_rasterized_prim(struct si_context *sctx, enum pipe_prim_type rast_prim,
+                       struct si_shader *hw_vs, bool ngg)
 {
    if (rast_prim != sctx->current_rast_prim) {
       bool is_rect = rast_prim == SI_PRIM_RECTANGLE_LIST;
@@ -2123,6 +2148,7 @@ si_set_rasterized_prim(struct si_context *sctx, enum pipe_prim_type rast_prim)
                           is_lines ? V_028A6C_LINESTRIP :
                           is_rect ? V_028A6C_RECTLIST : V_028A6C_POINTLIST;
       sctx->do_update_shaders = true;
+      si_update_ngg_prim_state_sgpr(sctx, hw_vs, ngg);
    }
 }
 
index ba0b204..4afee51 100644 (file)
@@ -1215,6 +1215,9 @@ static void si_bind_rs_state(struct pipe_context *ctx, void *state)
        old_rs->poly_stipple_enable != rs->poly_stipple_enable ||
        old_rs->flatshade != rs->flatshade)
       si_update_vrs_flat_shading(sctx);
+
+   if (old_rs->flatshade_first != rs->flatshade_first)
+      si_update_ngg_prim_state_sgpr(sctx, si_get_vs(sctx)->current, sctx->ngg);
 }
 
 static void si_delete_rs_state(struct pipe_context *ctx, void *state)
index 23e80fc..63c1de0 100644 (file)
@@ -110,6 +110,8 @@ static bool si_update_shaders(struct si_context *sctx)
    struct pipe_context *ctx = (struct pipe_context *)sctx;
    struct si_shader *old_vs = si_get_vs_inline(sctx, HAS_TESS, HAS_GS)->current;
    unsigned old_pa_cl_vs_out_cntl = old_vs ? old_vs->pa_cl_vs_out_cntl : 0;
+   bool old_uses_vs_state_provoking_vertex = old_vs ? old_vs->uses_vs_state_provoking_vertex : false;
+   bool old_uses_gs_state_outprim = old_vs ? old_vs->uses_gs_state_outprim : false;
    struct si_shader *old_ps = sctx->shader.ps.current;
    unsigned old_spi_shader_col_format =
       old_ps ? old_ps->key.ps.part.epilog.spi_shader_col_format : 0;
@@ -247,10 +249,16 @@ static bool si_update_shaders(struct si_context *sctx)
       *pm4 = si_build_vgt_shader_config(sctx->screen, key);
    si_pm4_bind_state(sctx, vgt_shader_config, *pm4);
 
-   if (old_pa_cl_vs_out_cntl !=
-          si_get_vs_inline(sctx, HAS_TESS, HAS_GS)->current->pa_cl_vs_out_cntl)
+   struct si_shader *hw_vs = si_get_vs_inline(sctx, HAS_TESS, HAS_GS)->current;
+
+   if (old_pa_cl_vs_out_cntl != hw_vs->pa_cl_vs_out_cntl)
       si_mark_atom_dirty(sctx, &sctx->atoms.s.clip_regs);
 
+   /* If we start to use any of these, we need to update the SGPR. */
+   if ((hw_vs->uses_vs_state_provoking_vertex && !old_uses_vs_state_provoking_vertex) ||
+       (hw_vs->uses_gs_state_outprim && !old_uses_gs_state_outprim))
+      si_update_ngg_prim_state_sgpr(sctx, hw_vs, NGG);
+
    r = si_shader_select(ctx, &sctx->shader.ps);
    if (r)
       return false;
@@ -1157,20 +1165,6 @@ static void si_emit_rasterizer_prim_state(struct si_context *sctx)
       radeon_end_update_context_roll(sctx);
    else
       radeon_end();
-
-   if (NGG) {
-      struct si_shader *hw_vs = si_get_vs_inline(sctx, HAS_TESS, HAS_GS)->current;
-
-      if (hw_vs->uses_vs_state_provoking_vertex) {
-         unsigned vtx_index = rs->flatshade_first ? 0 : gs_out_prim;
-
-         SET_FIELD(sctx->current_gs_state, GS_STATE_PROVOKING_VTX_INDEX, vtx_index);
-      }
-
-      if (hw_vs->uses_gs_state_outprim) {
-         SET_FIELD(sctx->current_gs_state, GS_STATE_OUTPRIM, gs_out_prim);
-      }
-   }
 }
 
 template <amd_gfx_level GFX_VERSION, si_has_tess HAS_TESS, si_has_gs HAS_GS, si_has_ngg NGG,
@@ -2333,7 +2327,8 @@ static void si_draw(struct pipe_context *ctx,
          rast_prim = prim;
       }
 
-      si_set_rasterized_prim(sctx, rast_prim);
+      si_set_rasterized_prim(sctx, rast_prim, si_get_vs_inline(sctx, HAS_TESS, HAS_GS)->current,
+                             NGG);
    }
 
    if (IS_DRAW_VERTEX_STATE) {
index 415d9cf..8d33e9b 100644 (file)
@@ -3313,15 +3313,20 @@ static void si_update_clip_regs(struct si_context *sctx, struct si_shader_select
 
 static void si_update_rasterized_prim(struct si_context *sctx)
 {
+   struct si_shader *hw_vs = si_get_vs(sctx)->current;
+
    if (sctx->shader.gs.cso) {
       /* Only possibilities: POINTS, LINE_STRIP, TRIANGLES */
-      si_set_rasterized_prim(sctx, sctx->shader.gs.cso->rast_prim);
+      si_set_rasterized_prim(sctx, sctx->shader.gs.cso->rast_prim, hw_vs, sctx->ngg);
    } else if (sctx->shader.tes.cso) {
       /* Only possibilities: POINTS, LINE_STRIP, TRIANGLES */
-      si_set_rasterized_prim(sctx, sctx->shader.tes.cso->rast_prim);
+      si_set_rasterized_prim(sctx, sctx->shader.tes.cso->rast_prim, hw_vs, sctx->ngg);
    } else {
       /* The rasterized prim is determined by draw calls. */
    }
+
+   /* This must be done unconditionally because it also depends on si_shader fields. */
+   si_update_ngg_prim_state_sgpr(sctx, hw_vs, sctx->ngg);
 }
 
 static void si_update_common_shader_state(struct si_context *sctx, struct si_shader_selector *sel,