From 4fc856af98ecee00f07a039b68dd82fb47b4e6da Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Tue, 4 Feb 2025 09:17:16 +0100 Subject: [PATCH] radv: fix caching on-demand meta shaders This switches to disk_cache instead of our own mechanism which only stored meta shaders when the logical was destroyed. Meta shaders are still stored separately from the application shaders because they are common to all applications on a given GPU/Mesa version. The default cache is 32MiB which should be large enough. This fixes massive stuttering in FF7 Rebirth but all apps are technically affected. Signed-off-by: Samuel Pitoiset Part-of: --- src/amd/vulkan/meta/radv_meta.c | 132 ++------------------------ src/amd/vulkan/radv_physical_device.c | 4 + src/amd/vulkan/radv_physical_device.h | 2 + 3 files changed, 12 insertions(+), 126 deletions(-) diff --git a/src/amd/vulkan/meta/radv_meta.c b/src/amd/vulkan/meta/radv_meta.c index c4c37caaa86..a19a7421d1a 100644 --- a/src/amd/vulkan/meta/radv_meta.c +++ b/src/amd/vulkan/meta/radv_meta.c @@ -13,13 +13,6 @@ #include "vk_pipeline_cache.h" #include "vk_util.h" -#include -#include -#ifndef _WIN32 -#include -#endif -#include - static void radv_suspend_queries(struct radv_meta_saved_state *state, struct radv_cmd_buffer *cmd_buffer) { @@ -292,54 +285,11 @@ meta_free(void *_device, void *data) device->vk.alloc.pfnFree(device->vk.alloc.pUserData, data); } -#ifndef _WIN32 -static bool -radv_builtin_cache_path(char *path) -{ - char *xdg_cache_home = secure_getenv("XDG_CACHE_HOME"); - const char *suffix = "/radv_builtin_shaders"; - const char *suffix2 = "/.cache/radv_builtin_shaders"; - struct passwd pwd, *result; - char path2[PATH_MAX + 1]; /* PATH_MAX is not a real max,but suffices here. */ - int ret; - - if (xdg_cache_home) { - ret = snprintf(path, PATH_MAX + 1, "%s%s%zd", xdg_cache_home, suffix, sizeof(void *) * 8); - return ret > 0 && ret < PATH_MAX + 1; - } - - getpwuid_r(getuid(), &pwd, path2, PATH_MAX - strlen(suffix2), &result); - if (!result) - return false; - - strcpy(path, pwd.pw_dir); - strcat(path, "/.cache"); - if (mkdir(path, 0755) && errno != EEXIST) - return false; - - ret = snprintf(path, PATH_MAX + 1, "%s%s%zd", pwd.pw_dir, suffix2, sizeof(void *) * 8); - return ret > 0 && ret < PATH_MAX + 1; -} -#endif - -static uint32_t -num_cache_entries(VkPipelineCache cache) -{ - struct set *s = vk_pipeline_cache_from_handle(cache)->object_cache; - if (!s) - return 0; - return s->entries; -} - static void -radv_load_meta_pipeline(struct radv_device *device) +radv_init_meta_cache(struct radv_device *device) { -#ifndef _WIN32 - char path[PATH_MAX + 1]; - struct stat st; - void *data = NULL; - int fd = -1; - struct vk_pipeline_cache *cache = NULL; + const struct radv_physical_device *pdev = radv_device_physical(device); + struct vk_pipeline_cache *cache; VkPipelineCacheCreateInfo create_info = { .sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, @@ -347,81 +297,12 @@ radv_load_meta_pipeline(struct radv_device *device) struct vk_pipeline_cache_create_info info = { .pCreateInfo = &create_info, - .skip_disk_cache = true, + .disk_cache = pdev->disk_cache_meta, }; - if (!radv_builtin_cache_path(path)) - goto fail; - - fd = open(path, O_RDONLY); - if (fd < 0) - goto fail; - if (fstat(fd, &st)) - goto fail; - data = malloc(st.st_size); - if (!data) - goto fail; - if (read(fd, data, st.st_size) == -1) - goto fail; - - create_info.initialDataSize = st.st_size; - create_info.pInitialData = data; - -fail: cache = vk_pipeline_cache_create(&device->vk, &info, NULL); - - if (cache) { + if (cache) device->meta_state.cache = vk_pipeline_cache_to_handle(cache); - device->meta_state.initial_cache_entries = num_cache_entries(device->meta_state.cache); - } - - free(data); - if (fd >= 0) - close(fd); -#endif -} - -static void -radv_store_meta_pipeline(struct radv_device *device) -{ -#ifndef _WIN32 - char path[PATH_MAX + 1], path2[PATH_MAX + 7]; - size_t size; - void *data = NULL; - - if (device->meta_state.cache == VK_NULL_HANDLE) - return; - - /* Skip serialization if no entries were added. */ - if (num_cache_entries(device->meta_state.cache) <= device->meta_state.initial_cache_entries) - return; - - if (vk_common_GetPipelineCacheData(radv_device_to_handle(device), device->meta_state.cache, &size, NULL)) - return; - - if (!radv_builtin_cache_path(path)) - return; - - strcpy(path2, path); - strcat(path2, "XXXXXX"); - int fd = mkstemp(path2); // open(path, O_WRONLY | O_CREAT, 0600); - if (fd < 0) - return; - data = malloc(size); - if (!data) - goto fail; - - if (vk_common_GetPipelineCacheData(radv_device_to_handle(device), device->meta_state.cache, &size, data)) - goto fail; - if (write(fd, data, size) == -1) - goto fail; - - rename(path2, path); -fail: - free(data); - close(fd); - unlink(path2); -#endif } VkResult @@ -439,7 +320,7 @@ radv_device_init_meta(struct radv_device *device) .pfnFree = meta_free, }; - radv_load_meta_pipeline(device); + radv_init_meta_cache(device); result = vk_meta_device_init(&device->vk, &device->meta_state.device); if (result != VK_SUCCESS) @@ -488,7 +369,6 @@ radv_device_finish_meta(struct radv_device *device) radv_device_finish_accel_struct_build_state(device); - radv_store_meta_pipeline(device); vk_common_DestroyPipelineCache(radv_device_to_handle(device), device->meta_state.cache, NULL); mtx_destroy(&device->meta_state.mtx); diff --git a/src/amd/vulkan/radv_physical_device.c b/src/amd/vulkan/radv_physical_device.c index 3ad4a29cec7..87609f84827 100644 --- a/src/amd/vulkan/radv_physical_device.c +++ b/src/amd/vulkan/radv_physical_device.c @@ -2253,6 +2253,8 @@ radv_physical_device_try_create(struct radv_instance *instance, drmDevicePtr drm mesa_bytes_to_hex(buf, pdev->cache_uuid, VK_UUID_SIZE); pdev->vk.disk_cache = disk_cache_create(pdev->name, buf, 0); + pdev->disk_cache_meta = disk_cache_create_custom(pdev->name, buf, 0, "radv_builtin_shaders", 1024 * 32 /* 32MiB */); + radv_get_physical_device_properties(pdev); if ((instance->debug_flags & RADV_DEBUG_INFO)) @@ -2298,6 +2300,7 @@ radv_physical_device_try_create(struct radv_instance *instance, drmDevicePtr drm fail_perfcounters: ac_destroy_perfcounters(&pdev->ac_perfcounters); disk_cache_destroy(pdev->vk.disk_cache); + disk_cache_destroy(pdev->disk_cache_meta); fail_wsi: if (pdev->addrlib) ac_addrlib_destroy(pdev->addrlib); @@ -2365,6 +2368,7 @@ radv_physical_device_destroy(struct vk_physical_device *vk_device) ac_addrlib_destroy(pdev->addrlib); pdev->ws->destroy(pdev->ws); disk_cache_destroy(pdev->vk.disk_cache); + disk_cache_destroy(pdev->disk_cache_meta); if (pdev->local_fd != -1) close(pdev->local_fd); if (pdev->master_fd != -1) diff --git a/src/amd/vulkan/radv_physical_device.h b/src/amd/vulkan/radv_physical_device.h index beeb808289b..733c8628d76 100644 --- a/src/amd/vulkan/radv_physical_device.h +++ b/src/amd/vulkan/radv_physical_device.h @@ -80,6 +80,8 @@ struct radv_physical_device { uint8_t device_uuid[VK_UUID_SIZE]; uint8_t cache_uuid[VK_UUID_SIZE]; + struct disk_cache *disk_cache_meta; + struct ac_addrlib *addrlib; int local_fd;