mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-03-26 18:22:55 -07:00
better performance
This commit is contained in:
@@ -43,7 +43,11 @@ android {
|
||||
"-DXEMU_ANDROID_BUILD_ID=3",
|
||||
"-DXEMU_ENABLE_XISO_CONVERTER=ON",
|
||||
"-DCMAKE_C_FLAGS_DEBUG=-O2 -g0",
|
||||
"-DCMAKE_CXX_FLAGS_DEBUG=-O2 -g0"
|
||||
"-DCMAKE_CXX_FLAGS_DEBUG=-O2 -g0",
|
||||
"-DCMAKE_C_FLAGS_RELEASE=-O3 -g0 -march=armv8.2-a -ffunction-sections -fdata-sections",
|
||||
"-DCMAKE_CXX_FLAGS_RELEASE=-O3 -g0 -march=armv8.2-a -ffunction-sections -fdata-sections",
|
||||
"-DCMAKE_EXE_LINKER_FLAGS_RELEASE=-Wl,--gc-sections",
|
||||
"-DCMAKE_SHARED_LINKER_FLAGS_RELEASE=-Wl,--gc-sections"
|
||||
)
|
||||
cppFlags += listOf("-std=c++17", "-fexceptions", "-frtti")
|
||||
}
|
||||
|
||||
@@ -844,6 +844,7 @@ target_compile_definitions(xemu_core PRIVATE
|
||||
|
||||
target_compile_options(xemu_core PRIVATE -g0
|
||||
$<$<OR:$<CONFIG:Release>,$<CONFIG:RelWithDebInfo>,$<CONFIG:MinSizeRel>>:-UNDEBUG>
|
||||
$<$<CONFIG:Release>:-O3 -march=armv8.2-a -ffunction-sections -fdata-sections>
|
||||
)
|
||||
|
||||
target_include_directories(xemu_core PRIVATE
|
||||
@@ -913,6 +914,7 @@ endif()
|
||||
|
||||
target_compile_options(xemu PRIVATE -fexceptions -frtti -g0
|
||||
$<$<OR:$<CONFIG:Release>,$<CONFIG:RelWithDebInfo>,$<CONFIG:MinSizeRel>>:-UNDEBUG>
|
||||
$<$<CONFIG:Release>:-O3 -march=armv8.2-a -ffunction-sections -fdata-sections>
|
||||
)
|
||||
|
||||
target_include_directories(xemu PRIVATE
|
||||
|
||||
@@ -22,6 +22,10 @@
|
||||
#include "renderer.h"
|
||||
#include "hw/xbox/nv2a/pgraph/prim_rewrite.h"
|
||||
#include <math.h>
|
||||
#ifdef __ANDROID__
|
||||
#include <SDL.h>
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
void pgraph_vk_draw_begin(NV2AState *d)
|
||||
{
|
||||
@@ -99,6 +103,22 @@ static bool pipeline_cache_entry_compare(Lru *lru, LruNode *node,
|
||||
return memcmp(&snode->key, key, sizeof(PipelineKey));
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
static char *get_pipeline_cache_path(PGRAPHVkState *r)
|
||||
{
|
||||
char *pref_path = SDL_GetPrefPath("xemu", "xemu");
|
||||
if (!pref_path) {
|
||||
return NULL;
|
||||
}
|
||||
char *path = g_strdup_printf("%svk_pipeline_cache_%08x_%08x.bin",
|
||||
pref_path,
|
||||
r->device_props.deviceID,
|
||||
r->device_props.driverVersion);
|
||||
SDL_free(pref_path);
|
||||
return path;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void init_pipeline_cache(PGRAPHState *pg)
|
||||
{
|
||||
PGRAPHVkState *r = pg->vk_renderer_state;
|
||||
@@ -110,9 +130,33 @@ static void init_pipeline_cache(PGRAPHState *pg)
|
||||
.pInitialData = NULL,
|
||||
.pNext = NULL,
|
||||
};
|
||||
|
||||
#ifdef __ANDROID__
|
||||
g_autofree char *cache_path = get_pipeline_cache_path(r);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
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 =
|
||||
@@ -135,6 +179,34 @@ static void finalize_pipeline_cache(PGRAPHState *pg)
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -498,15 +498,14 @@ void pgraph_vk_wait_for_surface_download(SurfaceBinding *surface)
|
||||
NV2AState *d = g_nv2a;
|
||||
bool require_download = qatomic_read(&surface->draw_dirty);
|
||||
|
||||
#ifdef __ANDROID__
|
||||
/*
|
||||
* Android Vulkan currently presents through the CPU/VGA fallback path.
|
||||
* Force framebuffer surface download so fallback upload sees fresh pixels.
|
||||
* Android presents through the CPU/VGA fallback path (no external memory
|
||||
* interop). We rely on draw_dirty to gate downloads: it is set atomically
|
||||
* whenever the Vulkan renderer draws to this surface and cleared after each
|
||||
* successful download. Skipping the download when draw_dirty is false
|
||||
* avoids a GPU stall on frames where the Xbox GPU has not redrawn the
|
||||
* framebuffer (static screens, menus, load screens, etc.).
|
||||
*/
|
||||
if (!d->pgraph.vk_renderer_state->display.use_external_memory) {
|
||||
require_download = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (require_download) {
|
||||
qemu_mutex_lock(&d->pfifo.lock);
|
||||
|
||||
@@ -1381,7 +1381,7 @@ void xemu_android_display_loop(void)
|
||||
sdl2_poll_events(&sdl2_console[0]);
|
||||
bql_unlock();
|
||||
qemu_mutex_unlock_main_loop();
|
||||
SDL_Delay(16);
|
||||
SDL_Delay(100);
|
||||
continue;
|
||||
}
|
||||
sdl2_gl_refresh(&sdl2_console[0].dcl);
|
||||
@@ -1570,7 +1570,7 @@ void sdl2_gl_refresh(DisplayChangeListener *dcl)
|
||||
sdl2_poll_events(scon);
|
||||
bql_unlock();
|
||||
qemu_mutex_unlock_main_loop();
|
||||
SDL_Delay(16);
|
||||
SDL_Delay(100);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -1776,7 +1776,11 @@ void sdl2_gl_refresh(DisplayChangeListener *dcl)
|
||||
bql_unlock();
|
||||
qemu_mutex_unlock_main_loop();
|
||||
|
||||
#ifdef __ANDROID__
|
||||
glFlush();
|
||||
#else
|
||||
glFinish();
|
||||
#endif
|
||||
nv2a_release_framebuffer_surface();
|
||||
#ifdef __ANDROID__
|
||||
android_log_gl_error("refresh-finish");
|
||||
@@ -1807,7 +1811,9 @@ void sdl2_gl_refresh(DisplayChangeListener *dcl)
|
||||
int64_t spin_acc = 0;
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifdef __ANDROID__
|
||||
const int64_t sleep_threshold = 500000; // 0.5ms — Android CFS scheduler jitter is ~0.2ms
|
||||
#elif !defined(_WIN32)
|
||||
const int64_t sleep_threshold = 2000000;
|
||||
#else
|
||||
const int64_t sleep_threshold = 250000;
|
||||
|
||||
Reference in New Issue
Block a user