System: Reuse existing texture/buffers for runahead/rewind

This commit is contained in:
Connor McLaughlin 2021-01-24 21:12:28 +10:00
parent e01d66d18e
commit 3f96473fb5
4 changed files with 62 additions and 28 deletions

View File

@ -99,9 +99,9 @@ bool GPU_HW_D3D11::DoState(StateWrapper& sw, HostDisplayTexture** host_texture,
static_cast<LONG>(m_vram_texture.GetHeight()), 1); static_cast<LONG>(m_vram_texture.GetHeight()), 1);
ComPtr<ID3D11Resource> resource; ComPtr<ID3D11Resource> resource;
HostDisplayTexture* tex = *host_texture;
if (sw.IsReading()) if (sw.IsReading())
{ {
HostDisplayTexture* tex = *host_texture;
if (tex->GetWidth() != m_vram_texture.GetWidth() || tex->GetHeight() != m_vram_texture.GetHeight() || if (tex->GetWidth() != m_vram_texture.GetWidth() || tex->GetHeight() != m_vram_texture.GetHeight() ||
tex->GetSamples() != m_vram_texture.GetSamples()) tex->GetSamples() != m_vram_texture.GetSamples())
{ {
@ -113,15 +113,22 @@ bool GPU_HW_D3D11::DoState(StateWrapper& sw, HostDisplayTexture** host_texture,
} }
else else
{ {
std::unique_ptr<HostDisplayTexture> tex = if (!tex || tex->GetWidth() != m_vram_texture.GetWidth() || tex->GetHeight() != m_vram_texture.GetHeight() ||
m_host_display->CreateTexture(m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 1, 1, tex->GetSamples() != m_vram_texture.GetSamples())
m_vram_texture.GetSamples(), HostDisplayPixelFormat::RGBA8, nullptr, 0, false); {
if (!tex) delete tex;
return false;
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<ID3D11ShaderResourceView*>(tex->GetHandle())->GetResource(resource.GetAddressOf()); static_cast<ID3D11ShaderResourceView*>(tex->GetHandle())->GetResource(resource.GetAddressOf());
m_context->CopySubresourceRegion(resource.Get(), 0, 0, 0, 0, m_vram_texture.GetD3DTexture(), 0, &src_box); m_context->CopySubresourceRegion(resource.Get(), 0, 0, 0, 0, m_vram_texture.GetD3DTexture(), 0, &src_box);
*host_texture = tex.release();
} }
} }

View File

@ -108,9 +108,9 @@ bool GPU_HW_OpenGL::DoState(StateWrapper& sw, HostDisplayTexture** host_texture,
{ {
if (host_texture) if (host_texture)
{ {
HostDisplayTexture* tex = *host_texture;
if (sw.IsReading()) if (sw.IsReading())
{ {
HostDisplayTexture* tex = *host_texture;
if (tex->GetWidth() != m_vram_texture.GetWidth() || tex->GetHeight() != m_vram_texture.GetHeight() || if (tex->GetWidth() != m_vram_texture.GetWidth() || tex->GetHeight() != m_vram_texture.GetHeight() ||
tex->GetSamples() != m_vram_texture.GetSamples()) tex->GetSamples() != m_vram_texture.GetSamples())
{ {
@ -123,16 +123,23 @@ bool GPU_HW_OpenGL::DoState(StateWrapper& sw, HostDisplayTexture** host_texture,
} }
else else
{ {
std::unique_ptr<HostDisplayTexture> tex = if (!tex || tex->GetWidth() != m_vram_texture.GetWidth() || tex->GetHeight() != m_vram_texture.GetHeight() ||
m_host_display->CreateTexture(m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 1, 1, tex->GetSamples() != m_vram_texture.GetSamples())
m_vram_texture.GetSamples(), HostDisplayPixelFormat::RGBA8, nullptr, 0, false); {
if (!tex) delete tex;
return false;
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, CopyFramebufferForState(m_vram_texture.GetGLTarget(), m_vram_texture.GetGLId(), m_vram_fbo_id, 0, 0,
static_cast<GLuint>(reinterpret_cast<uintptr_t>(tex->GetHandle())), 0, 0, 0, static_cast<GLuint>(reinterpret_cast<uintptr_t>(tex->GetHandle())), 0, 0, 0,
m_vram_texture.GetWidth(), m_vram_texture.GetHeight()); m_vram_texture.GetWidth(), m_vram_texture.GetHeight());
*host_texture = tex.release();
} }
} }

View File

@ -131,11 +131,20 @@ bool GPU_HW_Vulkan::DoState(StateWrapper& sw, HostDisplayTexture** host_texture,
} }
else else
{ {
std::unique_ptr<HostDisplayTexture> htex = HostDisplayTexture* htex = *host_texture;
m_host_display->CreateTexture(m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 1, 1, if (!htex || htex->GetWidth() != m_vram_texture.GetWidth() || htex->GetHeight() != m_vram_texture.GetHeight() ||
m_vram_texture.GetSamples(), HostDisplayPixelFormat::RGBA8, nullptr, 0, false); htex->GetSamples() != m_vram_texture.GetSamples())
if (!htex) {
return false; 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<Vulkan::Texture*>(htex->GetHandle()); Vulkan::Texture* tex = static_cast<Vulkan::Texture*>(htex->GetHandle());
if (tex->GetWidth() != m_vram_texture.GetWidth() || tex->GetHeight() != m_vram_texture.GetHeight() || 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); tex->GetImage(), tex->GetLayout(), 1, &ic);
m_vram_texture.TransitionToLayout(buf, old_vram_layout); m_vram_texture.TransitionToLayout(buf, old_vram_layout);
tex->TransitionToLayout(buf, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); tex->TransitionToLayout(buf, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
*host_texture = htex.release();
} }
} }

View File

@ -2046,13 +2046,17 @@ bool LoadMemoryState(const MemorySaveState& mss)
bool SaveMemoryState(MemorySaveState* mss) bool SaveMemoryState(MemorySaveState* mss)
{ {
mss->state_stream = std::make_unique<GrowableMemoryByteStream>(nullptr, MAX_SAVE_STATE_SIZE); if (!mss->state_stream)
mss->state_stream = std::make_unique<GrowableMemoryByteStream>(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); StateWrapper sw(mss->state_stream.get(), StateWrapper::Mode::Write, SAVE_STATE_VERSION);
if (!DoState(sw, &host_texture, false)) if (!DoState(sw, &host_texture, false))
{ {
Log_ErrorPrint("Failed to create rewind state."); Log_ErrorPrint("Failed to create rewind state.");
delete host_texture;
return false; return false;
} }
@ -2064,11 +2068,15 @@ bool SaveRewindState()
{ {
Common::Timer save_timer; Common::Timer save_timer;
// try to reuse the frontmost slot
const u32 save_slots = g_settings.rewind_save_slots; const u32 save_slots = g_settings.rewind_save_slots;
while (s_rewind_states.size() >= save_slots)
s_rewind_states.pop_front();
MemorySaveState mss; MemorySaveState mss;
while (s_rewind_states.size() >= save_slots)
{
mss = std::move(s_rewind_states.front());
s_rewind_states.pop_front();
}
if (!SaveMemoryState(&mss)) if (!SaveMemoryState(&mss))
return false; return false;
@ -2141,10 +2149,14 @@ void DoRewind()
void SaveRunaheadState() void SaveRunaheadState()
{ {
if (s_runahead_states.size() >= s_runahead_frames) // try to reuse the frontmost slot
s_runahead_states.pop_front();
MemorySaveState mss; MemorySaveState mss;
while (s_runahead_states.size() >= s_runahead_frames)
{
mss = std::move(s_runahead_states.front());
s_runahead_states.pop_front();
}
if (!SaveMemoryState(&mss)) if (!SaveMemoryState(&mss))
{ {
Log_ErrorPrint("Failed to save runahead state."); Log_ErrorPrint("Failed to save runahead state.");