From 8e8e13de302d05449be6a0f821aac75bc57eca36 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 22 Aug 2026 16:42:45 +1000 Subject: [PATCH] System: Reserve state memory for texture cache when enabled --- src/core/fullscreenui_settings.cpp | 3 ++- src/core/system.cpp | 23 +++++++++++-------- src/core/system.h | 6 ++--- .../emulationsettingswidget.cpp | 3 ++- src/duckstation-regtest/regtest_host.cpp | 3 ++- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/core/fullscreenui_settings.cpp b/src/core/fullscreenui_settings.cpp index 134adba16..518bd9479 100644 --- a/src/core/fullscreenui_settings.cpp +++ b/src/core/fullscreenui_settings.cpp @@ -3646,6 +3646,7 @@ void FullscreenUI::DrawEmulationSettingsPage() const u32 multisamples = GetEffectiveUIntSetting(bsi, "GPU", "Multisamples", 1); const bool use_software_renderer = GetEffectiveBoolSetting(bsi, "GPU", "UseSoftwareRendererForMemoryStates", false); const bool enable_8mb_ram = GetEffectiveBoolSetting(bsi, "Console", "Enable8MBRAM", false); + const bool enable_texture_cache = GetEffectiveBoolSetting(bsi, "GPU", "EnableTextureCache", false); const float rewind_frequency = GetEffectiveFloatSetting(bsi, "Main", "RewindFrequency", 10.0f); const s32 rewind_save_slots = GetEffectiveIntSetting(bsi, "Main", "RewindSaveSlots", 10); const float duration = @@ -3654,7 +3655,7 @@ void FullscreenUI::DrawEmulationSettingsPage() u64 ram_usage, vram_usage; System::CalculateRewindMemoryUsage(rewind_save_slots, resolution_scale, multisamples, use_software_renderer, - enable_8mb_ram, &ram_usage, &vram_usage); + enable_8mb_ram, enable_texture_cache, &ram_usage, &vram_usage); if (vram_usage > 0) { rewind_summary.format( diff --git a/src/core/system.cpp b/src/core/system.cpp index 1d6039dd2..165af0e84 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -2610,7 +2610,8 @@ bool System::AllocateMemoryStates(size_t state_count, bool recycle_old_textures) // Allocate CPU buffers. // TODO: Maybe look at host memory limits here... - const size_t size = GetMaxMemorySaveStateSize(g_settings.cpu_enable_8mb_ram, CPU::PGXP::ShouldSavePGXPState()); + const size_t size = GetMaxMemorySaveStateSize(g_settings.cpu_enable_8mb_ram, CPU::PGXP::ShouldSavePGXPState(), + g_settings.gpu_texture_cache); for (MemorySaveState& mss : s_state.memory_save_states) { mss.state_size = 0; @@ -2893,17 +2894,19 @@ bool System::SetBootMode(BootMode new_boot_mode, DiscRegion disc_region, bool* m return true; } -size_t System::GetMaxSaveStateSize(bool enable_8mb_ram) +size_t System::GetMaxSaveStateSize(bool enable_8mb_ram, bool enable_texture_cache) { // 5 megabytes is sufficient for now, at the moment they're around 4.3MB, or 10.3MB with 8MB RAM enabled. static constexpr u32 MAX_2MB_SAVE_STATE_SIZE = 5 * 1024 * 1024; static constexpr u32 MAX_8MB_SAVE_STATE_SIZE = 11 * 1024 * 1024; - return enable_8mb_ram ? MAX_8MB_SAVE_STATE_SIZE : MAX_2MB_SAVE_STATE_SIZE; + return (enable_8mb_ram ? MAX_8MB_SAVE_STATE_SIZE : MAX_2MB_SAVE_STATE_SIZE) + + (enable_texture_cache ? GPUTextureCache::MAX_SAVE_STATE_DATA_SIZE : 0); } -size_t System::GetMaxMemorySaveStateSize(bool enable_8mb_ram, bool pgxp) +size_t System::GetMaxMemorySaveStateSize(bool enable_8mb_ram, bool pgxp, bool enable_texture_cache) { - return GetMaxSaveStateSize(enable_8mb_ram) + (pgxp ? CPU::PGXP::GetStateSize(enable_8mb_ram) : 0); + return GetMaxSaveStateSize(enable_8mb_ram, enable_texture_cache) + + (pgxp ? CPU::PGXP::GetStateSize(enable_8mb_ram) : 0); } std::string System::GetMediaPathFromSaveState(const char* path) @@ -3432,7 +3435,7 @@ bool System::SaveStateToBuffer(SaveStateBuffer* buffer, Error* error, u32 screen // write data if (buffer->state_data.empty()) - buffer->state_data.resize(GetMaxSaveStateSize(g_bus.ram_size > Bus::RAM_2MB_SIZE)); + buffer->state_data.resize(GetMaxSaveStateSize(g_bus.ram_size > Bus::RAM_2MB_SIZE, g_settings.gpu_texture_cache)); return SaveStateDataToBuffer(buffer->state_data, &buffer->state_size, error); } @@ -5125,11 +5128,11 @@ void System::LogUnsafeSettingsToConsole(const SmallStringBase& messages) } void System::CalculateRewindMemoryUsage(u32 num_saves, u32 resolution_scale, u32 multisamples, - bool use_software_renderer, bool enable_8mb_ram, u64* ram_usage, - u64* vram_usage) + bool use_software_renderer, bool enable_8mb_ram, bool gpu_texture_cache, + u64* ram_usage, u64* vram_usage) { const u32 real_resolution_scale = std::max(resolution_scale, 1u); - *ram_usage = GetMaxMemorySaveStateSize(enable_8mb_ram, false) * static_cast(num_saves); + *ram_usage = GetMaxMemorySaveStateSize(enable_8mb_ram, false, gpu_texture_cache) * static_cast(num_saves); *vram_usage = use_software_renderer ? 0 : ((static_cast(VRAM_WIDTH * real_resolution_scale) * static_cast(VRAM_HEIGHT * real_resolution_scale) * 4) * @@ -5159,7 +5162,7 @@ void System::UpdateMemorySaveStateSettings() u64 ram_usage, vram_usage; CalculateRewindMemoryUsage(g_settings.rewind_save_slots, g_settings.gpu_resolution_scale, g_settings.gpu_multisamples, g_settings.gpu_use_software_renderer_for_memory_states, - g_settings.cpu_enable_8mb_ram, &ram_usage, &vram_usage); + g_settings.cpu_enable_8mb_ram, g_settings.gpu_texture_cache, &ram_usage, &vram_usage); INFO_LOG("Rewind is enabled, saving every {} frames, with {} slots and {}MB RAM and {}MB VRAM usage", std::max(s_state.rewind_save_frequency, 1), g_settings.rewind_save_slots, ram_usage / 1048576, vram_usage / 1048576); diff --git a/src/core/system.h b/src/core/system.h index 8f9d783d5..bd90ca04b 100644 --- a/src/core/system.h +++ b/src/core/system.h @@ -293,10 +293,10 @@ void ResetSystem(); bool CanPauseSystem(bool display_message); /// Returns the maximum size of a save state, considering the current configuration. -size_t GetMaxSaveStateSize(bool enable_8mb_ram); +size_t GetMaxSaveStateSize(bool enable_8mb_ram, bool enable_texture_cache); /// Returns the maximum size of a save state that is not expected to be serialized to file. -size_t GetMaxMemorySaveStateSize(bool enable_8mb_ram, bool pgxp); +size_t GetMaxMemorySaveStateSize(bool enable_8mb_ram, bool pgxp, bool enable_texture_cache); /// Loads state from the specified path. std::optional LoadState(const char* path, Error* error, bool save_undo_state, bool force_update_display); @@ -474,7 +474,7 @@ std::string GetImageForLoadingScreen(const std::string& game_path, bool fallback // Memory Save States (Rewind and Runahead) ////////////////////////////////////////////////////////////////////////// void CalculateRewindMemoryUsage(u32 num_saves, u32 resolution_scale, u32 multisamples, bool use_software_renderer, - bool enable_8mb_ram, u64* ram_usage, u64* vram_usage); + bool enable_8mb_ram, bool gpu_texture_cache, u64* ram_usage, u64* vram_usage); void ClearMemorySaveStates(bool reallocate_resources, bool recycle_textures); void SetRunaheadReplayFlag(bool is_analog_input); diff --git a/src/duckstation-qt/emulationsettingswidget.cpp b/src/duckstation-qt/emulationsettingswidget.cpp index d486f9b70..d1598bb49 100644 --- a/src/duckstation-qt/emulationsettingswidget.cpp +++ b/src/duckstation-qt/emulationsettingswidget.cpp @@ -273,6 +273,7 @@ void EmulationSettingsWidget::updateRewind() const bool use_software_renderer = m_dialog->getEffectiveBoolValue("GPU", "UseSoftwareRendererForMemoryStates", false); const bool enable_8mb_ram = m_dialog->getEffectiveBoolValue("Console", "Enable8MBRAM", false); + const bool enable_texture_cache = m_dialog->getEffectiveBoolValue("GPU", "EnableTextureCache", false); const u32 frames = static_cast(m_ui.rewindSaveSlots->value()); const float frequency = static_cast(m_ui.rewindSaveFrequency->value()); const float duration = @@ -280,7 +281,7 @@ void EmulationSettingsWidget::updateRewind() u64 ram_usage, vram_usage; System::CalculateRewindMemoryUsage(frames, resolution_scale, multisamples, use_software_renderer, enable_8mb_ram, - &ram_usage, &vram_usage); + enable_texture_cache, &ram_usage, &vram_usage); m_ui.rewindSummary->setText( (vram_usage > 0) ? diff --git a/src/duckstation-regtest/regtest_host.cpp b/src/duckstation-regtest/regtest_host.cpp index e74666e63..61bc6b5f0 100644 --- a/src/duckstation-regtest/regtest_host.cpp +++ b/src/duckstation-regtest/regtest_host.cpp @@ -683,7 +683,8 @@ void RegTestHost::DumpSystemStateHashes() // don't save full state on gpu dump, it's not going to be complete... if (!System::IsReplayingGPUDump()) { - DynamicHeapArray state_data(System::GetMaxSaveStateSize(g_settings.cpu_enable_8mb_ram)); + DynamicHeapArray state_data( + System::GetMaxSaveStateSize(g_settings.cpu_enable_8mb_ram, g_settings.gpu_texture_cache)); size_t state_data_size; if (!System::SaveStateDataToBuffer(state_data, &state_data_size, &error)) {