Port hakuX Vulkan pipeline cache save throttling

This commit is contained in:
izzy2lost
2026-04-08 02:34:51 -04:00
parent c59cf41268
commit c622e1ad85
2 changed files with 89 additions and 44 deletions
+88 -44
View File
@@ -19,7 +19,9 @@
#include "qemu/osdep.h"
#include "qemu/fast-hash.h"
#include "qemu/timer.h"
#include "renderer.h"
#include "ui/xemu-settings.h"
#include "hw/xbox/nv2a/pgraph/prim_rewrite.h"
#include <math.h>
#ifdef __aarch64__
@@ -107,6 +109,8 @@ static bool pipeline_cache_entry_compare(Lru *lru, LruNode *node,
}
#ifdef __ANDROID__
#define PIPELINE_CACHE_SAVE_INTERVAL_US (30 * 1000000LL)
static char *get_pipeline_cache_path(PGRAPHVkState *r)
{
char *pref_path = SDL_GetPrefPath("xemu", "xemu");
@@ -120,6 +124,62 @@ static char *get_pipeline_cache_path(PGRAPHVkState *r)
SDL_free(pref_path);
return path;
}
static void save_pipeline_cache_to_disk(PGRAPHVkState *r)
{
g_autofree char *cache_path = get_pipeline_cache_path(r);
size_t data_size = 0;
VkResult res;
if (!cache_path) {
return;
}
res = vkGetPipelineCacheData(r->device, r->vk_pipeline_cache,
&data_size, NULL);
if (res != VK_SUCCESS || data_size == 0) {
return;
}
g_autofree void *data = g_malloc(data_size);
res = vkGetPipelineCacheData(r->device, r->vk_pipeline_cache,
&data_size, data);
if (res != VK_SUCCESS) {
return;
}
GError *err = NULL;
if (g_file_set_contents(cache_path, (const gchar *)data,
(gssize)data_size, &err)) {
__android_log_print(ANDROID_LOG_INFO, "xemu-vk",
"Saved pipeline cache: %zu bytes", data_size);
} else {
__android_log_print(ANDROID_LOG_WARN, "xemu-vk",
"Failed to save pipeline cache");
if (err) {
g_error_free(err);
}
}
}
static void maybe_save_pipeline_cache(PGRAPHVkState *r)
{
int64_t now;
if (!g_config.perf.cache_shaders) {
return;
}
now = qemu_clock_get_us(QEMU_CLOCK_REALTIME);
if (r->pipeline_cache_last_save_us != 0 &&
(now - r->pipeline_cache_last_save_us) <
PIPELINE_CACHE_SAVE_INTERVAL_US) {
return;
}
r->pipeline_cache_last_save_us = now;
save_pipeline_cache_to_disk(r);
}
#endif
static void init_pipeline_cache(PGRAPHState *pg)
@@ -135,19 +195,23 @@ static void init_pipeline_cache(PGRAPHState *pg)
};
#ifdef __ANDROID__
g_autofree char *cache_path = get_pipeline_cache_path(r);
gchar *cache_data = NULL;
g_autofree gchar *cache_data = NULL;
gsize cache_data_size = 0;
if (cache_path) {
GError *err = NULL;
if (g_file_get_contents(cache_path, &cache_data, &cache_data_size, &err)) {
cache_info.initialDataSize = (size_t)cache_data_size;
cache_info.pInitialData = (const void *)cache_data;
__android_log_print(ANDROID_LOG_INFO, "xemu-vk",
"Loaded pipeline cache: %zu bytes", cache_data_size);
} else {
if (err) {
g_error_free(err);
if (g_config.perf.cache_shaders) {
g_autofree char *cache_path = get_pipeline_cache_path(r);
if (cache_path) {
GError *err = NULL;
if (g_file_get_contents(cache_path, &cache_data, &cache_data_size,
&err)) {
cache_info.initialDataSize = (size_t)cache_data_size;
cache_info.pInitialData = (const void *)cache_data;
__android_log_print(ANDROID_LOG_INFO, "xemu-vk",
"Loaded pipeline cache: %zu bytes",
cache_data_size);
} else {
if (err) {
g_error_free(err);
}
}
}
}
@@ -156,10 +220,6 @@ static void init_pipeline_cache(PGRAPHState *pg)
VK_CHECK(vkCreatePipelineCache(r->device, &cache_info, NULL,
&r->vk_pipeline_cache));
#ifdef __ANDROID__
g_free(cache_data);
#endif
const size_t pipeline_cache_size = 2048;
lru_init(&r->pipeline_cache);
r->pipeline_cache_entries =
@@ -178,38 +238,16 @@ static void finalize_pipeline_cache(PGRAPHState *pg)
{
PGRAPHVkState *r = pg->vk_renderer_state;
#ifdef __ANDROID__
if (g_config.perf.cache_shaders) {
save_pipeline_cache_to_disk(r);
}
#endif
lru_flush(&r->pipeline_cache);
g_free(r->pipeline_cache_entries);
r->pipeline_cache_entries = NULL;
#ifdef __ANDROID__
g_autofree char *cache_path = get_pipeline_cache_path(r);
if (cache_path) {
size_t data_size = 0;
VkResult res = vkGetPipelineCacheData(r->device, r->vk_pipeline_cache,
&data_size, NULL);
if (res == VK_SUCCESS && data_size > 0) {
g_autofree void *data = g_malloc(data_size);
res = vkGetPipelineCacheData(r->device, r->vk_pipeline_cache,
&data_size, data);
if (res == VK_SUCCESS) {
GError *err = NULL;
if (g_file_set_contents(cache_path, (const gchar *)data,
(gssize)data_size, &err)) {
__android_log_print(ANDROID_LOG_INFO, "xemu-vk",
"Saved pipeline cache: %zu bytes", data_size);
} else {
__android_log_print(ANDROID_LOG_WARN, "xemu-vk",
"Failed to save pipeline cache");
if (err) {
g_error_free(err);
}
}
}
}
}
#endif
vkDestroyPipelineCache(r->device, r->vk_pipeline_cache, NULL);
}
@@ -661,6 +699,9 @@ static void create_clear_pipeline(PGRAPHState *pg)
r->pipeline_binding = snode;
r->pipeline_binding_changed = true;
#ifdef __ANDROID__
maybe_save_pipeline_cache(r);
#endif
NV2A_VK_DGROUP_END();
}
@@ -1077,6 +1118,9 @@ static void create_pipeline(PGRAPHState *pg)
r->pipeline_binding = snode;
r->pipeline_binding_changed = true;
#ifdef __ANDROID__
maybe_save_pipeline_cache(r);
#endif
NV2A_VK_DGROUP_END();
}
+1
View File
@@ -364,6 +364,7 @@ typedef struct PGRAPHVkState {
PipelineBinding *pipeline_cache_entries;
PipelineBinding *pipeline_binding;
bool pipeline_binding_changed;
int64_t pipeline_cache_last_save_us;
VkDescriptorPool descriptor_pool;
VkDescriptorSetLayout descriptor_set_layout;