[Mesa-dev] [PATCH 45/61] radeonsi/gfx9: make sure the 1st shader's main part exists for merged shaders

Marek Olšák maraeo at gmail.com
Mon Apr 24 08:45:42 UTC 2017


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

---
 src/gallium/drivers/radeonsi/si_state_shaders.c | 78 +++++++++++++++++++------
 1 file changed, 60 insertions(+), 18 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c b/src/gallium/drivers/radeonsi/si_state_shaders.c
index b35bdfa..6bb3f50 100644
--- a/src/gallium/drivers/radeonsi/si_state_shaders.c
+++ b/src/gallium/drivers/radeonsi/si_state_shaders.c
@@ -1428,28 +1428,57 @@ static void si_build_shader_variant(void *job, int thread_index)
 					 &shader->shader_log_size);
 		if (f) {
 			si_shader_dump(sscreen, shader, NULL, sel->type, f, false);
 			fclose(f);
 		}
 	}
 
 	si_shader_init_pm4_state(sscreen, shader);
 }
 
+static const struct si_shader_key zeroed;
+
+static bool si_check_missing_main_part(struct si_screen *sscreen,
+				       struct si_shader_selector *sel,
+				       struct si_compiler_ctx_state *compiler_state,
+				       struct si_shader_key *key)
+{
+	struct si_shader **mainp = si_get_main_shader_part(sel, key);
+
+	if (!*mainp) {
+		struct si_shader *main_part = CALLOC_STRUCT(si_shader);
+
+		if (!main_part)
+			return false;
+
+		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);
+			return false;
+		}
+		*mainp = main_part;
+	}
+	return true;
+}
+
 /* Select the hw shader variant depending on the current state. */
 static int si_shader_select_with_key(struct si_screen *sscreen,
 				     struct si_shader_ctx_state *state,
 				     struct si_compiler_ctx_state *compiler_state,
 				     struct si_shader_key *key,
 				     int thread_index)
 {
-	static const struct si_shader_key zeroed;
 	struct si_shader_selector *sel = state->cso;
 	struct si_shader *current = state->current;
 	struct si_shader *iter, *shader = NULL;
 
 	if (unlikely(sscreen->b.debug_flags & DBG_NO_OPT_VARIANT)) {
 		memset(&key->opt, 0, sizeof(key->opt));
 	}
 
 again:
 	/* Check if we don't need to change anything.
@@ -1506,47 +1535,60 @@ again:
 	if (!shader) {
 		mtx_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 =
 		sscreen->use_monolithic_shaders ||
 		memcmp(&key->mono, &zeroed.mono, sizeof(key->mono)) != 0;
 
-	if (!*mainp && !is_pure_monolithic) {
-		struct si_shader *main_part = CALLOC_STRUCT(si_shader);
+	if (!is_pure_monolithic) {
+		bool ok;
 
-		if (!main_part) {
-			FREE(shader);
-			mtx_unlock(&sel->mutex);
-			return -ENOMEM; /* skip the draw call */
+		/* Make sure the main shader part is present. This is needed
+		 * for shaders that can be compiled as VS, LS, or ES, and only
+		 * one of them is compiled at creation.
+		 *
+		 * For merged shaders, check that the starting shader's main
+		 * part is present.
+		 */
+		if (sscreen->b.chip_class >= GFX9 &&
+		    (sel->type == PIPE_SHADER_TESS_CTRL ||
+		     sel->type == PIPE_SHADER_GEOMETRY)) {
+			struct si_shader_selector *shader1 = NULL;
+			struct si_shader_key shader1_key = zeroed;
+
+			if (sel->type == PIPE_SHADER_TESS_CTRL) {
+				shader1 = key->part.tcs.ls;
+				shader1_key.as_ls = 1;
+			} else if (sel->type == PIPE_SHADER_GEOMETRY) {
+				shader1 = key->part.gs.es;
+				shader1_key.as_es = 1;
+			} else
+				assert(0);
+
+			ok = si_check_missing_main_part(sscreen, shader1,
+							compiler_state, &shader1_key);
+		} else {
+			ok = si_check_missing_main_part(sscreen, sel,
+							compiler_state, key);
 		}
-
-		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);
+		if (!ok) {
 			FREE(shader);
 			mtx_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 =
 		is_pure_monolithic ||
 		memcmp(&key->opt, &zeroed.opt, sizeof(key->opt)) != 0;
 
 	shader->is_optimized =
 		!is_pure_monolithic &&
-- 
2.7.4



More information about the mesa-dev mailing list