[Mesa-dev] [PATCH] radv: Fix pipeline cache locking issues

Bas Nieuwenhuizen bas at basnieuwenhuizen.nl
Sat Oct 21 01:54:41 UTC 2017


For radv_create_shader_variants_from_pipeline_cache I'm not really
sure why this would cause corruption. Yes we might create the variants
a few times too much, but that should not cause any corruption.

Either way, it is a fix, so
Reviewed-by: Bas Nieuwenhuizen <bas at basnieuwenhuizen.nl>

and pushed. Thanks.

On Thu, Oct 19, 2017 at 12:49 PM, Alex Smith
<asmith at feralinteractive.com> wrote:
> Need to lock around the whole process of retrieving cached shaders, and
> around GetPipelineCacheData.
>
> This fixes GPU hangs observed when creating multiple pipelines in
> parallel, which appeared to be due to invalid shader code being pulled
> from the cache.
>
> Signed-off-by: Alex Smith <asmith at feralinteractive.com>
> ---
>  src/amd/vulkan/radv_pipeline_cache.c | 30 +++++++++++++++++++++++-------
>  1 file changed, 23 insertions(+), 7 deletions(-)
>
> diff --git a/src/amd/vulkan/radv_pipeline_cache.c b/src/amd/vulkan/radv_pipeline_cache.c
> index 034dc35af8..a75356b822 100644
> --- a/src/amd/vulkan/radv_pipeline_cache.c
> +++ b/src/amd/vulkan/radv_pipeline_cache.c
> @@ -177,15 +177,20 @@ radv_create_shader_variants_from_pipeline_cache(struct radv_device *device,
>                                                 struct radv_shader_variant **variants)
>  {
>         struct cache_entry *entry;
> -       if (cache)
> -               entry = radv_pipeline_cache_search(cache, sha1);
> -       else
> -               entry = radv_pipeline_cache_search(device->mem_cache, sha1);
> +
> +       if (!cache)
> +               cache = device->mem_cache;
> +
> +       pthread_mutex_lock(&cache->mutex);
> +
> +       entry = radv_pipeline_cache_search_unlocked(cache, sha1);
>
>         if (!entry) {
>                 if (!device->physical_device->disk_cache ||
> -                   (device->instance->debug_flags & RADV_DEBUG_NO_CACHE))
> +                   (device->instance->debug_flags & RADV_DEBUG_NO_CACHE)) {
> +                       pthread_mutex_unlock(&cache->mutex);
>                         return false;
> +               }
>
>                 uint8_t disk_sha1[20];
>                 disk_cache_compute_key(device->physical_device->disk_cache,
> @@ -193,8 +198,10 @@ radv_create_shader_variants_from_pipeline_cache(struct radv_device *device,
>                 entry = (struct cache_entry *)
>                         disk_cache_get(device->physical_device->disk_cache,
>                                        disk_sha1, NULL);
> -               if (!entry)
> +               if (!entry) {
> +                       pthread_mutex_unlock(&cache->mutex);
>                         return false;
> +               }
>         }
>
>         char *p = entry->code;
> @@ -204,8 +211,10 @@ radv_create_shader_variants_from_pipeline_cache(struct radv_device *device,
>                         struct cache_entry_variant_info info;
>
>                         variant = calloc(1, sizeof(struct radv_shader_variant));
> -                       if (!variant)
> +                       if (!variant) {
> +                               pthread_mutex_unlock(&cache->mutex);
>                                 return false;
> +                       }
>
>                         memcpy(&info, p, sizeof(struct cache_entry_variant_info));
>                         p += sizeof(struct cache_entry_variant_info);
> @@ -231,6 +240,7 @@ radv_create_shader_variants_from_pipeline_cache(struct radv_device *device,
>                         p_atomic_inc(&entry->variants[i]->ref_count);
>
>         memcpy(variants, entry->variants, sizeof(entry->variants));
> +       pthread_mutex_unlock(&cache->mutex);
>         return true;
>  }
>
> @@ -509,12 +519,17 @@ VkResult radv_GetPipelineCacheData(
>         RADV_FROM_HANDLE(radv_pipeline_cache, cache, _cache);
>         struct cache_header *header;
>         VkResult result = VK_SUCCESS;
> +
> +       pthread_mutex_lock(&cache->mutex);
> +
>         const size_t size = sizeof(*header) + cache->total_size;
>         if (pData == NULL) {
> +               pthread_mutex_unlock(&cache->mutex);
>                 *pDataSize = size;
>                 return VK_SUCCESS;
>         }
>         if (*pDataSize < sizeof(*header)) {
> +               pthread_mutex_unlock(&cache->mutex);
>                 *pDataSize = 0;
>                 return VK_INCOMPLETE;
>         }
> @@ -545,6 +560,7 @@ VkResult radv_GetPipelineCacheData(
>         }
>         *pDataSize = p - pData;
>
> +       pthread_mutex_unlock(&cache->mutex);
>         return result;
>  }
>
> --
> 2.13.6
>


More information about the mesa-dev mailing list