VideoCommon: implement swap requests in the full async way

This commit is contained in:
degasus 2015-01-31 12:01:01 +01:00
parent bc248f8941
commit ad7264da7d
6 changed files with 42 additions and 51 deletions

View File

@ -4,7 +4,7 @@
AsyncRequests AsyncRequests::s_singleton;
AsyncRequests::AsyncRequests()
: m_enable(false)
: m_enable(false), m_passthrough(true)
{
}
@ -34,6 +34,13 @@ void AsyncRequests::PullEventsInternal()
void AsyncRequests::PushEvent(const AsyncRequests::Event& event, bool blocking)
{
std::unique_lock<std::mutex> lock(m_mutex);
if (m_passthrough)
{
HandleEvent(event);
return;
}
m_empty.store(false);
m_wake_me_up_again |= blocking;
@ -65,6 +72,7 @@ void AsyncRequests::SetEnable(bool enable)
void AsyncRequests::HandleEvent(const AsyncRequests::Event& e)
{
EFBRectangle rc;
switch (e.type)
{
case Event::EFB_POKE_COLOR:
@ -83,6 +91,16 @@ void AsyncRequests::HandleEvent(const AsyncRequests::Event& e)
*e.efb_peek.data = g_renderer->AccessEFB(PEEK_Z, e.efb_peek.x, e.efb_peek.y, 0);
break;
case Event::SWAP_EVENT:
Renderer::Swap(e.swap_event.xfbAddr, e.swap_event.fbWidth, e.swap_event.fbStride, e.swap_event.fbHeight, rc);
break;
}
}
void AsyncRequests::SetPassthrough(bool enable)
{
std::unique_lock<std::mutex> lock(m_mutex);
m_passthrough = enable;
}

View File

@ -22,6 +22,7 @@ public:
EFB_POKE_Z,
EFB_PEEK_COLOR,
EFB_PEEK_Z,
SWAP_EVENT,
} type;
u64 time;
@ -40,6 +41,14 @@ public:
u16 y;
u32* data;
} efb_peek;
struct
{
u32 xfbAddr;
u32 fbWidth;
u32 fbStride;
u32 fbHeight;
} swap_event;
};
};
@ -52,6 +61,7 @@ public:
}
void PushEvent(const Event& event, bool blocking = false);
void SetEnable(bool enable);
void SetPassthrough(bool enable);
static AsyncRequests* GetInstance() { return &s_singleton; }
@ -68,4 +78,5 @@ private:
bool m_wake_me_up_again;
bool m_enable;
bool m_passthrough;
};

View File

@ -284,6 +284,7 @@ void RunGpuLoop()
bool yield_cpu = cpu_info.num_cores <= 2;
AsyncRequests::GetInstance()->SetEnable(true);
AsyncRequests::GetInstance()->SetPassthrough(false);
while (GpuRunningState)
{
@ -383,6 +384,7 @@ void RunGpuLoop()
// wake up SyncGPU if we were interrupted
s_video_buffer_cond.notify_all();
AsyncRequests::GetInstance()->SetEnable(false);
AsyncRequests::GetInstance()->SetPassthrough(true);
}

View File

@ -19,7 +19,6 @@
bool s_BackendInitialized = false;
Common::Flag s_swapRequested;
static Common::Flag s_FifoShuttingDown;
static Common::Flag s_perfQueryRequested;
@ -61,45 +60,11 @@ void VideoBackendHardware::Video_SetRendering(bool bEnabled)
Fifo_SetRendering(bEnabled);
}
// Run from the graphics thread (from Fifo.cpp)
static void VideoFifo_CheckSwapRequest()
{
if (g_ActiveConfig.bUseXFB)
{
if (s_swapRequested.IsSet())
{
EFBRectangle rc;
Renderer::Swap(s_beginFieldArgs.xfbAddr, s_beginFieldArgs.fbWidth, s_beginFieldArgs.fbStride, s_beginFieldArgs.fbHeight, rc);
s_swapRequested.Clear();
}
}
}
// Run from the graphics thread (from Fifo.cpp)
void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
{
if (g_ActiveConfig.bUseXFB)
{
if (s_swapRequested.IsSet())
{
u32 aLower = xfbAddr;
u32 aUpper = xfbAddr + 2 * fbWidth * fbHeight;
u32 bLower = s_beginFieldArgs.xfbAddr;
u32 bUpper = s_beginFieldArgs.xfbAddr + 2 * s_beginFieldArgs.fbStride * s_beginFieldArgs.fbHeight;
if (AddressRangesOverlap(aLower, aUpper, bLower, bUpper))
VideoFifo_CheckSwapRequest();
}
}
}
// Run from the CPU thread (from VideoInterface.cpp)
void VideoBackendHardware::Video_BeginField(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight)
{
if (s_BackendInitialized && g_ActiveConfig.bUseXFB)
{
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread)
VideoFifo_CheckSwapRequest();
s_beginFieldArgs.xfbAddr = xfbAddr;
s_beginFieldArgs.fbWidth = fbWidth;
s_beginFieldArgs.fbStride = fbStride;
@ -110,16 +75,19 @@ void VideoBackendHardware::Video_BeginField(u32 xfbAddr, u32 fbWidth, u32 fbStri
// Run from the CPU thread (from VideoInterface.cpp)
void VideoBackendHardware::Video_EndField()
{
if (s_BackendInitialized)
if (s_BackendInitialized && g_ActiveConfig.bUseXFB && g_renderer)
{
SyncGPU(SYNC_GPU_SWAP);
// Wait until the GPU thread has swapped. Prevents FIFO overflows.
while (g_ActiveConfig.bUseXFB && SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread && s_swapRequested.IsSet())
{
Common::YieldCPU();
}
s_swapRequested.Set();
AsyncRequests::Event e;
e.time = 0;
e.type = AsyncRequests::Event::SWAP_EVENT;
e.swap_event.xfbAddr = s_beginFieldArgs.xfbAddr;
e.swap_event.fbWidth = s_beginFieldArgs.fbWidth;
e.swap_event.fbStride = s_beginFieldArgs.fbStride;
e.swap_event.fbHeight = s_beginFieldArgs.fbHeight;
AsyncRequests::GetInstance()->PushEvent(e, false);
}
}
@ -246,7 +214,6 @@ void VideoBackendHardware::InitializeShared()
{
VideoCommon_Init();
s_swapRequested.Clear();
s_perfQueryRequested.Clear();
s_FifoShuttingDown.Clear();
memset((void*)&s_beginFieldArgs, 0, sizeof(s_beginFieldArgs));
@ -268,7 +235,6 @@ void VideoBackendHardware::DoState(PointerWrap& p)
VideoCommon_DoState(p);
p.DoMarker("VideoCommon");
p.Do(s_swapRequested);
p.Do(s_beginFieldArgs);
p.DoMarker("VideoBackendHardware");
@ -308,7 +274,6 @@ void VideoBackendHardware::RunLoop(bool enable)
void VideoFifo_CheckAsyncRequest()
{
VideoFifo_CheckSwapRequest();
VideoFifo_CheckPerfQueryRequest();
VideoFifo_CheckBBoxRequest();
}

View File

@ -4,6 +4,3 @@
#include "Common/Flag.h"
extern bool s_BackendInitialized;
extern Common::Flag s_swapRequested;
void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight);

View File

@ -116,7 +116,6 @@ void Renderer::RenderToXFB(u32 xfbAddr, const EFBRectangle& sourceRc, u32 fbWidt
if (!fbWidth || !fbHeight)
return;
VideoFifo_CheckSwapRequestAt(xfbAddr, fbWidth, fbHeight);
XFBWrited = true;
if (g_ActiveConfig.bUseXFB)
@ -126,7 +125,6 @@ void Renderer::RenderToXFB(u32 xfbAddr, const EFBRectangle& sourceRc, u32 fbWidt
else
{
Swap(xfbAddr, fbWidth, fbWidth, fbHeight, sourceRc, Gamma);
s_swapRequested.Clear();
}
}