summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/etnaviv/etnaviv_shader.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/etnaviv/etnaviv_shader.c')
-rw-r--r--src/gallium/drivers/etnaviv/etnaviv_shader.c67
1 files changed, 61 insertions, 6 deletions
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);
}