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

Axel Davy axel.davy at ens.fr
Wed Mar 1 23:33:05 UTC 2017


On 02/03/2017 00:27, Timothy Arceri wrote:
>
>
> 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.
>
I get a different view from our irc discussion.

In my understanding, MESA_GLSL_CACHE_DISABLE only affects the glsl->tgsi 
cache.
The radeon tgsi->asm cache is always enabled and cannot be disabled.
But it is fine with me, because the cache is discarded if the buildtime 
of llvm or mesa changes.

Axel
>>
>> 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