From 1141ed585901e2ac5897291ac17a6ba23aa44137 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Mon, 31 Jan 2022 16:40:45 +0100 Subject: [PATCH] etnaviv: async shader compile Passes following piglit: - spec@khr_parallel_shader_compile@basic Signed-off-by: Christian Gmeiner Reviewed-by: Philipp Zabel Part-of: --- 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