diff --git a/Source/Core/Common/ChunkFile.h b/Source/Core/Common/ChunkFile.h index 8e4280e9ab..2c82749599 100644 --- a/Source/Core/Common/ChunkFile.h +++ b/Source/Core/Common/ChunkFile.h @@ -25,6 +25,7 @@ #include "Common/Common.h" #include "Common/FileUtil.h" +#include "Common/Flag.h" // ewww #if _LIBCPP_VERSION @@ -165,6 +166,14 @@ public: Do(x[i]); } + void Do(Common::Flag& flag) + { + bool s = flag.IsSet(); + Do(s); + if (mode == MODE_READ) + flag.Set(s); + } + template void Do(T& x) { diff --git a/Source/Core/VideoBackends/D3D/main.cpp b/Source/Core/VideoBackends/D3D/main.cpp index 38edd04668..5d6a1c14c9 100644 --- a/Source/Core/VideoBackends/D3D/main.cpp +++ b/Source/Core/VideoBackends/D3D/main.cpp @@ -160,11 +160,6 @@ bool VideoBackend::Initialize(void *window_handle) void VideoBackend::Video_Prepare() { - // Better be safe... - s_efbAccessRequested = FALSE; - s_FifoShuttingDown = FALSE; - s_swapRequested = FALSE; - // internal interfaces g_renderer = new Renderer(m_window_handle); g_texture_cache = new TextureCache; @@ -196,10 +191,6 @@ void VideoBackend::Shutdown() // TODO: should be in Video_Cleanup if (g_renderer) { - s_efbAccessRequested = FALSE; - s_FifoShuttingDown = FALSE; - s_swapRequested = FALSE; - // VideoCommon Fifo_Shutdown(); CommandProcessor::Shutdown(); diff --git a/Source/Core/VideoBackends/OGL/main.cpp b/Source/Core/VideoBackends/OGL/main.cpp index 1a378eb74f..f2741cc9ba 100644 --- a/Source/Core/VideoBackends/OGL/main.cpp +++ b/Source/Core/VideoBackends/OGL/main.cpp @@ -189,10 +189,6 @@ void VideoBackend::Video_Prepare() g_renderer = new Renderer; - s_efbAccessRequested = false; - s_FifoShuttingDown = false; - s_swapRequested = false; - CommandProcessor::Init(); PixelEngine::Init(); @@ -230,9 +226,6 @@ void VideoBackend::Video_Cleanup() { if (g_renderer) { - s_efbAccessRequested = false; - s_FifoShuttingDown = false; - s_swapRequested = false; Fifo_Shutdown(); // The following calls are NOT Thread Safe diff --git a/Source/Core/VideoCommon/CommandProcessor.cpp b/Source/Core/VideoCommon/CommandProcessor.cpp index 9da48f5302..b54e503240 100644 --- a/Source/Core/VideoCommon/CommandProcessor.cpp +++ b/Source/Core/VideoCommon/CommandProcessor.cpp @@ -317,7 +317,7 @@ void STACKALIGN GatherPipeBursted() } if (IsOnThread()) - SetCpStatus(true); + SetCPStatusFromCPU(); // update the fifo pointer if (fifo.CPWritePointer >= fifo.CPEnd) @@ -361,30 +361,17 @@ void UpdateInterruptsFromVideoBackend(u64 userdata) CoreTiming::ScheduleEvent_Threadsafe(0, et_UpdateInterrupts, userdata); } -void SetCpStatus(bool isCPUThread) +void SetCPStatusFromGPU() { - // overflow & underflow check - fifo.bFF_HiWatermark = (fifo.CPReadWriteDistance > fifo.CPHiWatermark); - fifo.bFF_LoWatermark = (fifo.CPReadWriteDistance < fifo.CPLoWatermark); - // breakpoint - if (!isCPUThread) + if (fifo.bFF_BPEnable) { - if (fifo.bFF_BPEnable) + if (fifo.CPBreakpoint == fifo.CPReadPointer) { - if (fifo.CPBreakpoint == fifo.CPReadPointer) + if (!fifo.bFF_Breakpoint) { - if (!fifo.bFF_Breakpoint) - { - INFO_LOG(COMMANDPROCESSOR, "Hit breakpoint at %i", fifo.CPReadPointer); - fifo.bFF_Breakpoint = true; - } - } - else - { - if (fifo.bFF_Breakpoint) - INFO_LOG(COMMANDPROCESSOR, "Cleared breakpoint at %i", fifo.CPReadPointer); - fifo.bFF_Breakpoint = false; + INFO_LOG(COMMANDPROCESSOR, "Hit breakpoint at %i", fifo.CPReadPointer); + fifo.bFF_Breakpoint = true; } } else @@ -394,6 +381,20 @@ void SetCpStatus(bool isCPUThread) fifo.bFF_Breakpoint = false; } } + else + { + if (fifo.bFF_Breakpoint) + INFO_LOG(COMMANDPROCESSOR, "Cleared breakpoint at %i", fifo.CPReadPointer); + fifo.bFF_Breakpoint = false; + } + SetCPStatusFromCPU(); +} + +void SetCPStatusFromCPU() +{ + // overflow & underflow check + fifo.bFF_HiWatermark = (fifo.CPReadWriteDistance > fifo.CPHiWatermark); + fifo.bFF_LoWatermark = (fifo.CPReadWriteDistance < fifo.CPLoWatermark); bool bpInt = fifo.bFF_Breakpoint && fifo.bFF_BPInt; bool ovfInt = fifo.bFF_HiWatermark && fifo.bFF_HiWatermarkInt; @@ -408,15 +409,14 @@ void SetCpStatus(bool isCPUThread) { if (!interrupt || bpInt || undfInt || ovfInt) { - if (!isCPUThread) + if (Core::IsGPUThread()) { - // GPU thread: + // Schedule the interrupt asynchronously interruptWaiting = true; CommandProcessor::UpdateInterruptsFromVideoBackend(userdata); } else { - // CPU thread: interruptSet = interrupt; INFO_LOG(COMMANDPROCESSOR,"Interrupt set"); ProcessorInterface::SetInterrupt(INT_CAUSE_CP, interrupt); diff --git a/Source/Core/VideoCommon/CommandProcessor.h b/Source/Core/VideoCommon/CommandProcessor.h index 300893d755..a70c30fb36 100644 --- a/Source/Core/VideoCommon/CommandProcessor.h +++ b/Source/Core/VideoCommon/CommandProcessor.h @@ -135,7 +135,8 @@ void DoState(PointerWrap &p); void RegisterMMIO(MMIO::Mapping* mmio, u32 base); -void SetCpStatus(bool isCPUThread = false); +void SetCPStatusFromGPU(); +void SetCPStatusFromCPU(); void GatherPipeBursted(); void UpdateInterrupts(u64 userdata); void UpdateInterruptsFromVideoBackend(u64 userdata); diff --git a/Source/Core/VideoCommon/Fifo.cpp b/Source/Core/VideoCommon/Fifo.cpp index 3460b25956..165cd8e239 100644 --- a/Source/Core/VideoCommon/Fifo.cpp +++ b/Source/Core/VideoCommon/Fifo.cpp @@ -148,7 +148,7 @@ void RunGpuLoop() VideoFifo_CheckAsyncRequest(); - CommandProcessor::SetCpStatus(); + CommandProcessor::SetCPStatusFromGPU(); Common::AtomicStore(CommandProcessor::VITicks, CommandProcessor::m_cpClockOrigin); @@ -184,7 +184,7 @@ void RunGpuLoop() Common::AtomicStore(fifo.SafeCPReadPointer, fifo.CPReadPointer); } - CommandProcessor::SetCpStatus(); + CommandProcessor::SetCPStatusFromGPU(); // This call is pretty important in DualCore mode and must be called in the FIFO Loop. // If we don't, s_swapRequested or s_efbAccessRequested won't be set to false @@ -247,5 +247,5 @@ void RunGpu() fifo.CPReadWriteDistance -= 32; } - CommandProcessor::SetCpStatus(); + CommandProcessor::SetCPStatusFromGPU(); } diff --git a/Source/Core/VideoCommon/MainBase.cpp b/Source/Core/VideoCommon/MainBase.cpp index f96201c92d..97a2f5d017 100644 --- a/Source/Core/VideoCommon/MainBase.cpp +++ b/Source/Core/VideoCommon/MainBase.cpp @@ -1,5 +1,4 @@ - -#include "Common/Atomic.h" +#include "Common/Event.h" #include "Core/ConfigManager.h" #include "VideoCommon/BPStructs.h" @@ -18,13 +17,13 @@ bool s_BackendInitialized = false; -volatile u32 s_swapRequested = false; -u32 s_efbAccessRequested = false; -volatile u32 s_FifoShuttingDown = false; +Common::Flag s_swapRequested; +static Common::Flag s_FifoShuttingDown; +static Common::Flag s_efbAccessRequested; +static Common::Event s_efbAccessReadyEvent; -static std::condition_variable s_perf_query_cond; -static std::mutex s_perf_query_lock; -static volatile bool s_perf_query_requested; +static Common::Flag s_perfQueryRequested; +static Common::Event s_perfQueryReadyEvent; static volatile struct { @@ -57,7 +56,9 @@ void VideoBackendHardware::Video_EnterLoop() void VideoBackendHardware::Video_ExitLoop() { ExitGpuLoop(); - s_FifoShuttingDown = true; + s_FifoShuttingDown.Set(); + s_efbAccessReadyEvent.Set(); + s_perfQueryReadyEvent.Set(); } void VideoBackendHardware::Video_SetRendering(bool bEnabled) @@ -70,11 +71,11 @@ static void VideoFifo_CheckSwapRequest() { if (g_ActiveConfig.bUseXFB) { - if (Common::AtomicLoadAcquire(s_swapRequested)) + if (s_swapRequested.IsSet()) { EFBRectangle rc; Renderer::Swap(s_beginFieldArgs.xfbAddr, s_beginFieldArgs.fbWidth, s_beginFieldArgs.fbHeight,rc); - Common::AtomicStoreRelease(s_swapRequested, false); + s_swapRequested.Clear(); } } } @@ -84,7 +85,7 @@ void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight) { if (g_ActiveConfig.bUseXFB) { - if (Common::AtomicLoadAcquire(s_swapRequested)) + if (s_swapRequested.IsSet()) { u32 aLower = xfbAddr; u32 aUpper = xfbAddr + 2 * fbWidth * fbHeight; @@ -115,7 +116,7 @@ void VideoBackendHardware::Video_EndField() { if (s_BackendInitialized) { - Common::AtomicStoreRelease(s_swapRequested, true); + s_swapRequested.Set(); } } @@ -138,11 +139,11 @@ bool VideoBackendHardware::Video_Screenshot(const std::string& filename) void VideoFifo_CheckEFBAccess() { - if (Common::AtomicLoadAcquire(s_efbAccessRequested)) + if (s_efbAccessRequested.IsSet()) { s_AccessEFBResult = g_renderer->AccessEFB(s_accessEFBArgs.type, s_accessEFBArgs.x, s_accessEFBArgs.y, s_accessEFBArgs.Data); - - Common::AtomicStoreRelease(s_efbAccessRequested, false); + s_efbAccessRequested.Clear(); + s_efbAccessReadyEvent.Set(); } } @@ -155,13 +156,15 @@ u32 VideoBackendHardware::Video_AccessEFB(EFBAccessType type, u32 x, u32 y, u32 s_accessEFBArgs.y = y; s_accessEFBArgs.Data = InputData; - Common::AtomicStoreRelease(s_efbAccessRequested, true); + s_efbAccessRequested.Set(); if (SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread) { - while (Common::AtomicLoadAcquire(s_efbAccessRequested) && !s_FifoShuttingDown) - //Common::SleepCurrentThread(1); - Common::YieldCPU(); + s_efbAccessReadyEvent.Reset(); + if (s_FifoShuttingDown.IsSet()) + return 0; + s_efbAccessRequested.Set(); + s_efbAccessReadyEvent.Wait(); } else VideoFifo_CheckEFBAccess(); @@ -172,23 +175,13 @@ u32 VideoBackendHardware::Video_AccessEFB(EFBAccessType type, u32 x, u32 y, u32 return 0; } -static bool QueryResultIsReady() -{ - return !s_perf_query_requested || s_FifoShuttingDown; -} - static void VideoFifo_CheckPerfQueryRequest() { - if (s_perf_query_requested) + if (s_perfQueryRequested.IsSet()) { g_perf_query->FlushResults(); - - { - std::lock_guard lk(s_perf_query_lock); - s_perf_query_requested = false; - } - - s_perf_query_cond.notify_one(); + s_perfQueryRequested.Clear(); + s_perfQueryReadyEvent.Set(); } } @@ -204,9 +197,11 @@ u32 VideoBackendHardware::Video_GetQueryResult(PerfQueryType type) { if (SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread) { - s_perf_query_requested = true; - std::unique_lock lk(s_perf_query_lock); - s_perf_query_cond.wait(lk, QueryResultIsReady); + s_perfQueryReadyEvent.Reset(); + if (s_FifoShuttingDown.IsSet()) + return 0; + s_perfQueryRequested.Set(); + s_perfQueryReadyEvent.Wait(); } else g_perf_query->FlushResults(); @@ -219,10 +214,10 @@ void VideoBackendHardware::InitializeShared() { VideoCommon_Init(); - s_swapRequested = 0; - s_efbAccessRequested = 0; - s_perf_query_requested = false; - s_FifoShuttingDown = 0; + s_swapRequested.Clear(); + s_efbAccessRequested.Clear(); + s_perfQueryRequested.Clear(); + s_FifoShuttingDown.Clear(); memset((void*)&s_beginFieldArgs, 0, sizeof(s_beginFieldArgs)); memset(&s_accessEFBArgs, 0, sizeof(s_accessEFBArgs)); s_AccessEFBResult = 0; diff --git a/Source/Core/VideoCommon/MainBase.h b/Source/Core/VideoCommon/MainBase.h index 3b4d574439..bcef8024ec 100644 --- a/Source/Core/VideoCommon/MainBase.h +++ b/Source/Core/VideoCommon/MainBase.h @@ -1,11 +1,10 @@ #pragma once #include "Common/CommonTypes.h" +#include "Common/Flag.h" extern bool s_BackendInitialized; -extern u32 s_efbAccessRequested; -extern volatile u32 s_FifoShuttingDown; -extern volatile u32 s_swapRequested; +extern Common::Flag s_swapRequested; void VideoFifo_CheckEFBAccess(); void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight); diff --git a/Source/Core/VideoCommon/OpcodeDecoding.cpp b/Source/Core/VideoCommon/OpcodeDecoding.cpp index 4dc80f8c3e..ff9cd8e735 100644 --- a/Source/Core/VideoCommon/OpcodeDecoding.cpp +++ b/Source/Core/VideoCommon/OpcodeDecoding.cpp @@ -469,12 +469,13 @@ void OpcodeDecoder_Shutdown() u32 OpcodeDecoder_Run(bool skipped_frame) { u32 totalCycles = 0; - u32 cycles = FifoCommandRunnable(); - while (cycles > 0) + while (true) { + u32 cycles = FifoCommandRunnable(); + if (cycles == 0) + break; skipped_frame ? DecodeSemiNop() : Decode(); totalCycles += cycles; - cycles = FifoCommandRunnable(); } return totalCycles; } diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index 07b4f8bccb..e877023293 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -126,7 +126,7 @@ void Renderer::RenderToXFB(u32 xfbAddr, const EFBRectangle& sourceRc, u32 fbWidt else { Swap(xfbAddr, fbWidth, fbHeight,sourceRc,Gamma); - Common::AtomicStoreRelease(s_swapRequested, false); + s_swapRequested.Clear(); } }