[Mesa-dev] [PATCH 3/4] radeonsi: add support for an on-disk shader cache

Timothy Arceri tarceri at itsqueeze.com
Wed Mar 1 23:27:19 UTC 2017



On 01/03/17 18:36, Axel Davy wrote:
> My understanding of the code is that the disk cache just depends on the
> sscreen->b.disk_shader_cache being initialized, and it looks like this
> is always
> initialized.
> Thus the disk cache is always enabled.
>
> Could you add a RADEON_DEBUG env var to disable it, please ?

Replying here for completeness but as discussed on irc the entire cache 
can be turned off with MESA_GLSL_CACHE_DISABLE=1. I don't think there is 
much justification for a RADEON_DEBUG flag to disable only the radeonsi 
cache.

>
> Thanks,
>
> Axel Davy
>
> On 01/03/2017 06:25, Timothy Arceri wrote:
>> V2:
>> - when loading from disk cache also binary insert into memory cache.
>> - check that the binary loaded from disk is the correct size. If not
>>    delete the cache item and skip loading from cache.
>>
>> V3:
>> - remove unrequired variable
>>
>> Tested-by: Michel Dänzer <michel.daenzer at amd.com>
>> ---
>>   src/gallium/drivers/radeonsi/si_state_shaders.c | 67
>> ++++++++++++++++++++++---
>>   1 file changed, 60 insertions(+), 7 deletions(-)
>>
>> diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c
>> b/src/gallium/drivers/radeonsi/si_state_shaders.c
>> index 750cdd6..a82e38e 100644
>> --- a/src/gallium/drivers/radeonsi/si_state_shaders.c
>> +++ b/src/gallium/drivers/radeonsi/si_state_shaders.c
>> @@ -29,20 +29,23 @@
>>   #include "sid.h"
>>   #include "radeon/r600_cs.h"
>>     #include "tgsi/tgsi_parse.h"
>>   #include "tgsi/tgsi_ureg.h"
>>   #include "util/hash_table.h"
>>   #include "util/crc32.h"
>>   #include "util/u_memory.h"
>>   #include "util/u_prim.h"
>>   +#include "util/disk_cache.h"
>> +#include "util/mesa-sha1.h"
>> +
>>   /* SHADER_CACHE */
>>     /**
>>    * Return the TGSI binary in a buffer. The first 4 bytes contain its
>> size as
>>    * integer.
>>    */
>>   static void *si_get_tgsi_binary(struct si_shader_selector *sel)
>>   {
>>       unsigned tgsi_size = tgsi_num_tokens(sel->tokens) *
>>                    sizeof(struct tgsi_token);
>> @@ -175,54 +178,104 @@ 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 tgsi_binary should be
>> freed.
>>    */
>>   static bool si_shader_cache_insert_shader(struct si_screen *sscreen,
>>                         void *tgsi_binary,
>> -                      struct si_shader *shader)
>> +                      struct si_shader *shader,
>> +                      bool insert_into_disk_cache)
>>   {
>>       void *hw_binary;
>>       struct hash_entry *entry;
>> +    uint8_t key[CACHE_KEY_SIZE];
>>         entry = _mesa_hash_table_search(sscreen->shader_cache,
>> tgsi_binary);
>>       if (entry)
>>           return false; /* already added */
>>         hw_binary = si_get_shader_binary(shader);
>>       if (!hw_binary)
>>           return false;
>>         if (_mesa_hash_table_insert(sscreen->shader_cache, tgsi_binary,
>>                       hw_binary) == NULL) {
>>           FREE(hw_binary);
>>           return false;
>>       }
>>   +    if (sscreen->b.disk_shader_cache && insert_into_disk_cache) {
>> +        _mesa_sha1_compute(tgsi_binary, *((uint32_t *)tgsi_binary),
>> key);
>> +        disk_cache_put(sscreen->b.disk_shader_cache, key, hw_binary,
>> +                   *((uint32_t *) hw_binary));
>> +    }
>> +
>>       return true;
>>   }
>>     static bool si_shader_cache_load_shader(struct si_screen *sscreen,
>>                       void *tgsi_binary,
>>                           struct si_shader *shader)
>>   {
>>       struct hash_entry *entry =
>>           _mesa_hash_table_search(sscreen->shader_cache, tgsi_binary);
>> -    if (!entry)
>> -        return false;
>> +    if (!entry) {
>> +        if (sscreen->b.disk_shader_cache) {
>> +            unsigned char sha1[CACHE_KEY_SIZE];
>> +            size_t tg_size = *((uint32_t *) tgsi_binary);
>> +
>> +            _mesa_sha1_compute(tgsi_binary, tg_size, sha1);
>> +
>> +            size_t binary_size;
>> +            uint8_t *buffer =
>> +                disk_cache_get(sscreen->b.disk_shader_cache,
>> +                           sha1, &binary_size);
>> +            if (!buffer)
>> +                return false;
>>   -    if (!si_load_shader_binary(shader, entry->data))
>> -        return false;
>> +            if (binary_size < sizeof(uint32_t) ||
>> +                *((uint32_t*)buffer) != binary_size) {
>> +                 /* Something has gone wrong discard the item
>> +                  * from the cache and rebuild/link from
>> +                  * source.
>> +                  */
>> +                assert(!"Invalid radeonsi shader disk cache "
>> +                       "item!");
>> +
>> +                disk_cache_remove(sscreen->b.disk_shader_cache,
>> +                          sha1);
>> +                free(buffer);
>> +
>> +                return false;
>> +            }
>> +
>> +            if (!si_load_shader_binary(shader, buffer)) {
>> +                free(buffer);
>> +                return false;
>> +            }
>> +            free(buffer);
>>   +            if (!si_shader_cache_insert_shader(sscreen, tgsi_binary,
>> +                               shader, false))
>> +                FREE(tgsi_binary);
>> +        } else {
>> +            return false;
>> +        }
>> +    } else {
>> +        if (si_load_shader_binary(shader, entry->data))
>> +            FREE(tgsi_binary);
>> +        else
>> +            return false;
>> +    }
>>       p_atomic_inc(&sscreen->b.num_shader_cache_hits);
>>       return true;
>>   }
>>     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);
>>   }
>>   @@ -244,20 +297,21 @@ static void
>> si_destroy_shader_cache_entry(struct hash_entry *entry)
>>       FREE(entry->data);
>>   }
>>     bool si_init_shader_cache(struct si_screen *sscreen)
>>   {
>>       pipe_mutex_init(sscreen->shader_cache_mutex);
>>       sscreen->shader_cache =
>>           _mesa_hash_table_create(NULL,
>>                       si_shader_cache_key_hash,
>>                       si_shader_cache_key_equals);
>> +
>>       return sscreen->shader_cache != NULL;
>>   }
>>     void si_destroy_shader_cache(struct si_screen *sscreen)
>>   {
>>       if (sscreen->shader_cache)
>>           _mesa_hash_table_destroy(sscreen->shader_cache,
>>                        si_destroy_shader_cache_entry);
>>       pipe_mutex_destroy(sscreen->shader_cache_mutex);
>>   }
>> @@ -1400,37 +1454,36 @@ void si_init_shader_selector_async(void *job,
>> int thread_index)
>>           shader->selector = sel;
>>           si_parse_next_shader_property(&sel->info, &shader->key);
>>             tgsi_binary = si_get_tgsi_binary(sel);
>>             /* Try to load the shader from the shader cache. */
>>           pipe_mutex_lock(sscreen->shader_cache_mutex);
>>             if (tgsi_binary &&
>>               si_shader_cache_load_shader(sscreen, tgsi_binary,
>> shader)) {
>> -            FREE(tgsi_binary);
>>               pipe_mutex_unlock(sscreen->shader_cache_mutex);
>>           } else {
>>               pipe_mutex_unlock(sscreen->shader_cache_mutex);
>>                 /* Compile the shader if it hasn't been loaded from
>> the cache. */
>>               if (si_compile_tgsi_shader(sscreen, tm, shader, false,
>>                              debug) != 0) {
>>                   FREE(shader);
>>                   FREE(tgsi_binary);
>>                   fprintf(stderr, "radeonsi: can't compile a main
>> shader part\n");
>>                   return;
>>               }
>>                 if (tgsi_binary) {
>>                   pipe_mutex_lock(sscreen->shader_cache_mutex);
>> -                if (!si_shader_cache_insert_shader(sscreen,
>> tgsi_binary, shader))
>> +                if (!si_shader_cache_insert_shader(sscreen,
>> tgsi_binary, shader, true))
>>                       FREE(tgsi_binary);
>>                   pipe_mutex_unlock(sscreen->shader_cache_mutex);
>>               }
>>           }
>>             *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
>
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list