mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-24 06:51:17 +01:00
This could alleviate the suffering of dual core synchronization a bit.
But I doubt you would notice it in most cases. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4830 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
b186f0821e
commit
571a47ef9a
@ -106,7 +106,6 @@ void DSound::SoundLoop()
|
||||
while (!threadData)
|
||||
{
|
||||
// No blocking inside the csection
|
||||
soundCriticalSection.Enter();
|
||||
dsBuffer->GetCurrentPosition((DWORD*)¤tPos, 0);
|
||||
int numBytesToRender = FIX128(ModBufferSize(currentPos - lastPos));
|
||||
if (numBytesToRender >= 256)
|
||||
@ -117,7 +116,6 @@ void DSound::SoundLoop()
|
||||
WriteDataToBuffer(lastPos, (char*)realtimeBuffer, numBytesToRender);
|
||||
lastPos = ModBufferSize(lastPos + numBytesToRender);
|
||||
}
|
||||
soundCriticalSection.Leave();
|
||||
soundSyncEvent.Wait();
|
||||
}
|
||||
}
|
||||
@ -149,10 +147,8 @@ void DSound::SetVolume(int volume)
|
||||
// This is in "dBA attenuation" from 0 to -10000, logarithmic
|
||||
m_volume = (int)floor(log10((float)volume) * 5000.0f) - 10000;
|
||||
|
||||
soundCriticalSection.Enter();
|
||||
if (dsBuffer != NULL)
|
||||
dsBuffer->SetVolume(m_volume);
|
||||
soundCriticalSection.Leave();
|
||||
}
|
||||
|
||||
void DSound::Update()
|
||||
@ -164,7 +160,6 @@ void DSound::Clear(bool mute)
|
||||
{
|
||||
m_muted = mute;
|
||||
|
||||
soundCriticalSection.Enter();
|
||||
if (m_muted)
|
||||
{
|
||||
dsBuffer->Stop();
|
||||
@ -173,7 +168,6 @@ void DSound::Clear(bool mute)
|
||||
{
|
||||
dsBuffer->Play(0, 0, DSBPLAY_LOOPING);
|
||||
}
|
||||
soundCriticalSection.Leave();
|
||||
}
|
||||
|
||||
void DSound::Stop()
|
||||
@ -182,13 +176,11 @@ void DSound::Stop()
|
||||
// kick the thread if it's waiting
|
||||
soundSyncEvent.Set();
|
||||
|
||||
soundCriticalSection.Enter();
|
||||
delete thread;
|
||||
thread = NULL;
|
||||
dsBuffer->Stop();
|
||||
dsBuffer->Release();
|
||||
ds->Release();
|
||||
soundCriticalSection.Leave();
|
||||
|
||||
soundSyncEvent.Shutdown();
|
||||
}
|
||||
|
@ -32,8 +32,7 @@ class DSound : public SoundStream
|
||||
{
|
||||
#ifdef _WIN32
|
||||
Common::Thread *thread;
|
||||
Common::CriticalSection soundCriticalSection;
|
||||
Common::Event soundSyncEvent;
|
||||
Common::EventEx soundSyncEvent;
|
||||
void *hWnd;
|
||||
|
||||
IDirectSound8* ds;
|
||||
|
@ -64,8 +64,7 @@ public:
|
||||
|
||||
private:
|
||||
Common::Thread *thread;
|
||||
Common::CriticalSection soundCriticalSection;
|
||||
Common::Event soundSyncEvent;
|
||||
Common::EventEx soundSyncEvent;
|
||||
|
||||
short realtimeBuffer[OAL_MAX_SAMPLES * 2];
|
||||
ALuint uiBuffers[OAL_NUM_BUFFERS];
|
||||
|
@ -117,6 +117,60 @@ void Thread::SetCurrentThreadAffinity(int mask)
|
||||
SetThreadAffinityMask(GetCurrentThread(), mask);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
EventEx::EventEx()
|
||||
{
|
||||
InterlockedExchange(&m_Lock, 1);
|
||||
}
|
||||
|
||||
void EventEx::Init()
|
||||
{
|
||||
InterlockedExchange(&m_Lock, 1);
|
||||
}
|
||||
|
||||
void EventEx::Shutdown()
|
||||
{
|
||||
InterlockedExchange(&m_Lock, 0);
|
||||
}
|
||||
|
||||
void EventEx::Set()
|
||||
{
|
||||
InterlockedExchange(&m_Lock, 0);
|
||||
}
|
||||
|
||||
void EventEx::Spin()
|
||||
{
|
||||
while (InterlockedCompareExchange(&m_Lock, 1, 0))
|
||||
// This only yields when there is a runnable thread on this core
|
||||
// If not, spin
|
||||
SwitchToThread();
|
||||
}
|
||||
|
||||
void EventEx::Wait()
|
||||
{
|
||||
while (InterlockedCompareExchange(&m_Lock, 1, 0))
|
||||
// This directly enters Ring0 and enforces a sleep about 15ms
|
||||
SleepCurrentThread(1);
|
||||
}
|
||||
|
||||
bool EventEx::MsgWait()
|
||||
{
|
||||
while (InterlockedCompareExchange(&m_Lock, 1, 0))
|
||||
{
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
|
||||
{
|
||||
if (msg.message == WM_QUIT) return false;
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
// This directly enters Ring0 and enforces a sleep about 15ms
|
||||
SleepCurrentThread(1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Regular same thread loop based waiting
|
||||
Event::Event()
|
||||
{
|
||||
@ -164,6 +218,7 @@ void Event::MsgWait()
|
||||
if (msg.message == WM_QUIT)
|
||||
return;
|
||||
// Otherwise, dispatch the message.
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
|
@ -137,7 +137,31 @@ private:
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
// Event(WaitForSingleObject) is too expensive
|
||||
// as it always enters Ring0 regardless of the state of lock
|
||||
// This EventEx will try to stay in Ring3 as much as possible
|
||||
// If the lock can be obtained in the first time, Ring0 won't be entered at all
|
||||
class EventEx
|
||||
{
|
||||
public:
|
||||
EventEx();
|
||||
void Init();
|
||||
void Shutdown();
|
||||
void Set();
|
||||
// Infinite wait
|
||||
void Spin();
|
||||
// Infinite wait with sleep
|
||||
void Wait();
|
||||
// Wait with message processing and sleep
|
||||
bool MsgWait();
|
||||
private:
|
||||
volatile long m_Lock;
|
||||
};
|
||||
#else
|
||||
// TODO: implement for Linux
|
||||
#define EventEx Event
|
||||
#endif
|
||||
|
||||
class Event
|
||||
{
|
||||
@ -182,9 +206,10 @@ 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. This may be more efficient than using
|
||||
// events because event functions use kernel calls.
|
||||
// YieldCPU: This function is only effective on HyperThreading CPU
|
||||
// Use this function during a spin-wait to make the current thread
|
||||
// relax while another thread is working. This may be more efficient
|
||||
// than using events because event functions use kernel calls.
|
||||
inline void YieldCPU()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
@ -548,13 +548,14 @@ void ScreenShot()
|
||||
// This should only be called from VI
|
||||
void VideoThrottle()
|
||||
{
|
||||
u32 TargetVPS = (SConfig::GetInstance().m_Framelimit > 1) ? SConfig::GetInstance().m_Framelimit * 10
|
||||
: VideoInterface::TargetRefreshRate;
|
||||
u32 TargetVPS = (SConfig::GetInstance().m_Framelimit > 1) ?
|
||||
SConfig::GetInstance().m_Framelimit * 10 : VideoInterface::TargetRefreshRate;
|
||||
|
||||
// When frame limit is NOT off
|
||||
if (SConfig::GetInstance().m_Framelimit)
|
||||
{
|
||||
u32 frametime = DrawnVideo * 1000 / TargetVPS;
|
||||
// Make the limiter a bit loose
|
||||
u32 frametime = DrawnVideo * 1000 / ++TargetVPS;
|
||||
while ((u32)Timer.GetTimeDifference() < frametime)
|
||||
Common::YieldCPU();
|
||||
//Common::SleepCurrentThread(1);
|
||||
@ -567,7 +568,7 @@ void VideoThrottle()
|
||||
SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter;
|
||||
|
||||
u32 FPS = Common::AtomicLoad(DrawnFrame) * 1000 / ElapseTime;
|
||||
u32 VPS = DrawnVideo * 1000 / ElapseTime;
|
||||
u32 VPS = --DrawnVideo * 1000 / ElapseTime;
|
||||
u32 Speed = VPS * 100 / VideoInterface::TargetRefreshRate;
|
||||
|
||||
// Settings are shown the same for both extended and summary info
|
||||
@ -611,7 +612,7 @@ void VideoThrottle()
|
||||
SystemTimers::GetTicksPerSecond() / 1000000,
|
||||
_CoreParameter.bSkipIdle ? "~" : "",
|
||||
TicksPercentage);
|
||||
|
||||
|
||||
#else // Summary information
|
||||
std::string SFPS = StringFromFormat("FPS: %u - VPS: %u - SPEED: %u%%", FPS, VPS, Speed);
|
||||
#endif
|
||||
@ -630,7 +631,7 @@ void VideoThrottle()
|
||||
Common::AtomicStore(DrawnFrame, 0);
|
||||
DrawnVideo = 0;
|
||||
}
|
||||
|
||||
|
||||
DrawnVideo++;
|
||||
}
|
||||
|
||||
|
@ -132,13 +132,7 @@ int
|
||||
|
||||
// This is completely arbitrary. If we find that we need lower latency, we can just
|
||||
// increase this number.
|
||||
IPC_HLE_PERIOD,
|
||||
|
||||
// For DC watchdog hack
|
||||
// Once every 4 frame-period seems to be enough (arbitrary taking 60fps as the ref).
|
||||
// TODO: make it VI output frame rate compliant (30/60 and 25/50)
|
||||
// Assuming game's frame-finish-watchdog wait more than 4 emulated frame-period before starting its mess.
|
||||
FAKE_GP_WATCHDOG_PERIOD;
|
||||
IPC_HLE_PERIOD;
|
||||
|
||||
|
||||
|
||||
@ -227,7 +221,7 @@ void AdvanceCallback(int cyclesExecuted)
|
||||
void FakeGPWatchdogCallback(u64 userdata, int cyclesLate)
|
||||
{
|
||||
CPluginManager::GetInstance().GetVideo()->Video_WaitForFrameFinish(); // lock CPUThread until frame finish
|
||||
CoreTiming::ScheduleEvent(FAKE_GP_WATCHDOG_PERIOD-cyclesLate, et_FakeGPWD);
|
||||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame() - cyclesLate, et_FakeGPWD);
|
||||
}
|
||||
|
||||
void PatchEngineCallback(u64 userdata, int cyclesLate)
|
||||
@ -235,7 +229,7 @@ void PatchEngineCallback(u64 userdata, int cyclesLate)
|
||||
// Patch mem and run the Action Replay
|
||||
PatchEngine::ApplyFramePatches();
|
||||
PatchEngine::ApplyARPatches();
|
||||
CoreTiming::ScheduleEvent((GetTicksPerSecond() / 5000) - cyclesLate, et_PatchEngine);
|
||||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame() - cyclesLate, et_PatchEngine);
|
||||
}
|
||||
|
||||
void Init()
|
||||
@ -271,8 +265,6 @@ void Init()
|
||||
if (UsingDSPLLE)
|
||||
DSP_PERIOD = 12000; // TO BE TWEAKED
|
||||
|
||||
FAKE_GP_WATCHDOG_PERIOD = GetTicksPerSecond() / 60;
|
||||
|
||||
// This is the biggest question mark.
|
||||
AI_PERIOD = GetTicksPerSecond() / 80;
|
||||
|
||||
@ -297,16 +289,14 @@ void Init()
|
||||
CoreTiming::ScheduleEvent(AI_PERIOD, et_AI);
|
||||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame(), et_VI);
|
||||
CoreTiming::ScheduleEvent(DSP_PERIOD, et_DSP);
|
||||
CoreTiming::ScheduleEvent(GetTicksPerSecond() / 60, et_SI);
|
||||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame(), et_SI);
|
||||
CoreTiming::ScheduleEvent(AUDIO_DMA_PERIOD, et_AudioDMA);
|
||||
|
||||
// For DC watchdog hack
|
||||
if (Core::GetStartupParameter().bCPUThread)
|
||||
{
|
||||
CoreTiming::ScheduleEvent(FAKE_GP_WATCHDOG_PERIOD, et_FakeGPWD);
|
||||
}
|
||||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame(), et_FakeGPWD);
|
||||
|
||||
CoreTiming::ScheduleEvent(GetTicksPerSecond() / 60, et_PatchEngine);
|
||||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame(), et_PatchEngine);
|
||||
|
||||
if (Core::GetStartupParameter().bWii)
|
||||
CoreTiming::ScheduleEvent(IPC_HLE_PERIOD, et_IPC_HLE);
|
||||
|
@ -391,7 +391,7 @@ void CMemoryWindow::onSearch(wxCommandEvent& event){
|
||||
}
|
||||
if(size){
|
||||
unsigned char* pnt=&Dest.front();
|
||||
int k=0;
|
||||
unsigned int k=0;
|
||||
//grab
|
||||
|
||||
wxString txt = addrbox->GetValue();
|
||||
|
@ -187,7 +187,7 @@ void CLogWindow::LoadSettings()
|
||||
m_verbosity->SetSelection(verbosity - 1);
|
||||
ini.Get("Options", "Font", &font, 0);
|
||||
m_FontChoice->SetSelection(font);
|
||||
if (m_FontChoice->GetSelection() < Font.size())
|
||||
if (m_FontChoice->GetSelection() < (int)Font.size())
|
||||
m_Log->SetDefaultStyle(wxTextAttr(wxNullColour, wxNullColour, Font.at(m_FontChoice->GetSelection())));
|
||||
ini.Get("Options", "WriteToFile", &m_writeFile, true);
|
||||
m_writeFileCB->SetValue(m_writeFile);
|
||||
@ -303,7 +303,7 @@ wxTextCtrl* CLogWindow::CreateTextCtrl(wxPanel* parent, wxWindowID id, long Styl
|
||||
TC->SetBackgroundColour(*wxBLACK);
|
||||
if (m_FontChoice)
|
||||
{
|
||||
if (m_FontChoice->GetSelection() < Font.size())
|
||||
if (m_FontChoice->GetSelection() < (int)Font.size())
|
||||
TC->SetDefaultStyle(wxTextAttr(wxNullColour, wxNullColour, Font.at(m_FontChoice->GetSelection())));
|
||||
}
|
||||
return TC;
|
||||
|
@ -105,7 +105,7 @@ int m_bboxbottom;
|
||||
u16 m_tokenReg;
|
||||
|
||||
static u32 fake_GPWatchdogLastToken = 0;
|
||||
static Common::Event s_fifoIdleEvent;
|
||||
static Common::EventEx s_fifoIdleEvent;
|
||||
static Common::CriticalSection sFifoCritical;
|
||||
|
||||
void FifoCriticalEnter()
|
||||
@ -381,7 +381,7 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||
// Touching that game is a no-go so I don't want to take the risk :p
|
||||
while (fifo.bFF_GPReadEnable && ((!fifo.bFF_BPEnable && fifo.CPReadWriteDistance) || (fifo.bFF_BPEnable && !fifo.bFF_Breakpoint)))
|
||||
{
|
||||
s_fifoIdleEvent.MsgWait();
|
||||
s_fifoIdleEvent.Wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -573,7 +573,7 @@ void WaitForFrameFinish()
|
||||
{
|
||||
while ((fake_GPWatchdogLastToken == fifo.Fake_GPWDToken) && fifo.bFF_GPReadEnable && ((!fifo.bFF_BPEnable && fifo.CPReadWriteDistance) || (fifo.bFF_BPEnable && !fifo.bFF_Breakpoint)));
|
||||
{
|
||||
s_fifoIdleEvent.MsgWait();
|
||||
s_fifoIdleEvent.Wait();
|
||||
}
|
||||
|
||||
fake_GPWatchdogLastToken = fifo.Fake_GPWDToken;
|
||||
@ -618,7 +618,7 @@ void STACKALIGN GatherPipeBursted()
|
||||
// Wait for GPU to catch up
|
||||
while (fifo.CPReadWriteDistance > fifo.CPLoWatermark && fifo.bFF_GPReadEnable && (!fifo.bFF_BPEnable || (fifo.bFF_BPEnable && !fifo.bFF_Breakpoint)))
|
||||
{
|
||||
s_fifoIdleEvent.MsgWait();
|
||||
s_fifoIdleEvent.Wait();
|
||||
}
|
||||
}
|
||||
// check if we are in sync
|
||||
|
@ -36,7 +36,7 @@ namespace
|
||||
static volatile bool fifoStateRun = false;
|
||||
static volatile bool EmuRunning = false;
|
||||
static u8 *videoBuffer;
|
||||
static Common::Event fifo_run_event;
|
||||
static Common::EventEx fifo_run_event;
|
||||
// STATE_TO_SAVE
|
||||
static int size = 0;
|
||||
} // namespace
|
||||
@ -170,6 +170,7 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
|
||||
{
|
||||
Common::AtomicStore(_fifo.bFF_Breakpoint, 1);
|
||||
CommandProcessor::UpdateInterruptsFromVideoPlugin(true);
|
||||
CommandProcessor::FifoCriticalLeave();
|
||||
break;
|
||||
}
|
||||
distToSend = 32;
|
||||
@ -208,10 +209,7 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
|
||||
// leading the CPU thread to wait in Video_BeginField or Video_AccessEFB thus slowing things down.
|
||||
VideoFifo_CheckEFBAccess();
|
||||
VideoFifo_CheckSwapRequest();
|
||||
|
||||
CommandProcessor::SetFifoIdleFromVideoPlugin();
|
||||
}
|
||||
|
||||
CommandProcessor::SetFifoIdleFromVideoPlugin();
|
||||
if (EmuRunning)
|
||||
Common::YieldCPU();
|
||||
|
Loading…
x
Reference in New Issue
Block a user