WIP: fix(vk): a late page the game reads is no longer overwritten with older words by its pending fix #526

Draft
mooki wants to merge 2 commits from mooki/Longshot:fix/nightly-flicker into main
Member

Regression: black flashes on Link and other characters since nightly 123, caused by #248. Nightly 80 was fine. Workaround until this is in a nightly: RX_VK_LATE_FIX=0 in longshot_env.txt.

Why

Players on Windows with NVIDIA cards see short black flashes on Link and other characters, in Zora's Fountain and Hyrule Field among other places, with frame generation off too; setting RX_VK_LATE_FIX=0 stops them for every player who tried it (#366). The cause is in the late pages' fix from #248 (nightly 123): when the game reads a page whose GPU fix is still pending, the capture could end with older words than the game had written. This changes only that read.

What is measured: a game-free test of the sequence fails on main and passes here (below). Not measured: the flash itself. It was not seen in a game run on Linux, and nothing was run on Windows or on a GPU that is slow enough to make late pages frequent.

What changed

  • late_fix_cpu_read in gpu/vk/vk_memory.cpp: the replay reads a late page of a capture on the CPU (for a draw's descriptors and constants) and the page has a fix. Before, a fix recorded in an earlier part of the same submission was neither waited for nor dropped; the function waited for the write-back, copied the page again from the game's memory and left the fix to run. Now that part is waited for (it is already submitted, so the wait is for work that is on its way), so its fix has run, and the capture is read as the fix left it, with nothing written to it (what a fix of an earlier recording already did). The wait has a hang guard of 5 s, logged; a part that ran past it is not waited for again. Three cases keep the old copy, with the fix's table counts set to 0 first so the fix writes nothing over it: the current part (not submitted, so the GPU has not read its table), a part past the guard, and a part that cannot be waited for. The last is only the case of RX_VK_PER_QUEUE_FENCES=0 or a recordings' timeline that could not be created (gpu/vk/vk_replay.cpp, per_queue_fences_off, replay_start): no GPU, driver or OS decides it, so NVIDIA's driver on Windows takes the wait unless that switch is set. That fallback keeps the race of zeroing a table a running part may be reading; it is rare by construction and counted (next bullet).
  • vk_part_wait in gpu/vk/vk_replay.cpp, declared in gpu/vk/vk_internal.h: waits for one part of a submission on the recordings' timeline, the same signal the readback wait already uses (wait_recorded_part); returns 1 done, 0 ran out, -1 cannot be waited for.
  • The late pages' fix (600 recordings with one) log line gets two counts at its end: of the reads on the CPU, how many waited for an earlier part's fix and how many copied the page again instead, so a player's log shows which way it went.
  • tests/test_late_fix_build.py: the function is cut out of the source and run beside the existing cases, with a stand-in for shaders/late_fix.comp run over the fix table. Cases: the fix of an earlier part, the current part, a part that cannot be waited for (and its second page), an earlier recording done and not done.
  • Unchanged: the shaders, the stamps, the shadows, every other path of the late pages' fix, the default of RX_VK_LATE_FIX and of RX_VK_SHADOW_FOLLOWS_SYNC.

The chain of causes

  1. A page the CPU wrote that a submission still on the GPU writes back is "late" (capture_make, gpu/vk/vk_memory.cpp). Since #248 the capture copies it at once and a small compute pass (shaders/late_fix.comp), recorded in the uploads of the submission's first part, writes the words the write-backs wrote into the capture before the mirror is made from it.
  2. A long submission goes to the GPU in parts of about 120 draws while the later parts are still recorded (maybe_split, submit_recording in gpu/vk/vk_replay.cpp). The part that recorded the fix can be running, or run after what the replay thread does next.
  3. While recording a later part, the replay reads words of guest memory "as submitted" (memory_read_as_submitted), which for a late page goes through late_fix_cpu_read. For a fix recorded in an earlier part it took the last else branch: wait for the write-back, copy the page again from guest memory, leave the fix.
  4. After the write-back has landed, the game's thread can write newer words to the same addresses. The copy has those; the fix then runs and writes the write-back's older words (shaders/late_fix.comp reads the pool's write-back shadow) over them.
  5. The mirror is made from that capture: a draw reads stale words. The pull request's own description names this kind of stale word (the per-character animation records' padding) as the cause of black flashes on characters during its development.

The other branches of the function do not do this: a fix already run, or recorded by an earlier recording, only reads the fixed buffer; a fix not recorded yet, or recorded in the current part, is dropped before the copy.

Flags and settings

None. RX_VK_LATE_FIX=0 stays the way to get the old wait. No flag is added.

Flag What it does Default now Recommendation Helps on Doesn't help on Untested on
none - - - - - -

Measurements

Branch state: on main 7ff5256e000671d0fccf27f77ba41275916b21df; head fea96c39c04c802882c545107202068fb7b5b32f; whole game-free suite on this head: 553 passed, 2 failed, 16 skipped (main 7ff5256e000671d0fccf27f77ba41275916b21df: 553 passed, 2 failed, 16 skipped). The 2 failing tests fail on main the same way: tests/test_cpm_discovery.py, tests/test_walk_key.py. The commits are unchanged by rebases apart from the results table.

main: 543846ebb0 (2026-11-14)
this PR: fix/nightly-flicker @ 4610ffdda
Hardware: game-free test, Arch Linux 7.2.15, Core i9-13900K, g++ with -Wall -Wextra -Werror; no GPU
Scene: none (a unit test of the function over a made-up page)
Method: python -I -B tests/test_late_fix_build.py, run on the test commit alone (test only, main's source) and on this head
How to reproduce: from the branch, git checkout a1929ba56 -- tests/test_late_fix_build.py is the test alone on main's source (it fails); python -I -B tests/test_late_fix_build.py on the head passes

main @ 543846ebb this PR @ 4610ffdda
tests/test_late_fix_build.py, case j: a CPU read of a late page whose fix an earlier part recorded; the write-back landed and the game wrote a newer word fails: failed line 868: slot[kX] == kA && slot[kY] == kCpu (the page was copied again, then the fix ran over it) passes
the other new cases (current part, a part that cannot be waited for, earlier recording done or not) not reached on main (stops at case j) pass
main's source:  failed line 868: slot[kX] == kA && slot[kY] == kCpu
this PR:        PASS: late_fix_build's fixes and waits, its stamp blocks, snapshots, their ranges and slots, and a CPU read of a fixed late page

What the players' logs show, as evidence that the path is hit (not a measurement of this change):

  • An RTX 4080 on Windows (nightly 143, Hyrule Field, frame generation 3x): the two late pages' fix (600 recordings with one) lines of the flickering run read 674 captures with late pages, 659 fixed, 82.8 pages a capture, 235 read on the CPU first, and 764 captures, 759 fixed, 113.8 pages, 587 read on the CPU first. Its run with RX_VK_LATE_FIX=0 does not flicker.
  • An RTX 4050 Laptop (6 GB) on Windows, nightly 127, Zora's Fountain: eight summaries, 9 to 17 percent of the captures read on the CPU first; RX_VK_LATE_FIX=0 stops the flicker, on, off, on.
  • RTX 3060 (12 GB), GTX 1660 Ti (6 GB) and a further player on nightly 143 report the same stop with RX_VK_LATE_FIX=0; three players who set the three switches of #324 back still saw the flicker.
  • One player saw no flicker in a short run with RX_VK_SHADOW_FOLLOWS_SYNC=0 and the late fix on. That fits this cause: with it on, the pages a mirror sync took are "known" to the write-back shadow and are not filled again (shadow_sync_copy, shadow_synced_known), so the fix reads shadow words older than guest memory; with it off those pages are unknown at the next write-back and are filled again from guest memory on the GPU, so the shadow follows the newer words and the old fix's overwrite wrote nearly current ones. Not proven in a game.

Arc laptop: frame rate and dark frames, main against this pull request (Windows)

Baseline: main @ 543846ebb, this pull request's base when it was measured. Measured at 4610ffdda before the carry onto the current main; the carry replays the same two commits unchanged, and main's changes since (the replay's reserved core on Linux, the per-CPU game build) do not touch the late pages' fix, so the numbers were not taken again.

main: 543846ebb0 (2026-11-14)
this PR: fix/nightly-flicker @ 4610ffdda
Hardware: Intel Arc Graphics, integrated (Core Ultra 9 185H laptop, shared memory), driver 32.0.101.9175; 64 GB; Windows 11 Pro 10.0.26300
Scene: Kokiri Forest (child), the same autosave resumed on the forest floor, a 50 s walk of fixed stick inputs between the houses, camera centering off; frame generation off; 1280x720 window; Windows builds of both commits (same compiler and settings), shader caches warmed and restored to the same saved state before each measured run
Method: the two builds alternated, main / this PR / main / this PR. Picture-free runs: no pictures during the walk; fps from the game's own vi: ... frames presented (... fps over the last 5.0 s) lines inside the walk (ten per run). Dense-picture runs: a picture of every frame the game's control bridge could take (about half of the presented frames, 306 to 365 per run); a program flags frames where part of the picture is much darker than in both neighbours, and every flagged frame was looked at.
How to reproduce: Kokiri Forest, an autosave on the forest floor, the same 50 s walk on both builds, alternated; the late-page counters are in the game's log (a capture taken (ms): ... GPU wait for late pages (N of 600 takes)), the fix's own summary line (late pages' fix (600 recordings with one)) did not appear in any run.

main @ 543846ebb this PR @ 4610ffdda
fps, median of each picture-free run's ten 5 s readings (2 runs each) 12.75, 12.90 14.00, 12.90
fps over the walk, frames shown / seconds (same runs) 12.87, 13.30 13.90, 13.61
same-build spread of those two medians 0.15 fps 1.10 fps
fps, median in the dense-picture runs (2 each; main with RX_VK_LATE_FIX=0 as control: 13.35) 12.05, 13.85 12.15, 14.55
fps, the twenty 5 s readings of the two picture-free runs pooled: median (lowest, highest) 12.9 (9.5, 15.6) 13.4 (11.1, 17.0)
walking pictures with a dark Link or character after looking at every flagged frame 0 of 661 (control RX_VK_LATE_FIX=0: 0 of 347) 0 of 685
captures that waited for the GPU because of a late page, in the walks of all 4 runs 51 of 16,200 (0.3%) (control: 11 of 4,200) 43 of 16,800 (0.3%)
late pages' fix (600 recordings with one) lines, and the new counts "waited for an earlier part's fix" / "copied the page again instead" 0 lines in 12 runs (warm-up, survey and measured) 0 lines in 8 runs
T1 main  12.75  T2 PR 14.00  T3 main 12.90  T4 PR 12.90      (median of ten 5 s readings, picture-free)
D1 main  12.05  D2 PR 12.15  D3 main 13.85  D4 PR 14.55  D5 main LATE_FIX=0 13.35   (dense-picture runs, not timing runs)

How to read the frame-rate rows: four picture-free runs, two per build, is a small sample. The two runs of one build differ by up to 1.1 fps; this PR's medians are 0.6 fps higher on average, inside that spread, so the claim is "not slower", not "faster". The walks end in different places (real-time physics) and first-time shader translations differ (0 to 35 per walk), so differences of about 1 fps are not meaningful. The late-page path is hardly used in these walks (0.3% of captures wait for a late page, about 12 to 14% in the menus before the walk), so these rows show no regression and the frame-rate comparison, not the fault or its fix. The flash was not seen on this GPU, with or without the fix.

Testing

Tested: the new cases both ways (table above) on Linux; the test commit alone fails; the rest of tests/test_late_fix_build.py is unchanged and passes. Game runs on Linux (RTX 4090, NVIDIA 615.78.08, windowless) of the nightly 140 build only, for the late-page counts; the build of this change was made but not run in the game, since this card shows too few late pages for a run to say anything. No flash was seen and none was expected: the card finishes a write-back before the next capture is taken, so late pages are rare in play (a walk through the field, the market and Kokiri Forest with area loads gave no late-pages summary line at all, which needs 600 recordings with a fix) and come in bursts at loads (618 captures with late pages, 371 read on the CPU first, at 5120x2880). Whole game-free suite on this head: 554 passed, 1 failed, 16 skipped (Linux, --jobs 6 --strict, 153 s). The one failure, tests/test_walk_key.py (a link error, undefined reference to hos_oot_autoload_input), fails the same way on main @ 543846ebb; this change does not touch it, and #497 fixes it.

Built for Windows and Linux at the previous head, not run (the pushed head fea96c39c is built again before the build box is ticked): At 4610ffddad50771e1b26b63bfe9e06837765c32f, the Windows x86-64 Vulkan renderer DLL and all 50 selected host translation units were cross-built on Linux with llvm-mingw 20261104 (Clang 23.1.5), using the project's production flags and pinned dependencies (renderer: 35 newly compiled / 170 reused; host: 50 newly compiled / 0 reused; lifted C: 72 newly compiled / 8 reused; all Windows units: 317 newly compiled / 332 reused from matching object-cache entries), the renderer DLL linked and the full game executable linked; nothing was run on Windows or under Wine, and this is neither the project's hosted builder run nor a Windows UTF-8 run-time path test.

That previous head 4610ffddad50771e1b26b63bfe9e06837765c32f also compiled and linked its full native Linux executable and renderer with Clang 23.1.3 through the documented resume path (322 newly compiled units, 169 matching Linux-cache units, source stamp d01a77d5), using the verified target-neutral C from lift 5c175a4727d82f85e425e85400dca17fea0750fb rather than carrying the patch onto another commit; neither Linux binary was run.

Not tested: a game run on Windows or with NVIDIA's Windows driver; any card slow enough for late pages to be frequent in play; frame generation; a before and after picture of a flash (none was captured here); whether the part wait costs frame time where many late pages are read in later parts (the old way waited for the write-back instead; no frame times were taken); the fallback paths (a part that cannot be waited for or past the guard) in a real game, and the race that fallback keeps.

Needs other testers:

  • Windows with an NVIDIA card, Zora's Fountain or Hyrule Field, default settings and no RX_VK_LATE_FIX line: watch Link and other characters for brief black flashes, expecting none (test request T-LUBF).

Screenshots

Nothing on screen: the flash was not captured here.

Risk and rollback

The wait for an earlier part can stall the replay thread for as long as that part runs on the GPU (about 120 draws) the first time a later part reads one of its late pages; the old way waited for the write-back instead. A wait past 5 s (a hang guard that is logged) falls back to the old copy and that part is not waited for again. RX_VK_LATE_FIX=0 turns the whole late pages' fix off; reverting the commit is enough.

Reviewer notes

  • Start at late_fix_cpu_read (about 2384 on main) and the new case j in tests/test_late_fix_build.py.
  • In case j the capture ends as the fix leaves it (the write-back's word), not with the game's newer word: that word was written after the submit, and a read on the CPU must not change what the GPU reads. Only where the fix is dropped (the current part, a part that cannot be waited for) does the capture keep the newer word, as the old wait did.
  • Left alone on purpose: the fallback (the current part, a part past the guard, a part that cannot be waited for) still zeroes a table that an already submitted part may be reading at that moment. For the current part that cannot happen; the other two are a hang and RX_VK_PER_QUEUE_FENCES=0.

Issues

Fixes #366

Checklist

For everyone

  • One topic.
  • The title is a Conventional Commit (type(scope): description).
  • Rebased on current main.
  • python -I -B tests/run_all.py run and passing (any failure that also fails on main is named above).
  • Tested in the game, or what wasn't is named under Testing.
  • Testing filled in: what was tested, what wasn't, and what needs other testers (with test requests).
  • Measured: main and this PR at named commits, on the same PC, scene and settings, at least 2 interleaved runs each, the median reported. (Arc laptop, Windows: main @ 543846ebb against this PR @ 4610ffdda, two alternated runs each, medians above; it shows no regression and the frame rate, not the flash, which this hardware does not produce.)
  • No game files, dumps, build output or generated files.
  • third_party/ untouched (a new folder with a PROVENANCE.md instead).
  • The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled.

If applicable

  • AI assistance recorded with Assisted-by: / Co-Authored-By: trailers.
  • Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths. The pushed head is built again for both before this box is ticked; the previous head's builds are above.
  • A game-free test added for the fix, failing on main and passing here.
  • A check under tests/ that reads changed source updated in this PR, not weakened.

New on this forge; not opened on GitHub.

**Regression:** black flashes on Link and other characters since nightly 123, caused by https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/248. Nightly 80 was fine. Workaround until this is in a nightly: `RX_VK_LATE_FIX=0` in `longshot_env.txt`. ## Why Players on Windows with NVIDIA cards see short black flashes on Link and other characters, in Zora's Fountain and Hyrule Field among other places, with frame generation off too; setting `RX_VK_LATE_FIX=0` stops them for every player who tried it (https://git.magicbean.dev/MagicBeanDev/Longshot/issues/366). The cause is in the late pages' fix from https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/248 (nightly 123): when the game reads a page whose GPU fix is still pending, the capture could end with older words than the game had written. This changes only that read. **What is measured:** a game-free test of the sequence fails on main and passes here (below). **Not measured:** the flash itself. It was not seen in a game run on Linux, and nothing was run on Windows or on a GPU that is slow enough to make late pages frequent. ## What changed - `late_fix_cpu_read` in `gpu/vk/vk_memory.cpp`: the replay reads a late page of a capture on the CPU (for a draw's descriptors and constants) and the page has a fix. Before, a fix recorded in an earlier part of the same submission was neither waited for nor dropped; the function waited for the write-back, copied the page again from the game's memory and left the fix to run. Now that part is waited for (it is already submitted, so the wait is for work that is on its way), so its fix has run, and the capture is read as the fix left it, with nothing written to it (what a fix of an earlier recording already did). The wait has a hang guard of 5 s, logged; a part that ran past it is not waited for again. Three cases keep the old copy, with the fix's table counts set to 0 first so the fix writes nothing over it: the current part (not submitted, so the GPU has not read its table), a part past the guard, and a part that cannot be waited for. The last is only the case of `RX_VK_PER_QUEUE_FENCES=0` or a recordings' timeline that could not be created (`gpu/vk/vk_replay.cpp`, `per_queue_fences_off`, `replay_start`): no GPU, driver or OS decides it, so NVIDIA's driver on Windows takes the wait unless that switch is set. That fallback keeps the race of zeroing a table a running part may be reading; it is rare by construction and counted (next bullet). - `vk_part_wait` in `gpu/vk/vk_replay.cpp`, declared in `gpu/vk/vk_internal.h`: waits for one part of a submission on the recordings' timeline, the same signal the readback wait already uses (`wait_recorded_part`); returns 1 done, 0 ran out, -1 cannot be waited for. - The `late pages' fix (600 recordings with one)` log line gets two counts at its end: of the reads on the CPU, how many waited for an earlier part's fix and how many copied the page again instead, so a player's log shows which way it went. - `tests/test_late_fix_build.py`: the function is cut out of the source and run beside the existing cases, with a stand-in for `shaders/late_fix.comp` run over the fix table. Cases: the fix of an earlier part, the current part, a part that cannot be waited for (and its second page), an earlier recording done and not done. - Unchanged: the shaders, the stamps, the shadows, every other path of the late pages' fix, the default of `RX_VK_LATE_FIX` and of `RX_VK_SHADOW_FOLLOWS_SYNC`. ### The chain of causes 1. A page the CPU wrote that a submission still on the GPU writes back is "late" (`capture_make`, `gpu/vk/vk_memory.cpp`). Since #248 the capture copies it at once and a small compute pass (`shaders/late_fix.comp`), recorded in the uploads of the submission's first part, writes the words the write-backs wrote into the capture before the mirror is made from it. 2. A long submission goes to the GPU in parts of about 120 draws while the later parts are still recorded (`maybe_split`, `submit_recording` in `gpu/vk/vk_replay.cpp`). The part that recorded the fix can be running, or run after what the replay thread does next. 3. While recording a later part, the replay reads words of guest memory "as submitted" (`memory_read_as_submitted`), which for a late page goes through `late_fix_cpu_read`. For a fix recorded in an earlier part it took the last `else` branch: wait for the write-back, copy the page again from guest memory, leave the fix. 4. After the write-back has landed, the game's thread can write newer words to the same addresses. The copy has those; the fix then runs and writes the write-back's older words (`shaders/late_fix.comp` reads the pool's write-back shadow) over them. 5. The mirror is made from that capture: a draw reads stale words. The pull request's own description names this kind of stale word (the per-character animation records' padding) as the cause of black flashes on characters during its development. The other branches of the function do not do this: a fix already run, or recorded by an earlier recording, only reads the fixed buffer; a fix not recorded yet, or recorded in the current part, is dropped before the copy. ## Flags and settings None. `RX_VK_LATE_FIX=0` stays the way to get the old wait. No flag is added. | Flag | What it does | Default now | Recommendation | Helps on | Doesn't help on | Untested on | |---|---|---|---|---|---|---| | none | - | - | - | - | - | - | ## Measurements <!-- branch-state --> Branch state: on main `7ff5256e000671d0fccf27f77ba41275916b21df`; head `fea96c39c04c802882c545107202068fb7b5b32f`; whole game-free suite on this head: `553 passed, 2 failed, 16 skipped` (main `7ff5256e000671d0fccf27f77ba41275916b21df`: `553 passed, 2 failed, 16 skipped`). The 2 failing tests fail on main the same way: `tests/test_cpm_discovery.py`, `tests/test_walk_key.py`. The commits are unchanged by rebases apart from the results table. <!-- /branch-state --> main: 543846ebb08ded4ce75d364403bc4dcf24e83e85 (2026-11-14) this PR: fix/nightly-flicker @ 4610ffdda Hardware: game-free test, Arch Linux 7.2.15, Core i9-13900K, g++ with `-Wall -Wextra -Werror`; no GPU Scene: none (a unit test of the function over a made-up page) Method: `python -I -B tests/test_late_fix_build.py`, run on the test commit alone (test only, main's source) and on this head How to reproduce: from the branch, `git checkout a1929ba56 -- tests/test_late_fix_build.py` is the test alone on main's source (it fails); `python -I -B tests/test_late_fix_build.py` on the head passes | | main @ 543846ebb | this PR @ 4610ffdda | |---|---|---| | `tests/test_late_fix_build.py`, case j: a CPU read of a late page whose fix an earlier part recorded; the write-back landed and the game wrote a newer word | fails: `failed line 868: slot[kX] == kA && slot[kY] == kCpu` (the page was copied again, then the fix ran over it) | passes | | the other new cases (current part, a part that cannot be waited for, earlier recording done or not) | not reached on main (stops at case j) | pass | ``` main's source: failed line 868: slot[kX] == kA && slot[kY] == kCpu this PR: PASS: late_fix_build's fixes and waits, its stamp blocks, snapshots, their ranges and slots, and a CPU read of a fixed late page ``` What the players' logs show, as evidence that the path is hit (not a measurement of this change): - An RTX 4080 on Windows (nightly 143, Hyrule Field, frame generation 3x): the two `late pages' fix (600 recordings with one)` lines of the flickering run read 674 captures with late pages, 659 fixed, 82.8 pages a capture, 235 read on the CPU first, and 764 captures, 759 fixed, 113.8 pages, 587 read on the CPU first. Its run with `RX_VK_LATE_FIX=0` does not flicker. - An RTX 4050 Laptop (6 GB) on Windows, nightly 127, Zora's Fountain: eight summaries, 9 to 17 percent of the captures read on the CPU first; `RX_VK_LATE_FIX=0` stops the flicker, on, off, on. - RTX 3060 (12 GB), GTX 1660 Ti (6 GB) and a further player on nightly 143 report the same stop with `RX_VK_LATE_FIX=0`; three players who set the three switches of https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/324 back still saw the flicker. - One player saw no flicker in a short run with `RX_VK_SHADOW_FOLLOWS_SYNC=0` and the late fix on. That fits this cause: with it on, the pages a mirror sync took are "known" to the write-back shadow and are not filled again (`shadow_sync_copy`, `shadow_synced_known`), so the fix reads shadow words older than guest memory; with it off those pages are unknown at the next write-back and are filled again from guest memory on the GPU, so the shadow follows the newer words and the old fix's overwrite wrote nearly current ones. Not proven in a game. ### Arc laptop: frame rate and dark frames, main against this pull request (Windows) Baseline: main @ 543846ebb, this pull request's base when it was measured. Measured at `4610ffdda` before the carry onto the current main; the carry replays the same two commits unchanged, and main's changes since (the replay's reserved core on Linux, the per-CPU game build) do not touch the late pages' fix, so the numbers were not taken again. main: 543846ebb08ded4ce75d364403bc4dcf24e83e85 (2026-11-14) this PR: fix/nightly-flicker @ 4610ffdda Hardware: Intel Arc Graphics, integrated (Core Ultra 9 185H laptop, shared memory), driver 32.0.101.9175; 64 GB; Windows 11 Pro 10.0.26300 Scene: Kokiri Forest (child), the same autosave resumed on the forest floor, a 50 s walk of fixed stick inputs between the houses, camera centering off; frame generation off; 1280x720 window; Windows builds of both commits (same compiler and settings), shader caches warmed and restored to the same saved state before each measured run Method: the two builds alternated, main / this PR / main / this PR. Picture-free runs: no pictures during the walk; fps from the game's own `vi: ... frames presented (... fps over the last 5.0 s)` lines inside the walk (ten per run). Dense-picture runs: a picture of every frame the game's control bridge could take (about half of the presented frames, 306 to 365 per run); a program flags frames where part of the picture is much darker than in both neighbours, and every flagged frame was looked at. How to reproduce: Kokiri Forest, an autosave on the forest floor, the same 50 s walk on both builds, alternated; the late-page counters are in the game's log (`a capture taken (ms): ... GPU wait for late pages (N of 600 takes)`), the fix's own summary line (`late pages' fix (600 recordings with one)`) did not appear in any run. | | main @ 543846ebb | this PR @ 4610ffdda | |---|---|---| | fps, median of each picture-free run's ten 5 s readings (2 runs each) | 12.75, 12.90 | 14.00, 12.90 | | fps over the walk, frames shown / seconds (same runs) | 12.87, 13.30 | 13.90, 13.61 | | same-build spread of those two medians | 0.15 fps | 1.10 fps | | fps, median in the dense-picture runs (2 each; main with `RX_VK_LATE_FIX=0` as control: 13.35) | 12.05, 13.85 | 12.15, 14.55 | | fps, the twenty 5 s readings of the two picture-free runs pooled: median (lowest, highest) | 12.9 (9.5, 15.6) | 13.4 (11.1, 17.0) | | walking pictures with a dark Link or character after looking at every flagged frame | 0 of 661 (control `RX_VK_LATE_FIX=0`: 0 of 347) | 0 of 685 | | captures that waited for the GPU because of a late page, in the walks of all 4 runs | 51 of 16,200 (0.3%) (control: 11 of 4,200) | 43 of 16,800 (0.3%) | | `late pages' fix (600 recordings with one)` lines, and the new counts "waited for an earlier part's fix" / "copied the page again instead" | 0 lines in 12 runs (warm-up, survey and measured) | 0 lines in 8 runs | ``` T1 main 12.75 T2 PR 14.00 T3 main 12.90 T4 PR 12.90 (median of ten 5 s readings, picture-free) D1 main 12.05 D2 PR 12.15 D3 main 13.85 D4 PR 14.55 D5 main LATE_FIX=0 13.35 (dense-picture runs, not timing runs) ``` How to read the frame-rate rows: four picture-free runs, two per build, is a small sample. The two runs of one build differ by up to 1.1 fps; this PR's medians are 0.6 fps higher on average, inside that spread, so the claim is "not slower", not "faster". The walks end in different places (real-time physics) and first-time shader translations differ (0 to 35 per walk), so differences of about 1 fps are not meaningful. The late-page path is hardly used in these walks (0.3% of captures wait for a late page, about 12 to 14% in the menus before the walk), so these rows show no regression and the frame-rate comparison, not the fault or its fix. The flash was not seen on this GPU, with or without the fix. ## Testing **Tested:** the new cases both ways (table above) on Linux; the test commit alone fails; the rest of `tests/test_late_fix_build.py` is unchanged and passes. Game runs on Linux (RTX 4090, NVIDIA 615.78.08, windowless) of the nightly 140 build only, for the late-page counts; the build of this change was made but not run in the game, since this card shows too few late pages for a run to say anything. No flash was seen and none was expected: the card finishes a write-back before the next capture is taken, so late pages are rare in play (a walk through the field, the market and Kokiri Forest with area loads gave no late-pages summary line at all, which needs 600 recordings with a fix) and come in bursts at loads (618 captures with late pages, 371 read on the CPU first, at 5120x2880). Whole game-free suite on this head: `554 passed, 1 failed, 16 skipped` (Linux, `--jobs 6 --strict`, 153 s). The one failure, `tests/test_walk_key.py` (a link error, `undefined reference to hos_oot_autoload_input`), fails the same way on main @ 543846ebb; this change does not touch it, and https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/497 fixes it. **Built for Windows and Linux at the previous head, not run (the pushed head `fea96c39c` is built again before the build box is ticked):** At `4610ffddad50771e1b26b63bfe9e06837765c32f`, the Windows x86-64 Vulkan renderer DLL and all 50 selected host translation units were cross-built on Linux with llvm-mingw 20261104 (Clang 23.1.5), using the project's production flags and pinned dependencies (renderer: 35 newly compiled / 170 reused; host: 50 newly compiled / 0 reused; lifted C: 72 newly compiled / 8 reused; all Windows units: 317 newly compiled / 332 reused from matching object-cache entries), the renderer DLL linked and the full game executable linked; nothing was run on Windows or under Wine, and this is neither the project's hosted builder run nor a Windows UTF-8 run-time path test. That previous head `4610ffddad50771e1b26b63bfe9e06837765c32f` also compiled and linked its full native Linux executable and renderer with Clang 23.1.3 through the documented resume path (322 newly compiled units, 169 matching Linux-cache units, source stamp `d01a77d5`), using the verified target-neutral C from lift `5c175a4727d82f85e425e85400dca17fea0750fb` rather than carrying the patch onto another commit; neither Linux binary was run. **Not tested:** a game run on Windows or with NVIDIA's Windows driver; any card slow enough for late pages to be frequent in play; frame generation; a before and after picture of a flash (none was captured here); whether the part wait costs frame time where many late pages are read in later parts (the old way waited for the write-back instead; no frame times were taken); the fallback paths (a part that cannot be waited for or past the guard) in a real game, and the race that fallback keeps. **Needs other testers:** - Windows with an NVIDIA card, Zora's Fountain or Hyrule Field, default settings and no `RX_VK_LATE_FIX` line: watch Link and other characters for brief black flashes, expecting none (test request T-LUBF). ## Screenshots Nothing on screen: the flash was not captured here. ## Risk and rollback The wait for an earlier part can stall the replay thread for as long as that part runs on the GPU (about 120 draws) the first time a later part reads one of its late pages; the old way waited for the write-back instead. A wait past 5 s (a hang guard that is logged) falls back to the old copy and that part is not waited for again. `RX_VK_LATE_FIX=0` turns the whole late pages' fix off; reverting the commit is enough. ## Reviewer notes - Start at `late_fix_cpu_read` (about 2384 on main) and the new case j in `tests/test_late_fix_build.py`. - In case j the capture ends as the fix leaves it (the write-back's word), not with the game's newer word: that word was written after the submit, and a read on the CPU must not change what the GPU reads. Only where the fix is dropped (the current part, a part that cannot be waited for) does the capture keep the newer word, as the old wait did. - Left alone on purpose: the fallback (the current part, a part past the guard, a part that cannot be waited for) still zeroes a table that an already submitted part may be reading at that moment. For the current part that cannot happen; the other two are a hang and `RX_VK_PER_QUEUE_FENCES=0`. ## Issues Fixes https://git.magicbean.dev/MagicBeanDev/Longshot/issues/366 ## Checklist ### For everyone - [x] One topic. - [x] The title is a Conventional Commit (`type(scope): description`). - [x] Rebased on current `main`. - [x] `python -I -B tests/run_all.py` run and passing (any failure that also fails on `main` is named above). - [x] Tested in the game, or what wasn't is named under Testing. - [x] Testing filled in: what was tested, what wasn't, and what needs other testers (with test requests). - [x] Measured: main and this PR at named commits, on the same PC, scene and settings, at least 2 interleaved runs each, the median reported. (Arc laptop, Windows: main @ 543846ebb against this PR @ 4610ffdda, two alternated runs each, medians above; it shows no regression and the frame rate, not the flash, which this hardware does not produce.) - [x] No game files, dumps, build output or generated files. - [x] `third_party/` untouched (a new folder with a `PROVENANCE.md` instead). - [x] The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled. ### If applicable - [x] AI assistance recorded with `Assisted-by:` / `Co-Authored-By:` trailers. - [ ] Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths. The pushed head is built again for both before this box is ticked; the previous head's builds are above. - [x] A game-free test added for the fix, failing on `main` and passing here. - [x] A check under `tests/` that reads changed source updated in this PR, not weakened. --- New on this forge; not opened on GitHub.
The late pages' fix (PR 248) writes the write-backs' words into a capture's
page on the GPU. When the replay reads such a page on the CPU
(late_fix_cpu_read), a fix recorded in an earlier part of the same submission
may be running or still to run (parts go to the GPU while the later ones are
recorded). The function copies the page again from guest memory and leaves
that fix in place, so the fix puts the write-back's older words back over
words the game's thread wrote after the write-back landed.

Add the function to the fixture of test_late_fix_build.py with a stand-in
for shaders/late_fix.comp run over the fix table, and the cases: the fix of
an earlier part (the page must end as the fix leaves it, not copied again),
of the current part and of a part that cannot be waited for (the fix is
dropped before the copy), of an earlier recording, done or not.

This commit alone fails on main's source (case j: slot[kX] == kA); the next
commit fixes the source.

Assisted-by: Claude Sonnet 5.5
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
fix(vk): a page the game reads while its late fix is pending keeps the words the game wrote
Some checks are pending
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been skipped
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been skipped
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been skipped
Third-party parts / The same as upstream (pull_request) Has been skipped
Website / Website on Cloudflare (pull_request_target) Has been skipped
CI / Conventional Commit title (pull_request) Successful in 13s
CI / Workflow lint (actionlint) (pull_request) Successful in 24s
Third-party parts / As their notes say (pull_request) Successful in 32s
beanstalk/approval awaiting maintainer approval
PR description / Description follows the template (pull_request_target) Successful in 16s
4610ffddad
Since PR 248 (nightly 123) a capture's late page is fixed on the GPU: late_fix.comp
writes the words the write-backs still running wrote into the capture. When the
replay reads such a page on the CPU (late_fix_cpu_read, for a draw's descriptors
and constants), a fix recorded in an EARLIER part of the same submission was
neither waited for nor dropped: the function waited for the write-back, copied
the page again from guest memory, which by then holds the words the game's
thread wrote after the write-back landed, and left the fix to run. A long
submission goes to the GPU in parts while the later ones are recorded, so that
fix runs after the copy and puts the write-back's older words back over the
newer ones: stale words in the capture the mirror is made from, the same kind of
stale data as the black flashes on Link and other characters the pull request
names (issue 366).

An earlier part's fix is now waited for (vk_part_wait: the part's own signal on the
recordings' timeline, a hang guard of 5 s that is logged) and the capture read as
the fix left it, nothing written to it, as for a fix of an earlier recording. Only
a part that cannot be waited for (no timeline of its own for the recordings, or
RX_VK_PER_QUEUE_FENCES=0; no device or OS decides it) or one past the guard keeps the
old way with its table's counts zeroed before the copy; the current part, not yet
submitted, always does. The late-fix summary line counts the reads that waited for
an earlier part and those that copied the page again instead.

test_late_fix_build.py has the cases (previous commit, updated here for the
three results of vk_part_wait and the counters): the page ends as the fix leaves it,
with the write-back's word, not copied again; the current part's, an unwaitable
part's and a hang-guard part's fix is dropped and the newer word stays.

Assisted-by: Claude Sonnet 5.5
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Author
Member

Arc laptop check of this pull request: no regression seen

This is a check for regressions and frame rate on a slow integrated GPU. It does not show the fault or the fix: late pages turned out to be rare in these walks (see below), so I never saw the black flash with or without the change.

Hardware: Intel Arc Graphics (the integrated GPU of a Core Ultra 9 185H laptop, shared memory), driver 32.0.101.9175, Windows 11 Pro 10.0.26300, 64 GB RAM.
Built: this pull request's head 4610ffddad, and main 543846ebb0 (the pull request's base; the pull request is main plus its two commits). Both are Windows builds made from those exact commits with the same compiler and settings.

What I did, all in Kokiri Forest, frame generation off, window output 1280x720, no co-op, no audio, camera centering off:

  • The same autosave, resumed on the forest floor each time, and the same 50 second input sequence (walking and turning on the paths between the houses), in nine measured runs of the two builds in turn (below). Shader caches were warmed first with four or five runs of each build and then put back to the same saved state before each measured run.
  • Dense-picture runs: during the walk the game saved a picture of every frame it could, just over half of the frames it presented. Main, this pull request, main, this pull request, and one run of main with RX_VK_LATE_FIX=0 as a control. A small program compared each picture with the ones before and after it and flagged any frame where part of the picture was much darker than in both neighbours (the kind of dip a black Link would make). I looked at every flagged frame in a strip of before, flagged and after: 83 single frames and 26 pairs of frames.
  • Picture-free runs for the frame rate: main, this pull request, main, this pull request, with no pictures during the walk. The numbers are the game's own 5 second frame-rate lines in the 50 second walk (ten per run).

Late pages in these walks:

  • I first looked for them on main in Hyrule Field (two runs) and Kokiri Forest (one run). None of the 20 runs I made on main and on this pull request (those three, the warm-up runs and the nine measured runs) wrote the late pages' fix (600 recordings with one) line, so fewer than 600 recordings with a fix happen in a whole run of 2 to 5 minutes. For the same reason the two new counts this pull request adds to that line never appeared.
  • The periodic GPU wait for late pages (N of 600 takes) line is the other sign of them: in the walks 51 of 16,200 captures waited on main (0.3%), 43 of 16,800 on this pull request (0.3%), 11 of 4,200 with RX_VK_LATE_FIX=0 (0.3%). In the title screen, menus and loading before each walk it is about 12 to 14% (medians of 74 to 87 per 600 captures) on all three.
  • So the path this pull request changes is hardly used in these walks. That is also why the control run without the late fix looks the same as the others.

Results (D1 to D5 dense-picture runs, T1 to T4 picture-free runs, each one 50 second walk):

Run Build Pictures in the walk Flagged frames looked at (single + pairs) Dark Link or character after looking fps, median of the ten 5 s readings (lowest, highest) fps, frames shown over the walk Late-page waits in the walk First-time shader translations in the walk
D1 main 306 6 + 0 0 12.05 (9.7, 13.7) 11.95 13 of 3,600 6
D2 this PR 320 20 + 9 0 12.15 (8.9, 15.8) 12.48 24 of 4,200 33
D3 main 355 23 + 4 0 13.85 (9.7, 15.9) 13.92 12 of 4,200 0
D4 this PR 365 23 + 5 0 14.55 (9.8, 16.7) 14.24 9 of 4,200 11
D5 main, RX_VK_LATE_FIX=0 347 11 + 8 0 13.35 (9.4, 15.2) 13.53 11 of 4,200 0
T1 main none none none 12.75 (9.5, 15.5) 12.87 14 of 4,200 0
T2 this PR none none none 14.00 (11.1, 15.2) 13.90 1 of 4,200 1
T3 main none none none 12.90 (11.7, 15.6) 13.30 12 of 4,200 4
T4 this PR none none none 12.90 (11.7, 17.0) 13.61 9 of 4,200 35
  • Black flashes: none. In 1,693 walking pictures (661 on main, 685 on this pull request, 347 in the control) every flagged frame was camera or foliage movement, a branch or tree trunk crossing the picture, or Navi; Link was lit like the frames next to him in every one. The pictures cover only about half of the frames, so a flash that falls between two pictures would not show. Main and the control show none either, so this cannot show that the pull request removes anything here.
  • Frame rate: this pull request is not slower. Medians of the 5 second readings: main 12.75 and 12.90, this pull request 14.00 and 12.90 (T1 to T4); in the dense-picture runs main 12.05 and 13.85, this pull request 12.15 and 14.55. The two runs of the same build differ by up to 1.1 fps (T) and 2.4 fps (D), more than the 0.6 fps by which this pull request's medians are higher, so I do not claim it is faster. Counting frames shown over the walk the same way gives main 12.87 and 13.30, this pull request 13.90 and 13.61. Pooling the twenty 5 second readings of each build: main median 12.9 (lowest 9.5, highest 15.6), this pull request 13.4 (11.1, 17.0).
  • This is a small sample: two runs per build in each kind. The walks do not end in the same place every time (the game's physics runs in real time; T1 and T2 ended near one spot, T3 and T4 about 15 to 17 m from it), and first-time shader translations differ from run to run (T4 had 35, D2 had 33, the others 0 to 11, each roughly 10 to 35 ms), so differences of about 1 fps are not meaningful.
  • All 20 game runs ended by themselves with exit code 0 and no forced stop. The nine measured runs have no crash, fatal or device-lost line in the log, and none of the 20 logs shows the 5 second guard line this pull request adds. One survey run in Hyrule Field was stopped by my own check after Link was killed by enemies; it ended normally too and is not in the tables.

Not tested: NVIDIA cards or any Windows run on NVIDIA; Zora's Fountain; Hyrule Field with pictures (only the late-page survey on main); frame generation (off in every run); runs longer than a few minutes; the flash itself, which I did not see on this GPU in any run, with or without RX_VK_LATE_FIX=0.

Kokiri Forest on Intel Arc Graphics, Windows: main (top) and this pull request (bottom) at the same moments of the walk; nothing dark on Link or the scene in either row

Arc laptop check of this pull request: no regression seen This is a check for regressions and frame rate on a slow integrated GPU. It does not show the fault or the fix: late pages turned out to be rare in these walks (see below), so I never saw the black flash with or without the change. Hardware: Intel Arc Graphics (the integrated GPU of a Core Ultra 9 185H laptop, shared memory), driver 32.0.101.9175, Windows 11 Pro 10.0.26300, 64 GB RAM. Built: this pull request's head 4610ffddad50771e1b26b63bfe9e06837765c32f, and main 543846ebb08ded4ce75d364403bc4dcf24e83e85 (the pull request's base; the pull request is main plus its two commits). Both are Windows builds made from those exact commits with the same compiler and settings. What I did, all in Kokiri Forest, frame generation off, window output 1280x720, no co-op, no audio, camera centering off: - The same autosave, resumed on the forest floor each time, and the same 50 second input sequence (walking and turning on the paths between the houses), in nine measured runs of the two builds in turn (below). Shader caches were warmed first with four or five runs of each build and then put back to the same saved state before each measured run. - Dense-picture runs: during the walk the game saved a picture of every frame it could, just over half of the frames it presented. Main, this pull request, main, this pull request, and one run of main with `RX_VK_LATE_FIX=0` as a control. A small program compared each picture with the ones before and after it and flagged any frame where part of the picture was much darker than in both neighbours (the kind of dip a black Link would make). I looked at every flagged frame in a strip of before, flagged and after: 83 single frames and 26 pairs of frames. - Picture-free runs for the frame rate: main, this pull request, main, this pull request, with no pictures during the walk. The numbers are the game's own 5 second frame-rate lines in the 50 second walk (ten per run). Late pages in these walks: - I first looked for them on main in Hyrule Field (two runs) and Kokiri Forest (one run). None of the 20 runs I made on main and on this pull request (those three, the warm-up runs and the nine measured runs) wrote the `late pages' fix (600 recordings with one)` line, so fewer than 600 recordings with a fix happen in a whole run of 2 to 5 minutes. For the same reason the two new counts this pull request adds to that line never appeared. - The periodic `GPU wait for late pages (N of 600 takes)` line is the other sign of them: in the walks 51 of 16,200 captures waited on main (0.3%), 43 of 16,800 on this pull request (0.3%), 11 of 4,200 with `RX_VK_LATE_FIX=0` (0.3%). In the title screen, menus and loading before each walk it is about 12 to 14% (medians of 74 to 87 per 600 captures) on all three. - So the path this pull request changes is hardly used in these walks. That is also why the control run without the late fix looks the same as the others. Results (D1 to D5 dense-picture runs, T1 to T4 picture-free runs, each one 50 second walk): | Run | Build | Pictures in the walk | Flagged frames looked at (single + pairs) | Dark Link or character after looking | fps, median of the ten 5 s readings (lowest, highest) | fps, frames shown over the walk | Late-page waits in the walk | First-time shader translations in the walk | |---|---|---|---|---|---|---|---|---| | D1 | main | 306 | 6 + 0 | 0 | 12.05 (9.7, 13.7) | 11.95 | 13 of 3,600 | 6 | | D2 | this PR | 320 | 20 + 9 | 0 | 12.15 (8.9, 15.8) | 12.48 | 24 of 4,200 | 33 | | D3 | main | 355 | 23 + 4 | 0 | 13.85 (9.7, 15.9) | 13.92 | 12 of 4,200 | 0 | | D4 | this PR | 365 | 23 + 5 | 0 | 14.55 (9.8, 16.7) | 14.24 | 9 of 4,200 | 11 | | D5 | main, `RX_VK_LATE_FIX=0` | 347 | 11 + 8 | 0 | 13.35 (9.4, 15.2) | 13.53 | 11 of 4,200 | 0 | | T1 | main | none | none | none | 12.75 (9.5, 15.5) | 12.87 | 14 of 4,200 | 0 | | T2 | this PR | none | none | none | 14.00 (11.1, 15.2) | 13.90 | 1 of 4,200 | 1 | | T3 | main | none | none | none | 12.90 (11.7, 15.6) | 13.30 | 12 of 4,200 | 4 | | T4 | this PR | none | none | none | 12.90 (11.7, 17.0) | 13.61 | 9 of 4,200 | 35 | - Black flashes: none. In 1,693 walking pictures (661 on main, 685 on this pull request, 347 in the control) every flagged frame was camera or foliage movement, a branch or tree trunk crossing the picture, or Navi; Link was lit like the frames next to him in every one. The pictures cover only about half of the frames, so a flash that falls between two pictures would not show. Main and the control show none either, so this cannot show that the pull request removes anything here. - Frame rate: this pull request is not slower. Medians of the 5 second readings: main 12.75 and 12.90, this pull request 14.00 and 12.90 (T1 to T4); in the dense-picture runs main 12.05 and 13.85, this pull request 12.15 and 14.55. The two runs of the same build differ by up to 1.1 fps (T) and 2.4 fps (D), more than the 0.6 fps by which this pull request's medians are higher, so I do not claim it is faster. Counting frames shown over the walk the same way gives main 12.87 and 13.30, this pull request 13.90 and 13.61. Pooling the twenty 5 second readings of each build: main median 12.9 (lowest 9.5, highest 15.6), this pull request 13.4 (11.1, 17.0). - This is a small sample: two runs per build in each kind. The walks do not end in the same place every time (the game's physics runs in real time; T1 and T2 ended near one spot, T3 and T4 about 15 to 17 m from it), and first-time shader translations differ from run to run (T4 had 35, D2 had 33, the others 0 to 11, each roughly 10 to 35 ms), so differences of about 1 fps are not meaningful. - All 20 game runs ended by themselves with exit code 0 and no forced stop. The nine measured runs have no crash, fatal or device-lost line in the log, and none of the 20 logs shows the 5 second guard line this pull request adds. One survey run in Hyrule Field was stopped by my own check after Link was killed by enemies; it ended normally too and is not in the tables. Not tested: NVIDIA cards or any Windows run on NVIDIA; Zora's Fountain; Hyrule Field with pictures (only the late-page survey on main); frame generation (off in every run); runs longer than a few minutes; the flash itself, which I did not see on this GPU in any run, with or without `RX_VK_LATE_FIX=0`. ![Kokiri Forest on Intel Arc Graphics, Windows: main (top) and this pull request (bottom) at the same moments of the walk; nothing dark on Link or the scene in either row](https://git.magicbean.dev/attachments/12abf1e7-20a6-4d3f-999c-353e561b9d90)
mooki force-pushed fix/nightly-flicker from 4610ffddad
Some checks are pending
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been skipped
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been skipped
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been skipped
Third-party parts / The same as upstream (pull_request) Has been skipped
Website / Website on Cloudflare (pull_request_target) Has been skipped
CI / Conventional Commit title (pull_request) Successful in 13s
CI / Workflow lint (actionlint) (pull_request) Successful in 24s
Third-party parts / As their notes say (pull_request) Successful in 32s
beanstalk/approval awaiting maintainer approval
PR description / Description follows the template (pull_request_target) Successful in 16s
to fea96c39c0
Some checks are pending
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been skipped
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been skipped
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been skipped
Third-party parts / The same as upstream (pull_request) Has been skipped
beanstalk/approval awaiting maintainer approval
CI / Conventional Commit title (pull_request) Successful in 14s
CI / Workflow lint (actionlint) (pull_request) Successful in 22s
Third-party parts / As their notes say (pull_request) Successful in 29s
PR description / Description follows the template (pull_request_target) Successful in 16s
2026-11-14 19:05:04 +00:00
Compare
Author
Member

Carried onto main 7ff5256e0 (main gained the replay's reserved-core fix and the per-CPU game build since); new head fea96c39c. The two commits are unchanged. The whole suite on this exact head: 553 passed, 2 failed, 16 skipped. The build box is unticked until this pushed head has been built for Windows and Linux; it is ticked again then.

Carried onto main `7ff5256e0` (main gained the replay's reserved-core fix and the per-CPU game build since); new head `fea96c39c`. The two commits are unchanged. The whole suite on this exact head: 553 passed, 2 failed, 16 skipped. The build box is unticked until this pushed head has been built for Windows and Linux; it is ticked again then.
Some checks are pending
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been skipped
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been skipped
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been skipped
Third-party parts / The same as upstream (pull_request) Has been skipped
beanstalk/approval awaiting maintainer approval
CI / Conventional Commit title (pull_request) Successful in 14s
CI / Workflow lint (actionlint) (pull_request) Successful in 22s
Third-party parts / As their notes say (pull_request) Successful in 29s
PR description / Description follows the template (pull_request_target) Successful in 16s
This pull request is marked as a work in progress.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u 'fix/nightly-flicker:mooki-fix/nightly-flicker'
git switch 'mooki-fix/nightly-flicker'
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
MagicBeanDev/Longshot!526
No description provided.