zink: add a disk cache for pipeline objects

this writes the pipeline cache to disk on shutdown

ideally we'd rather write this incrementally any time we make a new pipeline,
but that ends up breaking the disk cache infrastructure since we're always writing
to the same file, so this is the best we can do for now

Reviewed-by: Dave Airlie <airlied@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9094>
This commit is contained in:
Mike Blumenkrantz 2020-10-06 11:42:27 -04:00 committed by Marge Bot
parent eb3cb170fc
commit c4cc3d915b
2 changed files with 51 additions and 0 deletions

View File

@ -93,6 +93,40 @@ get_video_mem(struct zink_screen *screen)
return (int)(size >> 20);
}
static void
disk_cache_init(struct zink_screen *screen)
{
#ifdef ENABLE_SHADER_CACHE
static char buf[1000];
snprintf(buf, sizeof(buf), "zink_%x04x", screen->info.props.vendorID);
screen->disk_cache = disk_cache_create(buf, screen->info.props.deviceName, 0);
if (screen->disk_cache)
disk_cache_compute_key(screen->disk_cache, buf, strlen(buf), screen->disk_cache_key);
#endif
}
void
zink_screen_update_pipeline_cache(struct zink_screen *screen)
{
size_t size = 0;
if (!screen->disk_cache)
return;
if (vkGetPipelineCacheData(screen->dev, screen->pipeline_cache, &size, NULL) != VK_SUCCESS)
return;
if (screen->pipeline_cache_size == size)
return;
void *data = malloc(size);
if (!data)
return;
if (vkGetPipelineCacheData(screen->dev, screen->pipeline_cache, &size, data) == VK_SUCCESS) {
screen->pipeline_cache_size = size;
disk_cache_put(screen->disk_cache, screen->disk_cache_key, data, size, NULL);
}
free(data);
}
static int
zink_get_compute_param(struct pipe_screen *pscreen, enum pipe_shader_ir ir_type,
enum pipe_compute_cap param, void *ret)
@ -772,6 +806,10 @@ zink_destroy_screen(struct pipe_screen *pscreen)
}
u_transfer_helper_destroy(pscreen->transfer_helper);
zink_screen_update_pipeline_cache(screen);
if (screen->disk_cache)
disk_cache_wait_for_idle(screen->disk_cache);
disk_cache_destroy(screen->disk_cache);
vkDestroyPipelineCache(screen->dev, screen->pipeline_cache, NULL);
vkDestroyDevice(screen->dev, NULL);
@ -1230,6 +1268,7 @@ zink_internal_create_screen(const struct pipe_screen_config *config)
zink_screen_fence_init(&screen->base);
zink_screen_init_compiler(screen);
disk_cache_init(screen);
VkPipelineCacheCreateInfo pcci;
pcci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
@ -1238,7 +1277,12 @@ zink_internal_create_screen(const struct pipe_screen_config *config)
pcci.flags = screen->info.have_EXT_pipeline_creation_cache_control ? VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT : 0;
pcci.initialDataSize = 0;
pcci.pInitialData = NULL;
if (screen->disk_cache) {
pcci.pInitialData = disk_cache_get(screen->disk_cache, screen->disk_cache_key, &screen->pipeline_cache_size);
pcci.initialDataSize = screen->pipeline_cache_size;
}
vkCreatePipelineCache(screen->dev, &pcci, NULL, &screen->pipeline_cache);
free((void*)pcci.pInitialData);
slab_create_parent(&screen->transfer_pool, sizeof(struct zink_transfer), 16);

View File

@ -30,6 +30,7 @@
#include "pipe/p_screen.h"
#include "util/slab.h"
#include "compiler/nir/nir.h"
#include "util/disk_cache.h"
#include <vulkan/vulkan.h>
@ -52,6 +53,9 @@ struct zink_screen {
struct slab_parent_pool transfer_pool;
VkPipelineCache pipeline_cache;
size_t pipeline_cache_size;
struct disk_cache *disk_cache;
cache_key disk_cache_key;
unsigned shader_id;
@ -143,4 +147,7 @@ zink_is_depth_format_supported(struct zink_screen *screen, VkFormat format);
#define GET_PROC_ADDR_INSTANCE_LOCAL(instance, x) PFN_vk##x vk_##x = (PFN_vk##x)vkGetInstanceProcAddr(instance, "vk"#x)
void
zink_screen_update_pipeline_cache(struct zink_screen *screen);
#endif