From fa964802d9cf9739da9bc062f62992a1bb09922b Mon Sep 17 00:00:00 2001 From: The412Banner Date: Wed, 23 Sep 2026 22:35:28 -0400 Subject: [PATCH] PS3: one shader cache, no interpreter precompile - A program from the rail draws with the desktop's Linux driver instead of the Steam session's. The driver's shader cache is keyed on its build, so with two drivers an emulator compiled everything once per way of starting it; seen on device: desktop on the imported Turnip 26.3.0, rail on the runtime's own. - RPCS3's default shader mode builds 6650 interpreter pipelines every boot. bannerlator-pad-defaults starts a new install on Async Recompiler (multi-threaded) and moves an existing one still on the default once; a marker leaves any later choice in RPCS3's settings alone. Enum strings from rpcs3/Emu/system_config_types.cpp. --- .../launcher/session/SessionService.kt | 7 +++- .../usr/local/bin/bannerlator-pad-defaults | 35 +++++++++++++++++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/droiddeck/launcher/session/SessionService.kt b/app/src/main/java/com/droiddeck/launcher/session/SessionService.kt index 0cfc3dce5..830cbe71b 100644 --- a/app/src/main/java/com/droiddeck/launcher/session/SessionService.kt +++ b/app/src/main/java/com/droiddeck/launcher/session/SessionService.kt @@ -280,7 +280,12 @@ class SessionService : Service() { // An imported glibc Turnip for this mode, when the user chose one: the session script checks // the manifest and its library from inside and points the loader at it with VK_DRIVER_FILES, // so the runtime's own driver above stays untouched and is what a bad import falls back to. - val linuxDriverId = SessionPrefs.linuxDriver(this, SessionPrefs.prefMode(SessionState.mode)) + // A program from the rail is one of the desktop's emulators, so it draws with the desktop's + // Linux driver, not the Steam session's: the driver's shader cache is keyed on the driver + // build, and with two drivers every emulator compiled its shaders twice - once per way of + // starting it (RPCS3's 6650 interpreter variants on each first boot). + val driverMode = if (SessionState.mode == MODE_RUN) MODE_DESKTOP else SessionPrefs.prefMode(SessionState.mode) + val linuxDriverId = SessionPrefs.linuxDriver(this, driverMode) LinuxVulkanDriver.resolveIcdPath(this, linuxDriverId) ?.let { guest.add(LinuxVulkanDriver.ENV + "=" + it) } // Turnip's own debug switches, for the runtime's driver and everything on it. The file in diff --git a/tools/linuxfs/overlay/usr/local/bin/bannerlator-pad-defaults b/tools/linuxfs/overlay/usr/local/bin/bannerlator-pad-defaults index 2c016d100..9d410e4e5 100755 --- a/tools/linuxfs/overlay/usr/local/bin/bannerlator-pad-defaults +++ b/tools/linuxfs/overlay/usr/local/bin/bannerlator-pad-defaults @@ -10,14 +10,14 @@ HOME = os.environ.get("HOME", "/root") CONFIG = os.environ.get("XDG_CONFIG_HOME", os.path.join(HOME, ".config")) -def seed(path, text, what): +def seed(path, text, what, done="Player 1 on the controller"): if os.path.exists(path): return False os.makedirs(os.path.dirname(path), exist_ok=True) with open(path + ".tmp", "w", encoding="utf-8") as f: f.write(text) os.replace(path + ".tmp", path) - print(f"bannerlator-pad-defaults: {what}: Player 1 on the controller ({path})") + print(f"bannerlator-pad-defaults: {what}: {done} ({path})") return True @@ -68,6 +68,37 @@ RPCS3_PLAYER1 = """Player 1 Input: def rpcs3(): seed(os.path.join(CONFIG, "rpcs3/input_configs/global/Default.yml"), RPCS3_PLAYER1, "RPCS3") + rpcs3_shader_mode() + + +# RPCS3's default shader mode (Async Recompiler with Shader Interpreter) builds 6650 interpreter +# pipelines at the start of every boot, minutes on an Adreno. The async recompiler compiles only +# what a game draws, in the background, once. A new install starts with it (a config.yml that +# holds only this is merged over RPCS3's defaults); an existing one still on the default is moved +# once, and a marker keeps any later choice the user makes in RPCS3's own settings. +RPCS3_INTERPRETER = "Async Recompiler with Shader Interpreter" +RPCS3_RECOMPILER = "Async Recompiler (multi-threaded)" # the GUI says "Async Shader Recompiler"; this is the value (system_config_types.cpp) + + +def rpcs3_shader_mode(): + d = os.path.join(CONFIG, "rpcs3") + marker = os.path.join(d, ".droiddeck-shader-mode") + if os.path.exists(marker): + return + cfg = os.path.join(d, "config.yml") + if not os.path.isfile(cfg): + if seed(cfg, f"Video:\n Shader Mode: {RPCS3_RECOMPILER}\n", "RPCS3", f"shader mode {RPCS3_RECOMPILER}"): + open(marker, "w").close() + return + with open(cfg, encoding="utf-8", errors="replace") as f: + text = f.read() + if f"Shader Mode: {RPCS3_INTERPRETER}" in text: + text = text.replace(f"Shader Mode: {RPCS3_INTERPRETER}", f"Shader Mode: {RPCS3_RECOMPILER}", 1) + with open(cfg + ".tmp", "w", encoding="utf-8") as f: + f.write(text) + os.replace(cfg + ".tmp", cfg) + print(f"bannerlator-pad-defaults: RPCS3: shader mode {RPCS3_RECOMPILER} ({cfg})") + open(marker, "w").close() # ---- ini helpers (DuckStation and PCSX2 share one ini dialect, keys may repeat) -------------