diff --git a/src/common/thread.h b/src/common/thread.h index 175ba9445..92cc0c59d 100644 --- a/src/common/thread.h +++ b/src/common/thread.h @@ -37,6 +37,10 @@ public: void Start(); void End(); + + std::chrono::nanoseconds GetTotalWait() const { + return total_wait; + } }; } // namespace Common diff --git a/src/core/debug_state.h b/src/core/debug_state.h index aab741fd0..a9e6f48b7 100644 --- a/src/core/debug_state.h +++ b/src/core/debug_state.h @@ -165,7 +165,7 @@ public: debug_message_popup.push(std::move(message)); } - bool& ShowingDebugMenuBar() { + bool& IsShowingDebugMenuBar() { return showing_debug_menu_bar; } diff --git a/src/core/devtools/layer.cpp b/src/core/devtools/layer.cpp index 11990a56f..c652849e7 100644 --- a/src/core/devtools/layer.cpp +++ b/src/core/devtools/layer.cpp @@ -253,7 +253,7 @@ void L::DrawAdvanced() { void L::DrawSimple() { const float frameRate = DebugState.Framerate; - Text("%d FPS (%.1f ms)", static_cast(std::round(1.0f / frameRate)), frameRate * 1000.0f); + Text("%d FPS (%.1f ms)", static_cast(std::round(frameRate)), 1000.0f / frameRate); } static void LoadSettings(const char* line) { @@ -264,7 +264,7 @@ static void LoadSettings(const char* line) { return; } if (sscanf(line, "show_advanced_debug=%d", &i) == 1) { - DebugState.ShowingDebugMenuBar() = i != 0; + DebugState.IsShowingDebugMenuBar() = i != 0; return; } if (sscanf(line, "show_frame_graph=%d", &i) == 1) { @@ -309,7 +309,7 @@ void L::SetupSettings() { handler.WriteAllFn = [](ImGuiContext*, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf) { buf->appendf("[%s][Data]\n", handler->TypeName); buf->appendf("fps_scale=%f\n", fps_scale); - buf->appendf("show_advanced_debug=%d\n", DebugState.ShowingDebugMenuBar()); + buf->appendf("show_advanced_debug=%d\n", DebugState.IsShowingDebugMenuBar()); buf->appendf("show_frame_graph=%d\n", frame_graph.is_open); buf->appendf("dump_frame_count=%d\n", dump_frame_count); buf->append("\n"); @@ -340,7 +340,7 @@ void L::Draw() { if (IsKeyPressed(ImGuiKey_F10, false)) { if (io.KeyCtrl) { - DebugState.ShowingDebugMenuBar() ^= true; + DebugState.IsShowingDebugMenuBar() ^= true; } else { show_simple_fps = !show_simple_fps; } @@ -375,7 +375,7 @@ void L::Draw() { End(); } - if (DebugState.ShowingDebugMenuBar()) { + if (DebugState.IsShowingDebugMenuBar()) { PushFont(io.Fonts->Fonts[IMGUI_FONT_MONO]); PushID("DevtoolsLayer"); DrawAdvanced(); diff --git a/src/core/libraries/videoout/driver.cpp b/src/core/libraries/videoout/driver.cpp index 29948f242..de5421fd7 100644 --- a/src/core/libraries/videoout/driver.cpp +++ b/src/core/libraries/videoout/driver.cpp @@ -9,6 +9,7 @@ #include "core/libraries/kernel/time.h" #include "core/libraries/videoout/driver.h" #include "core/libraries/videoout/videoout_error.h" +#include "imgui/renderer/imgui_core.h" #include "video_core/renderer_vulkan/vk_presenter.h" extern std::unique_ptr presenter; @@ -297,10 +298,12 @@ void VideoOutDriver::PresentThread(std::stop_token token) { if (vblank_status.count % (main_port.flip_rate + 1) == 0) { const auto request = receive_request(); if (!request) { - if (!main_port.is_open) { - DrawBlankFrame(); - } else { - DrawLastFrame(); + if (timer.GetTotalWait().count() < 0) { // Dont draw too fast + if (!main_port.is_open) { + DrawBlankFrame(); + } else if (ImGui::Core::MustKeepDrawing()) { + DrawLastFrame(); + } } } else { Flip(request); diff --git a/src/imgui/renderer/imgui_core.cpp b/src/imgui/renderer/imgui_core.cpp index b63f50340..f3e4609ba 100644 --- a/src/imgui/renderer/imgui_core.cpp +++ b/src/imgui/renderer/imgui_core.cpp @@ -187,7 +187,7 @@ ImGuiID NewFrame(bool is_reusing_frame) { ImGui::NewFrame(); ImGuiWindowFlags flags = ImGuiDockNodeFlags_PassthruCentralNode; - if (!DebugState.ShowingDebugMenuBar()) { + if (!DebugState.IsShowingDebugMenuBar()) { flags |= ImGuiDockNodeFlags_NoTabBar; } ImGuiID dockId = DockSpaceOverViewport(0, GetMainViewport(), flags); @@ -237,6 +237,10 @@ void Render(const vk::CommandBuffer& cmdbuf, const vk::ImageView& image_view, } } +bool MustKeepDrawing() { + return layers.size() > 1 || DebugState.IsShowingDebugMenuBar(); +} + } // namespace Core void Layer::AddLayer(Layer* layer) { diff --git a/src/imgui/renderer/imgui_core.h b/src/imgui/renderer/imgui_core.h index 7d5279bd6..ffee62cf8 100644 --- a/src/imgui/renderer/imgui_core.h +++ b/src/imgui/renderer/imgui_core.h @@ -31,4 +31,6 @@ ImGuiID NewFrame(bool is_reusing_frame = false); void Render(const vk::CommandBuffer& cmdbuf, const vk::ImageView& image_view, const vk::Extent2D& extent); +bool MustKeepDrawing(); // Force the emulator redraw + } // namespace ImGui::Core diff --git a/src/imgui/renderer/imgui_impl_sdl3.cpp b/src/imgui/renderer/imgui_impl_sdl3.cpp index ddd532cd0..ccd31d03a 100644 --- a/src/imgui/renderer/imgui_impl_sdl3.cpp +++ b/src/imgui/renderer/imgui_impl_sdl3.cpp @@ -46,6 +46,11 @@ struct SdlData { ImVector gamepads{}; GamepadMode gamepad_mode{}; bool want_update_gamepads_list{}; + + // Framerate counting (based on ImGui impl) + std::array framerateSecPerFrame; + int framerateSecPerFrameIdx{}; + float framerateSecPerFrameAcc{}; }; // Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui @@ -812,12 +817,15 @@ void NewFrame(bool is_reusing_frame) { : 1.0f / 60.0f; bd->nonReusedtime = current_time; DebugState.FrameDeltaTime = deltaTime; - float distribution = 0.016f / deltaTime / 10.0f; - if (distribution > 1.0f) { - distribution = 1.0f; - } - DebugState.Framerate = - deltaTime * distribution + DebugState.Framerate * (1.0f - distribution); + + int& frameIdx = bd->framerateSecPerFrameIdx; + float& framerateSec = bd->framerateSecPerFrame[frameIdx]; + float& acc = bd->framerateSecPerFrameAcc; + int count = bd->framerateSecPerFrame.size(); + acc += deltaTime - framerateSec; + framerateSec = deltaTime; + frameIdx = (frameIdx + 1) % count; + DebugState.Framerate = acc > 0.0f ? 1.0f / (acc / (float)count) : FLT_MAX; } if (bd->mouse_pending_leave_frame && bd->mouse_pending_leave_frame >= ImGui::GetFrameCount() &&