From 97906a6d4e0d83ff8f3ced35260cbeb47facbfa6 Mon Sep 17 00:00:00 2001 From: Dipshet <264011288+Dipshet@users.noreply.github.com> Date: Tue, 14 Jul 2026 20:23:27 +0200 Subject: [PATCH] Shader disk cache: fix mission-start pipeline-compile Xenia's pipeline disk cache (record + pre-create at launch) was built but never triggered, so pipelines compiled on-demand mid-gameplay every run. Wire InitializeShaderStorage after module launch: pre-create recorded pipelines during load, record new ones. New cvar use_shader_disk_cache (default on); cache at ./cache/shaders/. --- .../rexglue-sdk/src/native/ui/rex_app.cpp | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/thirdparty/rexglue-sdk/src/native/ui/rex_app.cpp b/thirdparty/rexglue-sdk/src/native/ui/rex_app.cpp index cab8a82c..46acee0a 100644 --- a/thirdparty/rexglue-sdk/src/native/ui/rex_app.cpp +++ b/thirdparty/rexglue-sdk/src/native/ui/rex_app.cpp @@ -43,6 +43,13 @@ REXCVAR_DEFINE_STRING(user_data_root, "", "Runtime", "Override user data path"); REXCVAR_DEFINE_STRING(update_data_root, "", "Runtime", "Override update data path"); +REXCVAR_DEFINE_BOOL(use_shader_disk_cache, true, "GPU", + "Pre-compile the game's GPU pipelines from a persistent on-disk cache at " + "launch (during load) and record new ones, so pipelines do not compile " + "on-demand mid-gameplay - the first-encounter stutter (e.g. at mission " + "start). First run of a scene records the pipelines; later runs load them. " + "Cache lives in ./cache/shaders/."); + namespace rex { // --- ReXApp --- @@ -246,6 +253,29 @@ bool ReXApp::OnInitialize() { return; } + // Wire up the GPU pipeline disk cache. The backend has the whole shader + // storage system (record + pre-create), but nothing triggers it otherwise, + // so every run compiles pipelines on demand during gameplay - the + // first-encounter stutter (mission start). Init here, now that the title is + // loaded (title_id known) and the GPU is set up: blocking, so previously + // recorded pipelines are pre-created during the initial load rather than + // mid-play, and new ones are recorded for next time. + if (REXCVAR_GET(use_shader_disk_cache) && runtime_->graphics_system() && + runtime_->kernel_state()) { + uint32_t shader_cache_title_id = runtime_->kernel_state()->title_id(); + if (shader_cache_title_id != 0) { + std::filesystem::path cache_root = std::filesystem::current_path() / "cache"; + REXLOG_INFO("Shader disk cache: initializing for title {:08X} at {}", + shader_cache_title_id, rex::path_to_utf8(cache_root)); + // graphics_system() returns the IGraphicsSystem interface; InitializeShaderStorage + // lives on the concrete GraphicsSystem (always a rex::graphics::GraphicsSystem here). + static_cast(runtime_->graphics_system()) + ->InitializeShaderStorage(cache_root, shader_cache_title_id, true); + } else { + REXLOG_WARN("Shader disk cache: title_id unavailable, skipping"); + } + } + module_thread_ = std::thread([this, main_thread = std::move(main_thread)]() mutable { main_thread->Wait(0, 0, 0, nullptr); REXLOG_INFO("Execution complete");