System: Improve texture recycling when changing rewind/runahead settings
Fix suprious failures when changing rewind settings when low on VRAM.
This commit is contained in:
parent
8605722cdf
commit
a08acdb93a
|
@ -332,21 +332,32 @@ bool GPUBackend::AllocateMemorySaveStates(std::span<System::MemorySaveState> sta
|
||||||
for (size_t i = 0; i < states.size(); i++)
|
for (size_t i = 0; i < states.size(); i++)
|
||||||
g_gpu_device->RecycleTexture(std::move(states[i].vram_texture));
|
g_gpu_device->RecycleTexture(std::move(states[i].vram_texture));
|
||||||
|
|
||||||
|
// Maximize potential for texture reuse by flushing the current command buffer.
|
||||||
|
g_gpu_device->WaitForGPUIdle();
|
||||||
|
|
||||||
for (size_t i = 0; i < states.size(); i++)
|
for (size_t i = 0; i < states.size(); i++)
|
||||||
{
|
{
|
||||||
if (!backend->AllocateMemorySaveState(states[i], error))
|
if (!backend->AllocateMemorySaveState(states[i], error))
|
||||||
{
|
{
|
||||||
// Free anything that was allocated.
|
// Try flushing the pool.
|
||||||
for (size_t j = 0; j <= i; i++)
|
WARNING_LOG("Failed to allocate memory save state texture, trying flushing pool.");
|
||||||
|
g_gpu_device->PurgeTexturePool();
|
||||||
|
g_gpu_device->WaitForGPUIdle();
|
||||||
|
if (!backend->AllocateMemorySaveState(states[i], error))
|
||||||
{
|
{
|
||||||
states[j].state_data.deallocate();
|
// Free anything that was allocated.
|
||||||
states[j].vram_texture.reset();
|
for (size_t j = 0; j <= i; i++)
|
||||||
result = false;
|
{
|
||||||
return;
|
states[j].state_data.deallocate();
|
||||||
|
states[j].vram_texture.reset();
|
||||||
|
result = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
backend->RestoreDeviceContext();
|
||||||
result = true;
|
result = true;
|
||||||
},
|
},
|
||||||
true, false);
|
true, false);
|
||||||
|
|
|
@ -59,7 +59,7 @@ static void HotkeyModifyResolutionScale(s32 increment)
|
||||||
|
|
||||||
if (System::IsValid())
|
if (System::IsValid())
|
||||||
{
|
{
|
||||||
System::ClearMemorySaveStates(true);
|
System::ClearMemorySaveStates(true, false);
|
||||||
GPUThread::UpdateSettings(true, false);
|
GPUThread::UpdateSettings(true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -373,7 +373,7 @@ DEFINE_HOTKEY("TogglePGXP", TRANSLATE_NOOP("Hotkeys", "Graphics"), TRANSLATE_NOO
|
||||||
[](s32 pressed) {
|
[](s32 pressed) {
|
||||||
if (!pressed && System::IsValid())
|
if (!pressed && System::IsValid())
|
||||||
{
|
{
|
||||||
System::ClearMemorySaveStates(true);
|
System::ClearMemorySaveStates(true, true);
|
||||||
|
|
||||||
g_settings.gpu_pgxp_enable = !g_settings.gpu_pgxp_enable;
|
g_settings.gpu_pgxp_enable = !g_settings.gpu_pgxp_enable;
|
||||||
GPUThread::UpdateSettings(true, false);
|
GPUThread::UpdateSettings(true, false);
|
||||||
|
@ -451,7 +451,7 @@ DEFINE_HOTKEY("TogglePGXPDepth", TRANSLATE_NOOP("Hotkeys", "Graphics"),
|
||||||
if (!g_settings.gpu_pgxp_enable)
|
if (!g_settings.gpu_pgxp_enable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
System::ClearMemorySaveStates(true);
|
System::ClearMemorySaveStates(true, true);
|
||||||
|
|
||||||
g_settings.gpu_pgxp_depth_buffer = !g_settings.gpu_pgxp_depth_buffer;
|
g_settings.gpu_pgxp_depth_buffer = !g_settings.gpu_pgxp_depth_buffer;
|
||||||
GPUThread::UpdateSettings(true, false);
|
GPUThread::UpdateSettings(true, false);
|
||||||
|
@ -471,7 +471,7 @@ DEFINE_HOTKEY("TogglePGXPCPU", TRANSLATE_NOOP("Hotkeys", "Graphics"), TRANSLATE_
|
||||||
if (!g_settings.gpu_pgxp_enable)
|
if (!g_settings.gpu_pgxp_enable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
System::ClearMemorySaveStates(true);
|
System::ClearMemorySaveStates(true, true);
|
||||||
|
|
||||||
// GPU thread is unchanged
|
// GPU thread is unchanged
|
||||||
g_settings.gpu_pgxp_cpu = !g_settings.gpu_pgxp_cpu;
|
g_settings.gpu_pgxp_cpu = !g_settings.gpu_pgxp_cpu;
|
||||||
|
|
|
@ -1167,7 +1167,7 @@ DiscRegion System::GetRegionForPsf(const char* path)
|
||||||
|
|
||||||
void System::RecreateGPU(GPURenderer renderer)
|
void System::RecreateGPU(GPURenderer renderer)
|
||||||
{
|
{
|
||||||
FreeMemoryStateTextures();
|
FreeMemoryStateStorage(false);
|
||||||
StopMediaCapture();
|
StopMediaCapture();
|
||||||
|
|
||||||
Error error;
|
Error error;
|
||||||
|
@ -1177,7 +1177,7 @@ void System::RecreateGPU(GPURenderer renderer)
|
||||||
Panic("Failed to switch renderer.");
|
Panic("Failed to switch renderer.");
|
||||||
}
|
}
|
||||||
|
|
||||||
ClearMemorySaveStates(true);
|
ClearMemorySaveStates(true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::LoadSettings(bool display_osd_messages)
|
void System::LoadSettings(bool display_osd_messages)
|
||||||
|
@ -1954,7 +1954,7 @@ void System::DestroySystem()
|
||||||
if (g_settings.inhibit_screensaver)
|
if (g_settings.inhibit_screensaver)
|
||||||
PlatformMisc::ResumeScreensaver();
|
PlatformMisc::ResumeScreensaver();
|
||||||
|
|
||||||
FreeMemoryStateStorage();
|
FreeMemoryStateStorage(false);
|
||||||
|
|
||||||
Cheats::UnloadAll();
|
Cheats::UnloadAll();
|
||||||
PCDrv::Shutdown();
|
PCDrv::Shutdown();
|
||||||
|
@ -2495,13 +2495,13 @@ System::MemorySaveState& System::PopMemoryState()
|
||||||
return s_state.memory_save_states[s_state.memory_save_state_front];
|
return s_state.memory_save_states[s_state.memory_save_state_front];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool System::AllocateMemoryStates(size_t state_count)
|
bool System::AllocateMemoryStates(size_t state_count, bool recycle_old_textures)
|
||||||
{
|
{
|
||||||
DEV_LOG("Allocating {} memory save state slots", state_count);
|
DEV_LOG("Allocating {} memory save state slots", state_count);
|
||||||
|
|
||||||
if (state_count != s_state.memory_save_states.size())
|
if (state_count != s_state.memory_save_states.size())
|
||||||
{
|
{
|
||||||
FreeMemoryStateStorage();
|
FreeMemoryStateStorage(recycle_old_textures);
|
||||||
s_state.memory_save_states.resize(state_count);
|
s_state.memory_save_states.resize(state_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2522,7 +2522,7 @@ bool System::AllocateMemoryStates(size_t state_count)
|
||||||
ERROR_LOG("Failed to allocate {} memory save states: {}", s_state.memory_save_states.size(),
|
ERROR_LOG("Failed to allocate {} memory save states: {}", s_state.memory_save_states.size(),
|
||||||
error.GetDescription());
|
error.GetDescription());
|
||||||
ERROR_LOG("Disabling runahead/rewind.");
|
ERROR_LOG("Disabling runahead/rewind.");
|
||||||
FreeMemoryStateStorage();
|
FreeMemoryStateStorage(false);
|
||||||
s_state.runahead_frames = 0;
|
s_state.runahead_frames = 0;
|
||||||
s_state.memory_save_state_front = 0;
|
s_state.memory_save_state_front = 0;
|
||||||
s_state.memory_save_state_count = 0;
|
s_state.memory_save_state_count = 0;
|
||||||
|
@ -2536,48 +2536,16 @@ bool System::AllocateMemoryStates(size_t state_count)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::ClearMemorySaveStates(bool reallocate_resources)
|
void System::ClearMemorySaveStates(bool reallocate_resources, bool recycle_textures)
|
||||||
{
|
{
|
||||||
s_state.memory_save_state_front = 0;
|
s_state.memory_save_state_front = 0;
|
||||||
s_state.memory_save_state_count = 0;
|
s_state.memory_save_state_count = 0;
|
||||||
|
|
||||||
if (reallocate_resources && !s_state.memory_save_states.empty())
|
if (reallocate_resources && !s_state.memory_save_states.empty())
|
||||||
AllocateMemoryStates(s_state.memory_save_states.size());
|
AllocateMemoryStates(s_state.memory_save_states.size(), recycle_textures);
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::FreeMemoryStateTextures()
|
void System::FreeMemoryStateStorage(bool recycle_textures)
|
||||||
{
|
|
||||||
// TODO: use non-copyable function, that way we don't need to store raw pointers
|
|
||||||
std::vector<GPUTexture*> textures;
|
|
||||||
bool gpu_thread_synced = false;
|
|
||||||
|
|
||||||
for (MemorySaveState& mss : s_state.memory_save_states)
|
|
||||||
{
|
|
||||||
if ((mss.vram_texture || !mss.gpu_state_data.empty()) && !gpu_thread_synced)
|
|
||||||
{
|
|
||||||
gpu_thread_synced = true;
|
|
||||||
GPUThread::SyncGPUThread(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mss.vram_texture)
|
|
||||||
{
|
|
||||||
if (textures.empty())
|
|
||||||
textures.reserve(s_state.memory_save_states.size());
|
|
||||||
|
|
||||||
textures.push_back(mss.vram_texture.release());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!textures.empty())
|
|
||||||
{
|
|
||||||
GPUThread::RunOnThread([textures = std::move(textures)]() mutable {
|
|
||||||
for (GPUTexture* texture : textures)
|
|
||||||
g_gpu_device->RecycleTexture(std::unique_ptr<GPUTexture>(texture));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void System::FreeMemoryStateStorage()
|
|
||||||
{
|
{
|
||||||
// TODO: use non-copyable function, that way we don't need to store raw pointers
|
// TODO: use non-copyable function, that way we don't need to store raw pointers
|
||||||
std::vector<GPUTexture*> textures;
|
std::vector<GPUTexture*> textures;
|
||||||
|
@ -2607,9 +2575,14 @@ void System::FreeMemoryStateStorage()
|
||||||
|
|
||||||
if (!textures.empty())
|
if (!textures.empty())
|
||||||
{
|
{
|
||||||
GPUThread::RunOnThread([textures = std::move(textures)]() mutable {
|
GPUThread::RunOnThread([textures = std::move(textures), recycle_textures]() mutable {
|
||||||
for (GPUTexture* texture : textures)
|
for (GPUTexture* texture : textures)
|
||||||
g_gpu_device->RecycleTexture(std::unique_ptr<GPUTexture>(texture));
|
{
|
||||||
|
if (recycle_textures)
|
||||||
|
g_gpu_device->RecycleTexture(std::unique_ptr<GPUTexture>(texture));
|
||||||
|
else
|
||||||
|
delete texture;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2919,7 +2892,7 @@ bool System::LoadStateFromBuffer(const SaveStateBuffer& buffer, Error* error, bo
|
||||||
if (g_settings.HasAnyPerGameMemoryCards())
|
if (g_settings.HasAnyPerGameMemoryCards())
|
||||||
UpdatePerGameMemoryCards();
|
UpdatePerGameMemoryCards();
|
||||||
|
|
||||||
ClearMemorySaveStates(false);
|
ClearMemorySaveStates(false, false);
|
||||||
|
|
||||||
// Updating game/loading settings can turn on hardcore mode. Catch this.
|
// Updating game/loading settings can turn on hardcore mode. Catch this.
|
||||||
Achievements::DisableHardcoreMode();
|
Achievements::DisableHardcoreMode();
|
||||||
|
@ -4005,7 +3978,7 @@ bool System::InsertMedia(const char* path)
|
||||||
if (IsGPUDumpPath(path)) [[unlikely]]
|
if (IsGPUDumpPath(path)) [[unlikely]]
|
||||||
return ChangeGPUDump(path);
|
return ChangeGPUDump(path);
|
||||||
|
|
||||||
ClearMemorySaveStates(true);
|
ClearMemorySaveStates(true, true);
|
||||||
|
|
||||||
Error error;
|
Error error;
|
||||||
std::unique_ptr<CDImage> image = CDImage::Open(path, g_settings.cdrom_load_image_patches, &error);
|
std::unique_ptr<CDImage> image = CDImage::Open(path, g_settings.cdrom_load_image_patches, &error);
|
||||||
|
@ -4044,7 +4017,7 @@ bool System::InsertMedia(const char* path)
|
||||||
|
|
||||||
void System::RemoveMedia()
|
void System::RemoveMedia()
|
||||||
{
|
{
|
||||||
ClearMemorySaveStates(true);
|
ClearMemorySaveStates(true, true);
|
||||||
CDROM::RemoveMedia(false);
|
CDROM::RemoveMedia(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4254,7 +4227,7 @@ bool System::SwitchMediaSubImage(u32 index)
|
||||||
if (!CDROM::HasMedia())
|
if (!CDROM::HasMedia())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ClearMemorySaveStates(true);
|
ClearMemorySaveStates(true, true);
|
||||||
|
|
||||||
std::unique_ptr<CDImage> image = CDROM::RemoveMedia(true);
|
std::unique_ptr<CDImage> image = CDROM::RemoveMedia(true);
|
||||||
Assert(image);
|
Assert(image);
|
||||||
|
@ -4308,7 +4281,7 @@ void System::CheckForSettingsChanges(const Settings& old_settings)
|
||||||
{
|
{
|
||||||
if (IsValid())
|
if (IsValid())
|
||||||
{
|
{
|
||||||
ClearMemorySaveStates(false);
|
ClearMemorySaveStates(false, false);
|
||||||
|
|
||||||
if (g_settings.cpu_overclock_active != old_settings.cpu_overclock_active ||
|
if (g_settings.cpu_overclock_active != old_settings.cpu_overclock_active ||
|
||||||
(g_settings.cpu_overclock_active &&
|
(g_settings.cpu_overclock_active &&
|
||||||
|
@ -4448,7 +4421,8 @@ void System::CheckForSettingsChanges(const Settings& old_settings)
|
||||||
GPUThread::UpdateSettings(true, false);
|
GPUThread::UpdateSettings(true, false);
|
||||||
|
|
||||||
// NOTE: Must come after the GPU thread settings update, otherwise it allocs the wrong size textures.
|
// NOTE: Must come after the GPU thread settings update, otherwise it allocs the wrong size textures.
|
||||||
ClearMemorySaveStates(true);
|
const bool use_existing_textures = (g_settings.gpu_resolution_scale == old_settings.gpu_resolution_scale);
|
||||||
|
ClearMemorySaveStates(true, use_existing_textures);
|
||||||
|
|
||||||
if (IsPaused())
|
if (IsPaused())
|
||||||
GPUThread::PresentCurrentFrame();
|
GPUThread::PresentCurrentFrame();
|
||||||
|
@ -4884,7 +4858,8 @@ void System::CalculateRewindMemoryUsage(u32 num_saves, u32 resolution_scale, u64
|
||||||
|
|
||||||
void System::UpdateMemorySaveStateSettings()
|
void System::UpdateMemorySaveStateSettings()
|
||||||
{
|
{
|
||||||
FreeMemoryStateStorage();
|
const bool any_memory_states_active = (g_settings.IsRunaheadEnabled() || g_settings.rewind_enable);
|
||||||
|
FreeMemoryStateStorage(any_memory_states_active);
|
||||||
|
|
||||||
if (IsReplayingGPUDump()) [[unlikely]]
|
if (IsReplayingGPUDump()) [[unlikely]]
|
||||||
{
|
{
|
||||||
|
@ -4926,7 +4901,7 @@ void System::UpdateMemorySaveStateSettings()
|
||||||
|
|
||||||
// allocate storage for memory save states
|
// allocate storage for memory save states
|
||||||
if (num_slots > 0)
|
if (num_slots > 0)
|
||||||
AllocateMemoryStates(num_slots);
|
AllocateMemoryStates(num_slots, true);
|
||||||
|
|
||||||
// reenter execution loop, don't want to try to save a state now if runahead was turned off
|
// reenter execution loop, don't want to try to save a state now if runahead was turned off
|
||||||
InterruptExecution();
|
InterruptExecution();
|
||||||
|
@ -5024,7 +4999,7 @@ bool System::DoRunahead()
|
||||||
s_state.runahead_replay_frames = s_state.memory_save_state_count;
|
s_state.runahead_replay_frames = s_state.memory_save_state_count;
|
||||||
|
|
||||||
// and throw away all the states, forcing us to catch up below
|
// and throw away all the states, forcing us to catch up below
|
||||||
ClearMemorySaveStates(false);
|
ClearMemorySaveStates(false, false);
|
||||||
|
|
||||||
// run the frames with no audio
|
// run the frames with no audio
|
||||||
SPU::SetAudioOutputMuted(true);
|
SPU::SetAudioOutputMuted(true);
|
||||||
|
|
|
@ -418,7 +418,7 @@ void RequestDisplaySize(float scale = 0.0f);
|
||||||
// Memory Save States (Rewind and Runahead)
|
// Memory Save States (Rewind and Runahead)
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
void CalculateRewindMemoryUsage(u32 num_saves, u32 resolution_scale, u64* ram_usage, u64* vram_usage);
|
void CalculateRewindMemoryUsage(u32 num_saves, u32 resolution_scale, u64* ram_usage, u64* vram_usage);
|
||||||
void ClearMemorySaveStates(bool reallocate_resources);
|
void ClearMemorySaveStates(bool reallocate_resources, bool recycle_textures);
|
||||||
void SetRunaheadReplayFlag();
|
void SetRunaheadReplayFlag();
|
||||||
|
|
||||||
/// Shared socket multiplexer, used by PINE/GDB/etc.
|
/// Shared socket multiplexer, used by PINE/GDB/etc.
|
||||||
|
|
|
@ -26,9 +26,8 @@ struct MemorySaveState
|
||||||
MemorySaveState& AllocateMemoryState();
|
MemorySaveState& AllocateMemoryState();
|
||||||
MemorySaveState& GetFirstMemoryState();
|
MemorySaveState& GetFirstMemoryState();
|
||||||
MemorySaveState& PopMemoryState();
|
MemorySaveState& PopMemoryState();
|
||||||
bool AllocateMemoryStates(size_t state_count);
|
bool AllocateMemoryStates(size_t state_count, bool recycle_old_textures);
|
||||||
void FreeMemoryStateTextures();
|
void FreeMemoryStateStorage(bool recycle_texture);
|
||||||
void FreeMemoryStateStorage();
|
|
||||||
void LoadMemoryState(MemorySaveState& mss, bool update_display);
|
void LoadMemoryState(MemorySaveState& mss, bool update_display);
|
||||||
void SaveMemoryState(MemorySaveState& mss);
|
void SaveMemoryState(MemorySaveState& mss);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue