Merge pull request #44 from degasus/throttling
CPU Throttling by CoreTiming
This commit is contained in:
commit
a0a65a2906
|
@ -55,7 +55,7 @@ struct ConfigCache
|
|||
unsigned int framelimit;
|
||||
TEXIDevices m_EXIDevice[MAX_EXI_CHANNELS];
|
||||
std::string strBackend, sBackend;
|
||||
bool bSetFramelimit, bSetEXIDevice[MAX_EXI_CHANNELS], bSetUseFPS, bSetVolume, bSetPads[MAX_SI_CHANNELS], bSetWiimoteSource[MAX_BBMOTES];
|
||||
bool bSetFramelimit, bSetEXIDevice[MAX_EXI_CHANNELS], bSetVolume, bSetPads[MAX_SI_CHANNELS], bSetWiimoteSource[MAX_BBMOTES];
|
||||
};
|
||||
static ConfigCache config_cache;
|
||||
|
||||
|
@ -114,7 +114,6 @@ bool BootCore(const std::string& _rFilename)
|
|||
config_cache.Volume = SConfig::GetInstance().m_Volume;
|
||||
config_cache.sBackend = SConfig::GetInstance().sBackend;
|
||||
config_cache.framelimit = SConfig::GetInstance().m_Framelimit;
|
||||
config_cache.bUseFPS = SConfig::GetInstance().b_UseFPS;
|
||||
for (unsigned int i = 0; i < MAX_BBMOTES; ++i)
|
||||
{
|
||||
config_cache.iWiimoteSource[i] = g_wiimote_sources[i];
|
||||
|
@ -150,8 +149,6 @@ bool BootCore(const std::string& _rFilename)
|
|||
game_ini.Get("Core", "HLE_BS2", &StartUp.bHLE_BS2, StartUp.bHLE_BS2);
|
||||
if (game_ini.Get("Core", "FrameLimit", &SConfig::GetInstance().m_Framelimit, SConfig::GetInstance().m_Framelimit))
|
||||
config_cache.bSetFramelimit = true;
|
||||
if (game_ini.Get("Core", "UseFPS", &SConfig::GetInstance().b_UseFPS, SConfig::GetInstance().b_UseFPS))
|
||||
config_cache.bSetUseFPS = true;
|
||||
if (game_ini.Get("DSP", "Volume", &SConfig::GetInstance().m_Volume, SConfig::GetInstance().m_Volume))
|
||||
config_cache.bSetVolume = true;
|
||||
game_ini.Get("DSP", "EnableJIT", &SConfig::GetInstance().m_EnableJIT, SConfig::GetInstance().m_EnableJIT);
|
||||
|
@ -269,8 +266,6 @@ void Stop()
|
|||
// Only change these back if they were actually set by game ini, since they can be changed while a game is running.
|
||||
if (config_cache.bSetFramelimit)
|
||||
SConfig::GetInstance().m_Framelimit = config_cache.framelimit;
|
||||
if (config_cache.bSetUseFPS)
|
||||
SConfig::GetInstance().b_UseFPS = config_cache.bUseFPS;
|
||||
if (config_cache.bSetVolume)
|
||||
SConfig::GetInstance().m_Volume = config_cache.Volume;
|
||||
|
||||
|
|
|
@ -256,7 +256,6 @@ void SConfig::SaveSettings()
|
|||
ini.Set("Core", "RunCompareServer", m_LocalCoreStartupParameter.bRunCompareServer);
|
||||
ini.Set("Core", "RunCompareClient", m_LocalCoreStartupParameter.bRunCompareClient);
|
||||
ini.Set("Core", "FrameLimit", m_Framelimit);
|
||||
ini.Set("Core", "UseFPS", b_UseFPS);
|
||||
|
||||
// GFX Backend
|
||||
ini.Set("Core", "GFXBackend", m_LocalCoreStartupParameter.m_strVideoBackend);
|
||||
|
@ -419,7 +418,6 @@ void SConfig::LoadSettings()
|
|||
ini.Get("Core", "FastDiscSpeed", &m_LocalCoreStartupParameter.bFastDiscSpeed, false);
|
||||
ini.Get("Core", "DCBZ", &m_LocalCoreStartupParameter.bDCBZOFF, false);
|
||||
ini.Get("Core", "FrameLimit", &m_Framelimit, 1); // auto frame limit by default
|
||||
ini.Get("Core", "UseFPS", &b_UseFPS, false); // use vps as default
|
||||
|
||||
// GFX Backend
|
||||
ini.Get("Core", "GFXBackend", &m_LocalCoreStartupParameter.m_strVideoBackend, "");
|
||||
|
|
|
@ -51,7 +51,6 @@ struct SConfig : NonCopyable
|
|||
int m_InterfaceLanguage;
|
||||
// framelimit choose
|
||||
unsigned int m_Framelimit;
|
||||
bool b_UseFPS;
|
||||
// other interface settings
|
||||
bool m_InterfaceToolbar;
|
||||
bool m_InterfaceStatusbar;
|
||||
|
|
|
@ -613,30 +613,6 @@ bool PauseAndLock(bool doLock, bool unpauseOnUnlock)
|
|||
// This should only be called from VI
|
||||
void VideoThrottle()
|
||||
{
|
||||
u32 TargetVPS = (SConfig::GetInstance().m_Framelimit > 2) ?
|
||||
(SConfig::GetInstance().m_Framelimit - 1) * 5 : VideoInterface::TargetRefreshRate;
|
||||
|
||||
if (Host_GetKeyState('\t'))
|
||||
isTabPressed = true;
|
||||
else
|
||||
isTabPressed = false;
|
||||
|
||||
// Disable the frame-limiter when the throttle (Tab) key is held down. Audio throttle: m_Framelimit = 2
|
||||
if (SConfig::GetInstance().m_Framelimit && SConfig::GetInstance().m_Framelimit != 2 && !Host_GetKeyState('\t'))
|
||||
{
|
||||
u32 frametime = ((SConfig::GetInstance().b_UseFPS)? Common::AtomicLoad(DrawnFrame) : DrawnVideo) * 1000 / TargetVPS;
|
||||
|
||||
u32 timeDifference = (u32)Timer.GetTimeDifference();
|
||||
if (timeDifference < frametime)
|
||||
{
|
||||
Common::SleepCurrentThread(frametime - timeDifference - 1);
|
||||
}
|
||||
|
||||
while ((u32)Timer.GetTimeDifference() < frametime)
|
||||
Common::YieldCPU();
|
||||
//Common::SleepCurrentThread(1);
|
||||
}
|
||||
|
||||
// Update info per second
|
||||
u32 ElapseTime = (u32)Timer.GetTimeDifference();
|
||||
if ((ElapseTime >= 1000 && DrawnVideo > 0) || g_requestRefreshInfo)
|
||||
|
@ -697,9 +673,9 @@ void UpdateTitle()
|
|||
if (ElapseTime == 0)
|
||||
ElapseTime = 1;
|
||||
|
||||
u32 FPS = Common::AtomicLoad(DrawnFrame) * 1000 / ElapseTime;
|
||||
u32 VPS = DrawnVideo * 1000 / ElapseTime;
|
||||
u32 Speed = DrawnVideo * (100 * 1000) / (VideoInterface::TargetRefreshRate * ElapseTime);
|
||||
float FPS = Common::AtomicLoad(DrawnFrame) * 1000.0 / ElapseTime;
|
||||
float VPS = DrawnVideo * 1000.0 / ElapseTime;
|
||||
float Speed = DrawnVideo * (100 * 1000.0) / (VideoInterface::TargetRefreshRate * ElapseTime);
|
||||
|
||||
// Settings are shown the same for both extended and summary info
|
||||
std::string SSettings = StringFromFormat("%s %s | %s | %s", cpu_core_base->GetName(), _CoreParameter.bCPUThread ? "DC" : "SC",
|
||||
|
@ -735,11 +711,11 @@ void UpdateTitle()
|
|||
#else // Summary information
|
||||
std::string SFPS;
|
||||
if (Movie::IsPlayingInput())
|
||||
SFPS = StringFromFormat("VI: %u/%u - Frame: %u/%u - FPS: %u - VPS: %u - %u%%", (u32)Movie::g_currentFrame, (u32)Movie::g_totalFrames, (u32)Movie::g_currentInputCount, (u32)Movie::g_totalInputCount, FPS, VPS, Speed);
|
||||
SFPS = StringFromFormat("VI: %u/%u - Frame: %u/%u - FPS: %.0f - VPS: %.0f - %.0f%%", (u32)Movie::g_currentFrame, (u32)Movie::g_totalFrames, (u32)Movie::g_currentInputCount, (u32)Movie::g_totalInputCount, FPS, VPS, Speed);
|
||||
else if (Movie::IsRecordingInput())
|
||||
SFPS = StringFromFormat("VI: %u - Frame: %u - FPS: %u - VPS: %u - %u%%", (u32)Movie::g_currentFrame, (u32)Movie::g_currentInputCount, FPS, VPS, Speed);
|
||||
SFPS = StringFromFormat("VI: %u - Frame: %u - FPS: %.0f - VPS: %.0f - %.0f%%", (u32)Movie::g_currentFrame, (u32)Movie::g_currentInputCount, FPS, VPS, Speed);
|
||||
else
|
||||
SFPS = StringFromFormat("FPS: %u - VPS: %u - %u%%", FPS, VPS, Speed);
|
||||
SFPS = StringFromFormat("FPS: %.0f - VPS: %.0f - %.0f%%", FPS, VPS, Speed);
|
||||
#endif
|
||||
|
||||
// This is our final "frame counter" string
|
||||
|
|
|
@ -75,6 +75,7 @@ IPC_HLE_PERIOD: For the Wiimote this is the call schedule:
|
|||
#include "Timer.h"
|
||||
#include "VideoBackendBase.h"
|
||||
#include "CommandProcessor.h"
|
||||
#include "Host.h"
|
||||
|
||||
|
||||
namespace SystemTimers
|
||||
|
@ -115,6 +116,7 @@ int et_AudioDMA;
|
|||
int et_DSP;
|
||||
int et_IPC_HLE;
|
||||
int et_PatchEngine; // PatchEngine updates every 1/60th of a second by default
|
||||
int et_Throttle;
|
||||
|
||||
// These are badly educated guesses
|
||||
// Feel free to experiment. Set these in Init below.
|
||||
|
@ -229,6 +231,29 @@ void PatchEngineCallback(u64 userdata, int cyclesLate)
|
|||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame() - cyclesLate, et_PatchEngine);
|
||||
}
|
||||
|
||||
void ThrottleCallback(u64 last_time, int cyclesLate)
|
||||
{
|
||||
u32 time = Common::Timer::GetTimeMs();
|
||||
|
||||
int diff = (u32)last_time - time;
|
||||
bool frame_limiter = SConfig::GetInstance().m_Framelimit && SConfig::GetInstance().m_Framelimit != 2 && !Host_GetKeyState('\t');
|
||||
u32 next_event = GetTicksPerSecond()/1000;
|
||||
if (SConfig::GetInstance().m_Framelimit > 2)
|
||||
{
|
||||
next_event = next_event * (SConfig::GetInstance().m_Framelimit - 1) * 5 / VideoInterface::TargetRefreshRate;
|
||||
}
|
||||
|
||||
const int max_fallback = 40; // 40 ms for one frame on 25 fps games
|
||||
if (frame_limiter && abs(diff) > max_fallback)
|
||||
{
|
||||
WARN_LOG(COMMON, "system too %s, %d ms skipped", diff<0 ? "slow" : "fast", abs(diff) - max_fallback);
|
||||
last_time = time - max_fallback;
|
||||
}
|
||||
else if (frame_limiter && diff > 0)
|
||||
Common::SleepCurrentThread(diff);
|
||||
CoreTiming::ScheduleEvent(next_event - cyclesLate, et_Throttle, last_time + 1);
|
||||
}
|
||||
|
||||
// split from Init to break a circular dependency between VideoInterface::Init and SystemTimers::Init
|
||||
void PreInit()
|
||||
{
|
||||
|
@ -274,11 +299,13 @@ void Init()
|
|||
et_AudioDMA = CoreTiming::RegisterEvent("AudioDMACallback", AudioDMACallback);
|
||||
et_IPC_HLE = CoreTiming::RegisterEvent("IPC_HLE_UpdateCallback", IPC_HLE_UpdateCallback);
|
||||
et_PatchEngine = CoreTiming::RegisterEvent("PatchEngine", PatchEngineCallback);
|
||||
et_Throttle = CoreTiming::RegisterEvent("Throttle", ThrottleCallback);
|
||||
|
||||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerLine(), et_VI);
|
||||
CoreTiming::ScheduleEvent(0, et_DSP);
|
||||
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame(), et_SI);
|
||||
CoreTiming::ScheduleEvent(AUDIO_DMA_PERIOD, et_AudioDMA);
|
||||
CoreTiming::ScheduleEvent(0, et_Throttle, Common::Timer::GetTimeMs());
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSyncGPU)
|
||||
CoreTiming::ScheduleEvent(CP_PERIOD, et_CP);
|
||||
|
||||
|
|
|
@ -118,7 +118,6 @@ EVT_CHECKBOX(ID_CPUTHREAD, CConfigMain::CoreSettingsChanged)
|
|||
EVT_CHECKBOX(ID_IDLESKIP, CConfigMain::CoreSettingsChanged)
|
||||
EVT_CHECKBOX(ID_ENABLECHEATS, CConfigMain::CoreSettingsChanged)
|
||||
EVT_CHOICE(ID_FRAMELIMIT, CConfigMain::CoreSettingsChanged)
|
||||
EVT_CHECKBOX(ID_FRAMELIMIT_USEFPSFORLIMITING, CConfigMain::CoreSettingsChanged)
|
||||
|
||||
EVT_RADIOBOX(ID_CPUENGINE, CConfigMain::CoreSettingsChanged)
|
||||
EVT_CHECKBOX(ID_NTSCJ, CConfigMain::CoreSettingsChanged)
|
||||
|
@ -324,7 +323,6 @@ void CConfigMain::InitializeGUIValues()
|
|||
SkipIdle->SetValue(startup_params.bSkipIdle);
|
||||
EnableCheats->SetValue(startup_params.bEnableCheats);
|
||||
Framelimit->SetSelection(SConfig::GetInstance().m_Framelimit);
|
||||
UseFPSForLimiting->SetValue(SConfig::GetInstance().b_UseFPS);
|
||||
|
||||
// General - Advanced
|
||||
for (unsigned int a = 0; a < (sizeof(CPUCores) / sizeof(CPUCore)); ++a)
|
||||
|
@ -549,7 +547,6 @@ void CConfigMain::CreateGUIControls()
|
|||
EnableCheats = new wxCheckBox(GeneralPage, ID_ENABLECHEATS, _("Enable Cheats"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||
// Framelimit
|
||||
Framelimit = new wxChoice(GeneralPage, ID_FRAMELIMIT, wxDefaultPosition, wxDefaultSize, arrayStringFor_Framelimit, 0, wxDefaultValidator);
|
||||
UseFPSForLimiting = new wxCheckBox(GeneralPage, ID_FRAMELIMIT_USEFPSFORLIMITING, _("Limit by FPS"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||
// Core Settings - Advanced
|
||||
CPUEngine = new wxRadioBox(GeneralPage, ID_CPUENGINE, _("CPU Emulator Engine"), wxDefaultPosition, wxDefaultSize, arrayStringFor_CPUEngine, 0, wxRA_SPECIFY_ROWS);
|
||||
_NTSCJ = new wxCheckBox(GeneralPage, ID_NTSCJ, _("Force Console as NTSC-J"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
|
||||
|
@ -558,7 +555,6 @@ void CConfigMain::CreateGUIControls()
|
|||
wxBoxSizer* sFramelimit = new wxBoxSizer(wxHORIZONTAL);
|
||||
sFramelimit->Add(TEXT_BOX(GeneralPage, _("Framelimit:")), 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
sFramelimit->Add(Framelimit, 0, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 5);
|
||||
sFramelimit->Add(UseFPSForLimiting, 0, wxALL | wxEXPAND, 5);
|
||||
wxStaticBoxSizer* const sbBasic = new wxStaticBoxSizer(wxVERTICAL, GeneralPage, _("Basic Settings"));
|
||||
sbBasic->Add(CPUThread, 0, wxALL, 5);
|
||||
sbBasic->Add(SkipIdle, 0, wxALL, 5);
|
||||
|
@ -890,9 +886,6 @@ void CConfigMain::CoreSettingsChanged(wxCommandEvent& event)
|
|||
SConfig::GetInstance().m_Framelimit = Framelimit->GetSelection();
|
||||
AudioCommon::UpdateSoundStream();
|
||||
break;
|
||||
case ID_FRAMELIMIT_USEFPSFORLIMITING:
|
||||
SConfig::GetInstance().b_UseFPS = UseFPSForLimiting->IsChecked();
|
||||
break;
|
||||
// Core - Advanced
|
||||
case ID_CPUENGINE:
|
||||
SConfig::GetInstance().m_LocalCoreStartupParameter.iCPUCore = CPUCores[CPUEngine->GetSelection()].CPUid;
|
||||
|
|
|
@ -53,7 +53,6 @@ private:
|
|||
ID_IDLESKIP,
|
||||
ID_ENABLECHEATS,
|
||||
ID_FRAMELIMIT,
|
||||
ID_FRAMELIMIT_USEFPSFORLIMITING,
|
||||
|
||||
ID_CPUENGINE,
|
||||
ID_DSPTHREAD,
|
||||
|
@ -123,7 +122,6 @@ private:
|
|||
wxCheckBox* SkipIdle;
|
||||
wxCheckBox* EnableCheats;
|
||||
wxChoice* Framelimit;
|
||||
wxCheckBox* UseFPSForLimiting;
|
||||
|
||||
// Advanced
|
||||
wxRadioBox* CPUEngine;
|
||||
|
|
Loading…
Reference in New Issue