WIP: fix(macos): leave MoltenVK's compute pipelines to the precompile and bound its giant compiles #664
No reviewers
Labels
No labels
area/accessibility
area/audio
area/input
area/install
area/menu
area/renderer
area/saves
area/upscaling
beanstalk: approved @ 1697603
beanstalk: approved @ 2c5a62e
beanstalk: approved @ 4fd82b7
beanstalk: approved @ 64d6d09
beanstalk: approved @ 6f91fae
beanstalk: approved @ 70a78f9
beanstalk: approved @ 8015c9a
beanstalk: approved @ 8d361dc
beanstalk: approved @ 9d8356e
beanstalk: approved @ abf2227
beanstalk: approved @ d82f202
beanstalk: approved @ e5f1e40
beanstalk: approved @ ee8ab5f
ci: approved
good first issue
gpu/amd
gpu/igpu
gpu/intel
gpu/nvidia
help wanted
kind
bug
kind
chore
kind
docs
kind
feature
kind
performance
kind
question
needs measurements
platform/linux
platform/macos
platform/steam-deck
platform/windows
preview
priority
critical
priority
high
priority
low
regression
status
blocked
status
confirmed
status
duplicate
status
invalid
status
needs-info
status
wontfix
testing wanted
ci: approved
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Longshot!664
Loading…
Reference in a new issue
No description provided.
Delete branch "mooki/Longshot:mac/warm-handoff"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Type: fix · Risk: medium · Tested on: macOS 26.7.1, Apple M4 Max (MoltenVK 1.4.2), arm64 and x86_64 under Rosetta · Needs: macOS, Apple silicon (a start on the rebased stack); Windows and Linux, any GPU (build and start)
Why
On a Mac starting without a program cache, the title did not come: the shader preparation compiled every compute program's
Metal pipeline itself, before the precompile that can hand slow compiles to the game, and Metal's compiler service took
minutes over the largest of them. In start 14, 13 of the preparation's 16 workers were each held for 205-274 s by one compute
compile of 122,000-209,000 SPIR-V words; the preparation reached 278 of 38,809 programs in 430 s and the precompile never
began. Once those compiles are the precompile's, the same giants could still take every one of its workers at once, so nothing
small finished and nothing told the start to go on. This PR leaves the compute pipelines to the precompile on MoltenVK and lets
only a few giant compiles run at a time, always leaving a worker for the small ones. It is part of the macOS port. See #420.
How to reproduce
Seen on: macOS 26.7.1, Apple M4 Max, MoltenVK 1.4.2 (main does not run on macOS yet: seen on the macOS port's integration
builds, which carry the open macOS PRs)
Settings and switches: defaults (start mode), a start whose program cache is translated anew (a first start, or a changed
translator)
Steps: start the game and wait for the title.
Expected: the preparation translates the programs in a minute or two, then the precompile builds what it can and hands the
slowest compiles to the game.
Actual: the preparation sits for minutes inside the compute warm's Metal compiles (start 14: 278 of 38,809 programs in 430 s;
start 16: 1,550 s, 1,381 compute pipelines compiled there), and the precompile with its hand-off comes only after it
(
reports/2026-11-14-mac-startup-14.md,-16.md; analysis inreports/2026-11-14-warm-handoff.md).What changed
Under
compiler_service(MoltenVK only, #652) the preparation still translates and keeps every compute program but compilesnone of their pipelines: the precompile takes every kept one on a first start (its order puts them last, smallest first) or the
first dispatch compiles it, as any program this start did not prepare. In the precompile, at most
RX_VK_GIANT_COMPILES(4)compiles of more than
RX_VK_GIANT_WORDS(100,000) SPIR-V words are in flight at once, and never as many as the workers of aphase (4 of 16 before the game, 3 of the 4 behind it); one more is deferred, named once, and built as soon as one ends, never
left out. Every other driver's preparation and precompile are unchanged.
gpu/vk/vk_draw.cppprepare_run:if (warm_cs && compiler_service_on())clears the compute warm before its.warmingmarker and says where the compiles went; the stage-library warm (
RX_VK_GPL), the state list and the prepared record are asbefore.
gpu/vk/precompile_handoff.h(no Vulkan):claim_below(a claim that never passes the end, so a worker waiting for adeferred giant does not count as one that ran out),
giant_compiles/giant_words(the two switches),Giants(nextreturns Run, Wait or None;
end;limit_for(cap, workers)= at most one fewer than the workers, at least 1;phasefor theshare behind the game).
gpu/vk/vk_draw.cppprecompile_run, underpre->handonly: each item's SPIR-V words,pre->giants,behind_workerthrough
Giants::nextwith a deferral line once per giant and the count inbehind_done's line;phase(share)at thehand-off. The classic worker (every other driver) is untouched.
docs/development.md: theRX_VK_COMPILER_SERVICErow (the preparation's compute pipelines) and a row forRX_VK_GIANT_COMPILES/RX_VK_GIANT_WORDS.tests/test_warm_handoff.py(new:prepare_run's warm decision andwarm_computecut from the source and run withstand-ins, six cases; source checks for the chain that keeps each variant for the precompile);
tests/precompile_handoff_test.cppandtests/test_precompile_handoff.py(the gate before the game and behind it, one workeralways on small items, the wiring).
Measurements
Verdict: helps: with this change a start that translates the programs anew spent 118.3 s in the preparation with 0 compute
pipelines compiled there (run #18), where it spent 1,550.4 s compiling 1,381 of them before (run #16); the precompile then
handed off after 670 s (#18) and 626 s (#19) with at most 4 giants in flight before the game (1,411 and 1,415 deferral lines),
and the title came 4.5-5 s later.
Baseline: main does not run on macOS yet, so both columns are the macOS port's integration builds, arm64, MoltenVK 1.4.2,
start mode, each translating the program cache anew. Before: 4e472987 (run #16), without this change. After: 1cbb594a (run
#18, Integration 25, which carries this topic). One run each; the runs are the port's start runs, not an A/B on one build.
Hardware: macOS 26.7.1, Apple M4 Max (40-core GPU), MoltenVK 1.4.2, 16-core CPU, 64 GB
Scene: a start to the title, windowless, defaults
Method: the game log's
vk: prepared …,vk: precompile: …and deferral lines, one run eachHow to reproduce: a start of a macOS build from a seeded Metal cache with a program cache that must be translated again
Run reports:
reports/2026-11-14-mac-startup-14.md,-16.md,-18.md,-19.md.Flags and settings
Two new switches for the giant bound, on with the compiler service; the
RX_VK_COMPILER_SERVICErow gains the preparation'spart. Nothing changes on other drivers.
RX_VK_GIANT_COMPILES0: no boundRX_VK_COMPILER_SERVICERX_VK_GIANT_WORDSRX_VK_COMPILER_SERVICE=0only to compareTesting
Tested: on macOS 26.7.1, Apple M4 Max, at this head (main
6c9edffeplus #650, #651, #652 and this PR):tests/test_warm_handoff.pyandtests/test_precompile_handoff.py, each--arch arm64and--arch x86_64(the fixtures rununder Rosetta): pass on both arches (
reports/PubWave-files/PubLate1/wh-proof-02/). On this branch's base (#6527ef7cff9)with the test files copied in (sha256 in
wh-test-files-02.sha256): both fail on both arches (the warm compiled 1 pipelineunder compiler_service, wrote the
.warmingmarker and said nothing; the gate fixture does not build: noclaim_below,Giants,limit_for) (wh-proof-02/wh-base-warm-*,wh-proof-01/wh-base-handoff-*). Before the adaptation commit(
e10c0ad5),test_warm_handofffails on both arches: its fixture lacks main's warm stand-ins (wh-proof-01/wh-warm-*).tools/ls-suite.py: 279pass, 19 fail, the same 19 by name as at #652's head (16 also fail on main
6c9edffeon macOS;test_precompile_compute_guard,test_shader_module_guardandtest_present_aspect_vulkanare skipped on macOS in a full run and fail only because named)(
wh-related-02/,wh-related-02-compare.txt).gpu/vk/vk_draw.cppcompiled whole for arm64 and x86_64 with main's renderer flags (with #476's and #492's macOS compile piecesin a scratch tree): both objects made, exit 0 (
reports/PubWave-files/PubLate1/compile/warm-handoff/).unifdef -U__APPLE__of each changed file, base against head):vk_draw.cppis the same;precompile_handoff.hdiffers (its new pieces are compiled on every platform, used only under
compiler_service)(
reports/PubWave-files/PubLate1/offapple-warm-handoff.txt).Not tested: the game at this head (main does not run on macOS without the other macOS PRs); Windows and Linux (no change in
behaviour there: the new code runs only under
compiler_service, off on their drivers; the header's new pieces are compiledthere): not built on Windows or Linux; its test request covers it.
Must be tested:
vk: preparation: the compute programs are translated and kept …line,0 compute pipelinesinvk: prepared …, deferral linesin the precompile and the hand-off (by hand: the parent's GPU slot).
20367871, it carries #650, #651 and #652) and main6c9edffethe same way andstart each to the title, expecting no
in this order for Metal's compiler service,deferredorthe compute programs are translated and keptline (precompile_handoff.h's new code is compiled there and not reached), and every other line to matchmain's (by hand: test request T-XXXX).
Risks
What could break: on MoltenVK a compute program the precompile does not reach before the hand-off is compiled behind the
game or at its first dispatch, which leaves that dispatch out until it is ready (as with play's own builds); with the bound, the
precompile may wait on four giants while small items are left, so the hand-off comes on the stall rule. Other drivers: one
ifthat
compiler_servicegates inprepare_run, and the header's new code, unused there.Turning it off:
RX_VK_GIANT_COMPILES=0(no bound);RX_VK_COMPILER_SERVICE=0(the warm and the precompile as on everyother driver); or revert the PR.
Compatibility: Nothing changes for players on Windows and Linux: no shader stamp, cache format or
MKWVK_API_VERSIONchange. On macOS the preparation writes no
.warmingmarker for compute pipelines any more.Reviewer notes
abfc05c8..20367871(5 commits; in git's notation7ef7cff9..20367871): the warm left to the precompile, the gate,the docs rows, the per-phase bound, and the test adaptation (
20367871).compiler_service,precompile_handoff.h,behind_worker,create_watched), and through it on #650 and#651. The branch is #652's head
7ef7cff9plus this PR's commits.-xfrommacos/warm-handoff(84c32d68 f1e028c8 8aaa2f33 acd3a71a), madeon the integration branch. Conflicts in the pick:
tests/test_precompile_handoff.pybehind_worker's needles: #652's adaptation needles (#252's quick builds:precompile_compute_quick,optimize_owed) and this PR's giant needles, both kept.docs/development.md(8aaa2f33,acd3a71a): theRX_VK_COMPILER_SERVICEandRX_VK_SLOW_COMPILE_Srows take main'scache/longshot_pipelines.bin.slow(#321) with this PR's text.20367871:test_warm_handoff's fixture gets stand-ins for main's warm (#252'sIntelDriverGateandguarded_compute_held, #190's and #650'screate_cached, #652'screate_watched/compiles_watched), andits dispatch check reads main's
p(the integration branch'splainis #663's rename).4253b972(#include "crash_markers.h", needed once#428 puts
crash_markers::begininprepare_run) and1cbb594a(a comment-tolerantseed_computecheck, needed once theSPIR-V profile switch, a later macOS PR, adds to that line). Neither is needed on this base. Whichever of this PR and #428 lands
second adds that include to
test_warm_handoff.py's fixture.git merge-treeof this head: no conflict with#423, #427, #431, #438, #476, #479, #480, #490, #491, #492;
gpu/vk/vk_main.cppwith #428, #498 and #653, andvk_main.cpp/vk_progcache.cpp/vk_shader.h/vk_vendor.hwith #646: the same conflicts as #652's own head(
reports/PubWave-files/PubLate1/merge-check-*.txt), none from this PR's lines.Issues
See #420
Checklist
Everyone
type(scope): description) of the status line's type.main(maine090cc48).python -I -B tests/run_all.pypasses (any failure that also fails onmainis named). (On the wave's merge of the macOS PRs this one is built with,bfe5c752(metal-cache2 + giant-mem-gate, which carry this PR): 544 passed, 32 failed, 17 skipped against main 6c9edffe's 531/32/17 on this Mac; the 32 failures are main's own, nothing that passes on main fails, 13 new tests pass;reports/PubWave-files/waveC1/.)third_party/untouched (a new folder with aPROVENANCE.mdinstead).When it applies
Assisted-by:/Co-Authored-By:trailers.mainand passing here.tests/that reads changed source updated in this PR, not weakened.7707c634) under the precompile hand-off f9f166f7cb20367871b5658b854052658b8540521f7065181dFolded into #849 (fix(macos): MoltenVK's precompile and pipelines on Metal)
Pull request closed