mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 06:09:50 -06:00
VideoCommon: FrameDump fixes/cleanups.
This commit is contained in:
@ -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()
|
||||
|
Reference in New Issue
Block a user