radeonsi: add si_install_draw_wrapper
authorPierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Wed, 19 May 2021 15:11:57 +0000 (17:11 +0200)
committerPierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Tue, 15 Jun 2021 08:19:04 +0000 (10:19 +0200)
This allows to implement custom draw_vbo code-path without
touching si_draw_vbo.

As an example, skipped all draw calls with an odd new_draws
could be done like this:

   void mywrapper(...) {
       if (new_draws % 2)
          return;
       return sctx->real_draw_vbo(...);
   }

   if (some_condition_is_met)
      si_install_draw_wrapper(sctx, mywrapper);

Instead of having to add the "if ()" condition inside si_draw_vbo.

Note that a single wrapper may be installed so care must be taken
to not override an existing wrapper.

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10979>

src/gallium/drivers/radeonsi/si_pipe.h
src/gallium/drivers/radeonsi/si_state_draw.cpp

index e741a76..1fc1d9e 100644 (file)
@@ -1286,6 +1286,8 @@ struct si_context {
    struct hash_table *dirty_implicit_resources;
 
    pipe_draw_vbo_func draw_vbo[NUM_GFX_VERSIONS - GFX6][2][2][2][2];
+   /* When b.draw_vbo is a wrapper, real_draw_vbo is the real draw_vbo function */
+   pipe_draw_vbo_func real_draw_vbo;
 
    /* SQTT */
    struct ac_thread_trace_data *thread_trace;
@@ -1341,6 +1343,11 @@ void si_replace_buffer_storage(struct pipe_context *ctx, struct pipe_resource *d
 void si_init_screen_buffer_functions(struct si_screen *sscreen);
 void si_init_buffer_functions(struct si_context *sctx);
 
+/* Replace the sctx->b.draw_vbo function with a wrapper. This can be use to implement
+ * optimizations without affecting the normal draw_vbo functions perf.
+ */
+void si_install_draw_wrapper(struct si_context *sctx, pipe_draw_vbo_func wrapper);
+
 /* si_clear.c */
 #define SI_CLEAR_TYPE_CMASK  (1 << 0)
 #define SI_CLEAR_TYPE_DCC    (1 << 1)
@@ -2010,12 +2017,16 @@ static inline unsigned si_get_shader_wave_size(struct si_shader *shader)
 
 static inline void si_select_draw_vbo(struct si_context *sctx)
 {
-   sctx->b.draw_vbo = sctx->draw_vbo[sctx->chip_class - GFX6]
-                                    [!!sctx->shader.tes.cso]
-                                    [!!sctx->shader.gs.cso]
-                                    [sctx->ngg]
-                                    [si_compute_prim_discard_enabled(sctx)];
-   assert(sctx->b.draw_vbo);
+   pipe_draw_vbo_func draw_vbo = sctx->draw_vbo[sctx->chip_class - GFX6]
+                                               [!!sctx->shader.tes.cso]
+                                               [!!sctx->shader.gs.cso]
+                                               [sctx->ngg]
+                                               [si_compute_prim_discard_enabled(sctx)];
+   assert(draw_vbo);
+   if (unlikely(sctx->real_draw_vbo))
+      sctx->real_draw_vbo = draw_vbo;
+   else
+      sctx->b.draw_vbo = draw_vbo;
 }
 
 /* Return the number of samples that the rasterizer uses. */
index f704967..67b6610 100644 (file)
@@ -2416,3 +2416,18 @@ void si_init_draw_functions(struct si_context *sctx)
 
    si_init_ia_multi_vgt_param_table(sctx);
 }
+
+extern "C"
+void si_install_draw_wrapper(struct si_context *sctx, pipe_draw_vbo_func wrapper)
+{
+   if (wrapper) {
+      if (wrapper != sctx->b.draw_vbo) {
+         assert (!sctx->real_draw_vbo);
+         sctx->real_draw_vbo = sctx->b.draw_vbo;
+         sctx->b.draw_vbo = wrapper;
+      }
+   } else if (sctx->real_draw_vbo) {
+      sctx->real_draw_vbo = NULL;
+      si_select_draw_vbo(sctx);
+   }
+}