Mesa (master): radeonsi: use IR SHA1 as the cache key for the in-memory shader cache

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Nov 6 04:30:36 UTC 2019


Module: Mesa
Branch: master
Commit: 62229e89490efd3ce2208571c4c4ef7ae8741760
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=62229e89490efd3ce2208571c4c4ef7ae8741760

Author: Marek Olšák <marek.olsak at amd.com>
Date:   Fri Nov  1 21:26:47 2019 -0400

radeonsi: use IR SHA1 as the cache key for the in-memory shader cache

instead of using whole IR binaries. This saves some memory.

Reviewed-by: Timothy Arceri <tarceri at itsqueeze.com>

---

 src/gallium/drivers/radeonsi/si_compute.c       |  16 ++--
 src/gallium/drivers/radeonsi/si_state.h         |   9 ++-
 src/gallium/drivers/radeonsi/si_state_shaders.c | 101 ++++++++++--------------
 3 files changed, 55 insertions(+), 71 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_compute.c b/src/gallium/drivers/radeonsi/si_compute.c
index 6d9b5d0ad6e..56af2aedbb7 100644
--- a/src/gallium/drivers/radeonsi/si_compute.c
+++ b/src/gallium/drivers/radeonsi/si_compute.c
@@ -148,13 +148,13 @@ static void si_create_compute_state_async(void *job, int thread_index)
 	program->num_cs_user_data_dwords =
 		sel->info.properties[TGSI_PROPERTY_CS_USER_DATA_COMPONENTS_AMD];
 
-	void *ir_binary = si_get_ir_binary(sel, false, false);
+	unsigned char ir_sha1_cache_key[20];
+	si_get_ir_cache_key(sel, false, false, ir_sha1_cache_key);
 
 	/* Try to load the shader from the shader cache. */
 	simple_mtx_lock(&sscreen->shader_cache_mutex);
 
-	if (ir_binary &&
-	    si_shader_cache_load_shader(sscreen, ir_binary, shader)) {
+	if (si_shader_cache_load_shader(sscreen, ir_sha1_cache_key, shader)) {
 		simple_mtx_unlock(&sscreen->shader_cache_mutex);
 
 		si_shader_dump_stats_for_shader_db(sscreen, shader, debug);
@@ -202,12 +202,10 @@ static void si_create_compute_state_async(void *job, int thread_index)
 						sel->info.uses_thread_id[1] ? 1 : 0) |
 			S_00B84C_LDS_SIZE(shader->config.lds_size);
 
-		if (ir_binary) {
-			simple_mtx_lock(&sscreen->shader_cache_mutex);
-			if (!si_shader_cache_insert_shader(sscreen, ir_binary, shader, true))
-				FREE(ir_binary);
-			simple_mtx_unlock(&sscreen->shader_cache_mutex);
-		}
+		simple_mtx_lock(&sscreen->shader_cache_mutex);
+		si_shader_cache_insert_shader(sscreen, ir_sha1_cache_key,
+					      shader, true);
+		simple_mtx_unlock(&sscreen->shader_cache_mutex);
 	}
 
 	if (program->ir_type == PIPE_SHADER_IR_TGSI)
diff --git a/src/gallium/drivers/radeonsi/si_state.h b/src/gallium/drivers/radeonsi/si_state.h
index 88e01512cd6..3a16e55e70a 100644
--- a/src/gallium/drivers/radeonsi/si_state.h
+++ b/src/gallium/drivers/radeonsi/si_state.h
@@ -583,10 +583,13 @@ si_compute_fast_udiv_info32(uint32_t D, unsigned num_bits);
 void si_emit_dpbb_state(struct si_context *sctx);
 
 /* si_state_shaders.c */
-void *si_get_ir_binary(struct si_shader_selector *sel, bool ngg, bool es);
-bool si_shader_cache_load_shader(struct si_screen *sscreen, void *ir_binary,
+void si_get_ir_cache_key(struct si_shader_selector *sel, bool ngg, bool es,
+			 unsigned char ir_sha1_cache_key[20]);
+bool si_shader_cache_load_shader(struct si_screen *sscreen,
+				 unsigned char ir_sha1_cache_key[20],
 				 struct si_shader *shader);
-bool si_shader_cache_insert_shader(struct si_screen *sscreen, void *ir_binary,
+void si_shader_cache_insert_shader(struct si_screen *sscreen,
+				   unsigned char ir_sha1_cache_key[20],
 				   struct si_shader *shader,
 				   bool insert_into_disk_cache);
 bool si_update_shaders(struct si_context *sctx);
diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c b/src/gallium/drivers/radeonsi/si_state_shaders.c
index a6307950400..10b95ff0e78 100644
--- a/src/gallium/drivers/radeonsi/si_state_shaders.c
+++ b/src/gallium/drivers/radeonsi/si_state_shaders.c
@@ -42,10 +42,10 @@
 /* SHADER_CACHE */
 
 /**
- * Return the IR binary in a buffer. For TGSI the first 4 bytes contain its
- * size as integer.
+ * Return the IR key for the shader cache.
  */
-void *si_get_ir_binary(struct si_shader_selector *sel, bool ngg, bool es)
+void si_get_ir_cache_key(struct si_shader_selector *sel, bool ngg, bool es,
+			 unsigned char ir_sha1_cache_key[20])
 {
 	struct blob blob;
 	unsigned ir_size;
@@ -54,7 +54,7 @@ void *si_get_ir_binary(struct si_shader_selector *sel, bool ngg, bool es)
 	if (sel->tokens) {
 		ir_binary = sel->tokens;
 		ir_size = tgsi_num_tokens(sel->tokens) *
-					  sizeof(struct tgsi_token);
+			  sizeof(struct tgsi_token);
 	} else {
 		assert(sel->nir);
 
@@ -78,20 +78,18 @@ void *si_get_ir_binary(struct si_shader_selector *sel, bool ngg, bool es)
 	if (sel->force_correct_derivs_after_kill)
 		shader_variant_flags |= 1 << 3;
 
-	unsigned size = 4 + 4 + ir_size + sizeof(sel->so);
-	char *result = (char*)MALLOC(size);
-	if (!result)
-		return NULL;
-
-	((uint32_t*)result)[0] = size;
-	((uint32_t*)result)[1] = shader_variant_flags;
-	memcpy(result + 8, ir_binary, ir_size);
-	memcpy(result + 8 + ir_size, &sel->so, sizeof(sel->so));
+	struct mesa_sha1 ctx;
+	_mesa_sha1_init(&ctx);
+	_mesa_sha1_update(&ctx, &shader_variant_flags, 4);
+	_mesa_sha1_update(&ctx, ir_binary, ir_size);
+	if (sel->type == PIPE_SHADER_VERTEX ||
+	    sel->type == PIPE_SHADER_TESS_EVAL ||
+	    sel->type == PIPE_SHADER_GEOMETRY)
+		_mesa_sha1_update(&ctx, &sel->so, sizeof(sel->so));
+	_mesa_sha1_final(&ctx, ir_sha1_cache_key);
 
 	if (sel->nir)
 		blob_finish(&blob);
-
-	return result;
 }
 
 /** Copy "data" to "ptr" and return the next dword following copied data. */
@@ -208,10 +206,9 @@ static bool si_load_shader_binary(struct si_shader *shader, void *binary)
 /**
  * Insert a shader into the cache. It's assumed the shader is not in the cache.
  * Use si_shader_cache_load_shader before calling this.
- *
- * Returns false on failure, in which case the ir_binary should be freed.
  */
-bool si_shader_cache_insert_shader(struct si_screen *sscreen, void *ir_binary,
+void si_shader_cache_insert_shader(struct si_screen *sscreen,
+				   unsigned char ir_sha1_cache_key[20],
 				   struct si_shader *shader,
 				   bool insert_into_disk_cache)
 {
@@ -219,42 +216,41 @@ bool si_shader_cache_insert_shader(struct si_screen *sscreen, void *ir_binary,
 	struct hash_entry *entry;
 	uint8_t key[CACHE_KEY_SIZE];
 
-	entry = _mesa_hash_table_search(sscreen->shader_cache, ir_binary);
+	entry = _mesa_hash_table_search(sscreen->shader_cache, ir_sha1_cache_key);
 	if (entry)
-		return false; /* already added */
+		return; /* already added */
 
 	hw_binary = si_get_shader_binary(shader);
 	if (!hw_binary)
-		return false;
+		return;
 
-	if (_mesa_hash_table_insert(sscreen->shader_cache, ir_binary,
+	if (_mesa_hash_table_insert(sscreen->shader_cache,
+				    mem_dup(ir_sha1_cache_key, 20),
 				    hw_binary) == NULL) {
 		FREE(hw_binary);
-		return false;
+		return;
 	}
 
 	if (sscreen->disk_shader_cache && insert_into_disk_cache) {
-		disk_cache_compute_key(sscreen->disk_shader_cache, ir_binary,
-				       *((uint32_t *)ir_binary), key);
+		disk_cache_compute_key(sscreen->disk_shader_cache,
+				       ir_sha1_cache_key, 20, key);
 		disk_cache_put(sscreen->disk_shader_cache, key, hw_binary,
 			       *((uint32_t *) hw_binary), NULL);
 	}
-
-	return true;
 }
 
-bool si_shader_cache_load_shader(struct si_screen *sscreen, void *ir_binary,
+bool si_shader_cache_load_shader(struct si_screen *sscreen,
+				 unsigned char ir_sha1_cache_key[20],
 				 struct si_shader *shader)
 {
 	struct hash_entry *entry =
-		_mesa_hash_table_search(sscreen->shader_cache, ir_binary);
+		_mesa_hash_table_search(sscreen->shader_cache, ir_sha1_cache_key);
 	if (!entry) {
 		if (sscreen->disk_shader_cache) {
 			unsigned char sha1[CACHE_KEY_SIZE];
-			size_t tg_size = *((uint32_t *) ir_binary);
 
 			disk_cache_compute_key(sscreen->disk_shader_cache,
-					       ir_binary, tg_size, sha1);
+					       ir_sha1_cache_key, 20, sha1);
 
 			size_t binary_size;
 			uint8_t *buffer =
@@ -285,16 +281,13 @@ bool si_shader_cache_load_shader(struct si_screen *sscreen, void *ir_binary,
 			}
 			free(buffer);
 
-			if (!si_shader_cache_insert_shader(sscreen, ir_binary,
-							   shader, false))
-				FREE(ir_binary);
+			si_shader_cache_insert_shader(sscreen, ir_sha1_cache_key,
+						      shader, false);
 		} else {
 			return false;
 		}
 	} else {
-		if (si_load_shader_binary(shader, entry->data))
-			FREE(ir_binary);
-		else
+		if (!si_load_shader_binary(shader, entry->data))
 			return false;
 	}
 	p_atomic_inc(&sscreen->num_shader_cache_hits);
@@ -303,20 +296,14 @@ bool si_shader_cache_load_shader(struct si_screen *sscreen, void *ir_binary,
 
 static uint32_t si_shader_cache_key_hash(const void *key)
 {
-	/* The first dword is the key size. */
-	return util_hash_crc32(key, *(uint32_t*)key);
+	/* Take the first dword of SHA1. */
+	return *(uint32_t*)key;
 }
 
 static bool si_shader_cache_key_equals(const void *a, const void *b)
 {
-	uint32_t *keya = (uint32_t*)a;
-	uint32_t *keyb = (uint32_t*)b;
-
-	/* The first dword is the key size. */
-	if (*keya != *keyb)
-		return false;
-
-	return memcmp(keya, keyb, *keya) == 0;
+	/* Compare SHA1s. */
+	return memcmp(a, b, 20) == 0;
 }
 
 static void si_destroy_shader_cache_entry(struct hash_entry *entry)
@@ -2484,7 +2471,7 @@ static void si_init_shader_selector_async(void *job, int thread_index)
 	 */
 	if (!sscreen->use_monolithic_shaders) {
 		struct si_shader *shader = CALLOC_STRUCT(si_shader);
-		void *ir_binary = NULL;
+		unsigned char ir_sha1_cache_key[20];
 
 		if (!shader) {
 			fprintf(stderr, "radeonsi: can't allocate a main shader part\n");
@@ -2509,15 +2496,14 @@ static void si_init_shader_selector_async(void *job, int thread_index)
 			shader->key.as_ngg = 1;
 
 		if (sel->tokens || sel->nir) {
-			ir_binary = si_get_ir_binary(sel, shader->key.as_ngg,
-						     shader->key.as_es);
+			si_get_ir_cache_key(sel, shader->key.as_ngg,
+					    shader->key.as_es, ir_sha1_cache_key);
 		}
 
 		/* Try to load the shader from the shader cache. */
 		simple_mtx_lock(&sscreen->shader_cache_mutex);
 
-		if (ir_binary &&
-		    si_shader_cache_load_shader(sscreen, ir_binary, shader)) {
+		if (si_shader_cache_load_shader(sscreen, ir_sha1_cache_key, shader)) {
 			simple_mtx_unlock(&sscreen->shader_cache_mutex);
 			si_shader_dump_stats_for_shader_db(sscreen, shader, debug);
 		} else {
@@ -2527,17 +2513,14 @@ static void si_init_shader_selector_async(void *job, int thread_index)
 			if (si_compile_tgsi_shader(sscreen, compiler, shader,
 						   debug) != 0) {
 				FREE(shader);
-				FREE(ir_binary);
 				fprintf(stderr, "radeonsi: can't compile a main shader part\n");
 				return;
 			}
 
-			if (ir_binary) {
-				simple_mtx_lock(&sscreen->shader_cache_mutex);
-				if (!si_shader_cache_insert_shader(sscreen, ir_binary, shader, true))
-					FREE(ir_binary);
-				simple_mtx_unlock(&sscreen->shader_cache_mutex);
-			}
+			simple_mtx_lock(&sscreen->shader_cache_mutex);
+			si_shader_cache_insert_shader(sscreen, ir_sha1_cache_key,
+						      shader, true);
+			simple_mtx_unlock(&sscreen->shader_cache_mutex);
 		}
 
 		*si_get_main_shader_part(sel, &shader->key) = shader;




More information about the mesa-commit mailing list