Repository navigation
Windows GL: wall-clock pacing instead of driver vsync (windowed/borderless) - #723
Conversation
Windowed or borderless, DWM composes the window and owns the display's vsync, so a driver swap interval only adds a stall. On NVIDIA (RTX 4080 SUPER, 610.88) a vsync'd SwapBuffers holds the GPU queue the render thread submits to: every render-thread frame cost a full refresh (16.7 ms "GPU" at any internal scale, render_busy 100 %), back-pressure slowed the guest to 52-57 Hz, and dynamic resolution dropped for nothing. Measured on R4 0.8 at 7680x4320, windowed and borderless: guest 60.0 Hz, render_busy 5-8 %, GPU 4.4 ms. Exclusive fullscreen keeps driver vsync; PSX_TRUST_DRIVER_VSYNC=1 restores it everywhere. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mstan
left a comment
There was a problem hiding this comment.
Reviewed head 594b507.
The measured NVIDIA stall is a valuable correctness/performance finding. The proposed default policy is broader than that evidence: it disables driver synchronization for every Windows GL windowed/borderless path, including unthreaded rendering and other GPU/driver families, on the assumption that DWM composition always supplies equivalent synchronization. Borderless windows can use independent/direct presentation, and g_fullscreen is requested settings rather than proof of the effective presentation mode. Please qualify the affected path and default behavior with actual swap cadence/tearing/latency evidence, including an unthreaded path and another Windows driver family, or narrow the automatic workaround to the supported conditions. Verify switching windowed/borderless/exclusive and vsync at runtime, and retain a functional synchronized fallback. Coordinate with #712 and #713 so window geometry and cadence are not changed independently to treat the same symptom. A default correctness fix is appropriate once its supported scope is established; another enhancement opt-in is not the rollout solution. Tracking: beads-8zz2.
Narrow host_driver_vsync_unreliable() on Windows to the configuration the stall was measured on: GL active, render thread running, GL_VENDOR NVIDIA, not exclusive fullscreen. Other driver families and the unthreaded path keep driver vsync; PSX_TRUST_DRIVER_VSYNC=1 still forces it everywhere. Evaluated per call, so runtime renderer/fullscreen changes apply. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Narrowed in cb17f2f: the workaround now applies only to the measured case: GL active, render thread running, GL_VENDOR NVIDIA, and not exclusive fullscreen. The unthreaded path, other driver families and exclusive fullscreen keep driver vsync, and PSX_TRUST_DRIVER_VSYNC=1 still forces it. The check runs on every call, so runtime renderer and fullscreen changes take effect. I have not yet measured swap cadence, tearing or latency on another driver family, or done the runtime mode-switch matrix. #712/#713 coordination is still open. |
|
Re-reviewed cb17f2f. Narrowing to active threaded NVIDIA GL is a useful response; the other-driver/unthreaded default-policy objection is addressed by that scope. There is still a lifecycle gap: the new predicate becomes true only after |
|
Maintainer fixes pushed in 3a2057c. The actual swap policy is reapplied immediately after successful render-worker startup and after successful fullscreen changes through the hotkey and live settings path. The predicate now uses the effective window mode, rather than the configured startup preference. Scope remains the measured Windows/NVIDIA/threaded GL path, with the trust-driver fallback. This is a default correctness/performance repair within that scope. The combined native/GL fixture passes; actual runtime startup interval and fallback checks are included in the pending title smoke batch. Tracking: beads-kgof. |
mstan
left a comment
There was a problem hiding this comment.
Maintainer fixes reapply cadence after lazy render-worker startup and effective fullscreen changes. Actual driver readback is interval 0 on the scoped Windows/NVIDIA/threaded path; trust-driver threaded and ordinary unthreaded fallbacks read interval 1. This establishes configuration, not monitor/tearing measurement. The correctness repair applies by default within its narrow scope.
One bounded muted OpenGL boot/progression/visual smoke passed for Tomba, Tomba 2, Ape Escape and Mega Man X6. Tomba 2 reached its title screen after the opening FMV at native aspect; its unsupported widescreen package remains disabled. Supported debug quit returned exit 0 for all four; this is not extended gameplay, normal-teardown or native-card-write qualification.
Combined integration 9ee1a8c63996cc91e4068aa27f100d407ab1ac0e includes #710/#723/#736/#737/#746; #736 remains held for residency policy. Six focused native checks and the GL fixture passed. This evidence qualifies the reviewed heads as a compatible subset, not an exact final-master-tree claim. Tracking: beads-kgof.
What: on Windows with the OpenGL renderer, windowed or borderless,
host_driver_vsync_unreliable()now returns true, as it already does under WSL. The swap interval becomes 0 and the existing wall-clock pacer holds the guest rate. Exclusive fullscreen (fullscreen = 2) keeps driver vsync, andPSX_TRUST_DRIVER_VSYNC=1restores it everywhere. This is a correctness fix, so it is on by default.Why: DWM composes windowed and borderless GL windows and owns the display's vsync. On NVIDIA (RTX 4080 SUPER, driver 610.88), a vsync'd SwapBuffers holds the GPU queue the render thread submits to. Every render-thread frame then costs a full refresh, and the guest slows.
Measured on R4 0.8 at 7680x4320, 60 Hz panel, race savestate:
Same shape as the GL software-present self-heal comment (NVIDIA wglSwapBuffers stalls).
Siblings: #722 (
match_display_max_lines), tetrisgm/RidgeRacerType4Recomp#47 (Max Detail pacing).🤖 Generated with Claude Code