radeonsi: use IR SHA1 as the cache key for the in-memory shader cache
authorMarek Olšák <marek.olsak@amd.com>
Sat, 2 Nov 2019 01:26:47 +0000 (21:26 -0400)
committerMarek Olšák <marek.olsak@amd.com>
Wed, 6 Nov 2019 04:28:42 +0000 (23:28 -0500)
instead of using whole IR binaries. This saves some memory.

Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com>
src/gallium/drivers/radeonsi/si_compute.c
src/gallium/drivers/radeonsi/si_state.h
src/gallium/drivers/radeonsi/si_state_shaders.c

index 6d9b5d0..56af2ae 100644 (file)
@@ -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)
index 88e0151..3a16e55 100644 (file)
@@ -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);
index a630795..10b95ff 100644 (file)
 /* 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;