Repository navigation
feat(vk): frame generation Auto: a frame for each of the display's refreshes - #1121
Merged
Merged
Conversation
…freshes The Insert menu's Frame generation gets Auto (its value 1, the step it skipped so far). Instead of a whole multiplier, each game frame is given the display's refreshes that fall in its interval (on the game's timeline, a refresh period apart), and each of them a frame made at its place between the two game frames: 45 fps on a 60 Hz display makes one frame for every three of the game's (60 shown a second, at 3/4, 1/2 and 1/4), on 120 Hz 120; at 60 fps on 60 Hz none are made. The display thread shows each at its refresh's time, one game frame later. The sets' frames are made once for the most a game frame may be given (the refresh over 30 fps, 2 to 4). The fixed multipliers are unchanged. The refresh is the window's display's: on Linux SDL's (SDL_GetDisplayForWindow and SDL_GetCurrentDisplayMode; SDL2's SDL_GetWindowDisplayIndex), asked on the main thread once a second and handed over in the window bridge's new refresh_mhz (MKWVK_WINDOW_VERSION 2; a version 1 bridge still starts); on Windows the window's monitor's (EnumDisplaySettingsW). An unknown refresh counts as 60 Hz. tests/test_framegen_auto.py runs the real functions over refresh rates and frame rates; tests/test_framegen_gate.py now counts Auto as asking for interpolation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013mj4MdWTJo5ht4ShZX8Vpp
Conflicts: the display loop keeps wait_until_near, the bridge check keeps prep_window = w (and takes versions 1 and 2), set_row keeps step_output_choice / stops_at_ends (Auto's 1 is no longer skipped). Review (hckrman101): - A refresh within a quarter period of the game's frame shows that frame itself, and the timeline is pulled an eighth of the way to it. At 60 fps on 60 Hz with jitter (and 59.94/60.06 Hz drift) no frame is made and none dropped; other rates keep the display's count. The test now runs with jitter. - The overlay's game rate counts each Auto game frame once, given a refresh or not (menu_note_frame(true, 0)). - Windows: a whole-Hz rate one under a multiple of 6 (59, 119, 143...) is taken as its /1.001 rate. - Frame pacing's help says Auto paces itself; framegen_wanted's comment names Auto. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013mj4MdWTJo5ht4ShZX8Vpp
Contributor
Author
|
Thanks for the careful review, all points taken:
Smaller:
Played on Linux (RX 7900 XTX, RADV, 120 Hz) on current main plus this PR: the game runs at 45 to 60 fps, and Auto holds a steady 120. |
… Auto The Frame generation row takes main's hint scheme: Auto's hint says what it makes and that Frame pacing does not apply there (main skipped the value 1). menu_note_frame keeps the shown count beside menu_note_present_sizes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013mj4MdWTJo5ht4ShZX8Vpp
…windows.h defines it empty) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013mj4MdWTJo5ht4ShZX8Vpp
Contributor
Author
|
Renamed it to |
notquiteog
added a commit
to notquiteog/Hookshot
that referenced
this pull request
Nov 9, 2026
41 upstream commits, among them Frame generation's Auto (NotRexed#1121: a made frame for each of the display's refreshes), our AppImage parts fix (NotRexed#1312), the audio output row and mesh fallback fixes. Frame generation: upstream's Auto (framegen = 1) keeps its own refresh-paced built-in path; the fork's Frame generation method row (DLSS, FSR 4, FSR 3.1, built-in) applies at 2x to 8x, and its help says so. hos_sdl.h keeps both refresh queries (nn_vi.c's Hz, display_sdl.c's mHz). The audio output test's fixture gains the fork's nr_backend, which ini_key names. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
What
Frame generation gets Auto in the Insert menu (its value 1, the step the row skipped so far). Auto makes a frame for each of the display's refreshes and no more:
The fixed 2x to 8x are unchanged.
How
auto_slots).tbetween the two game frames.fg_synthalready takes anyt. A refresh att = 1gets the game's own frame.OutSet::due), instead of spreading the frames evenly over the game frame.The refresh rate comes from the display the window is on, and an unknown refresh counts as 60 Hz:
SDL_GetDisplayForWindow+SDL_GetCurrentDisplayMode(SDL2:SDL_GetWindowDisplayIndex+SDL_GetCurrentDisplayMode). Both are looked up optionally, are asked on the main thread once a second, and are handed to the renderer through a newrefresh_mhzin the window bridge (MKWVK_WINDOW_VERSION2; a version 1 bridge still starts).EnumDisplaySettingsWfor the window's monitor, cached for a second.Why
With fixed multipliers, a game running between the display's rate and half of it either makes too many frames or too few:
Auto follows the display, also when the same install is played on a TV one day and a monitor the next.
Tested
RX 7900 XTX, RADV (Mesa 26.2.6), Linux (Hyprland, native Wayland), v2.0.7 plus this change, Kokiri Forest:
EnumDisplaySettingsWpath is written but not built or run; I have no Windows machine. The Windows builder CI will compile it. Its rate is whole Hz, so one under a multiple of 6 (59, 119, 143, ...) is taken as that rate's /1.001 (59.94 Hz etc.), also untested.tests/test_framegen_auto.pyruns the realauto_cap,multiplierandauto_slotsover refresh rates and game rates. It covers 45 fps on 60 Hz (60 shown, three of four made at 1/4 to 3/4), 60 on 60, 75 on 60, 45 on 120, 30 on 240 (capped) and a restarted timeline. It also checks thatdisplay_refresh_mhzis declared outside the unnamed namespace: an earlier draft declared it inside, and the shared library linked with the symbol undefined.tests/test_framegen_gate.pynow counts Auto as asking for interpolation.Not covered
🤖 Generated with Claude Code