diff --git a/src/core/gpu_hw_d3d11.cpp b/src/core/gpu_hw_d3d11.cpp index ad5937023..312a6035c 100644 --- a/src/core/gpu_hw_d3d11.cpp +++ b/src/core/gpu_hw_d3d11.cpp @@ -99,9 +99,9 @@ bool GPU_HW_D3D11::DoState(StateWrapper& sw, HostDisplayTexture** host_texture, static_cast(m_vram_texture.GetHeight()), 1); ComPtr resource; + HostDisplayTexture* tex = *host_texture; if (sw.IsReading()) { - HostDisplayTexture* tex = *host_texture; if (tex->GetWidth() != m_vram_texture.GetWidth() || tex->GetHeight() != m_vram_texture.GetHeight() || tex->GetSamples() != m_vram_texture.GetSamples()) { @@ -113,15 +113,22 @@ bool GPU_HW_D3D11::DoState(StateWrapper& sw, HostDisplayTexture** host_texture, } else { - std::unique_ptr tex = - m_host_display->CreateTexture(m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 1, 1, - m_vram_texture.GetSamples(), HostDisplayPixelFormat::RGBA8, nullptr, 0, false); - if (!tex) - return false; + if (!tex || tex->GetWidth() != m_vram_texture.GetWidth() || tex->GetHeight() != m_vram_texture.GetHeight() || + tex->GetSamples() != m_vram_texture.GetSamples()) + { + delete tex; + + tex = m_host_display + ->CreateTexture(m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 1, 1, + m_vram_texture.GetSamples(), HostDisplayPixelFormat::RGBA8, nullptr, 0, false) + .release(); + *host_texture = tex; + if (!tex) + return false; + } static_cast(tex->GetHandle())->GetResource(resource.GetAddressOf()); m_context->CopySubresourceRegion(resource.Get(), 0, 0, 0, 0, m_vram_texture.GetD3DTexture(), 0, &src_box); - *host_texture = tex.release(); } } diff --git a/src/core/gpu_hw_opengl.cpp b/src/core/gpu_hw_opengl.cpp index 24c2d91f9..d7e59e2ca 100644 --- a/src/core/gpu_hw_opengl.cpp +++ b/src/core/gpu_hw_opengl.cpp @@ -108,9 +108,9 @@ bool GPU_HW_OpenGL::DoState(StateWrapper& sw, HostDisplayTexture** host_texture, { if (host_texture) { + HostDisplayTexture* tex = *host_texture; if (sw.IsReading()) { - HostDisplayTexture* tex = *host_texture; if (tex->GetWidth() != m_vram_texture.GetWidth() || tex->GetHeight() != m_vram_texture.GetHeight() || tex->GetSamples() != m_vram_texture.GetSamples()) { @@ -123,16 +123,23 @@ bool GPU_HW_OpenGL::DoState(StateWrapper& sw, HostDisplayTexture** host_texture, } else { - std::unique_ptr tex = - m_host_display->CreateTexture(m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 1, 1, - m_vram_texture.GetSamples(), HostDisplayPixelFormat::RGBA8, nullptr, 0, false); - if (!tex) - return false; + if (!tex || tex->GetWidth() != m_vram_texture.GetWidth() || tex->GetHeight() != m_vram_texture.GetHeight() || + tex->GetSamples() != m_vram_texture.GetSamples()) + { + delete tex; + + tex = m_host_display + ->CreateTexture(m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 1, 1, + m_vram_texture.GetSamples(), HostDisplayPixelFormat::RGBA8, nullptr, 0, false) + .release(); + *host_texture = tex; + if (!tex) + return false; + } CopyFramebufferForState(m_vram_texture.GetGLTarget(), m_vram_texture.GetGLId(), m_vram_fbo_id, 0, 0, static_cast(reinterpret_cast(tex->GetHandle())), 0, 0, 0, m_vram_texture.GetWidth(), m_vram_texture.GetHeight()); - *host_texture = tex.release(); } } diff --git a/src/core/gpu_hw_vulkan.cpp b/src/core/gpu_hw_vulkan.cpp index 8d860bf75..aa7bfddeb 100644 --- a/src/core/gpu_hw_vulkan.cpp +++ b/src/core/gpu_hw_vulkan.cpp @@ -131,11 +131,20 @@ bool GPU_HW_Vulkan::DoState(StateWrapper& sw, HostDisplayTexture** host_texture, } else { - std::unique_ptr htex = - m_host_display->CreateTexture(m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 1, 1, - m_vram_texture.GetSamples(), HostDisplayPixelFormat::RGBA8, nullptr, 0, false); - if (!htex) - return false; + HostDisplayTexture* htex = *host_texture; + if (!htex || htex->GetWidth() != m_vram_texture.GetWidth() || htex->GetHeight() != m_vram_texture.GetHeight() || + htex->GetSamples() != m_vram_texture.GetSamples()) + { + delete htex; + + htex = m_host_display + ->CreateTexture(m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 1, 1, + m_vram_texture.GetSamples(), HostDisplayPixelFormat::RGBA8, nullptr, 0, false) + .release(); + *host_texture = htex; + if (!htex) + return false; + } Vulkan::Texture* tex = static_cast(htex->GetHandle()); if (tex->GetWidth() != m_vram_texture.GetWidth() || tex->GetHeight() != m_vram_texture.GetHeight() || @@ -152,7 +161,6 @@ bool GPU_HW_Vulkan::DoState(StateWrapper& sw, HostDisplayTexture** host_texture, tex->GetImage(), tex->GetLayout(), 1, &ic); m_vram_texture.TransitionToLayout(buf, old_vram_layout); tex->TransitionToLayout(buf, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - *host_texture = htex.release(); } } diff --git a/src/core/system.cpp b/src/core/system.cpp index 4113f7472..ceabf4c0f 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -2046,13 +2046,17 @@ bool LoadMemoryState(const MemorySaveState& mss) bool SaveMemoryState(MemorySaveState* mss) { - mss->state_stream = std::make_unique(nullptr, MAX_SAVE_STATE_SIZE); + if (!mss->state_stream) + mss->state_stream = std::make_unique(nullptr, MAX_SAVE_STATE_SIZE); + else + mss->state_stream->SeekAbsolute(0); - HostDisplayTexture* host_texture = nullptr; + HostDisplayTexture* host_texture = mss->vram_texture.release(); StateWrapper sw(mss->state_stream.get(), StateWrapper::Mode::Write, SAVE_STATE_VERSION); if (!DoState(sw, &host_texture, false)) { Log_ErrorPrint("Failed to create rewind state."); + delete host_texture; return false; } @@ -2064,11 +2068,15 @@ bool SaveRewindState() { Common::Timer save_timer; + // try to reuse the frontmost slot const u32 save_slots = g_settings.rewind_save_slots; + MemorySaveState mss; while (s_rewind_states.size() >= save_slots) + { + mss = std::move(s_rewind_states.front()); s_rewind_states.pop_front(); + } - MemorySaveState mss; if (!SaveMemoryState(&mss)) return false; @@ -2141,10 +2149,14 @@ void DoRewind() void SaveRunaheadState() { - if (s_runahead_states.size() >= s_runahead_frames) + // try to reuse the frontmost slot + MemorySaveState mss; + while (s_runahead_states.size() >= s_runahead_frames) + { + mss = std::move(s_runahead_states.front()); s_runahead_states.pop_front(); + } - MemorySaveState mss; if (!SaveMemoryState(&mss)) { Log_ErrorPrint("Failed to save runahead state.");