mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-01 14:00:16 +01:00
anv: Add support for the on-disk shader cache
The Vulkan API provides a mechanism for applications to cache their own shaders and manage on-disk pipeline caching themselves. Generally, this is what I would recommend to application developers and I've resisted implementing driver-side transparent caching in the Vulkan driver for a long time. However, not all applications do this and, for some use-cases, it's just not practical. Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com>
This commit is contained in:
parent
e0f7a3aa5b
commit
afa8f58921
3 changed files with 126 additions and 11 deletions
|
|
@ -35,6 +35,7 @@
|
|||
#include "util/strtod.h"
|
||||
#include "util/debug.h"
|
||||
#include "util/build_id.h"
|
||||
#include "util/disk_cache.h"
|
||||
#include "util/mesa-sha1.h"
|
||||
#include "vk_util.h"
|
||||
#include "common/gen_defines.h"
|
||||
|
|
@ -233,6 +234,8 @@ anv_physical_device_init_uuids(struct anv_physical_device *device)
|
|||
"build-id too short. It needs to be a SHA");
|
||||
}
|
||||
|
||||
memcpy(device->driver_build_sha1, build_id_data(note), 20);
|
||||
|
||||
struct mesa_sha1 sha1_ctx;
|
||||
uint8_t sha1[20];
|
||||
STATIC_ASSERT(VK_UUID_SIZE <= sizeof(sha1));
|
||||
|
|
@ -271,6 +274,35 @@ anv_physical_device_init_uuids(struct anv_physical_device *device)
|
|||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
anv_physical_device_init_disk_cache(struct anv_physical_device *device)
|
||||
{
|
||||
#ifdef ENABLE_SHADER_CACHE
|
||||
char renderer[9];
|
||||
MAYBE_UNUSED int len = snprintf(renderer, sizeof(renderer), "anv_%04x",
|
||||
device->chipset_id);
|
||||
assert(len == sizeof(renderer) - 1);
|
||||
|
||||
char timestamp[41];
|
||||
_mesa_sha1_format(timestamp, device->driver_build_sha1);
|
||||
|
||||
device->disk_cache = disk_cache_create(renderer, timestamp, 0);
|
||||
#else
|
||||
device->disk_cache = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
anv_physical_device_free_disk_cache(struct anv_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 VkResult
|
||||
anv_physical_device_init(struct anv_physical_device *device,
|
||||
struct anv_instance *instance,
|
||||
|
|
@ -442,6 +474,8 @@ anv_physical_device_init(struct anv_physical_device *device,
|
|||
if (result != VK_SUCCESS)
|
||||
goto fail;
|
||||
|
||||
anv_physical_device_init_disk_cache(device);
|
||||
|
||||
if (instance->enabled_extensions.KHR_display) {
|
||||
master_fd = open(primary_path, O_RDWR | O_CLOEXEC);
|
||||
if (master_fd >= 0) {
|
||||
|
|
@ -459,6 +493,7 @@ anv_physical_device_init(struct anv_physical_device *device,
|
|||
result = anv_init_wsi(device);
|
||||
if (result != VK_SUCCESS) {
|
||||
ralloc_free(device->compiler);
|
||||
anv_physical_device_free_disk_cache(device);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
@ -481,6 +516,7 @@ static void
|
|||
anv_physical_device_finish(struct anv_physical_device *device)
|
||||
{
|
||||
anv_finish_wsi(device);
|
||||
anv_physical_device_free_disk_cache(device);
|
||||
ralloc_free(device->compiler);
|
||||
close(device->local_fd);
|
||||
if (device->master_fd >= 0)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
#include "compiler/blob.h"
|
||||
#include "util/hash_table.h"
|
||||
#include "util/debug.h"
|
||||
#include "util/disk_cache.h"
|
||||
#include "util/mesa-sha1.h"
|
||||
#include "anv_private.h"
|
||||
|
||||
struct anv_shader_bin *
|
||||
|
|
@ -280,6 +282,25 @@ anv_pipeline_cache_search(struct anv_pipeline_cache *cache,
|
|||
return shader;
|
||||
}
|
||||
|
||||
static void
|
||||
anv_pipeline_cache_add_shader_bin(struct anv_pipeline_cache *cache,
|
||||
struct anv_shader_bin *bin)
|
||||
{
|
||||
if (!cache->cache)
|
||||
return;
|
||||
|
||||
pthread_mutex_lock(&cache->mutex);
|
||||
|
||||
struct hash_entry *entry = _mesa_hash_table_search(cache->cache, bin->key);
|
||||
if (entry == NULL) {
|
||||
/* Take a reference for the cache */
|
||||
anv_shader_bin_ref(bin);
|
||||
_mesa_hash_table_insert(cache->cache, bin->key, bin);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&cache->mutex);
|
||||
}
|
||||
|
||||
static struct anv_shader_bin *
|
||||
anv_pipeline_cache_add_shader_locked(struct anv_pipeline_cache *cache,
|
||||
const void *key_data, uint32_t key_size,
|
||||
|
|
@ -540,7 +561,38 @@ anv_device_search_for_kernel(struct anv_device *device,
|
|||
struct anv_pipeline_cache *cache,
|
||||
const void *key_data, uint32_t key_size)
|
||||
{
|
||||
return cache ? anv_pipeline_cache_search(cache, key_data, key_size) : NULL;
|
||||
struct anv_shader_bin *bin;
|
||||
|
||||
if (cache) {
|
||||
bin = anv_pipeline_cache_search(cache, key_data, key_size);
|
||||
if (bin)
|
||||
return bin;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SHADER_CACHE
|
||||
struct disk_cache *disk_cache = device->instance->physicalDevice.disk_cache;
|
||||
if (disk_cache) {
|
||||
cache_key cache_key;
|
||||
disk_cache_compute_key(disk_cache, key_data, key_size, cache_key);
|
||||
|
||||
size_t buffer_size;
|
||||
uint8_t *buffer = disk_cache_get(disk_cache, cache_key, &buffer_size);
|
||||
if (buffer) {
|
||||
struct blob_reader blob;
|
||||
blob_reader_init(&blob, buffer, buffer_size);
|
||||
bin = anv_shader_bin_create_from_blob(device, &blob);
|
||||
free(buffer);
|
||||
|
||||
if (bin) {
|
||||
if (cache)
|
||||
anv_pipeline_cache_add_shader_bin(cache, bin);
|
||||
return bin;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct anv_shader_bin *
|
||||
|
|
@ -554,17 +606,41 @@ anv_device_upload_kernel(struct anv_device *device,
|
|||
uint32_t prog_data_size,
|
||||
const struct anv_pipeline_bind_map *bind_map)
|
||||
{
|
||||
struct anv_shader_bin *bin;
|
||||
if (cache) {
|
||||
return anv_pipeline_cache_upload_kernel(cache, key_data, key_size,
|
||||
kernel_data, kernel_size,
|
||||
constant_data, constant_data_size,
|
||||
prog_data, prog_data_size,
|
||||
bind_map);
|
||||
bin = anv_pipeline_cache_upload_kernel(cache, key_data, key_size,
|
||||
kernel_data, kernel_size,
|
||||
constant_data, constant_data_size,
|
||||
prog_data, prog_data_size,
|
||||
bind_map);
|
||||
} else {
|
||||
return anv_shader_bin_create(device, key_data, key_size,
|
||||
kernel_data, kernel_size,
|
||||
constant_data, constant_data_size,
|
||||
prog_data, prog_data_size,
|
||||
prog_data->param, bind_map);
|
||||
bin = anv_shader_bin_create(device, key_data, key_size,
|
||||
kernel_data, kernel_size,
|
||||
constant_data, constant_data_size,
|
||||
prog_data, prog_data_size,
|
||||
prog_data->param, bind_map);
|
||||
}
|
||||
|
||||
if (bin == NULL)
|
||||
return NULL;
|
||||
|
||||
#ifdef ENABLE_SHADER_CACHE
|
||||
struct disk_cache *disk_cache = device->instance->physicalDevice.disk_cache;
|
||||
if (disk_cache) {
|
||||
struct blob binary;
|
||||
blob_init(&binary);
|
||||
anv_shader_bin_write_to_blob(bin, &binary);
|
||||
|
||||
if (!binary.out_of_memory) {
|
||||
cache_key cache_key;
|
||||
disk_cache_compute_key(disk_cache, key_data, key_size, cache_key);
|
||||
|
||||
disk_cache_put(disk_cache, cache_key, binary.data, binary.size, NULL);
|
||||
}
|
||||
|
||||
blob_finish(&binary);
|
||||
}
|
||||
#endif
|
||||
|
||||
return bin;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -870,10 +870,13 @@ struct anv_physical_device {
|
|||
struct anv_memory_heap heaps[VK_MAX_MEMORY_HEAPS];
|
||||
} memory;
|
||||
|
||||
uint8_t driver_build_sha1[20];
|
||||
uint8_t pipeline_cache_uuid[VK_UUID_SIZE];
|
||||
uint8_t driver_uuid[VK_UUID_SIZE];
|
||||
uint8_t device_uuid[VK_UUID_SIZE];
|
||||
|
||||
struct disk_cache * disk_cache;
|
||||
|
||||
struct wsi_device wsi_device;
|
||||
int local_fd;
|
||||
int master_fd;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue