Fix inverted vsync latch from the implicit swapchain present interval#149
Open
BinqAdams wants to merge 1 commit into
Open
Fix inverted vsync latch from the implicit swapchain present interval#149BinqAdams wants to merge 1 commit into
BinqAdams wants to merge 1 commit into
Conversation
When rtx.enableVsync is in its default WaitingForImplicitSwapchain state, the vsync default is latched from the first swapchain's PresentationInterval with a truthiness check. In D3D9, D3DPRESENT_INTERVAL_IMMEDIATE (the only "present unsynchronized" request) is 0x80000000, i.e. nonzero, so a game explicitly asking for no vsync latches vsync On; D3DPRESENT_INTERVAL_DEFAULT (0), which presents synchronized, latches Off. The two most common values map backwards. A game requesting IMMEDIATE at device creation therefore runs capped to the display refresh with elevated present latency from boot. With DLFG enabled the cap silently clears on the first interpolated 3D frame (dispatchDLFG forces vsync off), which disguises the bug as affecting menus and loading screens only; with DLFG off it persists. The d3d9.presentInterval config cannot help because enableVsyncState overrides the present interval at Present time. Latch Off only for D3DPRESENT_INTERVAL_IMMEDIATE; DEFAULT, ONE and TWO through FOUR latch On, matching D3D9 presentation interval semantics. An explicit rtx.enableVsync user setting still takes precedence.
3f5ae6b to
ae33976
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When
rtx.enableVsyncis in its defaultWaitingForImplicitSwapchainstate, the vsync default is latched from the first swapchain'sPresentationIntervalusing a truthiness check:In D3D9,
D3DPRESENT_INTERVAL_IMMEDIATE(the only "present unsynchronized" request) is0x80000000, i.e. nonzero, so a game explicitly asking for no vsync latches vsync On. ConverselyD3DPRESENT_INTERVAL_DEFAULT(0), which presents synchronized, latches Off. The two most common values map backwards.Observable symptom: a game requesting IMMEDIATE at device creation runs capped to display refresh with elevated present latency (FIFO queue depth) from boot. With DLFG enabled the cap silently clears on the first interpolated 3D frame, since
dispatchDLFGforces vsync off; this disguises the bug as "menus/loading only". With DLFG off it persists. Native present-interval overrides (d3d9.presentInterval) cannot help becauseenableVsyncStateoverrides the interval at Present time.Fix: latch
Offonly forD3DPRESENT_INTERVAL_IMMEDIATE;DEFAULT,ONE, andTWOthroughFOURlatchOn, matching D3D9 presentation-interval semantics. An explicitrtx.enableVsyncuser setting still takes precedence, and the developer-menu V-Sync toggle behaves as before.Testing
Test game: Painkiller Black Edition (D3D9; its device requests a nonzero presentation interval at creation, and IMMEDIATE on the level-load Reset).
Before the fix: the menu frame rate is locked to the display refresh rate (observed 60 on a 60 Hz display; observed as 30/60/120 across different displays in the original report), and cannot be raised by the game's own frame limiter, by
d3d9.presentInterval = 0, or by any present-interval request from the game. Loading a level with frame generation enabled releases the cap; returning to the menu it stays released, since the latch only runs while the option is in its startup state.After the fix: the first menu runs uncapped from the first frame. Verified on the same machine and display as the before measurement, same build otherwise. Setting
rtx.enableVsync = Truere-engages vsync as expected.