radv: Implement VK_AMD_shader_info
[mesa.git] / src / amd / vulkan / radv_pipeline_cache.c
index d721f8b9f9e233dd3e80b67bab4058d8d21b3237..441e2257d55c67fdf9f0925e74996c2d8ac59b33 100644 (file)
@@ -62,9 +62,11 @@ radv_pipeline_cache_init(struct radv_pipeline_cache *cache,
        cache->hash_table = malloc(byte_size);
 
        /* We don't consider allocation failure fatal, we just start with a 0-sized
-        * cache. */
+        * cache. Disable caching when we want to keep shader debug info, since
+        * we don't get the debug info on cached shaders. */
        if (cache->hash_table == NULL ||
-           (device->instance->debug_flags & RADV_DEBUG_NO_CACHE))
+           (device->instance->debug_flags & RADV_DEBUG_NO_CACHE) ||
+           device->keep_shader_info)
                cache->table_size = 0;
        else
                memset(cache->hash_table, 0, byte_size);
@@ -97,26 +99,33 @@ entry_size(struct cache_entry *entry)
 }
 
 void
-radv_hash_shader(unsigned char *hash, struct radv_shader_module *module,
-                const char *entrypoint,
-                const VkSpecializationInfo *spec_info,
-                const struct radv_pipeline_layout *layout,
-                const struct ac_shader_variant_key *key,
-                uint32_t flags)
+radv_hash_shaders(unsigned char *hash,
+                 const VkPipelineShaderStageCreateInfo **stages,
+                 const struct radv_pipeline_layout *layout,
+                 const struct radv_pipeline_key *key,
+                 uint32_t flags)
 {
        struct mesa_sha1 ctx;
 
        _mesa_sha1_init(&ctx);
        if (key)
                _mesa_sha1_update(&ctx, key, sizeof(*key));
-       _mesa_sha1_update(&ctx, module->sha1, sizeof(module->sha1));
-       _mesa_sha1_update(&ctx, entrypoint, strlen(entrypoint));
        if (layout)
                _mesa_sha1_update(&ctx, layout->sha1, sizeof(layout->sha1));
-       if (spec_info) {
-               _mesa_sha1_update(&ctx, spec_info->pMapEntries,
-                                 spec_info->mapEntryCount * sizeof spec_info->pMapEntries[0]);
-               _mesa_sha1_update(&ctx, spec_info->pData, spec_info->dataSize);
+
+       for (int i = 0; i < MESA_SHADER_STAGES; ++i) {
+               if (stages[i]) {
+                       RADV_FROM_HANDLE(radv_shader_module, module, stages[i]->module);
+                       const VkSpecializationInfo *spec_info = stages[i]->pSpecializationInfo;
+
+                       _mesa_sha1_update(&ctx, module->sha1, sizeof(module->sha1));
+                       _mesa_sha1_update(&ctx, stages[i]->pName, strlen(stages[i]->pName));
+                       if (spec_info) {
+                               _mesa_sha1_update(&ctx, spec_info->pMapEntries,
+                                                 spec_info->mapEntryCount * sizeof spec_info->pMapEntries[0]);
+                               _mesa_sha1_update(&ctx, spec_info->pData, spec_info->dataSize);
+                       }
+               }
        }
        _mesa_sha1_update(&ctx, &flags, 4);
        _mesa_sha1_final(&ctx, hash);
@@ -163,60 +172,6 @@ radv_pipeline_cache_search(struct radv_pipeline_cache *cache,
        return entry;
 }
 
-struct radv_shader_variant *
-radv_create_shader_variant_from_pipeline_cache(struct radv_device *device,
-                                              struct radv_pipeline_cache *cache,
-                                              const unsigned char *sha1)
-{
-       struct cache_entry *entry = NULL;
-
-       if (cache)
-               entry = radv_pipeline_cache_search(cache, sha1);
-       else
-               entry = radv_pipeline_cache_search(device->mem_cache, sha1);
-
-       if (!entry) {
-               if (!device->physical_device->disk_cache)
-                       return NULL;
-               uint8_t disk_sha1[20];
-               disk_cache_compute_key(device->physical_device->disk_cache,
-                                      sha1, 20, disk_sha1);
-               entry = (struct cache_entry *)
-                       disk_cache_get(device->physical_device->disk_cache,
-                                      disk_sha1, NULL);
-               if (!entry)
-                       return NULL;
-       }
-
-       if (!entry->variants[0]) {
-               struct radv_shader_variant *variant;
-               char *p = entry->code;
-               struct cache_entry_variant_info info;
-
-               variant = calloc(1, sizeof(struct radv_shader_variant));
-               if (!variant)
-                       return NULL;
-
-               memcpy(&info, p, sizeof(struct cache_entry_variant_info));
-               p += sizeof(struct cache_entry_variant_info);
-
-               variant->code_size = entry->code_sizes[0];
-               variant->config = info.config;
-               variant->info = info.variant_info;
-               variant->rsrc1 = info.rsrc1;
-               variant->rsrc2 = info.rsrc2;
-               variant->ref_count = 1;
-
-               void *ptr = radv_alloc_shader_memory(device, variant);
-               memcpy(ptr, p, entry->code_sizes[0]);
-
-               entry->variants[0] = variant;
-       }
-
-       p_atomic_inc(&entry->variants[0]->ref_count);
-       return entry->variants[0];
-}
-
 bool
 radv_create_shader_variants_from_pipeline_cache(struct radv_device *device,
                                                struct radv_pipeline_cache *cache,
@@ -224,14 +179,23 @@ 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)
+               /* Again, don't cache when we want debug info, since this isn't
+                * present in the cache. */
+               if (!device->physical_device->disk_cache ||
+                   (device->instance->debug_flags & RADV_DEBUG_NO_CACHE) ||
+                   device->keep_shader_info) {
+                       pthread_mutex_unlock(&cache->mutex);
                        return false;
+               }
 
                uint8_t disk_sha1[20];
                disk_cache_compute_key(device->physical_device->disk_cache,
@@ -239,8 +203,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;
@@ -250,8 +216,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);
@@ -268,6 +236,8 @@ radv_create_shader_variants_from_pipeline_cache(struct radv_device *device,
                        p += entry->code_sizes[i];
 
                        entry->variants[i] = variant;
+               } else if (entry->code_sizes[i]) {
+                       p += sizeof(struct cache_entry_variant_info) + entry->code_sizes[i];
                }
 
        }
@@ -277,6 +247,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;
 }
 
@@ -350,79 +321,6 @@ radv_pipeline_cache_add_entry(struct radv_pipeline_cache *cache,
                radv_pipeline_cache_set_entry(cache, entry);
 }
 
-struct radv_shader_variant *
-radv_pipeline_cache_insert_shader(struct radv_device *device,
-                                 struct radv_pipeline_cache *cache,
-                                 const unsigned char *sha1,
-                                 struct radv_shader_variant *variant,
-                                 const void *code, unsigned code_size)
-{
-       if (!cache)
-               cache = device->mem_cache;
-
-       pthread_mutex_lock(&cache->mutex);
-       struct cache_entry *entry = radv_pipeline_cache_search_unlocked(cache, sha1);
-       if (entry) {
-               if (entry->variants[0]) {
-                       radv_shader_variant_destroy(cache->device, variant);
-                       variant = entry->variants[0];
-               } else {
-                       entry->variants[0] = variant;
-               }
-               p_atomic_inc(&variant->ref_count);
-               pthread_mutex_unlock(&cache->mutex);
-               return variant;
-       }
-
-       entry = vk_alloc(&cache->alloc, sizeof(*entry) + sizeof(struct cache_entry_variant_info) + code_size, 8,
-                          VK_SYSTEM_ALLOCATION_SCOPE_CACHE);
-       if (!entry) {
-               pthread_mutex_unlock(&cache->mutex);
-               return variant;
-       }
-
-       memset(entry, 0, sizeof(*entry));
-
-       char* p = entry->code;
-       struct cache_entry_variant_info info;
-
-       info.config = variant->config;
-       info.variant_info = variant->info;
-       info.rsrc1 = variant->rsrc1;
-       info.rsrc2 = variant->rsrc2;
-       memcpy(p, &info, sizeof(struct cache_entry_variant_info));
-       p += sizeof(struct cache_entry_variant_info);
-
-       memcpy(entry->sha1, sha1, 20);
-       memcpy(p, code, code_size);
-
-       entry->code_sizes[0] = code_size;
-
-       /* Set variant to NULL so we have reproducible cache items */
-       entry->variants[0] = NULL;
-
-       /* Always add cache items to disk. This will allow collection of
-        * compiled shaders by third parties such as steam, even if the app
-        * implements its own pipeline cache.
-        */
-       if (device->physical_device->disk_cache) {
-               uint8_t disk_sha1[20];
-               disk_cache_compute_key(device->physical_device->disk_cache, sha1, 20,
-                                      disk_sha1);
-               disk_cache_put(device->physical_device->disk_cache,
-                              disk_sha1, entry, entry_size(entry), NULL);
-       }
-
-       entry->variants[0] = variant;
-       p_atomic_inc(&variant->ref_count);
-
-       radv_pipeline_cache_add_entry(cache, entry);
-
-       cache->modified = true;
-       pthread_mutex_unlock(&cache->mutex);
-       return variant;
-}
-
 void
 radv_pipeline_cache_insert_shaders(struct radv_device *device,
                                   struct radv_pipeline_cache *cache,
@@ -628,12 +526,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;
        }
@@ -664,6 +567,7 @@ VkResult radv_GetPipelineCacheData(
        }
        *pDataSize = p - pData;
 
+       pthread_mutex_unlock(&cache->mutex);
        return result;
 }