VideoCommon: FrameDump fixes/cleanups.

This commit is contained in:
Jordan Woyak
2020-10-21 09:37:16 -05:00
parent 89b01cd6d3
commit 4807a5e157
5 changed files with 448 additions and 312 deletions

View File

@ -1409,17 +1409,13 @@ void Renderer::DumpCurrentFrame(const AbstractTexture* src_texture,
copy_rect = src_texture->GetRect();
}
// Index 0 was just sent to FFMPEG dump. Swap with the second texture.
if (m_frame_dump_readback_textures[0])
std::swap(m_frame_dump_readback_textures[0], m_frame_dump_readback_textures[1]);
if (!CheckFrameDumpReadbackTexture(target_width, target_height))
return;
m_frame_dump_readback_textures[0]->CopyFromTexture(src_texture, copy_rect, 0, 0,
m_frame_dump_readback_textures[0]->GetRect());
m_last_frame_state = FrameDump::FetchState(ticks);
m_last_frame_exported = true;
m_frame_dump_readback_texture->CopyFromTexture(src_texture, copy_rect, 0, 0,
m_frame_dump_readback_texture->GetRect());
m_last_frame_state = m_frame_dump.FetchState(ticks);
m_frame_dump_needs_flush = true;
}
bool Renderer::CheckFrameDumpRenderTexture(u32 target_width, u32 target_height)
@ -1450,7 +1446,7 @@ bool Renderer::CheckFrameDumpRenderTexture(u32 target_width, u32 target_height)
bool Renderer::CheckFrameDumpReadbackTexture(u32 target_width, u32 target_height)
{
std::unique_ptr<AbstractStagingTexture>& rbtex = m_frame_dump_readback_textures[0];
std::unique_ptr<AbstractStagingTexture>& rbtex = m_frame_dump_readback_texture;
if (rbtex && rbtex->GetWidth() == target_width && rbtex->GetHeight() == target_height)
return true;
@ -1466,24 +1462,28 @@ bool Renderer::CheckFrameDumpReadbackTexture(u32 target_width, u32 target_height
void Renderer::FlushFrameDump()
{
if (!m_last_frame_exported)
if (!m_frame_dump_needs_flush)
return;
// Ensure the previously-queued frame was encoded.
// Ensure dumping thread is done with output texture before swapping.
FinishFrameData();
std::swap(m_frame_dump_output_texture, m_frame_dump_readback_texture);
// Queue encoding of the last frame dumped.
std::unique_ptr<AbstractStagingTexture>& rbtex = m_frame_dump_readback_textures[0];
rbtex->Flush();
if (rbtex->Map())
auto& output = m_frame_dump_output_texture;
output->Flush();
if (output->Map())
{
DumpFrameData(reinterpret_cast<u8*>(rbtex->GetMappedPointer()), rbtex->GetConfig().width,
rbtex->GetConfig().height, static_cast<int>(rbtex->GetMappedStride()),
m_last_frame_state);
rbtex->Unmap();
DumpFrameData(reinterpret_cast<u8*>(output->GetMappedPointer()), output->GetConfig().width,
output->GetConfig().height, static_cast<int>(output->GetMappedStride()));
}
else
{
ERROR_LOG(VIDEO, "Failed to map texture for dumping.");
}
m_last_frame_exported = false;
m_frame_dump_needs_flush = false;
// Shutdown frame dumping if it is no longer active.
if (!IsFrameDumping())
@ -1508,21 +1508,21 @@ void Renderer::ShutdownFrameDumping()
m_frame_dump_thread.join();
m_frame_dump_render_framebuffer.reset();
m_frame_dump_render_texture.reset();
for (auto& tex : m_frame_dump_readback_textures)
tex.reset();
m_frame_dump_readback_texture.reset();
m_frame_dump_output_texture.reset();
}
void Renderer::DumpFrameData(const u8* data, int w, int h, int stride,
const FrameDump::Frame& state)
void Renderer::DumpFrameData(const u8* data, int w, int h, int stride)
{
m_frame_dump_config = FrameDumpConfig{data, w, h, stride, state};
m_frame_dump_data = FrameDump::FrameData{data, w, h, stride, m_last_frame_state};
if (!m_frame_dump_thread_running.IsSet())
{
if (m_frame_dump_thread.joinable())
m_frame_dump_thread.join();
m_frame_dump_thread_running.Set();
m_frame_dump_thread = std::thread(&Renderer::RunFrameDumps, this);
m_frame_dump_thread = std::thread(&Renderer::FrameDumpThreadFunc, this);
}
// Wake worker thread up.
@ -1537,11 +1537,14 @@ void Renderer::FinishFrameData()
m_frame_dump_done.Wait();
m_frame_dump_frame_running = false;
m_frame_dump_output_texture->Unmap();
}
void Renderer::RunFrameDumps()
void Renderer::FrameDumpThreadFunc()
{
Common::SetCurrentThreadName("FrameDumping");
bool dump_to_ffmpeg = !g_ActiveConfig.bDumpFramesAsImages;
bool frame_dump_started = false;
@ -1561,14 +1564,14 @@ void Renderer::RunFrameDumps()
if (!m_frame_dump_thread_running.IsSet())
break;
auto config = m_frame_dump_config;
auto frame = m_frame_dump_data;
// Save screenshot
if (m_screenshot_request.TestAndClear())
{
std::lock_guard<std::mutex> lk(m_screenshot_lock);
if (TextureToPng(config.data, config.stride, m_screenshot_name, config.width, config.height,
if (TextureToPng(frame.data, frame.stride, m_screenshot_name, frame.width, frame.height,
false))
OSD::AddMessage("Screenshot saved to " + m_screenshot_name);
@ -1582,9 +1585,9 @@ void Renderer::RunFrameDumps()
if (!frame_dump_started)
{
if (dump_to_ffmpeg)
frame_dump_started = StartFrameDumpToFFMPEG(config);
frame_dump_started = StartFrameDumpToFFMPEG(frame);
else
frame_dump_started = StartFrameDumpToImage(config);
frame_dump_started = StartFrameDumpToImage(frame);
// Stop frame dumping if we fail to start.
if (!frame_dump_started)
@ -1595,9 +1598,9 @@ void Renderer::RunFrameDumps()
if (frame_dump_started)
{
if (dump_to_ffmpeg)
DumpFrameToFFMPEG(config);
DumpFrameToFFMPEG(frame);
else
DumpFrameToImage(config);
DumpFrameToImage(frame);
}
}
@ -1614,29 +1617,29 @@ void Renderer::RunFrameDumps()
#if defined(HAVE_FFMPEG)
bool Renderer::StartFrameDumpToFFMPEG(const FrameDumpConfig& config)
bool Renderer::StartFrameDumpToFFMPEG(const FrameDump::FrameData& frame)
{
return FrameDump::Start(config.width, config.height);
return m_frame_dump.Start(frame.width, frame.height);
}
void Renderer::DumpFrameToFFMPEG(const FrameDumpConfig& config)
void Renderer::DumpFrameToFFMPEG(const FrameDump::FrameData& frame)
{
FrameDump::AddFrame(config.data, config.width, config.height, config.stride, config.state);
m_frame_dump.AddFrame(frame);
}
void Renderer::StopFrameDumpToFFMPEG()
{
FrameDump::Stop();
m_frame_dump.Stop();
}
#else
bool Renderer::StartFrameDumpToFFMPEG(const FrameDumpConfig& config)
bool Renderer::StartFrameDumpToFFMPEG(const FrameDump::FrameData&)
{
return false;
}
void Renderer::DumpFrameToFFMPEG(const FrameDumpConfig& config)
void Renderer::DumpFrameToFFMPEG(const FrameDump::FrameData&)
{
}
@ -1652,7 +1655,7 @@ std::string Renderer::GetFrameDumpNextImageFileName() const
m_frame_dump_image_counter);
}
bool Renderer::StartFrameDumpToImage(const FrameDumpConfig& config)
bool Renderer::StartFrameDumpToImage(const FrameDump::FrameData&)
{
m_frame_dump_image_counter = 1;
if (!SConfig::GetInstance().m_DumpFramesSilent)
@ -1671,10 +1674,10 @@ bool Renderer::StartFrameDumpToImage(const FrameDumpConfig& config)
return true;
}
void Renderer::DumpFrameToImage(const FrameDumpConfig& config)
void Renderer::DumpFrameToImage(const FrameDump::FrameData& frame)
{
std::string filename = GetFrameDumpNextImageFileName();
TextureToPng(config.data, config.stride, filename, config.width, config.height, false);
TextureToPng(frame.data, frame.stride, filename, frame.width, frame.height, false);
m_frame_dump_image_counter++;
}
@ -1718,6 +1721,10 @@ void Renderer::DoState(PointerWrap& p)
// And actually display it.
Swap(m_last_xfb_addr, m_last_xfb_width, m_last_xfb_stride, m_last_xfb_height, m_last_xfb_ticks);
}
#if defined(HAVE_FFMPEG)
m_frame_dump.DoState(p);
#endif
}
std::unique_ptr<VideoCommon::AsyncShaderCompiler> Renderer::CreateAsyncShaderCompiler()