From a5d65b3b222c0f5306e4f1dd72268491f29b0f07 Mon Sep 17 00:00:00 2001 From: Nolan Check Date: Fri, 17 Jul 2009 22:57:02 +0000 Subject: [PATCH] No more SleepCurrentThreads in Command Processor. Some Fifo cleanup. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3822 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/AudioCommon/Src/Mixer.cpp | 2 +- Source/Core/Common/Src/Thread.h | 13 ++++++ Source/Core/Core/Src/HW/CommandProcessor.cpp | 26 ++--------- Source/Core/Core/Src/HW/CommandProcessor.h | 3 -- Source/Core/VideoCommon/Src/Fifo.cpp | 47 +++++++++----------- Source/Core/VideoCommon/Src/Fifo.h | 2 +- Source/Plugins/Plugin_VideoDX9/Src/main.cpp | 5 +++ Source/Plugins/Plugin_VideoOGL/Src/main.cpp | 4 ++ 8 files changed, 47 insertions(+), 55 deletions(-) diff --git a/Source/Core/AudioCommon/Src/Mixer.cpp b/Source/Core/AudioCommon/Src/Mixer.cpp index 264254e6ed..3a28622c8b 100644 --- a/Source/Core/AudioCommon/Src/Mixer.cpp +++ b/Source/Core/AudioCommon/Src/Mixer.cpp @@ -108,7 +108,7 @@ void CMixer::PushSamples(short *samples, int num_stereo_samples, int core_sample return; } soundStream->Update(); - Common::SleepCurrentThread(0); + Common::YieldCPU(); } // ----------------------------------------------------------------------- diff --git a/Source/Core/Common/Src/Thread.h b/Source/Core/Common/Src/Thread.h index a8c1192a7c..052f3ce02a 100644 --- a/Source/Core/Common/Src/Thread.h +++ b/Source/Core/Common/Src/Thread.h @@ -174,6 +174,19 @@ private: void InitThreading(); void SleepCurrentThread(int ms); +// YieldCPU: Use this function during a spin-wait to make the current thread +// relax while another thread is working. +// If you find yourself calling this function, please consider using an event- +// based design instead. +inline void YieldCPU() +{ +#ifdef _WIN32 + YieldProcessor(); +#else + // TODO: Implement for other platforms. +#endif +} + void SetCurrentThreadName(const char *name); } // namespace Common diff --git a/Source/Core/Core/Src/HW/CommandProcessor.cpp b/Source/Core/Core/Src/HW/CommandProcessor.cpp index 856ab8450f..36c7a7ddb3 100644 --- a/Source/Core/Core/Src/HW/CommandProcessor.cpp +++ b/Source/Core/Core/Src/HW/CommandProcessor.cpp @@ -152,13 +152,6 @@ u16 m_tokenReg; SCPFifoStruct fifo; //This one is shared between gfx thread and emulator thread static u32 fake_GPWatchdogLastToken = 0; -static bool fake_CommandProcessorNotUsed = true; // This is used by VI when homebrews use directly XFB without FIFO and CP - -// hack: This is used by VI when homebrews use directly XFB without FIFO and CP -bool IsCommandProcessorNotUsed() -{ - return fake_CommandProcessorNotUsed; -} void DoState(PointerWrap &p) { @@ -198,7 +191,7 @@ void IncrementGPWDToken() void WaitForFrameFinish() { while ((fake_GPWatchdogLastToken == fifo.Fake_GPWDToken) && fifo.bFF_GPReadEnable && (fifo.CPReadWriteDistance > 0) && !(fifo.bFF_BPEnable && fifo.bFF_Breakpoint)) - Common::SleepCurrentThread(1); + Common::YieldCPU(); fake_GPWatchdogLastToken = fifo.Fake_GPWDToken; } @@ -229,7 +222,6 @@ void Init() fifo.CPReadIdle = 1; et_UpdateInterrupts = CoreTiming::RegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper); - fake_CommandProcessorNotUsed = true; } void Shutdown() @@ -384,12 +376,10 @@ void Write16(const u16 _Value, const u32 _Address) " - We aren't betting on that :)", fifo.CPReadWriteDistance); */ DEBUG_LOG(COMMANDPROCESSOR, "*********************** GXSetGPFifo very soon? ***********************"); - u32 ct=0; // (mb2) We don't sleep here since it could be a perf issue for super monkey ball (yup only this game IIRC) // Touching that game is a no-go so I don't want to take the risk :p while (fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance > 0 ) - ct++; - if (ct) {INFO_LOG(COMMANDPROCESSOR, "(Write16): %lu cycles for nothing :[ ", ct);} + Common::YieldCPU(); } } @@ -424,7 +414,6 @@ void Write16(const u16 _Value, const u32 _Address) case CTRL_REGISTER: { - fake_CommandProcessorNotUsed = false; UCPCtrlReg tmpCtrl(_Value); Common::AtomicStore(fifo.bFF_GPReadEnable, tmpCtrl.GPReadEnable); @@ -604,7 +593,6 @@ void STACKALIGN GatherPipeBursted() Common::AtomicAdd(fifo.CPReadWriteDistance, GPFifo::GATHER_PIPE_SIZE); // High watermark overflow handling (hacked way) - u32 ct = 0; if (fifo.CPReadWriteDistance > fifo.CPHiWatermark) { // we should raise an Ov interrupt for an accurate fifo emulation and let PPC deal with it. @@ -626,15 +614,7 @@ void STACKALIGN GatherPipeBursted() INFO_LOG(COMMANDPROCESSOR, "(GatherPipeBursted): CPHiWatermark reached"); // Wait for GPU to catch up while (!(fifo.bFF_BPEnable && fifo.bFF_Breakpoint) && fifo.CPReadWriteDistance > fifo.CPLoWatermark) - { - ct++; - Common::SleepCurrentThread(1); - } - if (ct) { - // This is actually kind of fine. See big comment above. - DEBUG_LOG(COMMANDPROCESSOR, "(GatherPipeBursted): waited %lu ms. ", ct); - } - /**/ + Common::YieldCPU(); } // check if we are in sync _assert_msg_(COMMANDPROCESSOR, fifo.CPWritePointer == CPeripheralInterface::Fifo_CPUWritePointer, "FIFOs linked but out of sync"); diff --git a/Source/Core/Core/Src/HW/CommandProcessor.h b/Source/Core/Core/Src/HW/CommandProcessor.h index e1408e07d3..e80a980798 100644 --- a/Source/Core/Core/Src/HW/CommandProcessor.h +++ b/Source/Core/Core/Src/HW/CommandProcessor.h @@ -88,9 +88,6 @@ bool AllowIdleSkipping(); void IncrementGPWDToken(); void WaitForFrameFinish(); -// hack: This is used by VI when homebrews use directly XFB without FIFO and CP -bool IsCommandProcessorNotUsed(); - } // end of namespace CommandProcessor #endif diff --git a/Source/Core/VideoCommon/Src/Fifo.cpp b/Source/Core/VideoCommon/Src/Fifo.cpp index 84cb52dc9b..5f1491e6ed 100644 --- a/Source/Core/VideoCommon/Src/Fifo.cpp +++ b/Source/Core/VideoCommon/Src/Fifo.cpp @@ -97,8 +97,7 @@ void Fifo_ExitLoopNonBlocking() { } // Description: Fifo_EnterLoop() sends data through this function. -// TODO: Possibly inline it? This one is exported so it will likely not be inlined at all. -void Video_SendFifoData(u8* _uData, u32 len) +void Fifo_SendFifoData(u8* _uData, u32 len) { if (size + len >= FIFO_SIZE) { @@ -127,12 +126,11 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize) while (fifoStateRun) { -#if defined(_WIN32) video_initialize.pPeekMessages(); -#endif + + VideoFifo_CheckEFBAccess(); VideoFifo_CheckSwapRequest(); - VideoFifo_CheckEFBAccess(); s_criticalFifo.Enter(); @@ -140,18 +138,12 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize) if ((_fifo.bFF_GPReadEnable) && _fifo.CPReadWriteDistance && !(_fifo.bFF_BPEnable && _fifo.bFF_Breakpoint)) { Common::AtomicStore(_fifo.CPReadIdle, 0); - //video_initialize.pLog("RUN...........................",FALSE); - int peek_counter = 0; + while (_fifo.bFF_GPReadEnable && _fifo.CPReadWriteDistance) { if(!fifoStateRun) break; - peek_counter++; - if (peek_counter == 1000) { - video_initialize.pPeekMessages(); - peek_counter = 0; - } // Create pointer to video data and send it to the VideoPlugin u32 readPtr = _fifo.CPReadPointer; u8 *uData = video_initialize.pGetMemoryPointer(readPtr); @@ -162,9 +154,7 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize) { if (readPtr == _fifo.CPBreakpoint) { - video_initialize.pLog("!!! BP irq raised",FALSE); Common::AtomicStore(_fifo.bFF_Breakpoint, 1); - video_initialize.pUpdateInterrupts(); break; } @@ -175,15 +165,6 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize) } else { -#if 0 // ugly random GP slowdown for testing DC robustness... TODO: remove when completly sure DC is ok - int r = rand(); - if ((r & 0xF) == r) - Common::SleepCurrentThread(r); - distToSend = 32; - readPtr += 32; - if (readPtr >= _fifo.CPEnd) - readPtr = _fifo.CPBase; -#else distToSend = _fifo.CPReadWriteDistance; // send 1024B chunk max length to have better control over PeekMessages' period distToSend = distToSend > 1024 ? 1024 : distToSend; @@ -193,17 +174,29 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize) readPtr = _fifo.CPBase; } else - readPtr += distToSend; -#endif + readPtr += distToSend; } + // Execute new instructions found in uData - Video_SendFifoData(uData, distToSend); + Fifo_SendFifoData(uData, distToSend); + Common::AtomicStore(_fifo.CPReadPointer, readPtr); Common::AtomicAdd(_fifo.CPReadWriteDistance, -distToSend); + + video_initialize.pPeekMessages(); + + VideoFifo_CheckEFBAccess(); + + VideoFifo_CheckSwapRequest(); } - //video_initialize.pLog("..........................IDLE",FALSE); + Common::AtomicStore(_fifo.CPReadIdle, 1); } + else + { + Common::YieldCPU(); + } + s_criticalFifo.Leave(); } fifo_exit_event.Set(); diff --git a/Source/Core/VideoCommon/Src/Fifo.h b/Source/Core/VideoCommon/Src/Fifo.h index 5674a7b673..efbf12b7fd 100644 --- a/Source/Core/VideoCommon/Src/Fifo.h +++ b/Source/Core/VideoCommon/Src/Fifo.h @@ -28,7 +28,7 @@ void Fifo_Init(); void Fifo_Shutdown(); -/* void Video_SendFifoData(); */ // defined in plugin spec - implemented in Fifo.cpp +void Fifo_SendFifoData(u8* _uData, u32 len); // These two are for dual core mode only. void Fifo_EnterLoop(const SVideoInitialize &video_initialize); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp index 1b5078dd00..c2a51b7a20 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp @@ -256,6 +256,11 @@ void Shutdown(void) DeInit(); } +void Video_SendFifoData(u8* _uData, u32 len) +{ + Fifo_SendFifoData(_uData, len); +} + void VideoFifo_CheckSwapRequest() { } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp index e4549af63a..125168e059 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp @@ -416,6 +416,10 @@ void Shutdown(void) } +void Video_SendFifoData(u8* _uData, u32 len) +{ + Fifo_SendFifoData(_uData, len); +} // Enter and exit the video loop void Video_EnterLoop()