Throttler: Rename "framelimiter" to "emulation speed".

We don't throttle by frames, we throttle by coretiming speed.
So looking up VI for calculating the speed was just very wrong.
The new ini option is a float, 1.0f for fullspeed.
In the GUI, percentual values are used.
This commit is contained in:
degasus 2015-12-16 00:10:47 +01:00
parent f3098bf426
commit 3ff4ec275a
14 changed files with 86 additions and 69 deletions

View File

@ -11,7 +11,6 @@
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/HW/AudioInterface.h"
#include "Core/HW/VideoInterface.h"
// UGLINESS
#include "Core/PowerPC/PowerPC.h"
@ -60,11 +59,11 @@ unsigned int CMixer::MixerFifo::Mix(short* samples, unsigned int numSamples, boo
//advance indexR with sample position
//remember fractional offset
u32 framelimit = SConfig::GetInstance().m_Framelimit;
float emulationspeed = SConfig::GetInstance().m_EmulationSpeed;
float aid_sample_rate = m_input_sample_rate + offset;
if (consider_framelimit && framelimit > 1)
if (consider_framelimit && emulationspeed > 0.0f)
{
aid_sample_rate = aid_sample_rate * (framelimit - 1) * 5 / VideoInterface::TargetRefreshRate;
aid_sample_rate = aid_sample_rate * emulationspeed;
}
const u32 ratio = (u32)(65536.0f * aid_sample_rate / (float)m_mixer->m_sampleRate);

View File

@ -55,7 +55,7 @@ public:
void RestoreConfig(SConfig* config);
// these store if the relevant setting should be reset back later (true) or if it should be left alone on restore (false)
bool bSetFramelimit, bSetEXIDevice[MAX_EXI_CHANNELS], bSetVolume, bSetPads[MAX_SI_CHANNELS], bSetWiimoteSource[MAX_BBMOTES], bSetFrameSkip;
bool bSetEmulationSpeed, bSetEXIDevice[MAX_EXI_CHANNELS], bSetVolume, bSetPads[MAX_SI_CHANNELS], bSetWiimoteSource[MAX_BBMOTES], bSetFrameSkip;
private:
bool valid, bCPUThread, bSkipIdle, bSyncGPUOnSkipIdleHack, bFPRF, bAccurateNaNs, bMMU, bDCBZOFF, m_EnableJIT,
@ -64,7 +64,8 @@ private:
int iCPUCore, Volume;
int iWiimoteSource[MAX_BBMOTES];
SIDevices Pads[MAX_SI_CHANNELS];
unsigned int framelimit, frameSkip;
unsigned int frameSkip;
float m_EmulationSpeed;
TEXIDevices m_EXIDevice[MAX_EXI_CHANNELS];
std::string strBackend, sBackend;
std::string m_strGPUDeterminismMode;
@ -102,7 +103,7 @@ void ConfigCache::SaveConfig(const SConfig& config)
Pads[i] = config.m_SIDevice[i];
}
framelimit = config.m_Framelimit;
m_EmulationSpeed = config.m_EmulationSpeed;
frameSkip = config.m_FrameSkip;
for (unsigned int i = 0; i < MAX_EXI_CHANNELS; ++i)
@ -114,7 +115,7 @@ void ConfigCache::SaveConfig(const SConfig& config)
sBackend = config.sBackend;
m_strGPUDeterminismMode = config.m_strGPUDeterminismMode;
bSetFramelimit = false;
bSetEmulationSpeed = false;
std::fill_n(bSetEXIDevice, (int)MAX_EXI_CHANNELS, false);
bSetVolume = false;
std::fill_n(bSetPads, (int)MAX_SI_CHANNELS, false);
@ -170,8 +171,8 @@ void ConfigCache::RestoreConfig(SConfig* config)
config->m_SIDevice[i] = Pads[i];
}
if (bSetFramelimit)
config->m_Framelimit = framelimit;
if (bSetEmulationSpeed)
config->m_EmulationSpeed = m_EmulationSpeed;
if (bSetFrameSkip)
{
@ -251,8 +252,8 @@ bool BootCore(const std::string& _rFilename)
core_section->Get("HLE_BS2", &StartUp.bHLE_BS2, StartUp.bHLE_BS2);
core_section->Get("ProgressiveScan", &StartUp.bProgressive, StartUp.bProgressive);
core_section->Get("PAL60", &StartUp.bPAL60, StartUp.bPAL60);
if (core_section->Get("FrameLimit", &SConfig::GetInstance().m_Framelimit, SConfig::GetInstance().m_Framelimit))
config_cache.bSetFramelimit = true;
if (core_section->Get("EmulationSpeed", &SConfig::GetInstance().m_EmulationSpeed, SConfig::GetInstance().m_EmulationSpeed))
config_cache.bSetEmulationSpeed = true;
if (core_section->Get("FrameSkip", &SConfig::GetInstance().m_FrameSkip))
{
config_cache.bSetFrameSkip = true;

View File

@ -261,7 +261,7 @@ void SConfig::SaveCoreSettings(IniFile& ini)
core->Set("WiimoteEnableSpeaker", m_WiimoteEnableSpeaker);
core->Set("RunCompareServer", bRunCompareServer);
core->Set("RunCompareClient", bRunCompareClient);
core->Set("FrameLimit", m_Framelimit);
core->Set("EmulationSpeed", m_EmulationSpeed);
core->Set("FrameSkip", m_FrameSkip);
core->Set("Overclock", m_OCFactor);
core->Set("OverclockEnable", m_OCEnable);
@ -526,7 +526,7 @@ void SConfig::LoadCoreSettings(IniFile& ini)
core->Get("DCBZ", &bDCBZOFF, false);
core->Get("FPRF", &bFPRF, false);
core->Get("AccurateNaNs", &bAccurateNaNs, false);
core->Get("FrameLimit", &m_Framelimit, 1); // auto frame limit by default
core->Get("EmulationSpeed", &m_EmulationSpeed, 1.0f);
core->Get("Overclock", &m_OCFactor, 1.0f);
core->Get("OverclockEnable", &m_OCEnable, false);
core->Get("FrameSkip", &m_FrameSkip, 0);

View File

@ -196,8 +196,7 @@ struct SConfig : NonCopyable
// interface language
int m_InterfaceLanguage;
// framelimit choose
unsigned int m_Framelimit;
float m_EmulationSpeed;
bool m_OCEnable;
float m_OCFactor;
// other interface settings

View File

@ -110,7 +110,7 @@ static StoppedCallbackFunc s_on_stopped_callback = nullptr;
static std::thread s_cpu_thread;
static bool s_request_refresh_info = false;
static int s_pause_and_lock_depth = 0;
static bool s_is_framelimiter_temp_disabled = false;
static bool s_is_throttler_temp_disabled = false;
#ifdef USE_MEMORYWATCHER
static std::unique_ptr<MemoryWatcher> s_memory_watcher;
@ -127,14 +127,14 @@ static void InitIsCPUKey()
}
#endif
bool GetIsFramelimiterTempDisabled()
bool GetIsThrottlerTempDisabled()
{
return s_is_framelimiter_temp_disabled;
return s_is_throttler_temp_disabled;
}
void SetIsFramelimiterTempDisabled(bool disable)
void SetIsThrottlerTempDisabled(bool disable)
{
s_is_framelimiter_temp_disabled = disable;
s_is_throttler_temp_disabled = disable;
}
std::string GetStateFileName() { return s_state_filename; }
@ -746,7 +746,7 @@ bool PauseAndLock(bool doLock, bool unpauseOnUnlock)
return wasUnpaused;
}
// Apply Frame Limit and Display FPS info
// Display FPS info
// This should only be called from VI
void VideoThrottle()
{
@ -767,12 +767,12 @@ void VideoThrottle()
// Executed from GPU thread
// reports if a frame should be skipped or not
// depending on the framelimit set
// depending on the emulation speed set
bool ShouldSkipFrame(int skipped)
{
const u32 TargetFPS = (SConfig::GetInstance().m_Framelimit > 1)
? (SConfig::GetInstance().m_Framelimit - 1) * 5
: VideoInterface::TargetRefreshRate;
u32 TargetFPS = VideoInterface::TargetRefreshRate;
if (SConfig::GetInstance().m_EmulationSpeed > 0.0f)
TargetFPS = u32(TargetFPS * SConfig::GetInstance().m_EmulationSpeed);
const u32 frames = s_drawn_frame.load();
const bool fps_slow = !(s_timer.GetTimeDifference() < (frames + skipped) * 1000 / TargetFPS);

View File

@ -24,8 +24,8 @@ extern bool g_aspect_wide;
extern bool g_want_determinism;
bool GetIsFramelimiterTempDisabled();
void SetIsFramelimiterTempDisabled(bool disable);
bool GetIsThrottlerTempDisabled();
void SetIsThrottlerTempDisabled(bool disable);
void Callback_VideoCopiedToXFB(bool video_update);

View File

@ -195,21 +195,21 @@ static void ThrottleCallback(u64 last_time, int cyclesLate)
int diff = (u32)last_time - time;
const SConfig& config = SConfig::GetInstance();
bool frame_limiter = config.m_Framelimit && !Core::GetIsFramelimiterTempDisabled();
bool frame_limiter = config.m_EmulationSpeed > 0.0f && !Core::GetIsThrottlerTempDisabled();
u32 next_event = GetTicksPerSecond()/1000;
if (config.m_Framelimit > 1)
if (frame_limiter)
{
next_event = next_event * (config.m_Framelimit - 1) * 5 / VideoInterface::TargetRefreshRate;
if (config.m_EmulationSpeed != 1.0f)
next_event = u32(next_event * config.m_EmulationSpeed);
const int max_fallback = config.iTimingVariance;
if (abs(diff) > max_fallback)
{
DEBUG_LOG(COMMON, "system too %s, %d ms skipped", diff<0 ? "slow" : "fast", abs(diff) - max_fallback);
last_time = time - max_fallback;
}
else if (diff > 0)
Common::SleepCurrentThread(diff);
}
const int max_fallback = config.iTimingVariance;
if (frame_limiter && abs(diff) > max_fallback)
{
DEBUG_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);
}

View File

@ -51,8 +51,8 @@ const std::string hotkey_labels[] =
_trans("Toggle EFB Copies"),
_trans("Toggle Fog"),
_trans("Toggle Frame limit"),
_trans("Decrease Frame limit"),
_trans("Increase Frame limit"),
_trans("Decrease Emulation Speed"),
_trans("Increase Emulation Speed"),
_trans("Freelook Decrease Speed"),
_trans("Freelook Increase Speed"),

View File

@ -50,8 +50,8 @@ enum Hotkey
HK_TOGGLE_FOG,
HK_TOGGLE_THROTTLE,
HK_DECREASE_FRAME_LIMIT,
HK_INCREASE_FRAME_LIMIT,
HK_DECREASE_EMULATION_SPEED,
HK_INCREASE_EMULATION_SPEED,
HK_FREELOOK_DECREASE_SPEED,
HK_FREELOOK_INCREASE_SPEED,

View File

@ -39,10 +39,9 @@ GeneralConfigPane::GeneralConfigPane(wxWindow* parent, wxWindowID id)
void GeneralConfigPane::InitializeGUI()
{
m_frame_limit_array_string.Add(_("Off"));
m_frame_limit_array_string.Add(_("Auto"));
for (int i = 5; i <= 120; i += 5) // from 5 to 120
m_frame_limit_array_string.Add(wxString::Format("%i", i));
m_throttler_array_string.Add(_("Unlimited"));
for (int i = 10; i <= 200; i += 10) // from 10% to 200%
m_throttler_array_string.Add(wxString::Format("%i%%", i));
for (const CPUCore& cpu_core : cpu_cores)
m_cpu_engine_array_string.Add(cpu_core.name);
@ -51,31 +50,31 @@ void GeneralConfigPane::InitializeGUI()
m_idle_skip_checkbox = new wxCheckBox(this, wxID_ANY, _("Enable Idle Skipping (speedup)"));
m_cheats_checkbox = new wxCheckBox(this, wxID_ANY, _("Enable Cheats"));
m_force_ntscj_checkbox = new wxCheckBox(this, wxID_ANY, _("Force Console as NTSC-J"));
m_frame_limit_choice = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_frame_limit_array_string);
m_throttler_choice = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_throttler_array_string);
m_cpu_engine_radiobox = new wxRadioBox(this, wxID_ANY, _("CPU Emulator Engine"), wxDefaultPosition, wxDefaultSize, m_cpu_engine_array_string, 0, wxRA_SPECIFY_ROWS);
m_dual_core_checkbox->SetToolTip(_("Splits the CPU and GPU threads so they can be run on separate cores.\nProvides major speed improvements on most modern PCs, but can cause occasional crashes/glitches."));
m_idle_skip_checkbox->SetToolTip(_("Attempt to detect and skip wait-loops.\nIf unsure, leave this checked."));
m_cheats_checkbox->SetToolTip(_("Enables the use of Action Replay and Gecko cheats."));
m_force_ntscj_checkbox->SetToolTip(_("Forces NTSC-J mode for using the Japanese ROM font.\nIf left unchecked, Dolphin defaults to NTSC-U and automatically enables this setting when playing Japanese games."));
m_frame_limit_choice->SetToolTip(_("Limits the game speed to the specified number of frames per second (full speed is 60 for NTSC and 50 for PAL)."));
m_throttler_choice->SetToolTip(_("Limits the emulation speed to the specified percentage.\nNote that raising or lowering the emulation speed will also raise or lower the audio pitch to prevent audio from stuttering."));
m_dual_core_checkbox->Bind(wxEVT_CHECKBOX, &GeneralConfigPane::OnDualCoreCheckBoxChanged, this);
m_idle_skip_checkbox->Bind(wxEVT_CHECKBOX, &GeneralConfigPane::OnIdleSkipCheckBoxChanged, this);
m_cheats_checkbox->Bind(wxEVT_CHECKBOX, &GeneralConfigPane::OnCheatCheckBoxChanged, this);
m_force_ntscj_checkbox->Bind(wxEVT_CHECKBOX, &GeneralConfigPane::OnForceNTSCJCheckBoxChanged, this);
m_frame_limit_choice->Bind(wxEVT_CHOICE, &GeneralConfigPane::OnFrameLimitChoiceChanged, this);
m_throttler_choice->Bind(wxEVT_CHOICE, &GeneralConfigPane::OnThrottlerChoiceChanged, this);
m_cpu_engine_radiobox->Bind(wxEVT_RADIOBOX, &GeneralConfigPane::OnCPUEngineRadioBoxChanged, this);
wxBoxSizer* const frame_limit_sizer = new wxBoxSizer(wxHORIZONTAL);
frame_limit_sizer->Add(new wxStaticText(this, wxID_ANY, _("Framelimit:")), 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT | wxBOTTOM, 5);
frame_limit_sizer->Add(m_frame_limit_choice, 0, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 5);
wxBoxSizer* const throttler_sizer = new wxBoxSizer(wxHORIZONTAL);
throttler_sizer->Add(new wxStaticText(this, wxID_ANY, _("Speed Limit:")), 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT | wxBOTTOM, 5);
throttler_sizer->Add(m_throttler_choice, 0, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 5);
wxStaticBoxSizer* const basic_settings_sizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Basic Settings"));
basic_settings_sizer->Add(m_dual_core_checkbox, 0, wxALL, 5);
basic_settings_sizer->Add(m_idle_skip_checkbox, 0, wxALL, 5);
basic_settings_sizer->Add(m_cheats_checkbox, 0, wxALL, 5);
basic_settings_sizer->Add(frame_limit_sizer);
basic_settings_sizer->Add(throttler_sizer);
wxStaticBoxSizer* const advanced_settings_sizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Advanced Settings"));
advanced_settings_sizer->Add(m_cpu_engine_radiobox, 0, wxALL, 5);
@ -96,7 +95,9 @@ void GeneralConfigPane::LoadGUIValues()
m_idle_skip_checkbox->SetValue(startup_params.bSkipIdle);
m_cheats_checkbox->SetValue(startup_params.bEnableCheats);
m_force_ntscj_checkbox->SetValue(startup_params.bForceNTSCJ);
m_frame_limit_choice->SetSelection(SConfig::GetInstance().m_Framelimit);
u32 selection = std::lround(startup_params.m_EmulationSpeed * 10.0f);
if (selection < m_throttler_array_string.size())
m_throttler_choice->SetSelection(selection);
for (size_t i = 0; i < cpu_cores.size(); ++i)
{
@ -140,9 +141,10 @@ void GeneralConfigPane::OnForceNTSCJCheckBoxChanged(wxCommandEvent& event)
SConfig::GetInstance().bForceNTSCJ = m_force_ntscj_checkbox->IsChecked();
}
void GeneralConfigPane::OnFrameLimitChoiceChanged(wxCommandEvent& event)
void GeneralConfigPane::OnThrottlerChoiceChanged(wxCommandEvent& event)
{
SConfig::GetInstance().m_Framelimit = m_frame_limit_choice->GetSelection();
if (m_throttler_choice->GetSelection() != wxNOT_FOUND)
SConfig::GetInstance().m_EmulationSpeed = m_throttler_choice->GetSelection() * 0.1f;
}
void GeneralConfigPane::OnCPUEngineRadioBoxChanged(wxCommandEvent& event)

View File

@ -32,10 +32,10 @@ private:
void OnIdleSkipCheckBoxChanged(wxCommandEvent&);
void OnCheatCheckBoxChanged(wxCommandEvent&);
void OnForceNTSCJCheckBoxChanged(wxCommandEvent&);
void OnFrameLimitChoiceChanged(wxCommandEvent&);
void OnThrottlerChoiceChanged(wxCommandEvent&);
void OnCPUEngineRadioBoxChanged(wxCommandEvent&);
wxArrayString m_frame_limit_array_string;
wxArrayString m_throttler_array_string;
wxArrayString m_cpu_engine_array_string;
wxCheckBox* m_dual_core_checkbox;
@ -43,7 +43,7 @@ private:
wxCheckBox* m_cheats_checkbox;
wxCheckBox* m_force_ntscj_checkbox;
wxChoice* m_frame_limit_choice;
wxChoice* m_throttler_choice;
wxRadioBox* m_cpu_engine_radiobox;
};

View File

@ -1404,16 +1404,30 @@ void CFrame::ParseHotkeys()
OSDChoice = 4;
g_Config.bDisableFog = !g_Config.bDisableFog;
}
Core::SetIsFramelimiterTempDisabled(IsHotkey(HK_TOGGLE_THROTTLE, true));
if (IsHotkey(HK_DECREASE_FRAME_LIMIT))
Core::SetIsThrottlerTempDisabled(IsHotkey(HK_TOGGLE_THROTTLE, true));
if (IsHotkey(HK_DECREASE_EMULATION_SPEED))
{
if (--SConfig::GetInstance().m_Framelimit > 0x19)
SConfig::GetInstance().m_Framelimit = 0x19;
OSDChoice = 5;
if (SConfig::GetInstance().m_EmulationSpeed <= 0.0f)
SConfig::GetInstance().m_EmulationSpeed = 1.0f;
else if (SConfig::GetInstance().m_EmulationSpeed >= 0.2f)
SConfig::GetInstance().m_EmulationSpeed -= 0.1f;
else
SConfig::GetInstance().m_EmulationSpeed = 0.1f;
if (SConfig::GetInstance().m_EmulationSpeed >= 0.95f && SConfig::GetInstance().m_EmulationSpeed <= 1.05f)
SConfig::GetInstance().m_EmulationSpeed = 1.0f;
}
if (IsHotkey(HK_INCREASE_FRAME_LIMIT))
if (IsHotkey(HK_INCREASE_EMULATION_SPEED))
{
if (++SConfig::GetInstance().m_Framelimit > 0x19)
SConfig::GetInstance().m_Framelimit = 0;
OSDChoice = 5;
if (SConfig::GetInstance().m_EmulationSpeed > 0.0f)
SConfig::GetInstance().m_EmulationSpeed += 0.1f;
if (SConfig::GetInstance().m_EmulationSpeed >= 0.95f && SConfig::GetInstance().m_EmulationSpeed <= 1.05f)
SConfig::GetInstance().m_EmulationSpeed = 1.0f;
}
if (IsHotkey(HK_SAVE_STATE_SLOT_SELECTED))
{

View File

@ -379,6 +379,8 @@ void Renderer::DrawDebugText()
std::string("Aspect Ratio: ") + ar_text + (g_ActiveConfig.bCrop ? " (crop)" : ""),
std::string("Copy EFB: ") + efbcopy_text,
std::string("Fog: ") + (g_ActiveConfig.bDisableFog ? "Disabled" : "Enabled"),
SConfig::GetInstance().m_EmulationSpeed <= 0 ? "Speed Limit: Unlimited" :
StringFromFormat("Speed Limit: %li%%", std::lround(SConfig::GetInstance().m_EmulationSpeed * 100.f)),
};
enum { lines_count = sizeof(lines) / sizeof(*lines) };

View File

@ -311,5 +311,5 @@ void VideoConfig::Save(const std::string& ini_file)
bool VideoConfig::IsVSync()
{
return bVSync && !Core::GetIsFramelimiterTempDisabled();
return bVSync && !Core::GetIsThrottlerTempDisabled();
}