Move input polling to its own thread; fixed-width fast-changing UI numbers

Input thread: controller polling, pad publishing, and rumble forwarding were
driven by the render loop, so a low/synced frame rate throttled how often guest
input reached the game. New InputWorker owns the InputSource and runs poll +
IPC publish + rumble on a dedicated ~1 kHz thread, independent of rendering. The
UI thread reads a copy-safe InputSnapshot for the Controllers panel and relays the
Steam-Input request/active/failed state to/from the worker (Steam init/shutdown now
happen on the worker thread). IpcServer gained a mutex so the worker's publish() /
hook_status() can't race the UI thread starting/stopping the shared-memory channel
(use-after-unmap); InjectionPanel::test_input_ is now atomic. ControllersPanel::draw
takes an InputSnapshot instead of the live InputSource.

Fixed-width numbers: fast-changing readouts (menu-bar FPS/ms, Video pipeline rates +
latency + graph legend, controller poll rates + round-trip sticks, audio buffered ms
+ frames/s) printed with %.0f etc., so they shifted/blurred as values crossed digit
thresholds (99 -> 100) each frame. Padded them to fixed field widths so they stay put.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-21 12:51:00 +02:00
parent feb8fc5dae
commit 4121ad4373
14 changed files with 299 additions and 78 deletions

View File

@@ -145,7 +145,9 @@ float draw_main_menu_bar(UiState& ui, const FrameStats& stats)
// Right-aligned performance readout: stable FPS with the frame-time spread
// (min/max over the last second) so stutter is visible at a glance.
char perf[96];
std::snprintf(perf, sizeof(perf), "%.0f FPS %.2f ms (%.2f-%.2f)", stats.fps(), stats.avg_ms(),
// Fixed field widths so the readout doesn't jitter/blur as values cross digit
// thresholds (e.g. 99 -> 100) each frame.
std::snprintf(perf, sizeof(perf), "%4.0f FPS %6.2f ms (%6.2f-%6.2f)", stats.fps(), stats.avg_ms(),
stats.min_ms(), stats.max_ms());
const float text_w = ImGui::CalcTextSize(perf).x;
ImGui::SameLine(ImGui::GetWindowWidth() - text_w - ImGui::GetStyle().FramePadding.x * 2.0f);