diff --git a/src/broadcom/vulkan/v3dv_device.c b/src/broadcom/vulkan/v3dv_device.c index 450b1f9c511..06846a06c29 100644 --- a/src/broadcom/vulkan/v3dv_device.c +++ b/src/broadcom/vulkan/v3dv_device.c @@ -174,11 +174,22 @@ v3dv_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, return VK_SUCCESS; } +static void +v3dv_physical_device_free_disk_cache(struct v3dv_physical_device *device) +{ +#ifdef ENABLE_SHADER_CACHE + if (device->disk_cache) + disk_cache_destroy(device->disk_cache); +#else + assert(device->disk_cache == NULL); +#endif +} + static void physical_device_finish(struct v3dv_physical_device *device) { v3dv_wsi_finish(device); - + v3dv_physical_device_free_disk_cache(device); v3d_compiler_free(device->compiler); close(device->render_fd); @@ -551,6 +562,8 @@ init_uuids(struct v3dv_physical_device *device) "build-id too short. It needs to be a SHA"); } + memcpy(device->driver_build_sha1, build_id_data(note), 20); + uint32_t vendor_id = v3dv_physical_device_vendor_id(device); uint32_t device_id = v3dv_physical_device_device_id(device); @@ -587,6 +600,20 @@ init_uuids(struct v3dv_physical_device *device) return VK_SUCCESS; } +static void +v3dv_physical_device_init_disk_cache(struct v3dv_physical_device *device) +{ +#ifdef ENABLE_SHADER_CACHE + char timestamp[41]; + _mesa_sha1_format(timestamp, device->driver_build_sha1); + + assert(device->name); + device->disk_cache = disk_cache_create(device->name, timestamp, 0); +#else + device->disk_cache = NULL; +#endif +} + static VkResult physical_device_init(struct v3dv_physical_device *device, struct v3dv_instance *instance, @@ -671,6 +698,8 @@ physical_device_init(struct v3dv_physical_device *device, device->devinfo.ver / 10, device->devinfo.ver % 10); assert(len != -1); + v3dv_physical_device_init_disk_cache(device); + /* Setup available memory heaps and types */ VkPhysicalDeviceMemoryProperties *mem = &device->memory; mem->memoryHeapCount = 1; diff --git a/src/broadcom/vulkan/v3dv_pipeline_cache.c b/src/broadcom/vulkan/v3dv_pipeline_cache.c index 4200eba9fa5..d2468b0c4cd 100644 --- a/src/broadcom/vulkan/v3dv_pipeline_cache.c +++ b/src/broadcom/vulkan/v3dv_pipeline_cache.c @@ -209,6 +209,19 @@ v3dv_pipeline_cache_init(struct v3dv_pipeline_cache *cache, } +static struct v3dv_pipeline_shared_data * +v3dv_pipeline_shared_data_create_from_blob(struct v3dv_pipeline_cache *cache, + struct blob_reader *blob); + +static void +pipeline_cache_upload_shared_data(struct v3dv_pipeline_cache *cache, + struct v3dv_pipeline_shared_data *shared_data, + bool from_disk_cache); + +static bool +v3dv_pipeline_shared_data_write_to_blob(const struct v3dv_pipeline_shared_data *cache_entry, + struct blob *blob); + /** * It searchs for pipeline cached data, and returns a v3dv_pipeline_shared_data with * it, or NULL if doesn't have it cached. On the former, it will increases the @@ -261,6 +274,44 @@ v3dv_pipeline_cache_search_for_pipeline(struct v3dv_pipeline_cache *cache, } pthread_mutex_unlock(&cache->mutex); + +#ifdef ENABLE_SHADER_CACHE + struct v3dv_device *device = cache->device; + struct disk_cache *disk_cache = device->pdevice->disk_cache; + /* Note that the on-disk-cache can be independently disabled, while keeping + * the pipeline cache working, by using the environment variable + * MESA_GLSL_CACHE_DISABLE. In that case the calls to disk_cache_put/get + * will not do anything. + */ + if (disk_cache && device->instance->pipeline_cache_enabled) { + cache_key cache_key; + disk_cache_compute_key(disk_cache, sha1_key, 20, cache_key); + + size_t buffer_size; + uint8_t *buffer = disk_cache_get(disk_cache, cache_key, &buffer_size); + if (buffer) { + struct blob_reader blob; + struct v3dv_pipeline_shared_data *shared_data; + + if (debug_cache) + fprintf(stderr, "\ton-disk-cache hit\n"); + + blob_reader_init(&blob, buffer, buffer_size); + shared_data = v3dv_pipeline_shared_data_create_from_blob(cache, &blob); + free(buffer); + + if (shared_data) { + if (cache) + pipeline_cache_upload_shared_data(cache, shared_data, true); + return shared_data; + } + } else { + if (debug_cache) + fprintf(stderr, "\ton-disk-cache miss\n"); + } + } +#endif + return NULL; } @@ -338,11 +389,13 @@ v3dv_pipeline_shared_data_new(struct v3dv_pipeline_cache *cache, return new_entry; } -/* Uploads all the "cacheable" or shared data from the pipeline */ -void -v3dv_pipeline_cache_upload_pipeline(struct v3dv_pipeline *pipeline, - struct v3dv_pipeline_cache *cache) +static void +pipeline_cache_upload_shared_data(struct v3dv_pipeline_cache *cache, + struct v3dv_pipeline_shared_data *shared_data, + bool from_disk_cache) { + assert(shared_data); + if (!cache || !cache->cache) return; @@ -351,28 +404,65 @@ v3dv_pipeline_cache_upload_pipeline(struct v3dv_pipeline *pipeline, pthread_mutex_lock(&cache->mutex); struct hash_entry *entry = - _mesa_hash_table_search(cache->cache, pipeline->shared_data->sha1_key); + _mesa_hash_table_search(cache->cache, shared_data->sha1_key); if (entry) { pthread_mutex_unlock(&cache->mutex); return; } - v3dv_pipeline_shared_data_ref(pipeline->shared_data); - _mesa_hash_table_insert(cache->cache, pipeline->shared_data->sha1_key, - pipeline->shared_data); + v3dv_pipeline_shared_data_ref(shared_data); + _mesa_hash_table_insert(cache->cache, shared_data->sha1_key, shared_data); cache->stats.count++; if (debug_cache) { char sha1buf[41]; - _mesa_sha1_format(sha1buf, pipeline->shared_data->sha1_key); + _mesa_sha1_format(sha1buf, shared_data->sha1_key); fprintf(stderr, "pipeline cache %p, new cache entry with sha1 key %s:%p\n\n", - cache, sha1buf, pipeline->shared_data); + cache, sha1buf, shared_data); if (dump_stats) cache_dump_stats(cache); } pthread_mutex_unlock(&cache->mutex); + +#ifdef ENABLE_SHADER_CACHE + /* If we are being called from a on-disk-cache hit, we can skip writing to + * the disk cache + */ + if (from_disk_cache) + return; + + struct v3dv_device *device = cache->device; + struct disk_cache *disk_cache = device->pdevice->disk_cache; + if (disk_cache) { + struct blob binary; + blob_init(&binary); + if (v3dv_pipeline_shared_data_write_to_blob(shared_data, &binary)) { + cache_key cache_key; + disk_cache_compute_key(disk_cache, shared_data->sha1_key, 20, cache_key); + + disk_cache_put(disk_cache, cache_key, binary.data, binary.size, NULL); + if (debug_cache) { + char sha1buf[41]; + _mesa_sha1_format(sha1buf, shared_data->sha1_key); + + fprintf(stderr, "on-disk-cache, new cache entry with sha1 key %s:%p\n\n", + sha1buf, shared_data); + } + } + + blob_finish(&binary); + } +#endif +} + +/* Uploads all the "cacheable" or shared data from the pipeline */ +void +v3dv_pipeline_cache_upload_pipeline(struct v3dv_pipeline *pipeline, + struct v3dv_pipeline_cache *cache) +{ + pipeline_cache_upload_shared_data(cache, pipeline->shared_data, false); } static struct serialized_nir* diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h index 6266f5e3f52..334d7aa1f2b 100644 --- a/src/broadcom/vulkan/v3dv_private.h +++ b/src/broadcom/vulkan/v3dv_private.h @@ -131,10 +131,13 @@ struct v3dv_physical_device { int32_t display_fd; int32_t master_fd; + uint8_t driver_build_sha1[20]; uint8_t pipeline_cache_uuid[VK_UUID_SIZE]; uint8_t device_uuid[VK_UUID_SIZE]; uint8_t driver_uuid[VK_UUID_SIZE]; + struct disk_cache *disk_cache; + mtx_t mutex; struct wsi_device wsi_device;