Merge pull request #3560 from lioncash/fifo

Fifo: get rid of global variables
This commit is contained in:
Mathew Maidment 2016-01-25 05:34:43 -05:00
commit bdfcaa0e00
12 changed files with 48 additions and 41 deletions

View File

@ -714,7 +714,7 @@ void formatBufferDump(const u8* in, u8* out, int w, int h, int p)
// This function has the final picture. We adjust the aspect ratio here. // This function has the final picture. We adjust the aspect ratio here.
void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc, float Gamma) void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc, float Gamma)
{ {
if (Fifo::g_bSkipCurrentFrame || (!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight) if (Fifo::WillSkipCurrentFrame() || (!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight)
{ {
if (SConfig::GetInstance().m_DumpFrames && !frame_data.empty()) if (SConfig::GetInstance().m_DumpFrames && !frame_data.empty())
AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight); AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight);

View File

@ -1260,7 +1260,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co
} }
static int w = 0, h = 0; static int w = 0, h = 0;
if (Fifo::g_bSkipCurrentFrame || (!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight) if (Fifo::WillSkipCurrentFrame() || (!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight)
{ {
DumpFrame(frame_data, w, h); DumpFrame(frame_data, w, h);
Core::Callback_VideoCopiedToXFB(false); Core::Callback_VideoCopiedToXFB(false);

View File

@ -191,7 +191,7 @@ void CopyTempBuffer(s16 x, s16 y, int bufferBase, int subBuffer, const char *nam
void OnObjectBegin() void OnObjectBegin()
{ {
if (!Fifo::g_bSkipCurrentFrame) if (!Fifo::WillSkipCurrentFrame())
{ {
if (g_ActiveConfig.bDumpTextures && stats.thisFrame.numDrawnObjects >= g_ActiveConfig.drawStart && stats.thisFrame.numDrawnObjects < g_ActiveConfig.drawEnd) if (g_ActiveConfig.bDumpTextures && stats.thisFrame.numDrawnObjects >= g_ActiveConfig.drawStart && stats.thisFrame.numDrawnObjects < g_ActiveConfig.drawEnd)
DumpActiveTextures(); DumpActiveTextures();
@ -200,7 +200,7 @@ void OnObjectBegin()
void OnObjectEnd() void OnObjectEnd()
{ {
if (!Fifo::g_bSkipCurrentFrame) if (!Fifo::WillSkipCurrentFrame())
{ {
if (g_ActiveConfig.bDumpObjects && stats.thisFrame.numDrawnObjects >= g_ActiveConfig.drawStart && stats.thisFrame.numDrawnObjects < g_ActiveConfig.drawEnd) if (g_ActiveConfig.bDumpObjects && stats.thisFrame.numDrawnObjects >= g_ActiveConfig.drawStart && stats.thisFrame.numDrawnObjects < g_ActiveConfig.drawEnd)
DumpEfb(StringFromFormat("%sobject%i.png", DumpEfb(StringFromFormat("%sobject%i.png",

View File

@ -72,7 +72,7 @@ namespace EfbCopy
rc.right = rc.left + (int)bpmem.copyTexSrcWH.x + 1; rc.right = rc.left + (int)bpmem.copyTexSrcWH.x + 1;
rc.bottom = rc.top + (int)bpmem.copyTexSrcWH.y + 1; rc.bottom = rc.top + (int)bpmem.copyTexSrcWH.y + 1;
if (!Fifo::g_bSkipCurrentFrame) if (!Fifo::WillSkipCurrentFrame())
{ {
if (bpmem.triggerEFBCopy.copy_to_xfb) if (bpmem.triggerEFBCopy.copy_to_xfb)
{ {

View File

@ -109,7 +109,7 @@ void SWRenderer::UpdateColorTexture(EfbInterface::yuv422_packed *xfb, u32 fbWidt
// Called on the GPU thread // Called on the GPU thread
void SWRenderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc, float Gamma) void SWRenderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, const EFBRectangle& rc, float Gamma)
{ {
if (!Fifo::g_bSkipCurrentFrame) if (!Fifo::WillSkipCurrentFrame())
{ {
if (g_ActiveConfig.bUseXFB) if (g_ActiveConfig.bUseXFB)

View File

@ -179,7 +179,7 @@ static void BPWritten(const BPCmd& bp)
switch (bp.newvalue & 0xFF) switch (bp.newvalue & 0xFF)
{ {
case 0x02: case 0x02:
if (!Fifo::g_use_deterministic_gpu_thread) if (!Fifo::UseDeterministicGPUThread())
PixelEngine::SetFinish(); // may generate interrupt PixelEngine::SetFinish(); // may generate interrupt
DEBUG_LOG(VIDEO, "GXSetDrawDone SetPEFinish (value: 0x%02X)", (bp.newvalue & 0xFFFF)); DEBUG_LOG(VIDEO, "GXSetDrawDone SetPEFinish (value: 0x%02X)", (bp.newvalue & 0xFFFF));
return; return;
@ -190,12 +190,12 @@ static void BPWritten(const BPCmd& bp)
} }
return; return;
case BPMEM_PE_TOKEN_ID: // Pixel Engine Token ID case BPMEM_PE_TOKEN_ID: // Pixel Engine Token ID
if (!Fifo::g_use_deterministic_gpu_thread) if (!Fifo::UseDeterministicGPUThread())
PixelEngine::SetToken(static_cast<u16>(bp.newvalue & 0xFFFF), false); PixelEngine::SetToken(static_cast<u16>(bp.newvalue & 0xFFFF), false);
DEBUG_LOG(VIDEO, "SetPEToken 0x%04x", (bp.newvalue & 0xFFFF)); DEBUG_LOG(VIDEO, "SetPEToken 0x%04x", (bp.newvalue & 0xFFFF));
return; return;
case BPMEM_PE_TOKEN_INT_ID: // Pixel Engine Interrupt Token ID case BPMEM_PE_TOKEN_INT_ID: // Pixel Engine Interrupt Token ID
if (!Fifo::g_use_deterministic_gpu_thread) if (!Fifo::UseDeterministicGPUThread())
PixelEngine::SetToken(static_cast<u16>(bp.newvalue & 0xFFFF), true); PixelEngine::SetToken(static_cast<u16>(bp.newvalue & 0xFFFF), true);
DEBUG_LOG(VIDEO, "SetPEToken + INT 0x%04x", (bp.newvalue & 0xFFFF)); DEBUG_LOG(VIDEO, "SetPEToken + INT 0x%04x", (bp.newvalue & 0xFFFF));
return; return;
@ -380,7 +380,7 @@ static void BPWritten(const BPCmd& bp)
case BPMEM_CLEARBBOX2: case BPMEM_CLEARBBOX2:
// Don't compute bounding box if this frame is being skipped! // Don't compute bounding box if this frame is being skipped!
// Wrong but valid values are better than bogus values... // Wrong but valid values are better than bogus values...
if (!Fifo::g_bSkipCurrentFrame) if (!Fifo::WillSkipCurrentFrame())
{ {
u8 offset = bp.address & 2; u8 offset = bp.address & 2;
BoundingBox::active = true; BoundingBox::active = true;

View File

@ -302,7 +302,7 @@ void GatherPipeBursted()
// if we aren't linked, we don't care about gather pipe data // if we aren't linked, we don't care about gather pipe data
if (!m_CPCtrlReg.GPLinkEnable) if (!m_CPCtrlReg.GPLinkEnable)
{ {
if (IsOnThread() && !Fifo::g_use_deterministic_gpu_thread) if (IsOnThread() && !Fifo::UseDeterministicGPUThread())
{ {
// In multibuffer mode is not allowed write in the same FIFO attached to the GPU. // In multibuffer mode is not allowed write in the same FIFO attached to the GPU.
// Fix Pokemon XD in DC mode. // Fix Pokemon XD in DC mode.
@ -368,7 +368,7 @@ void UpdateInterrupts(u64 userdata)
void UpdateInterruptsFromVideoBackend(u64 userdata) void UpdateInterruptsFromVideoBackend(u64 userdata)
{ {
if (!Fifo::g_use_deterministic_gpu_thread) if (!Fifo::UseDeterministicGPUThread())
CoreTiming::ScheduleEvent_Threadsafe(0, et_UpdateInterrupts, userdata); CoreTiming::ScheduleEvent_Threadsafe(0, et_UpdateInterrupts, userdata);
} }

View File

@ -33,7 +33,7 @@ namespace Fifo
static constexpr u32 FIFO_SIZE = 2 * 1024 * 1024; static constexpr u32 FIFO_SIZE = 2 * 1024 * 1024;
bool g_bSkipCurrentFrame = false; static bool s_skip_current_frame = false;
static Common::BlockingLoop s_gpu_mainloop; static Common::BlockingLoop s_gpu_mainloop;
@ -44,7 +44,9 @@ static u8 s_fifo_aux_data[FIFO_SIZE];
static u8* s_fifo_aux_write_ptr; static u8* s_fifo_aux_write_ptr;
static u8* s_fifo_aux_read_ptr; static u8* s_fifo_aux_read_ptr;
bool g_use_deterministic_gpu_thread; // This could be in SConfig, but it depends on multiple settings
// and can change at runtime.
static bool s_use_deterministic_gpu_thread;
static u64 s_last_sync_gpu_tick; static u64 s_last_sync_gpu_tick;
static int s_event_sync_gpu; static int s_event_sync_gpu;
@ -56,7 +58,7 @@ static std::atomic<u8*> s_video_buffer_write_ptr;
static std::atomic<u8*> s_video_buffer_seen_ptr; static std::atomic<u8*> s_video_buffer_seen_ptr;
static u8* s_video_buffer_pp_read_ptr; static u8* s_video_buffer_pp_read_ptr;
// The read_ptr is always owned by the GPU thread. In normal mode, so is the // The read_ptr is always owned by the GPU thread. In normal mode, so is the
// write_ptr, despite it being atomic. In g_use_deterministic_gpu_thread mode, // write_ptr, despite it being atomic. In deterministic GPU thread mode,
// things get a bit more complicated: // things get a bit more complicated:
// - The seen_ptr is written by the GPU thread, and points to what it's already // - The seen_ptr is written by the GPU thread, and points to what it's already
// processed as much of as possible - in the case of a partial command which // processed as much of as possible - in the case of a partial command which
@ -77,12 +79,13 @@ void DoState(PointerWrap &p)
p.DoPointer(write_ptr, s_video_buffer); p.DoPointer(write_ptr, s_video_buffer);
s_video_buffer_write_ptr = write_ptr; s_video_buffer_write_ptr = write_ptr;
p.DoPointer(s_video_buffer_read_ptr, s_video_buffer); p.DoPointer(s_video_buffer_read_ptr, s_video_buffer);
if (p.mode == PointerWrap::MODE_READ && g_use_deterministic_gpu_thread) if (p.mode == PointerWrap::MODE_READ && s_use_deterministic_gpu_thread)
{ {
// We're good and paused, right? // We're good and paused, right?
s_video_buffer_seen_ptr = s_video_buffer_pp_read_ptr = s_video_buffer_read_ptr; s_video_buffer_seen_ptr = s_video_buffer_pp_read_ptr = s_video_buffer_read_ptr;
} }
p.Do(g_bSkipCurrentFrame);
p.Do(s_skip_current_frame);
p.Do(s_last_sync_gpu_tick); p.Do(s_last_sync_gpu_tick);
} }
@ -129,7 +132,12 @@ void Shutdown()
void SetRendering(bool enabled) void SetRendering(bool enabled)
{ {
g_bSkipCurrentFrame = !enabled; s_skip_current_frame = !enabled;
}
bool WillSkipCurrentFrame()
{
return s_skip_current_frame;
} }
// May be executed from any thread, even the graphics thread. // May be executed from any thread, even the graphics thread.
@ -153,7 +161,7 @@ void EmulatorState(bool running)
void SyncGPU(SyncGPUReason reason, bool may_move_read_ptr) void SyncGPU(SyncGPUReason reason, bool may_move_read_ptr)
{ {
if (g_use_deterministic_gpu_thread) if (s_use_deterministic_gpu_thread)
{ {
s_gpu_mainloop.Wait(); s_gpu_mainloop.Wait();
if (!s_gpu_mainloop.IsRunning()) if (!s_gpu_mainloop.IsRunning())
@ -300,7 +308,7 @@ void RunGpuLoop()
if (!s_emu_running_state.load()) if (!s_emu_running_state.load())
return; return;
if (g_use_deterministic_gpu_thread) if (s_use_deterministic_gpu_thread)
{ {
AsyncRequests::GetInstance()->PullEvents(); AsyncRequests::GetInstance()->PullEvents();
@ -386,7 +394,7 @@ void FlushGpu()
{ {
const SConfig& param = SConfig::GetInstance(); const SConfig& param = SConfig::GetInstance();
if (!param.bCPUThread || g_use_deterministic_gpu_thread) if (!param.bCPUThread || s_use_deterministic_gpu_thread)
return; return;
s_gpu_mainloop.Wait(); s_gpu_mainloop.Wait();
@ -409,12 +417,12 @@ void RunGpu()
const SConfig& param = SConfig::GetInstance(); const SConfig& param = SConfig::GetInstance();
// execute GPU // execute GPU
if (!param.bCPUThread || g_use_deterministic_gpu_thread) if (!param.bCPUThread || s_use_deterministic_gpu_thread)
{ {
bool reset_simd_state = false; bool reset_simd_state = false;
while (fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint() ) while (fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint() )
{ {
if (g_use_deterministic_gpu_thread) if (s_use_deterministic_gpu_thread)
{ {
ReadDataFromFifoOnCPU(fifo.CPReadPointer); ReadDataFromFifoOnCPU(fifo.CPReadPointer);
s_gpu_mainloop.Wakeup(); s_gpu_mainloop.Wakeup();
@ -484,9 +492,9 @@ void UpdateWantDeterminism(bool want)
gpu_thread = gpu_thread && param.bCPUThread; gpu_thread = gpu_thread && param.bCPUThread;
if (g_use_deterministic_gpu_thread != gpu_thread) if (s_use_deterministic_gpu_thread != gpu_thread)
{ {
g_use_deterministic_gpu_thread = gpu_thread; s_use_deterministic_gpu_thread = gpu_thread;
if (gpu_thread) if (gpu_thread)
{ {
// These haven't been updated in non-deterministic mode. // These haven't been updated in non-deterministic mode.
@ -497,6 +505,11 @@ void UpdateWantDeterminism(bool want)
} }
} }
bool UseDeterministicGPUThread()
{
return s_use_deterministic_gpu_thread;
}
/* This function checks the emulated CPU - GPU distance and may wake up the GPU, /* This function checks the emulated CPU - GPU distance and may wake up the GPU,
* or block the CPU if required. It should be called by the CPU thread regulary. * or block the CPU if required. It should be called by the CPU thread regulary.
* @ticks The gone emulated CPU time. * @ticks The gone emulated CPU time.
@ -507,7 +520,7 @@ static int Update(int ticks)
const SConfig& param = SConfig::GetInstance(); const SConfig& param = SConfig::GetInstance();
// GPU is sleeping, so no need for synchronization // GPU is sleeping, so no need for synchronization
if (s_gpu_mainloop.IsDone() || g_use_deterministic_gpu_thread) if (s_gpu_mainloop.IsDone() || s_use_deterministic_gpu_thread)
{ {
if (s_sync_ticks.load() < 0) if (s_sync_ticks.load() < 0)
{ {

View File

@ -4,7 +4,6 @@
#pragma once #pragma once
#include <atomic>
#include <cstddef> #include <cstddef>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
@ -13,19 +12,13 @@ class PointerWrap;
namespace Fifo namespace Fifo
{ {
extern bool g_bSkipCurrentFrame;
// This could be in SConfig, but it depends on multiple settings
// and can change at runtime.
extern bool g_use_deterministic_gpu_thread;
extern std::atomic<u8*> g_video_buffer_write_ptr_xthread;
void Init(); void Init();
void Shutdown(); void Shutdown();
void Prepare(); // Must be called from the CPU thread. void Prepare(); // Must be called from the CPU thread.
void DoState(PointerWrap &f); void DoState(PointerWrap &f);
void PauseAndLock(bool doLock, bool unpauseOnUnlock); void PauseAndLock(bool doLock, bool unpauseOnUnlock);
void UpdateWantDeterminism(bool want); void UpdateWantDeterminism(bool want);
bool UseDeterministicGPUThread();
// Used for diagnostics. // Used for diagnostics.
enum SyncGPUReason enum SyncGPUReason
@ -38,7 +31,7 @@ enum SyncGPUReason
SYNC_GPU_SWAP, SYNC_GPU_SWAP,
SYNC_GPU_AUX_SPACE, SYNC_GPU_AUX_SPACE,
}; };
// In g_use_deterministic_gpu_thread mode, waits for the GPU to be done with pending work. // In deterministic GPU thread mode this waits for the GPU to be done with pending work.
void SyncGPU(SyncGPUReason reason, bool may_move_read_ptr = true); void SyncGPU(SyncGPUReason reason, bool may_move_read_ptr = true);
void PushFifoAuxBuffer(void* ptr, size_t size); void PushFifoAuxBuffer(void* ptr, size_t size);
@ -53,5 +46,6 @@ void EmulatorState(bool running);
bool AtBreakpoint(); bool AtBreakpoint();
void ResetVideoBuffer(); void ResetVideoBuffer();
void SetRendering(bool bEnabled); void SetRendering(bool bEnabled);
bool WillSkipCurrentFrame();
}; } // namespace Fifo

View File

@ -39,7 +39,7 @@ static u32 InterpretDisplayList(u32 address, u32 size)
{ {
u8* startAddress; u8* startAddress;
if (Fifo::g_use_deterministic_gpu_thread) if (Fifo::UseDeterministicGPUThread())
startAddress = (u8*)Fifo::PopFifoAuxBuffer(size); startAddress = (u8*)Fifo::PopFifoAuxBuffer(size);
else else
startAddress = Memory::GetPointer(address); startAddress = Memory::GetPointer(address);
@ -277,7 +277,7 @@ u8* Run(DataReader src, u32* cycles, bool in_display_list)
(cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT, (cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT,
num_vertices, num_vertices,
src, src,
Fifo::g_bSkipCurrentFrame, Fifo::WillSkipCurrentFrame(),
is_preprocess); is_preprocess);
if (bytes < 0) if (bytes < 0)

View File

@ -296,7 +296,7 @@ void SetToken(const u16 _token, const int _bSetTokenAcknowledge)
CommandProcessor::SetInterruptTokenWaiting(true); CommandProcessor::SetInterruptTokenWaiting(true);
if (!SConfig::GetInstance().bCPUThread || Fifo::g_use_deterministic_gpu_thread) if (!SConfig::GetInstance().bCPUThread || Fifo::UseDeterministicGPUThread())
CoreTiming::ScheduleEvent(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16)); CoreTiming::ScheduleEvent(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
else else
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16)); CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
@ -308,7 +308,7 @@ void SetFinish()
{ {
CommandProcessor::SetInterruptFinishWaiting(true); CommandProcessor::SetInterruptFinishWaiting(true);
if (!SConfig::GetInstance().bCPUThread || Fifo::g_use_deterministic_gpu_thread) if (!SConfig::GetInstance().bCPUThread || Fifo::UseDeterministicGPUThread())
CoreTiming::ScheduleEvent(0, et_SetFinishOnMainThread, 0); CoreTiming::ScheduleEvent(0, et_SetFinishOnMainThread, 0);
else else
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetFinishOnMainThread, 0); CoreTiming::ScheduleEvent_Threadsafe(0, et_SetFinishOnMainThread, 0);

View File

@ -259,7 +259,7 @@ void LoadIndexedXF(u32 val, int refarray)
u32* currData = (u32*)(&xfmem) + address; u32* currData = (u32*)(&xfmem) + address;
u32* newData; u32* newData;
if (Fifo::g_use_deterministic_gpu_thread) if (Fifo::UseDeterministicGPUThread())
{ {
newData = (u32*)Fifo::PopFifoAuxBuffer(size * sizeof(u32)); newData = (u32*)Fifo::PopFifoAuxBuffer(size * sizeof(u32));
} }