diff --git a/Source/Core/VideoCommon/AsyncRequests.cpp b/Source/Core/VideoCommon/AsyncRequests.cpp index d2945a3dbc..24cfe68513 100644 --- a/Source/Core/VideoCommon/AsyncRequests.cpp +++ b/Source/Core/VideoCommon/AsyncRequests.cpp @@ -16,7 +16,34 @@ void AsyncRequests::PullEventsInternal() while (!m_queue.empty()) { - const Event& e = m_queue.front(); + Event e = m_queue.front(); + + // try to merge as many efb pokes as possible + // it's a bit hacky, but some games render a complete frame in this way + if ((e.type == Event::EFB_POKE_COLOR || e.type == Event::EFB_POKE_Z)) + { + m_merged_efb_pokes.clear(); + Event first_event = m_queue.front(); + EFBAccessType t = first_event.type == Event::EFB_POKE_COLOR ? POKE_COLOR : POKE_Z; + + do + { + e = m_queue.front(); + + EfbPokeData d; + d.data = e.efb_poke.data; + d.x = e.efb_poke.x; + d.y = e.efb_poke.y; + m_merged_efb_pokes.push_back(d); + + m_queue.pop(); + } while(!m_queue.empty() && m_queue.front().type == first_event.type); + + lock.unlock(); + g_renderer->PokeEFB(t, m_merged_efb_pokes); + lock.lock(); + continue; + } lock.unlock(); HandleEvent(e); diff --git a/Source/Core/VideoCommon/AsyncRequests.h b/Source/Core/VideoCommon/AsyncRequests.h index 68ef08cf67..6a425888ef 100644 --- a/Source/Core/VideoCommon/AsyncRequests.h +++ b/Source/Core/VideoCommon/AsyncRequests.h @@ -11,6 +11,8 @@ #include "Common/CommonTypes.h" +struct EfbPokeData; + class AsyncRequests { public: @@ -91,4 +93,6 @@ private: bool m_wake_me_up_again; bool m_enable; bool m_passthrough; + + std::vector m_merged_efb_pokes; }; diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index b74a85c5a3..779c6faa63 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -599,3 +599,11 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const Core::Callback_VideoCopiedToXFB(XFBWrited || (g_ActiveConfig.bUseXFB && g_ActiveConfig.bUseRealXFB)); XFBWrited = false; } + +void Renderer::PokeEFB(EFBAccessType type, const std::vector& data) +{ + for (EfbPokeData poke : data) + { + AccessEFB(type, poke.x, poke.y, poke.data); + } +} diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index 42d1c2e438..aa5f5cc192 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -26,6 +26,12 @@ class PostProcessingShaderImplementation; +struct EfbPokeData +{ + u16 x,y; + u32 data; +}; + // TODO: Move these out of here. extern int frameCount; extern int OSDChoice; @@ -104,6 +110,7 @@ public: static void RenderToXFB(u32 xfbAddr, const EFBRectangle& sourceRc, u32 fbWidth, u32 fbHeight, float Gamma = 1.0f); virtual u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) = 0; + virtual void PokeEFB(EFBAccessType type, const std::vector& data); virtual u16 BBoxRead(int index) = 0; virtual void BBoxWrite(int index, u16 value) = 0;