Mesa (master): radv: Add multiple shader cache store & load functions.

Timothy Arceri tarceri at kemper.freedesktop.org
Tue Oct 17 22:20:21 UTC 2017


Module: Mesa
Branch: master
Commit: 7f29055751e6b89f4c87bc5e4602046c2cbdc08c
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=7f29055751e6b89f4c87bc5e4602046c2cbdc08c

Author: Bas Nieuwenhuizen <bas at basnieuwenhuizen.nl>
Date:   Thu Dec  1 23:07:57 2016 +0100

radv: Add multiple shader cache store & load functions.

Signed-off-by: Timothy Arceri <tarceri at itsqueeze.com>
Acked-by: Dave Airlie <airlied at redhat.com>

---

 src/amd/vulkan/radv_pipeline_cache.c | 156 +++++++++++++++++++++++++++++++++++
 src/amd/vulkan/radv_private.h        |  14 ++++
 2 files changed, 170 insertions(+)

diff --git a/src/amd/vulkan/radv_pipeline_cache.c b/src/amd/vulkan/radv_pipeline_cache.c
index fc34e07822..d721f8b9f9 100644
--- a/src/amd/vulkan/radv_pipeline_cache.c
+++ b/src/amd/vulkan/radv_pipeline_cache.c
@@ -217,6 +217,69 @@ radv_create_shader_variant_from_pipeline_cache(struct radv_device *device,
 	return entry->variants[0];
 }
 
+bool
+radv_create_shader_variants_from_pipeline_cache(struct radv_device *device,
+					        struct radv_pipeline_cache *cache,
+					        const unsigned char *sha1,
+					        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 (!entry) {
+		if (!device->physical_device->disk_cache)
+			return false;
+
+		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 false;
+	}
+
+	char *p = entry->code;
+	for(int i = 0; i < MESA_SHADER_STAGES; ++i) {
+		if (!entry->variants[i] && entry->code_sizes[i]) {
+			struct radv_shader_variant *variant;
+			struct cache_entry_variant_info info;
+
+			variant = calloc(1, sizeof(struct radv_shader_variant));
+			if (!variant)
+				return false;
+
+			memcpy(&info, p, sizeof(struct cache_entry_variant_info));
+			p += sizeof(struct cache_entry_variant_info);
+
+			variant->config = info.config;
+			variant->info = info.variant_info;
+			variant->rsrc1 = info.rsrc1;
+			variant->rsrc2 = info.rsrc2;
+			variant->code_size = entry->code_sizes[i];
+			variant->ref_count = 1;
+
+			void *ptr = radv_alloc_shader_memory(device, variant);
+			memcpy(ptr, p, entry->code_sizes[i]);
+			p += entry->code_sizes[i];
+
+			entry->variants[i] = variant;
+		}
+
+	}
+
+	for (int i = 0; i < MESA_SHADER_STAGES; ++i)
+		if (entry->variants[i])
+			p_atomic_inc(&entry->variants[i]->ref_count);
+
+	memcpy(variants, entry->variants, sizeof(entry->variants));
+	return true;
+}
+
 
 static void
 radv_pipeline_cache_set_entry(struct radv_pipeline_cache *cache,
@@ -360,6 +423,99 @@ radv_pipeline_cache_insert_shader(struct radv_device *device,
 	return variant;
 }
 
+void
+radv_pipeline_cache_insert_shaders(struct radv_device *device,
+				   struct radv_pipeline_cache *cache,
+				   const unsigned char *sha1,
+				   struct radv_shader_variant **variants,
+				   const void *const *codes,
+				   const unsigned *code_sizes)
+{
+	if (!cache)
+		cache = device->mem_cache;
+
+	pthread_mutex_lock(&cache->mutex);
+	struct cache_entry *entry = radv_pipeline_cache_search_unlocked(cache, sha1);
+	if (entry) {
+		for (int i = 0; i < MESA_SHADER_STAGES; ++i) {
+			if (entry->variants[i]) {
+				radv_shader_variant_destroy(cache->device, variants[i]);
+				variants[i] = entry->variants[i];
+			} else {
+				entry->variants[i] = variants[i];
+			}
+			if (variants[i])
+				p_atomic_inc(&variants[i]->ref_count);
+		}
+		pthread_mutex_unlock(&cache->mutex);
+		return;
+	}
+	size_t size = sizeof(*entry);
+	for (int i = 0; i < MESA_SHADER_STAGES; ++i)
+		if (variants[i])
+			size += sizeof(struct cache_entry_variant_info) + code_sizes[i];
+
+
+	entry = vk_alloc(&cache->alloc, size, 8,
+			   VK_SYSTEM_ALLOCATION_SCOPE_CACHE);
+	if (!entry) {
+		pthread_mutex_unlock(&cache->mutex);
+		return;
+	}
+
+	memset(entry, 0, sizeof(*entry));
+	memcpy(entry->sha1, sha1, 20);
+
+	char* p = entry->code;
+	struct cache_entry_variant_info info;
+
+	for (int i = 0; i < MESA_SHADER_STAGES; ++i) {
+		if (!variants[i])
+			continue;
+
+		entry->code_sizes[i] = code_sizes[i];
+
+		info.config = variants[i]->config;
+		info.variant_info = variants[i]->info;
+		info.rsrc1 = variants[i]->rsrc1;
+		info.rsrc2 = variants[i]->rsrc2;
+		memcpy(p, &info, sizeof(struct cache_entry_variant_info));
+		p += sizeof(struct cache_entry_variant_info);
+
+		memcpy(p, codes[i], code_sizes[i]);
+		p += code_sizes[i];
+	}
+
+	/* 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);
+	}
+
+	/* We delay setting the variant so we have reproducible disk cache
+	 * items.
+	 */
+	for (int i = 0; i < MESA_SHADER_STAGES; ++i) {
+		if (!variants[i])
+			continue;
+
+		entry->variants[i] = variants[i];
+		p_atomic_inc(&variants[i]->ref_count);
+	}
+
+	radv_pipeline_cache_add_entry(cache, entry);
+
+	cache->modified = true;
+	pthread_mutex_unlock(&cache->mutex);
+	return;
+}
+
 struct cache_header {
 	uint32_t header_size;
 	uint32_t header_version;
diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h
index ef0efae367..5be0706340 100644
--- a/src/amd/vulkan/radv_private.h
+++ b/src/amd/vulkan/radv_private.h
@@ -336,6 +336,20 @@ radv_pipeline_cache_insert_shader(struct radv_device *device,
 				  struct radv_shader_variant *variant,
 				  const void *code, unsigned code_size);
 
+bool
+radv_create_shader_variants_from_pipeline_cache(struct radv_device *device,
+					        struct radv_pipeline_cache *cache,
+					        const unsigned char *sha1,
+					        struct radv_shader_variant **variants);
+
+void
+radv_pipeline_cache_insert_shaders(struct radv_device *device,
+				   struct radv_pipeline_cache *cache,
+				   const unsigned char *sha1,
+				   struct radv_shader_variant **variants,
+				   const void *const *codes,
+				   const unsigned *code_sizes);
+
 struct radv_meta_state {
 	VkAllocationCallbacks alloc;
 




More information about the mesa-commit mailing list