[Mesa-dev] [PATCH 06/18] radeonsi: have separate LS and ES main shader parts in the shader selector

Marek Olšák maraeo at gmail.com
Thu Feb 16 12:52:58 UTC 2017


From: Marek Olšák <marek.olsak at amd.com>

This might reduce the on-demand compilation if the initial VS/LS/ES
determination is wrong.
---
 src/gallium/drivers/radeonsi/si_shader.c        |  2 +-
 src/gallium/drivers/radeonsi/si_shader.h        | 16 +++++++++++
 src/gallium/drivers/radeonsi/si_state_shaders.c | 36 ++++++++++++++++++++++---
 3 files changed, 49 insertions(+), 5 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c
index 1829e3e..de42778 100644
--- a/src/gallium/drivers/radeonsi/si_shader.c
+++ b/src/gallium/drivers/radeonsi/si_shader.c
@@ -8233,21 +8233,21 @@ static void si_fix_resource_usage(struct si_screen *sscreen,
 		si_multiwave_lds_size_workaround(sscreen,
 						 &shader->config.lds_size);
 	}
 }
 
 int si_shader_create(struct si_screen *sscreen, LLVMTargetMachineRef tm,
 		     struct si_shader *shader,
 		     struct pipe_debug_callback *debug)
 {
 	struct si_shader_selector *sel = shader->selector;
-	struct si_shader *mainp = sel->main_shader_part;
+	struct si_shader *mainp = *si_get_main_shader_part(sel, &shader->key);
 	int r;
 
 	/* LS, ES, VS are compiled on demand if the main part hasn't been
 	 * compiled for that stage.
 	 *
 	 * Vertex shaders are compiled on demand when a vertex fetch
 	 * workaround must be applied.
 	 */
 	if (shader->is_monolithic) {
 		/* Monolithic shader (compiled as a whole, has many variants,
diff --git a/src/gallium/drivers/radeonsi/si_shader.h b/src/gallium/drivers/radeonsi/si_shader.h
index da88df0..d4b57c9 100644
--- a/src/gallium/drivers/radeonsi/si_shader.h
+++ b/src/gallium/drivers/radeonsi/si_shader.h
@@ -280,20 +280,22 @@ struct si_shader_selector {
 	struct si_compiler_ctx_state compiler_ctx_state;
 
 	pipe_mutex		mutex;
 	struct si_shader	*first_variant; /* immutable after the first variant */
 	struct si_shader	*last_variant; /* mutable */
 
 	/* The compiled TGSI shader expecting a prolog and/or epilog (not
 	 * uploaded to a buffer).
 	 */
 	struct si_shader	*main_shader_part;
+	struct si_shader	*main_shader_part_ls; /* as_ls is set in the key */
+	struct si_shader	*main_shader_part_es; /* as_es is set in the key */
 
 	struct si_shader	*gs_copy_shader;
 
 	struct tgsi_token       *tokens;
 	struct pipe_stream_output_info  so;
 	struct tgsi_shader_info		info;
 
 	/* PIPE_SHADER_[VERTEX|FRAGMENT|...] */
 	unsigned	type;
 
@@ -578,11 +580,25 @@ void si_shader_apply_scratch_relocs(struct si_context *sctx,
 			struct si_shader *shader,
 			struct si_shader_config *config,
 			uint64_t scratch_va);
 void si_shader_binary_read_config(struct radeon_shader_binary *binary,
 				  struct si_shader_config *conf,
 				  unsigned symbol_offset);
 unsigned si_get_spi_shader_z_format(bool writes_z, bool writes_stencil,
 				    bool writes_samplemask);
 const char *si_get_shader_name(struct si_shader *shader, unsigned processor);
 
+/* Inline helpers. */
+
+/* Return the pointer to the main shader part's pointer. */
+static inline struct si_shader **
+si_get_main_shader_part(struct si_shader_selector *sel,
+			struct si_shader_key *key)
+{
+	if (key->as_ls)
+		return &sel->main_shader_part_ls;
+	if (key->as_es)
+		return &sel->main_shader_part_es;
+	return &sel->main_shader_part;
+}
+
 #endif
diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c b/src/gallium/drivers/radeonsi/si_state_shaders.c
index 3630911..179176c 100644
--- a/src/gallium/drivers/radeonsi/si_state_shaders.c
+++ b/src/gallium/drivers/radeonsi/si_state_shaders.c
@@ -1229,29 +1229,53 @@ again:
 	/* Build a new shader. */
 	shader = CALLOC_STRUCT(si_shader);
 	if (!shader) {
 		pipe_mutex_unlock(sel->mutex);
 		return -ENOMEM;
 	}
 	shader->selector = sel;
 	shader->key = *key;
 	shader->compiler_ctx_state = *compiler_state;
 
+	/* Compile the main shader part if it doesn't exist. This can happen
+	 * if the initial guess was wrong. */
+	struct si_shader **mainp = si_get_main_shader_part(sel, key);
 	bool is_pure_monolithic =
 		memcmp(&key->mono, &zeroed.mono, sizeof(key->mono)) != 0;
 
+	if (!*mainp && !is_pure_monolithic) {
+		struct si_shader *main_part = CALLOC_STRUCT(si_shader);
+
+		if (!main_part) {
+			FREE(shader);
+			pipe_mutex_unlock(sel->mutex);
+			return -ENOMEM; /* skip the draw call */
+		}
+
+		main_part->selector = sel;
+		main_part->key.as_es = key->as_es;
+		main_part->key.as_ls = key->as_ls;
+
+		if (si_compile_tgsi_shader(sscreen, compiler_state->tm,
+					   main_part, false,
+					   &compiler_state->debug) != 0) {
+			FREE(main_part);
+			FREE(shader);
+			pipe_mutex_unlock(sel->mutex);
+			return -ENOMEM; /* skip the draw call */
+		}
+		*mainp = main_part;
+	}
+
 	/* Monolithic-only shaders don't make a distinction between optimized
 	 * and unoptimized. */
 	shader->is_monolithic =
-		!sel->main_shader_part ||
-		sel->main_shader_part->key.as_ls != key->as_ls ||
-		sel->main_shader_part->key.as_es != key->as_es ||
 		is_pure_monolithic ||
 		memcmp(&key->opt, &zeroed.opt, sizeof(key->opt)) != 0;
 
 	shader->is_optimized =
 		!sscreen->use_monolithic_shaders &&
 		memcmp(&key->opt, &zeroed.opt, sizeof(key->opt)) != 0;
 	if (shader->is_optimized)
 		util_queue_fence_init(&shader->optimized_ready);
 
 	if (!sel->last_variant) {
@@ -1392,21 +1416,21 @@ void si_init_shader_selector_async(void *job, int thread_index)
 			}
 
 			if (tgsi_binary) {
 				pipe_mutex_lock(sscreen->shader_cache_mutex);
 				if (!si_shader_cache_insert_shader(sscreen, tgsi_binary, shader))
 					FREE(tgsi_binary);
 				pipe_mutex_unlock(sscreen->shader_cache_mutex);
 			}
 		}
 
-		sel->main_shader_part = shader;
+		*si_get_main_shader_part(sel, &shader->key) = shader;
 
 		/* Unset "outputs_written" flags for outputs converted to
 		 * DEFAULT_VAL, so that later inter-shader optimizations don't
 		 * try to eliminate outputs that don't exist in the final
 		 * shader.
 		 *
 		 * This is only done if non-monolithic shaders are enabled.
 		 */
 		if ((sel->type == PIPE_SHADER_VERTEX ||
 		     sel->type == PIPE_SHADER_TESS_EVAL) &&
@@ -1862,20 +1886,24 @@ static void si_delete_shader_selector(struct pipe_context *ctx, void *state)
 	}
 
 	while (p) {
 		c = p->next_variant;
 		si_delete_shader(sctx, p);
 		p = c;
 	}
 
 	if (sel->main_shader_part)
 		si_delete_shader(sctx, sel->main_shader_part);
+	if (sel->main_shader_part_ls)
+		si_delete_shader(sctx, sel->main_shader_part_ls);
+	if (sel->main_shader_part_es)
+		si_delete_shader(sctx, sel->main_shader_part_es);
 	if (sel->gs_copy_shader)
 		si_delete_shader(sctx, sel->gs_copy_shader);
 
 	util_queue_fence_destroy(&sel->ready);
 	pipe_mutex_destroy(sel->mutex);
 	free(sel->tokens);
 	free(sel);
 }
 
 static unsigned si_get_ps_input_cntl(struct si_context *sctx,
-- 
2.7.4



More information about the mesa-dev mailing list