Skip to content

fix(render): vsync-off 下 GUI 撕裂;F10 渲染性能采集 - #4

Merged
gaoyu06 merged 3 commits into
mainfrom
fix/vsync-off-tearing
Oct 16, 2026
Merged

gaoyu06 merged 3 commits into
mainfrom
fix/vsync-off-tearing

Conversation

@gaoyu06

@gaoyu06 gaoyu06 commented Oct 16, 2026

Copy link
Copy Markdown
Member

从本地分支 fix/extreme-ci-macos-build 中挑出两个未合并的提交,rebase 到当前 main。该分支上 3 个 CI 提交已在 main,没有带上。

改动

  • 撕裂修复:关闭 vsync 后走 Immediate 呈现,GUI 会撕裂,看起来像"闪烁/残留上一帧"。现在 gpu::frame_latency_for 按呈现模式选择帧延迟:非同步模式用 1,Fifo 用 2。初始化和切换 vsync 时都会同步更新。另外在 present 前调用 window.pre_present_notify(),并使用不透明 surface。
  • 同一提交还带了几项 UI 改动:GUI 缩放选项(Auto/1..4)、原版标题 logo、splash 文案、version 模块。
  • F10 渲染采集:按 F10 开始/停止逐帧采集,停止后输出帧时间分位数和 GPU/CPU 分项,并写出 perf_capture_<ts>.csv。Shift+F10 保留原来的 mods 热重载。

验证

  • cargo build -p fpsmaster_app 通过
  • cargo test -p fpsmaster_app -p fpsmaster_render:373 passed
  • 未在真机上用 vsync-off 实测撕裂是否消失,合并前需要验证。

The reported "GUI flicker / stale pixels" was screen tearing, not a cache bug.
vsync-off selects the Immediate present mode, and the faster GPU-quad UI (from
the CPU-rasterize -> quad refactor) pushes frames well past the refresh, so the
display scans out torn drawables -- visible only on the crisp, static GUI
(masked entirely by screen recording, which forces compositing at the refresh).

Fix: choose the surface frame latency per present mode (gpu::frame_latency_for)
-- 1 for the unsynced modes so drawable back-pressure paces Immediate to the
refresh at the lowest latency, 2 for Fifo so a spare frame keeps vsync from
hitching on a spike. Applied at init and kept in sync on vsync toggle. Plus
present hygiene: window.pre_present_notify() before present and an opaque
surface.

Also included (already in the working tree): user GUI-scale option
(guiScale Auto/1..4, published once per frame), vanilla title logo + splash
text, a version module, and the title-screen panorama post-pass passthrough.
Toggle a per-frame render capture in-game with F10 (press to start,
press again to stop); Shift+F10 keeps the mods/ hot-reload it replaces.

On stop it logs a statistical summary (frame-time min/avg/p50/p95/p99/max,
1%-low fps, GPU time, CPU pass costs, per-subsystem CPU breakdown, draw
counts) and writes the raw per-frame rows to perf_capture_<ts>.csv for
offline analysis. A red "REC PERF" banner shows while capturing and GPU
timing is forced on so samples carry a real gpu_us.

FrameProfiler now keeps the just-closed frame's per-phase durations
(last_frame_phases) so the capture can sample them each frame.
@gaoyu06
gaoyu06 merged commit a5af4c9 into main Oct 16, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant