Mesa (main): etnaviv: async shader compile

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Jul 1 20:10:17 UTC 2022


Module: Mesa
Branch: main
Commit: 1141ed585901e2ac5897291ac17a6ba23aa44137
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=1141ed585901e2ac5897291ac17a6ba23aa44137

Author: Christian Gmeiner <christian.gmeiner at gmail.com>
Date:   Mon Jan 31 16:40:45 2022 +0100

etnaviv: async shader compile

Passes following piglit:
 - spec at khr_parallel_shader_compile@basic

Signed-off-by: Christian Gmeiner <christian.gmeiner at gmail.com>
Reviewed-by: Philipp Zabel <p.zabel at pengutronix.de>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16172>

---

 docs/features.txt                             |  2 +-
 src/gallium/drivers/etnaviv/etnaviv_context.c |  3 ++
 src/gallium/drivers/etnaviv/etnaviv_screen.h  |  2 +
 src/gallium/drivers/etnaviv/etnaviv_shader.c  | 67 ++++++++++++++++++++++++---
 src/gallium/drivers/etnaviv/etnaviv_shader.h  |  4 ++
 5 files changed, 71 insertions(+), 7 deletions(-)

diff --git a/docs/features.txt b/docs/features.txt
index 7b2fee8870e..f9381c504bf 100644
--- a/docs/features.txt
+++ b/docs/features.txt
@@ -301,7 +301,7 @@ Khronos, ARB, and OES extensions that are not part of any OpenGL or OpenGL ES ve
   GL_ARB_ES3_2_compatibility                            DONE (i965/gen8+, radeonsi, virgl, zink)
   GL_ARB_fragment_shader_interlock                      DONE (i965, zink)
   GL_ARB_gpu_shader_int64                               DONE (i965/gen8+, nvc0, radeonsi, softpipe, llvmpipe, zink, d3d12)
-  GL_ARB_parallel_shader_compile                        DONE (freedreno, iris, radeonsi)
+  GL_ARB_parallel_shader_compile                        DONE (freedreno, iris, radeonsi, etnaviv)
   GL_ARB_post_depth_coverage                            DONE (i965, nvc0, radeonsi, llvmpipe, zink)
   GL_ARB_robustness_isolation                           not started
   GL_ARB_sample_locations                               DONE (nvc0, zink)
diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.c b/src/gallium/drivers/etnaviv/etnaviv_context.c
index bda29f93492..ee553d934fd 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_context.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_context.c
@@ -632,6 +632,9 @@ etna_set_debug_callback(struct pipe_context *pctx,
                         const struct util_debug_callback *cb)
 {
    struct etna_context *ctx = etna_context(pctx);
+   struct etna_screen *screen = ctx->screen;
+
+   util_queue_finish(&screen->shader_compiler_queue);
 
    if (cb)
       ctx->debug = *cb;
diff --git a/src/gallium/drivers/etnaviv/etnaviv_screen.h b/src/gallium/drivers/etnaviv/etnaviv_screen.h
index 3172cfd551a..e3d72968453 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_screen.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_screen.h
@@ -38,6 +38,7 @@
 #include "util/slab.h"
 #include "util/u_dynarray.h"
 #include "util/u_helpers.h"
+#include "util/u_queue.h"
 #include "compiler/nir/nir.h"
 
 struct etna_bo;
@@ -93,6 +94,7 @@ struct etna_screen {
 
    struct etna_compiler *compiler;
    nir_shader_compiler_options options;
+   struct util_queue shader_compiler_queue;
 };
 
 static inline struct etna_screen *
diff --git a/src/gallium/drivers/etnaviv/etnaviv_shader.c b/src/gallium/drivers/etnaviv/etnaviv_shader.c
index 90bd22770e2..67268f35304 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_shader.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_shader.c
@@ -37,6 +37,7 @@
 #include "tgsi/tgsi_parse.h"
 #include "nir/tgsi_to_nir.h"
 #include "util/u_atomic.h"
+#include "util/u_cpu_detect.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
 
@@ -449,6 +450,30 @@ etna_shader_variant(struct etna_shader *shader, struct etna_shader_key key,
    return v;
 }
 
+/**
+ * Should initial variants be compiled synchronously?
+ *
+ * The only case where pipe_debug_message() is used in the initial-variants
+ * path is with ETNA_MESA_DEBUG=shaderdb. So if either debug is disabled (ie.
+ * debug.debug_message==NULL), or shaderdb stats are not enabled, we can
+ * compile the initial shader variant asynchronously.
+ */
+static inline bool
+initial_variants_synchronous(struct etna_context *ctx)
+{
+   return unlikely(ctx->debug.debug_message) || (etna_mesa_debug & ETNA_DBG_SHADERDB);
+}
+
+static void
+create_initial_variants_async(void *job, void *gdata, int thread_index)
+{
+   struct etna_shader *shader = job;
+   struct util_debug_callback debug = {};
+   static struct etna_shader_key key;
+
+   etna_shader_variant(shader, key, &debug);
+}
+
 static void *
 etna_create_shader_state(struct pipe_context *pctx,
                          const struct pipe_shader_state *pss)
@@ -464,19 +489,20 @@ etna_create_shader_state(struct pipe_context *pctx,
    shader->id = p_atomic_inc_return(&compiler->shader_count);
    shader->specs = &screen->specs;
    shader->compiler = screen->compiler;
+   util_queue_fence_init(&shader->ready);
 
    shader->nir = (pss->type == PIPE_SHADER_IR_NIR) ? pss->ir.nir :
                   tgsi_to_nir(pss->tokens, pctx->screen, false);
 
    etna_disk_cache_init_shader_key(compiler, shader);
 
-   if (etna_mesa_debug & ETNA_DBG_SHADERDB) {
-      /* if shader-db run, create a standard variant immediately
-       * (as otherwise nothing will trigger the shader to be
-       * actually compiled).
-       */
+   if (initial_variants_synchronous(ctx)) {
       struct etna_shader_key key = {};
       etna_shader_variant(shader, key, &ctx->debug);
+   } else {
+      struct etna_screen *screen = ctx->screen;
+      util_queue_add_job(&screen->shader_compiler_queue, shader, &shader->ready,
+                         create_initial_variants_async, NULL, 0);
    }
 
    return shader;
@@ -521,6 +547,25 @@ etna_bind_vs_state(struct pipe_context *pctx, void *hwcso)
    ctx->dirty |= ETNA_DIRTY_SHADER;
 }
 
+static void
+etna_set_max_shader_compiler_threads(struct pipe_screen *pscreen,
+                                     unsigned max_threads)
+{
+   struct etna_screen *screen = etna_screen(pscreen);
+
+   util_queue_adjust_num_threads(&screen->shader_compiler_queue, max_threads);
+}
+
+static bool
+etna_is_parallel_shader_compilation_finished(struct pipe_screen *pscreen,
+                                             void *hwcso,
+                                             enum pipe_shader_type shader_type)
+{
+   struct etna_shader *shader = (struct etna_shader *)hwcso;
+
+   return util_queue_fence_is_signalled(&shader->ready);
+}
+
 void
 etna_shader_init(struct pipe_context *pctx)
 {
@@ -536,12 +581,21 @@ bool
 etna_shader_screen_init(struct pipe_screen *pscreen)
 {
    struct etna_screen *screen = etna_screen(pscreen);
+   unsigned num_threads = util_get_cpu_caps()->nr_cpus - 1;
+
+   /* Create at least one thread - even on single core CPU systems. */
+   num_threads = MAX2(1, num_threads);
 
    screen->compiler = etna_compiler_create(pscreen->get_name(pscreen));
    if (!screen->compiler)
       return false;
 
-   return true;
+   pscreen->set_max_shader_compiler_threads = etna_set_max_shader_compiler_threads;
+   pscreen->is_parallel_shader_compilation_finished = etna_is_parallel_shader_compilation_finished;
+
+   return util_queue_init(&screen->shader_compiler_queue, "sh", 64, num_threads,
+                          UTIL_QUEUE_INIT_RESIZE_IF_FULL | UTIL_QUEUE_INIT_SET_FULL_THREAD_AFFINITY,
+                          NULL);
 }
 
 void
@@ -549,5 +603,6 @@ etna_shader_screen_fini(struct pipe_screen *pscreen)
 {
    struct etna_screen *screen = etna_screen(pscreen);
 
+   util_queue_destroy(&screen->shader_compiler_queue);
    etna_compiler_destroy(screen->compiler);
 }
diff --git a/src/gallium/drivers/etnaviv/etnaviv_shader.h b/src/gallium/drivers/etnaviv/etnaviv_shader.h
index f6cbfa85f7f..58a56b184d7 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_shader.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_shader.h
@@ -31,6 +31,7 @@
 #include "nir.h"
 #include "pipe/p_state.h"
 #include "util/disk_cache.h"
+#include "util/u_queue.h"
 
 struct etna_context;
 struct etna_shader_variant;
@@ -85,6 +86,9 @@ struct etna_shader {
    struct etna_shader_variant *variants;
 
    cache_key cache_key;     /* shader disk-cache key */
+
+   /* parallel shader compiles */
+   struct util_queue_fence ready;
 };
 
 bool



More information about the mesa-commit mailing list