From 5ebd1e215b29bdbf74317ea1b6cb19578db0e41a Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 23 Jan 2016 23:20:13 -0500 Subject: [PATCH 1/3] Fifo: Make g_bSkipCurrentFrame a TU-local variable This is only ever queried, making it a global isn't necessary. --- Source/Core/VideoBackends/D3D/Render.cpp | 2 +- Source/Core/VideoBackends/OGL/Render.cpp | 2 +- Source/Core/VideoBackends/Software/DebugUtil.cpp | 4 ++-- Source/Core/VideoBackends/Software/EfbCopy.cpp | 2 +- Source/Core/VideoBackends/Software/SWRenderer.cpp | 2 +- Source/Core/VideoCommon/BPStructs.cpp | 2 +- Source/Core/VideoCommon/Fifo.cpp | 12 +++++++++--- Source/Core/VideoCommon/Fifo.h | 5 ++--- Source/Core/VideoCommon/OpcodeDecoding.cpp | 2 +- 9 files changed, 19 insertions(+), 14 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 412e30763c..2c1ca596f7 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -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. 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()) AVIDump::AddFrame(&frame_data[0], fbWidth, fbHeight); diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index b107e95645..bf2da15e3f 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -1260,7 +1260,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co } 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); Core::Callback_VideoCopiedToXFB(false); diff --git a/Source/Core/VideoBackends/Software/DebugUtil.cpp b/Source/Core/VideoBackends/Software/DebugUtil.cpp index e7f3089027..0e2b4e1934 100644 --- a/Source/Core/VideoBackends/Software/DebugUtil.cpp +++ b/Source/Core/VideoBackends/Software/DebugUtil.cpp @@ -191,7 +191,7 @@ void CopyTempBuffer(s16 x, s16 y, int bufferBase, int subBuffer, const char *nam 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) DumpActiveTextures(); @@ -200,7 +200,7 @@ void OnObjectBegin() 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) DumpEfb(StringFromFormat("%sobject%i.png", diff --git a/Source/Core/VideoBackends/Software/EfbCopy.cpp b/Source/Core/VideoBackends/Software/EfbCopy.cpp index b22a70e5cb..34032437c8 100644 --- a/Source/Core/VideoBackends/Software/EfbCopy.cpp +++ b/Source/Core/VideoBackends/Software/EfbCopy.cpp @@ -72,7 +72,7 @@ namespace EfbCopy rc.right = rc.left + (int)bpmem.copyTexSrcWH.x + 1; rc.bottom = rc.top + (int)bpmem.copyTexSrcWH.y + 1; - if (!Fifo::g_bSkipCurrentFrame) + if (!Fifo::WillSkipCurrentFrame()) { if (bpmem.triggerEFBCopy.copy_to_xfb) { diff --git a/Source/Core/VideoBackends/Software/SWRenderer.cpp b/Source/Core/VideoBackends/Software/SWRenderer.cpp index 0f03f3e840..312a315ec7 100644 --- a/Source/Core/VideoBackends/Software/SWRenderer.cpp +++ b/Source/Core/VideoBackends/Software/SWRenderer.cpp @@ -109,7 +109,7 @@ void SWRenderer::UpdateColorTexture(EfbInterface::yuv422_packed *xfb, u32 fbWidt // Called on the GPU thread 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) diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp index 4962dc59ed..ff125652a6 100644 --- a/Source/Core/VideoCommon/BPStructs.cpp +++ b/Source/Core/VideoCommon/BPStructs.cpp @@ -380,7 +380,7 @@ static void BPWritten(const BPCmd& bp) case BPMEM_CLEARBBOX2: // Don't compute bounding box if this frame is being skipped! // Wrong but valid values are better than bogus values... - if (!Fifo::g_bSkipCurrentFrame) + if (!Fifo::WillSkipCurrentFrame()) { u8 offset = bp.address & 2; BoundingBox::active = true; diff --git a/Source/Core/VideoCommon/Fifo.cpp b/Source/Core/VideoCommon/Fifo.cpp index e04f3ffcbf..953484c114 100644 --- a/Source/Core/VideoCommon/Fifo.cpp +++ b/Source/Core/VideoCommon/Fifo.cpp @@ -33,7 +33,7 @@ namespace Fifo 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; @@ -82,7 +82,8 @@ void DoState(PointerWrap &p) // We're good and paused, right? 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); } @@ -129,7 +130,12 @@ void Shutdown() 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. diff --git a/Source/Core/VideoCommon/Fifo.h b/Source/Core/VideoCommon/Fifo.h index b30d41069e..e5e5cd36ac 100644 --- a/Source/Core/VideoCommon/Fifo.h +++ b/Source/Core/VideoCommon/Fifo.h @@ -13,8 +13,6 @@ class PointerWrap; 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; @@ -53,5 +51,6 @@ void EmulatorState(bool running); bool AtBreakpoint(); void ResetVideoBuffer(); void SetRendering(bool bEnabled); +bool WillSkipCurrentFrame(); -}; +} // namespace Fifo diff --git a/Source/Core/VideoCommon/OpcodeDecoding.cpp b/Source/Core/VideoCommon/OpcodeDecoding.cpp index 3af3337b9e..1733a89ad9 100644 --- a/Source/Core/VideoCommon/OpcodeDecoding.cpp +++ b/Source/Core/VideoCommon/OpcodeDecoding.cpp @@ -277,7 +277,7 @@ u8* Run(DataReader src, u32* cycles, bool in_display_list) (cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT, num_vertices, src, - Fifo::g_bSkipCurrentFrame, + Fifo::WillSkipCurrentFrame(), is_preprocess); if (bytes < 0) From 32ce2be2bfc74f0b395800328c494b423480358d Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 23 Jan 2016 23:31:13 -0500 Subject: [PATCH 2/3] Fifo: Make g_use_deterministic_gpu_thread a TU-local variable --- Source/Core/VideoCommon/BPStructs.cpp | 6 ++-- Source/Core/VideoCommon/CommandProcessor.cpp | 4 +-- Source/Core/VideoCommon/Fifo.cpp | 29 ++++++++++++-------- Source/Core/VideoCommon/Fifo.h | 6 ++-- Source/Core/VideoCommon/OpcodeDecoding.cpp | 2 +- Source/Core/VideoCommon/PixelEngine.cpp | 4 +-- Source/Core/VideoCommon/XFStructs.cpp | 2 +- 7 files changed, 29 insertions(+), 24 deletions(-) diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp index ff125652a6..aaa73d991d 100644 --- a/Source/Core/VideoCommon/BPStructs.cpp +++ b/Source/Core/VideoCommon/BPStructs.cpp @@ -179,7 +179,7 @@ static void BPWritten(const BPCmd& bp) switch (bp.newvalue & 0xFF) { case 0x02: - if (!Fifo::g_use_deterministic_gpu_thread) + if (!Fifo::UseDeterministicGPUThread()) PixelEngine::SetFinish(); // may generate interrupt DEBUG_LOG(VIDEO, "GXSetDrawDone SetPEFinish (value: 0x%02X)", (bp.newvalue & 0xFFFF)); return; @@ -190,12 +190,12 @@ static void BPWritten(const BPCmd& bp) } return; case BPMEM_PE_TOKEN_ID: // Pixel Engine Token ID - if (!Fifo::g_use_deterministic_gpu_thread) + if (!Fifo::UseDeterministicGPUThread()) PixelEngine::SetToken(static_cast(bp.newvalue & 0xFFFF), false); DEBUG_LOG(VIDEO, "SetPEToken 0x%04x", (bp.newvalue & 0xFFFF)); return; 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(bp.newvalue & 0xFFFF), true); DEBUG_LOG(VIDEO, "SetPEToken + INT 0x%04x", (bp.newvalue & 0xFFFF)); return; diff --git a/Source/Core/VideoCommon/CommandProcessor.cpp b/Source/Core/VideoCommon/CommandProcessor.cpp index 747bec83fe..92bb3c715d 100644 --- a/Source/Core/VideoCommon/CommandProcessor.cpp +++ b/Source/Core/VideoCommon/CommandProcessor.cpp @@ -302,7 +302,7 @@ void GatherPipeBursted() // if we aren't linked, we don't care about gather pipe data 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. // Fix Pokemon XD in DC mode. @@ -368,7 +368,7 @@ void UpdateInterrupts(u64 userdata) void UpdateInterruptsFromVideoBackend(u64 userdata) { - if (!Fifo::g_use_deterministic_gpu_thread) + if (!Fifo::UseDeterministicGPUThread()) CoreTiming::ScheduleEvent_Threadsafe(0, et_UpdateInterrupts, userdata); } diff --git a/Source/Core/VideoCommon/Fifo.cpp b/Source/Core/VideoCommon/Fifo.cpp index 953484c114..9e383b84d4 100644 --- a/Source/Core/VideoCommon/Fifo.cpp +++ b/Source/Core/VideoCommon/Fifo.cpp @@ -44,7 +44,9 @@ static u8 s_fifo_aux_data[FIFO_SIZE]; static u8* s_fifo_aux_write_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 int s_event_sync_gpu; @@ -56,7 +58,7 @@ static std::atomic s_video_buffer_write_ptr; static std::atomic s_video_buffer_seen_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 -// 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: // - 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 @@ -77,7 +79,7 @@ void DoState(PointerWrap &p) p.DoPointer(write_ptr, s_video_buffer); s_video_buffer_write_ptr = write_ptr; 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? s_video_buffer_seen_ptr = s_video_buffer_pp_read_ptr = s_video_buffer_read_ptr; @@ -159,7 +161,7 @@ void EmulatorState(bool running) 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(); if (!s_gpu_mainloop.IsRunning()) @@ -306,7 +308,7 @@ void RunGpuLoop() if (!s_emu_running_state.load()) return; - if (g_use_deterministic_gpu_thread) + if (s_use_deterministic_gpu_thread) { AsyncRequests::GetInstance()->PullEvents(); @@ -392,7 +394,7 @@ void FlushGpu() { const SConfig& param = SConfig::GetInstance(); - if (!param.bCPUThread || g_use_deterministic_gpu_thread) + if (!param.bCPUThread || s_use_deterministic_gpu_thread) return; s_gpu_mainloop.Wait(); @@ -415,12 +417,12 @@ void RunGpu() const SConfig& param = SConfig::GetInstance(); // execute GPU - if (!param.bCPUThread || g_use_deterministic_gpu_thread) + if (!param.bCPUThread || s_use_deterministic_gpu_thread) { bool reset_simd_state = false; while (fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint() ) { - if (g_use_deterministic_gpu_thread) + if (s_use_deterministic_gpu_thread) { ReadDataFromFifoOnCPU(fifo.CPReadPointer); s_gpu_mainloop.Wakeup(); @@ -490,9 +492,9 @@ void UpdateWantDeterminism(bool want) 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) { // These haven't been updated in non-deterministic mode. @@ -503,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, * or block the CPU if required. It should be called by the CPU thread regulary. * @ticks The gone emulated CPU time. @@ -513,7 +520,7 @@ static int Update(int ticks) const SConfig& param = SConfig::GetInstance(); // 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) { diff --git a/Source/Core/VideoCommon/Fifo.h b/Source/Core/VideoCommon/Fifo.h index e5e5cd36ac..92cfc044af 100644 --- a/Source/Core/VideoCommon/Fifo.h +++ b/Source/Core/VideoCommon/Fifo.h @@ -13,9 +13,6 @@ class PointerWrap; namespace Fifo { -// 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 g_video_buffer_write_ptr_xthread; void Init(); @@ -24,6 +21,7 @@ void Prepare(); // Must be called from the CPU thread. void DoState(PointerWrap &f); void PauseAndLock(bool doLock, bool unpauseOnUnlock); void UpdateWantDeterminism(bool want); +bool UseDeterministicGPUThread(); // Used for diagnostics. enum SyncGPUReason @@ -36,7 +34,7 @@ enum SyncGPUReason SYNC_GPU_SWAP, 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 PushFifoAuxBuffer(void* ptr, size_t size); diff --git a/Source/Core/VideoCommon/OpcodeDecoding.cpp b/Source/Core/VideoCommon/OpcodeDecoding.cpp index 1733a89ad9..32a3782aaf 100644 --- a/Source/Core/VideoCommon/OpcodeDecoding.cpp +++ b/Source/Core/VideoCommon/OpcodeDecoding.cpp @@ -39,7 +39,7 @@ static u32 InterpretDisplayList(u32 address, u32 size) { u8* startAddress; - if (Fifo::g_use_deterministic_gpu_thread) + if (Fifo::UseDeterministicGPUThread()) startAddress = (u8*)Fifo::PopFifoAuxBuffer(size); else startAddress = Memory::GetPointer(address); diff --git a/Source/Core/VideoCommon/PixelEngine.cpp b/Source/Core/VideoCommon/PixelEngine.cpp index eec9a5730a..9b61ecee4c 100644 --- a/Source/Core/VideoCommon/PixelEngine.cpp +++ b/Source/Core/VideoCommon/PixelEngine.cpp @@ -296,7 +296,7 @@ void SetToken(const u16 _token, const int _bSetTokenAcknowledge) 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)); else CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16)); @@ -308,7 +308,7 @@ void SetFinish() { 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); else CoreTiming::ScheduleEvent_Threadsafe(0, et_SetFinishOnMainThread, 0); diff --git a/Source/Core/VideoCommon/XFStructs.cpp b/Source/Core/VideoCommon/XFStructs.cpp index 402f76c493..964dc15355 100644 --- a/Source/Core/VideoCommon/XFStructs.cpp +++ b/Source/Core/VideoCommon/XFStructs.cpp @@ -259,7 +259,7 @@ void LoadIndexedXF(u32 val, int refarray) u32* currData = (u32*)(&xfmem) + address; u32* newData; - if (Fifo::g_use_deterministic_gpu_thread) + if (Fifo::UseDeterministicGPUThread()) { newData = (u32*)Fifo::PopFifoAuxBuffer(size * sizeof(u32)); } From 488e7bd46a2504fc763d65ca5151b66cd83e97f9 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 23 Jan 2016 23:40:30 -0500 Subject: [PATCH 3/3] Fifo: Get rid of undefined global This declaration doesn't have a matching implementation so it can be removed entirely. --- Source/Core/VideoCommon/Fifo.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/Source/Core/VideoCommon/Fifo.h b/Source/Core/VideoCommon/Fifo.h index 92cfc044af..68b9ac2eee 100644 --- a/Source/Core/VideoCommon/Fifo.h +++ b/Source/Core/VideoCommon/Fifo.h @@ -4,7 +4,6 @@ #pragma once -#include #include #include "Common/CommonTypes.h" @@ -13,8 +12,6 @@ class PointerWrap; namespace Fifo { -extern std::atomic g_video_buffer_write_ptr_xthread; - void Init(); void Shutdown(); void Prepare(); // Must be called from the CPU thread.