diff --git a/src/core/gpu.cpp b/src/core/gpu.cpp index c3f7d12b1..eeec705e6 100644 --- a/src/core/gpu.cpp +++ b/src/core/gpu.cpp @@ -302,7 +302,7 @@ void GPU::UpdateCRTCConfig() const TickCount ticks_per_frame = cs.horizontal_total * cs.vertical_total; const double vertical_frequency = static_cast((u64(MASTER_CLOCK) * 11) / 7) / static_cast(ticks_per_frame); - m_system->GetHostInterface()->SetThrottleFrequency(vertical_frequency); + m_system->SetThrottleFrequency(vertical_frequency); const u8 horizontal_resolution_index = m_GPUSTAT.horizontal_resolution_1 | (m_GPUSTAT.horizontal_resolution_2 << 2); cs.dot_clock_divider = dot_clock_dividers[horizontal_resolution_index]; diff --git a/src/core/host_interface.cpp b/src/core/host_interface.cpp index 33260a522..c8283fa75 100644 --- a/src/core/host_interface.cpp +++ b/src/core/host_interface.cpp @@ -6,7 +6,6 @@ #include "common/file_system.h" #include "common/log.h" #include "common/string_util.h" -#include "common/timer.h" #include "dma.h" #include "game_list.h" #include "gpu.h" @@ -20,12 +19,6 @@ #include Log_SetChannel(HostInterface); -#ifdef _WIN32 -#include "common/windows_headers.h" -#else -#include -#endif - #if defined(ANDROID) || (defined(__GNUC__) && __GNUC__ < 8) static std::string GetRelativePath(const std::string& path, const char* new_filename) @@ -58,7 +51,6 @@ HostInterface::HostInterface() m_game_list = std::make_unique(); m_game_list->SetCacheFilename(GetGameListCacheFileName()); m_game_list->SetDatabaseFilename(GetGameListDatabaseFileName()); - m_last_throttle_time = Common::Timer::GetValue(); } HostInterface::~HostInterface() = default; @@ -91,7 +83,6 @@ bool HostInterface::BootSystem(const char* filename, const char* state_filename) void HostInterface::ResetSystem() { m_system->Reset(); - ResetPerformanceCounters(); AddOSDMessage("System reset."); } @@ -138,7 +129,7 @@ void HostInterface::DrawFPSWindow() const bool show_vps = true; const bool show_speed = true; - if (!(show_fps | show_vps | show_speed)) + if (!(show_fps | show_vps | show_speed) || !m_system) return; const ImVec2 window_size = @@ -158,7 +149,7 @@ void HostInterface::DrawFPSWindow() bool first = true; if (show_fps) { - ImGui::Text("%.2f", m_fps); + ImGui::Text("%.2f", m_system->GetFPS()); first = false; } if (show_vps) @@ -174,7 +165,7 @@ void HostInterface::DrawFPSWindow() ImGui::SameLine(); } - ImGui::Text("%.2f", m_vps); + ImGui::Text("%.2f", m_system->GetVPS()); } if (show_speed) { @@ -189,10 +180,11 @@ void HostInterface::DrawFPSWindow() ImGui::SameLine(); } - const u32 rounded_speed = static_cast(std::round(m_speed)); - if (m_speed < 90.0f) + const float speed = m_system->GetEmulationSpeed(); + const u32 rounded_speed = static_cast(std::round(speed)); + if (speed < 90.0f) ImGui::TextColored(ImVec4(1.0f, 0.4f, 0.4f, 1.0f), "%u%%", rounded_speed); - else if (m_speed < 110.0f) + else if (speed < 110.0f) ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, 1.0f), "%u%%", rounded_speed); else ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f), "%u%%", rounded_speed); @@ -347,45 +339,6 @@ std::optional> HostInterface::GetBIOSImage(ConsoleRegion region) return BIOS::LoadImageFromFile(m_settings.bios_path); } -void HostInterface::Throttle() -{ - // Allow variance of up to 40ms either way. - constexpr s64 MAX_VARIANCE_TIME = INT64_C(40000000); - - // Don't sleep for <1ms or >=period. - constexpr s64 MINIMUM_SLEEP_TIME = INT64_C(1000000); - - // Use unsigned for defined overflow/wrap-around. - const u64 time = static_cast(m_throttle_timer.GetTimeNanoseconds()); - const s64 sleep_time = static_cast(m_last_throttle_time - time); - if (std::abs(sleep_time) >= MAX_VARIANCE_TIME) - { -#ifndef _DEBUG - // Don't display the slow messages in debug, it'll always be slow... - // Limit how often the messages are displayed. - if (m_speed_lost_time_timestamp.GetTimeSeconds() >= 1.0f) - { - Log_WarningPrintf("System too %s, lost %.2f ms", sleep_time < 0 ? "slow" : "fast", - static_cast(std::abs(sleep_time) - MAX_VARIANCE_TIME) / 1000000.0); - m_speed_lost_time_timestamp.Reset(); - } -#endif - m_last_throttle_time = 0; - m_throttle_timer.Reset(); - } - else if (sleep_time >= MINIMUM_SLEEP_TIME && sleep_time <= m_throttle_period) - { -#ifdef WIN32 - Sleep(static_cast(sleep_time / 1000000)); -#else - const struct timespec ts = {0, static_cast(sleep_time)}; - nanosleep(&ts, nullptr); -#endif - } - - m_last_throttle_time += m_throttle_period; -} - bool HostInterface::LoadState(const char* filename) { std::unique_ptr stream = FileSystem::OpenFile(filename, BYTESTREAM_OPEN_READ | BYTESTREAM_OPEN_STREAMED); @@ -441,13 +394,13 @@ void HostInterface::UpdateSpeedLimiterState() m_audio_stream->EmptyBuffers(); m_display->SetVSync(video_sync_enabled); - m_throttle_timer.Reset(); - m_last_throttle_time = 0; + if (m_system) + m_system->ResetPerformanceCounters(); } void HostInterface::SwitchGPURenderer() {} -void HostInterface::OnPerformanceCountersUpdated() {} +void HostInterface::OnSystemPerformanceCountersUpdated() {} void HostInterface::OnRunningGameChanged() {} @@ -647,59 +600,3 @@ void HostInterface::ModifyResolutionScale(s32 increment) GPU::VRAM_WIDTH * m_settings.gpu_resolution_scale, GPU::VRAM_HEIGHT * m_settings.gpu_resolution_scale); } - -void HostInterface::RunFrame() -{ - m_frame_timer.Reset(); - m_system->RunFrame(); - UpdatePerformanceCounters(); -} - -void HostInterface::UpdatePerformanceCounters() -{ - const float frame_time = static_cast(m_frame_timer.GetTimeMilliseconds()); - m_average_frame_time_accumulator += frame_time; - m_worst_frame_time_accumulator = std::max(m_worst_frame_time_accumulator, frame_time); - - // update fps counter - const float time = static_cast(m_fps_timer.GetTimeSeconds()); - if (time < 1.0f) - return; - - const float frames_presented = static_cast(m_system->GetFrameNumber() - m_last_frame_number); - - m_worst_frame_time = m_worst_frame_time_accumulator; - m_worst_frame_time_accumulator = 0.0f; - m_average_frame_time = m_average_frame_time_accumulator / frames_presented; - m_average_frame_time_accumulator = 0.0f; - m_vps = static_cast(frames_presented / time); - m_last_frame_number = m_system->GetFrameNumber(); - m_fps = static_cast(m_system->GetInternalFrameNumber() - m_last_internal_frame_number) / time; - m_last_internal_frame_number = m_system->GetInternalFrameNumber(); - m_speed = static_cast(static_cast(m_system->GetGlobalTickCounter() - m_last_global_tick_counter) / - (static_cast(MASTER_CLOCK) * time)) * - 100.0f; - m_last_global_tick_counter = m_system->GetGlobalTickCounter(); - m_fps_timer.Reset(); - - OnPerformanceCountersUpdated(); -} - -void HostInterface::ResetPerformanceCounters() -{ - if (m_system) - { - m_last_frame_number = m_system->GetFrameNumber(); - m_last_internal_frame_number = m_system->GetInternalFrameNumber(); - m_last_global_tick_counter = m_system->GetGlobalTickCounter(); - } - else - { - m_last_frame_number = 0; - m_last_internal_frame_number = 0; - m_last_global_tick_counter = 0; - } - m_average_frame_time_accumulator = 0.0f; - m_worst_frame_time_accumulator = 0.0f; - m_fps_timer.Reset(); -} diff --git a/src/core/host_interface.h b/src/core/host_interface.h index d15346ba5..f5c8a6144 100644 --- a/src/core/host_interface.h +++ b/src/core/host_interface.h @@ -38,9 +38,6 @@ public: /// Returns the game list. const GameList* GetGameList() const { return m_game_list.get(); } - /// Adjusts the throttle frequency, i.e. how many times we should sleep per second. - void SetThrottleFrequency(double frequency) { m_throttle_period = static_cast(1000000000.0 / frequency); } - bool CreateSystem(); bool BootSystem(const char* filename, const char* state_filename); void ResetSystem(); @@ -68,12 +65,7 @@ public: /// Returns a path relative to the user directory. std::string GetUserDirectoryRelativePath(const char* format, ...) const; - /// Throttles the system, i.e. sleeps until it's time to execute the next frame. - void Throttle(); - protected: - using ThrottleClock = std::chrono::steady_clock; - enum : u32 { AUDIO_SAMPLE_RATE = 44100, @@ -90,7 +82,7 @@ protected: }; virtual void SwitchGPURenderer(); - virtual void OnPerformanceCountersUpdated(); + virtual void OnSystemPerformanceCountersUpdated(); virtual void OnRunningGameChanged(); void SetUserDirectory(); @@ -132,8 +124,6 @@ protected: /// Adjusts the internal (render) resolution of the hardware backends. void ModifyResolutionScale(s32 increment); - void RunFrame(); - void UpdateSpeedLimiterState(); void DrawFPSWindow(); @@ -141,9 +131,6 @@ protected: void DrawDebugWindows(); void ClearImGuiFocus(); - void UpdatePerformanceCounters(); - void ResetPerformanceCounters(); - std::unique_ptr m_display; std::unique_ptr m_audio_stream; std::unique_ptr m_system; @@ -151,29 +138,10 @@ protected: Settings m_settings; std::string m_user_directory; - u64 m_last_throttle_time = 0; - s64 m_throttle_period = INT64_C(1000000000) / 60; - Common::Timer m_throttle_timer; - Common::Timer m_speed_lost_time_timestamp; - bool m_paused = false; bool m_speed_limiter_temp_disabled = false; bool m_speed_limiter_enabled = false; - float m_average_frame_time_accumulator = 0.0f; - float m_worst_frame_time_accumulator = 0.0f; - - float m_vps = 0.0f; - float m_fps = 0.0f; - float m_speed = 0.0f; - float m_worst_frame_time = 0.0f; - float m_average_frame_time = 0.0f; - u32 m_last_frame_number = 0; - u32 m_last_internal_frame_number = 0; - u32 m_last_global_tick_counter = 0; - Common::Timer m_fps_timer; - Common::Timer m_frame_timer; - std::deque m_osd_messages; std::mutex m_osd_messages_lock; }; diff --git a/src/core/system.cpp b/src/core/system.cpp index f69d60b9a..d7962302a 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -23,6 +23,12 @@ #include Log_SetChannel(System); +#ifdef WIN32 +#include "common/windows_headers.h" +#else +#include +#endif + System::System(HostInterface* host_interface) : m_host_interface(host_interface) { m_cpu = std::make_unique(); @@ -350,6 +356,7 @@ void System::Reset() m_internal_frame_number = 0; m_global_tick_counter = 0; m_last_event_run_time = 0; + ResetPerformanceCounters(); } bool System::LoadState(ByteStream* state) @@ -366,8 +373,10 @@ bool System::SaveState(ByteStream* state) void System::RunFrame() { - // Duplicated to avoid branch in the while loop, as the downcount can be quite low at times. + m_frame_timer.Reset(); m_frame_done = false; + + // Duplicated to avoid branch in the while loop, as the downcount can be quite low at times. if (m_cpu_execution_mode == CPUExecutionMode::Interpreter) { do @@ -389,6 +398,89 @@ void System::RunFrame() // Generate any pending samples from the SPU before sleeping, this way we reduce the chances of underruns. m_spu->GeneratePendingSamples(); + + UpdatePerformanceCounters(); +} + +void System::Throttle() +{ + // Allow variance of up to 40ms either way. + constexpr s64 MAX_VARIANCE_TIME = INT64_C(40000000); + + // Don't sleep for <1ms or >=period. + constexpr s64 MINIMUM_SLEEP_TIME = INT64_C(1000000); + + // Use unsigned for defined overflow/wrap-around. + const u64 time = static_cast(m_throttle_timer.GetTimeNanoseconds()); + const s64 sleep_time = static_cast(m_last_throttle_time - time); + if (std::abs(sleep_time) >= MAX_VARIANCE_TIME) + { +#ifndef _DEBUG + // Don't display the slow messages in debug, it'll always be slow... + // Limit how often the messages are displayed. + if (m_speed_lost_time_timestamp.GetTimeSeconds() >= 1.0f) + { + Log_WarningPrintf("System too %s, lost %.2f ms", sleep_time < 0 ? "slow" : "fast", + static_cast(std::abs(sleep_time) - MAX_VARIANCE_TIME) / 1000000.0); + m_speed_lost_time_timestamp.Reset(); + } +#endif + m_last_throttle_time = 0; + m_throttle_timer.Reset(); + } + else if (sleep_time >= MINIMUM_SLEEP_TIME && sleep_time <= m_throttle_period) + { +#ifdef WIN32 + Sleep(static_cast(sleep_time / 1000000)); +#else + const struct timespec ts = {0, static_cast(sleep_time)}; + nanosleep(&ts, nullptr); +#endif + } + + m_last_throttle_time += m_throttle_period; +} + +void System::UpdatePerformanceCounters() +{ + const float frame_time = static_cast(m_frame_timer.GetTimeMilliseconds()); + m_average_frame_time_accumulator += frame_time; + m_worst_frame_time_accumulator = std::max(m_worst_frame_time_accumulator, frame_time); + + // update fps counter + const float time = static_cast(m_fps_timer.GetTimeSeconds()); + if (time < 1.0f) + return; + + const float frames_presented = static_cast(m_frame_number - m_last_frame_number); + + m_worst_frame_time = m_worst_frame_time_accumulator; + m_worst_frame_time_accumulator = 0.0f; + m_average_frame_time = m_average_frame_time_accumulator / frames_presented; + m_average_frame_time_accumulator = 0.0f; + m_vps = static_cast(frames_presented / time); + m_last_frame_number = m_frame_number; + m_fps = static_cast(m_internal_frame_number - m_last_internal_frame_number) / time; + m_last_internal_frame_number = m_internal_frame_number; + m_speed = static_cast(static_cast(m_global_tick_counter - m_last_global_tick_counter) / + (static_cast(MASTER_CLOCK) * time)) * + 100.0f; + m_last_global_tick_counter = m_global_tick_counter; + m_fps_timer.Reset(); + + m_host_interface->OnSystemPerformanceCountersUpdated(); +} + +void System::ResetPerformanceCounters() +{ + m_last_frame_number = m_frame_number; + m_last_internal_frame_number = m_internal_frame_number; + m_last_global_tick_counter = m_global_tick_counter; + m_average_frame_time_accumulator = 0.0f; + m_worst_frame_time_accumulator = 0.0f; + m_fps_timer.Reset(); + m_throttle_timer.Reset(); + m_last_throttle_time = 0; } bool System::LoadEXE(const char* filename, std::vector& bios_image) diff --git a/src/core/system.h b/src/core/system.h index 9e3f05e91..bde11d87b 100644 --- a/src/core/system.h +++ b/src/core/system.h @@ -1,4 +1,5 @@ #pragma once +#include "common/timer.h" #include "host_interface.h" #include "timing_event.h" #include "types.h" @@ -68,6 +69,12 @@ public: const std::string& GetRunningCode() const { return m_running_game_code; } const std::string& GetRunningTitle() const { return m_running_game_title; } + float GetFPS() const { return m_fps; } + float GetVPS() const { return m_vps; } + float GetEmulationSpeed() const { return m_speed; } + float GetAverageFrameTime() const { return m_average_frame_time; } + float GetWorstFrameTime() const { return m_worst_frame_time; } + bool Boot(const char* filename); void Reset(); @@ -85,6 +92,15 @@ public: void RunFrame(); + /// Adjusts the throttle frequency, i.e. how many times we should sleep per second. + void SetThrottleFrequency(double frequency) { m_throttle_period = static_cast(1000000000.0 / frequency); } + + /// Throttles the system, i.e. sleeps until it's time to execute the next frame. + void Throttle(); + + void UpdatePerformanceCounters(); + void ResetPerformanceCounters(); + bool LoadEXE(const char* filename, std::vector& bios_image); bool SetExpansionROM(const char* filename); @@ -104,8 +120,6 @@ public: std::unique_ptr CreateTimingEvent(std::string name, TickCount period, TickCount interval, TimingEventCallback callback, bool activate); - bool RUNNING_EVENTS() const { return m_running_events; } - private: System(HostInterface* host_interface); @@ -171,4 +185,23 @@ private: std::string m_running_game_path; std::string m_running_game_code; std::string m_running_game_title; + + u64 m_last_throttle_time = 0; + s64 m_throttle_period = INT64_C(1000000000) / 60; + Common::Timer m_throttle_timer; + Common::Timer m_speed_lost_time_timestamp; + + float m_average_frame_time_accumulator = 0.0f; + float m_worst_frame_time_accumulator = 0.0f; + + float m_vps = 0.0f; + float m_fps = 0.0f; + float m_speed = 0.0f; + float m_worst_frame_time = 0.0f; + float m_average_frame_time = 0.0f; + u32 m_last_frame_number = 0; + u32 m_last_internal_frame_number = 0; + u32 m_last_global_tick_counter = 0; + Common::Timer m_fps_timer; + Common::Timer m_frame_timer; }; diff --git a/src/duckstation-qt/mainwindow.cpp b/src/duckstation-qt/mainwindow.cpp index c7c001603..a54f33940 100644 --- a/src/duckstation-qt/mainwindow.cpp +++ b/src/duckstation-qt/mainwindow.cpp @@ -124,8 +124,8 @@ void MainWindow::recreateDisplayWidget(bool create_device_context) updateDebugMenuGPURenderer(); } -void MainWindow::onPerformanceCountersUpdated(float speed, float fps, float vps, float average_frame_time, - float worst_frame_time) +void MainWindow::onSystemPerformanceCountersUpdated(float speed, float fps, float vps, float average_frame_time, + float worst_frame_time) { m_status_speed_widget->setText(QStringLiteral("%1%").arg(speed, 0, 'f', 0)); m_status_fps_widget->setText( @@ -345,8 +345,8 @@ void MainWindow::connectSignals() connect(m_host_interface, &QtHostInterface::toggleFullscreenRequested, this, &MainWindow::toggleFullscreen); connect(m_host_interface, &QtHostInterface::recreateDisplayWidgetRequested, this, &MainWindow::recreateDisplayWidget, Qt::BlockingQueuedConnection); - connect(m_host_interface, &QtHostInterface::performanceCountersUpdated, this, - &MainWindow::onPerformanceCountersUpdated); + connect(m_host_interface, &QtHostInterface::systemPerformanceCountersUpdated, this, + &MainWindow::onSystemPerformanceCountersUpdated); connect(m_host_interface, &QtHostInterface::runningGameChanged, this, &MainWindow::onRunningGameChanged); connect(m_game_list_widget, &GameListWidget::bootEntryRequested, [this](const GameListEntry* entry) { diff --git a/src/duckstation-qt/mainwindow.h b/src/duckstation-qt/mainwindow.h index 8a88f458e..758b78cb3 100644 --- a/src/duckstation-qt/mainwindow.h +++ b/src/duckstation-qt/mainwindow.h @@ -29,8 +29,8 @@ private Q_SLOTS: void onEmulationPaused(bool paused); void toggleFullscreen(); void recreateDisplayWidget(bool create_device_context); - void onPerformanceCountersUpdated(float speed, float fps, float vps, float average_frame_time, - float worst_frame_time); + void onSystemPerformanceCountersUpdated(float speed, float fps, float vps, float average_frame_time, + float worst_frame_time); void onRunningGameChanged(QString filename, QString game_code, QString game_title); void onStartDiscActionTriggered(); diff --git a/src/duckstation-qt/qthostinterface.cpp b/src/duckstation-qt/qthostinterface.cpp index 9ac28ecfc..69811c1ff 100644 --- a/src/duckstation-qt/qthostinterface.cpp +++ b/src/duckstation-qt/qthostinterface.cpp @@ -52,9 +52,7 @@ void QtHostInterface::ReportMessage(const char* message) void QtHostInterface::setDefaultSettings() { - HostInterface::UpdateSettings([this]() { - HostInterface::SetDefaultSettings(); - }); + HostInterface::UpdateSettings([this]() { HostInterface::SetDefaultSettings(); }); // default input settings for Qt std::lock_guard guard(m_qsettings_mutex); @@ -263,16 +261,18 @@ void QtHostInterface::SwitchGPURenderer() m_audio_stream->PauseOutput(false); UpdateSpeedLimiterState(); } - } - ResetPerformanceCounters(); + m_system->ResetPerformanceCounters(); + } } -void QtHostInterface::OnPerformanceCountersUpdated() +void QtHostInterface::OnSystemPerformanceCountersUpdated() { - HostInterface::OnPerformanceCountersUpdated(); + HostInterface::OnSystemPerformanceCountersUpdated(); - emit performanceCountersUpdated(m_speed, m_fps, m_vps, m_average_frame_time, m_worst_frame_time); + DebugAssert(m_system); + emit systemPerformanceCountersUpdated(m_system->GetEmulationSpeed(), m_system->GetFPS(), m_system->GetVPS(), + m_system->GetAverageFrameTime(), m_system->GetWorstFrameTime()); } void QtHostInterface::OnRunningGameChanged() @@ -592,7 +592,7 @@ void QtHostInterface::threadEntryPoint() // execute the system, polling events inbetween frames // simulate the system if not paused - RunFrame(); + m_system->RunFrame(); // rendering { @@ -611,7 +611,7 @@ void QtHostInterface::threadEntryPoint() m_system->GetGPU()->RestoreGraphicsAPIState(); if (m_speed_limiter_enabled) - Throttle(); + m_system->Throttle(); } } diff --git a/src/duckstation-qt/qthostinterface.h b/src/duckstation-qt/qthostinterface.h index b8bdb86ca..337d42776 100644 --- a/src/duckstation-qt/qthostinterface.h +++ b/src/duckstation-qt/qthostinterface.h @@ -71,7 +71,8 @@ Q_SIGNALS: void gameListRefreshed(); void toggleFullscreenRequested(); void recreateDisplayWidgetRequested(bool create_device_context); - void performanceCountersUpdated(float speed, float fps, float vps, float avg_frame_time, float worst_frame_time); + void systemPerformanceCountersUpdated(float speed, float fps, float vps, float avg_frame_time, + float worst_frame_time); void runningGameChanged(QString filename, QString game_code, QString game_title); public Q_SLOTS: @@ -90,7 +91,7 @@ private Q_SLOTS: protected: void SwitchGPURenderer() override; - void OnPerformanceCountersUpdated() override; + void OnSystemPerformanceCountersUpdated() override; void OnRunningGameChanged() override; private: diff --git a/src/duckstation-sdl/sdl_host_interface.cpp b/src/duckstation-sdl/sdl_host_interface.cpp index 3b2b027a6..37258bea3 100644 --- a/src/duckstation-sdl/sdl_host_interface.cpp +++ b/src/duckstation-sdl/sdl_host_interface.cpp @@ -200,7 +200,8 @@ void SDLHostInterface::SwitchGPURenderer() } UpdateFullscreen(); - ResetPerformanceCounters(); + if (m_system) + m_system->ResetPerformanceCounters(); ClearImGuiFocus(); } @@ -886,19 +887,20 @@ void SDLHostInterface::DrawMainMenuBar() { ImGui::SetCursorPosX(ImGui::GetIO().DisplaySize.x - 210.0f); - const u32 rounded_speed = static_cast(std::round(m_speed)); - if (m_speed < 90.0f) + const float speed = m_system->GetEmulationSpeed(); + const u32 rounded_speed = static_cast(std::round(speed)); + if (speed < 90.0f) ImGui::TextColored(ImVec4(1.0f, 0.4f, 0.4f, 1.0f), "%u%%", rounded_speed); - else if (m_speed < 110.0f) + else if (speed < 110.0f) ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, 1.0f), "%u%%", rounded_speed); else ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f), "%u%%", rounded_speed); ImGui::SetCursorPosX(ImGui::GetIO().DisplaySize.x - 165.0f); - ImGui::Text("FPS: %.2f", m_fps); + ImGui::Text("FPS: %.2f", m_system->GetFPS()); ImGui::SetCursorPosX(ImGui::GetIO().DisplaySize.x - 80.0f); - ImGui::Text("VPS: %.2f", m_vps); + ImGui::Text("VPS: %.2f", m_system->GetVPS()); } else { @@ -1458,7 +1460,8 @@ void SDLHostInterface::DoResume() } UpdateControllerMapping(); - ResetPerformanceCounters(); + if (m_system) + m_system->ResetPerformanceCounters(); ClearImGuiFocus(); } @@ -1478,7 +1481,8 @@ void SDLHostInterface::DoStartDisc() } UpdateControllerMapping(); - ResetPerformanceCounters(); + if (m_system) + m_system->ResetPerformanceCounters(); ClearImGuiFocus(); } @@ -1494,7 +1498,8 @@ void SDLHostInterface::DoStartBIOS() } UpdateControllerMapping(); - ResetPerformanceCounters(); + if (m_system) + m_system->ResetPerformanceCounters(); ClearImGuiFocus(); } @@ -1511,7 +1516,8 @@ void SDLHostInterface::DoChangeDisc() else AddOSDMessage("Failed to switch CD. The log may contain further information."); - ResetPerformanceCounters(); + if (m_system) + m_system->ResetPerformanceCounters(); ClearImGuiFocus(); } @@ -1531,7 +1537,8 @@ void SDLHostInterface::DoLoadState(u32 index) } UpdateControllerMapping(); - ResetPerformanceCounters(); + if (m_system) + m_system->ResetPerformanceCounters(); ClearImGuiFocus(); } @@ -1549,7 +1556,7 @@ void SDLHostInterface::DoTogglePause() m_paused = !m_paused; if (!m_paused) - m_fps_timer.Reset(); + m_system->ResetPerformanceCounters(); } void SDLHostInterface::DoFrameStep() @@ -1584,7 +1591,7 @@ void SDLHostInterface::Run() if (m_system && !m_paused) { - RunFrame(); + m_system->RunFrame(); if (m_frame_step_request) { m_frame_step_request = false; @@ -1611,7 +1618,7 @@ void SDLHostInterface::Run() m_system->GetGPU()->RestoreGraphicsAPIState(); if (m_speed_limiter_enabled) - Throttle(); + m_system->Throttle(); } } }