diff options
| author | Markus Wick <degasus@users.noreply.github.com> | 2016-11-08 10:50:38 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-11-08 10:50:38 +0100 |
| commit | 363dec7bc7161215f32b4a1a16141d5c3509149c (patch) | |
| tree | 6b4519d96351c45f39b352d96c8b3b7929e490fd /Source/Core/VideoBackends/OGL/Render.cpp | |
| parent | 136a10482f099aec67cebd8673388f54b78458b6 (diff) | |
| parent | 741debe2291b0788ec2fb54ec24f49490704d609 (diff) | |
Merge pull request #4344 from degasus/framedump_ogl
OGL: Use PBO for framedump, with async readback.
Diffstat (limited to 'Source/Core/VideoBackends/OGL/Render.cpp')
| -rw-r--r-- | Source/Core/VideoBackends/OGL/Render.cpp | 73 |
1 files changed, 61 insertions, 12 deletions
diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index e3d3bea2d5..b1fae3b98c 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -767,6 +767,9 @@ Renderer::Renderer() Renderer::~Renderer() { + FlushFrameDump(); + if (m_frame_dumping_pbo[0]) + glDeleteBuffers(2, m_frame_dumping_pbo.data()); } void Renderer::Shutdown() @@ -1447,19 +1450,9 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - if (IsFrameDumping()) - { - std::vector<u8> image(flipped_trc.GetWidth() * flipped_trc.GetHeight() * 4); - - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(flipped_trc.left, flipped_trc.bottom, flipped_trc.GetWidth(), - flipped_trc.GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE, image.data()); + FlushFrameDump(); + DumpFrame(flipped_trc, ticks); - AVIDump::Frame state = AVIDump::FetchState(ticks); - DumpFrameData(image.data(), flipped_trc.GetWidth(), flipped_trc.GetHeight(), - flipped_trc.GetWidth() * 4, state, true); - FinishFrameData(); - } // Finish up the current frame, print some stats SetWindowSize(fbStride, fbHeight); @@ -1588,6 +1581,62 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, ClearEFBCache(); } +void Renderer::FlushFrameDump() +{ + if (!m_last_frame_exported) + return; + + FinishFrameData(); + glBindBuffer(GL_PIXEL_PACK_BUFFER, m_frame_dumping_pbo[0]); + m_frame_pbo_is_mapped[0] = true; + void* data = glMapBufferRange( + GL_PIXEL_PACK_BUFFER, 0, m_last_frame_width[0] * m_last_frame_height[0] * 4, GL_MAP_READ_BIT); + DumpFrameData(reinterpret_cast<u8*>(data), m_last_frame_width[0], m_last_frame_height[0], + m_last_frame_width[0] * 4, m_last_frame_state, true); + glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); + m_last_frame_exported = false; +} + +void Renderer::DumpFrame(const TargetRectangle& flipped_trc, u64 ticks) +{ + if (!IsFrameDumping()) + return; + + if (!m_frame_dumping_pbo[0]) + { + glGenBuffers(2, m_frame_dumping_pbo.data()); + glBindBuffer(GL_PIXEL_PACK_BUFFER, m_frame_dumping_pbo[0]); + } + else + { + std::swap(m_frame_dumping_pbo[0], m_frame_dumping_pbo[1]); + std::swap(m_frame_pbo_is_mapped[0], m_frame_pbo_is_mapped[1]); + std::swap(m_last_frame_width[0], m_last_frame_width[1]); + std::swap(m_last_frame_height[0], m_last_frame_height[1]); + glBindBuffer(GL_PIXEL_PACK_BUFFER, m_frame_dumping_pbo[0]); + if (m_frame_pbo_is_mapped[0]) + glUnmapBuffer(GL_PIXEL_PACK_BUFFER); + m_frame_pbo_is_mapped[0] = false; + } + + if (flipped_trc.GetWidth() != m_last_frame_width[0] || + flipped_trc.GetHeight() != m_last_frame_height[0]) + { + m_last_frame_width[0] = flipped_trc.GetWidth(); + m_last_frame_height[0] = flipped_trc.GetHeight(); + glBufferData(GL_PIXEL_PACK_BUFFER, m_last_frame_width[0] * m_last_frame_height[0] * 4, nullptr, + GL_STREAM_READ); + } + + m_last_frame_state = AVIDump::FetchState(ticks); + m_last_frame_exported = true; + + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glReadPixels(flipped_trc.left, flipped_trc.bottom, m_last_frame_width[0], m_last_frame_height[0], + GL_RGBA, GL_UNSIGNED_BYTE, 0); + glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); +} + // ALWAYS call RestoreAPIState for each ResetAPIState call you're doing void Renderer::ResetAPIState() { |
