From 62229e89490efd3ce2208571c4c4ef7ae8741760 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Fri, 1 Nov 2019 21:26:47 -0400 Subject: [PATCH] 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 --- src/gallium/drivers/radeonsi/si_compute.c | 16 ++- src/gallium/drivers/radeonsi/si_state.h | 9 +- .../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; -- 2.30.2