WIP: fix(macos): KosmicKrisp's compiles go through the compiler service's precompile, as MoltenVK's do #785
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 @ 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!785
Loading…
Reference in a new issue
No description provided.
Delete branch "mooki/Longshot:mac/kk-compiler-service"
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: low · Tested on: macOS 26.7.1, Apple M4 Max (MoltenVK 1.4.2; KosmicKrisp from the LunarG SDK 1.4.363.1 in probes KK-03 and KK-04), game-free on arm64 and x86_64 under Rosetta · Needs: macOS, Apple silicon (a start with KosmicKrisp); Windows and Linux, any GPU (build and start)
Why
On a Mac, KosmicKrisp (Mesa's Vulkan driver on Metal 4, opt-in since #654:
RX_VK_DRIVER=kosmickrisp) compiles everypipeline in Metal's compiler service, as MoltenVK does, but the game treated it as any other driver: its shader preparation
compiled every compute program's pipelines itself, the place where nothing can hand a slow compile to the game. The first
start with KosmicKrisp (start #20) reached 1,607 of 38,809 programs in 29.5 minutes and never showed the title; on MoltenVK
(start #19, Integration 27) the preparation translated all 38,809 in 75 s and the precompile compiled them, then the game
started. This PR gives KosmicKrisp the same compiler-service path as MoltenVK: the preparation only translates, the
precompile compiles (a few giants at a time, the rest behind the game), and a compile that Metal's service failed is tried
again. It is part of the macOS port. See #420.
How to reproduce
Seen on: macOS 26.7.1, Apple M4 Max, KosmicKrisp from the LunarG Vulkan SDK 1.4.363.1 (Mesa 269a955c); main does not
start on macOS yet: seen on the macOS port's integration build 09f9a171, which carries the open macOS PRs
Settings and switches:
RX_VK_DRIVER=kosmickrisp(start #20 chose it by itself: that build picked KosmicKrisp onmacOS 26; MoltenVK has been the default since)
Steps: start the game with KosmicKrisp and a translated program cache missing (a new translator stamp), and watch the
vk: start-up: N of 38809lines.Expected: the preparation translates the programs in about a minute, then the precompile compiles their pipelines and
hands the rest to the game, as on MoltenVK (start #19).
Actual: the preparation compiles every compute program's pipelines itself: 0.9 programs a second, 1,607 of 38,809 after
29.5 minutes, no title (
reports/2026-11-14-mac-startup-20.md,reports/2026-11-14-kk-slow.md§3).What changed
On KosmicKrisp's driver (
VK_DRIVER_ID_MESA_KOSMICKRISP)compiler_serviceis on by default, as on MoltenVK's, and itsfailed-compile code is read as MoltenVK's where the service's compiles are made. Every other driver, MoltenVK's included, runs
the code it ran before.
gpu/vk/vk_vendor.hvendor_fixes:compiler_serviceon for MoltenVK's and KosmicKrisp's drivers;RX_VK_COMPILER_SERVICE=0still turns it off. The comment carries KK-03's numbers (below).gpu/vk/vk_draw.cppservice_failed: KosmicKrisp reports every Metal library or pipeline it could not make, a compilerservice that ended under it included (start #20 had three), as
VK_ERROR_INVALID_SHADER_NV. Where the service's compilesare made (
create_watchedwithcompiler_serviceon, andcompile_again's result) that code is read asVK_ERROR_INITIALIZATION_FAILED, MoltenVK's, on KosmicKrisp only, and said once (vk: KosmicKrisp: a pipeline compile failed (VK_ERROR_INVALID_SHADER_NV: …); read as VK_ERROR_INITIALIZATION_FAILED from here on …). So #665's tries again applyunchanged: once more with a new pipeline cache, or a giant's alone. KosmicKrisp's pipeline cache keeps no failed compile
(Mesa
vk_pipeline.c), so the new cache costs it the one compile alone.compile_again's line still prints the driver'sown code. The comments on the section and on
prepare_run's warm name KosmicKrisp and start #20.docs/development.md: theRX_VK_COMPILER_SERVICEandRX_VK_PRECOMPILE_STALL_Srows.tests/test_precompile_handoff.py:service_failed,compile_againandcreate_watchedcompiled from the source against amade-up KosmicKrisp (its failed compile is
VK_ERROR_INVALID_SHADER_NV, its cache keeps none): a compile that failed once ismade by the second try and said once; one that always fails is tried twice and said
not made (-1000012000); a giant'sfailure is left for its try alone; on MoltenVK's driver the same code is returned as it is; on KosmicKrisp without
compiler_servicetoo. The vendor keying (KosmicKrisp on, the switch off on it, HoneyKrisp off), and the source's wiring(
service_failed(three times: its definition and the two places).Measurements
Verdict: the cause is measured, the fix's start is not yet. Probe KK-03 measured KosmicKrisp's compiles on identical
synthetic SPIR-V against MoltenVK's: 1.0× MoltenVK's at 3,003 words, 2.5× at 29,310, 5.8× at 110,406 (2.4× at the middle size
with robustness off on both), 16 at once 4.7×; its pipeline cache saves 8% in a new process, Metal's own cache 94-95% on both
drivers. So the compiler-service path that keeps MoltenVK's giants out of the preparation is needed on KosmicKrisp at least as
much. Probe KK-04 confirmed the driver facts the fix keys on (5 of 5 predictions): for a module Metal cannot compile,
KosmicKrisp returns
VK_ERROR_INVALID_SHADER_NVboth times and compiles it again on the second ask (its cache keeps nofailure), while MoltenVK returns
VK_ERROR_INITIALIZATION_FAILEDand answers the second ask from its cache in 0.0 ms (whycompile_againtakes a new cache). A game start with this PR is in the table's After column.Baseline: main does not start on macOS. The "before" is the integration build 09f9a171 (start #20, KosmicKrisp, without this
change; MoltenVK's start #19 on Integration 27 for comparison); KK-03 compares the two drivers in one standalone process each,
with no LS code.
Hardware: macOS 26.7.1 (25G241), Apple M4 Max (40-core GPU), 16-core CPU, 64 GB; KosmicKrisp from the LunarG SDK 1.4.363.1
(Mesa 269a955c), MoltenVK 1.4.2, both through the SDK's loader
Scene: start #20: the preparation from a program cache to translate again in full (a new stamp), windowless; KK-03: one
compute module each of 3,003, 29,310 and 110,406 SPIR-V words, cold and warm Metal caches, 16 at once
Method: start #20: the
vk: start-up: N of 38809readings every 60 s; KK-03: the Vulkan call's time per compile in eachphase's
probe.log(reports/KkSlow-files/kk03/runs-kk03-kk/run.json449dfd7b…,runs-kk03-mvk/run.json7acdbc04…),one run per route; KK-04: the result and time of each
vkCreateComputePipelinesfor a 300-deep (past Metal's bracket nesting of256) and a 200-deep module, twice each with the same
VkPipelineCache, one run per route, released by the parent at 05:02-05:03 CSTHow to reproduce: KK-03's
runcommands (reports/KkSlow-files/kk03/FROZEN-COMMAND.md); KK-04'srunandscorecommands(
reports/2026-11-14-kk-slow.md§5.5); a start withRX_VK_DRIVER=kosmickrispreading the preparation's and the precompile's linesa4d31a59nest-300(Metal cannot compile it), firstVK_ERROR_INVALID_SHADER_NV), 190.1VK_ERROR_INITIALIZATION_FAILED), 14.9nest-300, again, same cachenest-200, first / againReports:
reports/2026-11-14-kk-slow.md(KosmicKrisp's compile path from the SDK's Mesa source, KK-03, the fix, KK-04),reports/2026-11-14-mac-startup-20.md.Flags and settings
One default changes, on KosmicKrisp only:
compiler_service, whichRX_VK_COMPILER_SERVICEoverrides. The diff against mainalso shows the switches of the PRs it stacks on, theirs to list:
RX_VK_COMPILE_QOS,RX_VK_GIANT_COMPILES,RX_VK_GIANT_HOLD_PRESENTS,RX_VK_GIANT_HOLD_S,RX_VK_GIANT_WORDS,RX_VK_SLOW_COMPILE_S,RX_VK_WORKER_CACHES.RX_VK_COMPILER_SERVICE=0or1Testing
Tested: on macOS 26.7.1, Apple M4 Max:
e090cc48plus #650, #651, #652, #664, #665 and this PR), every run under the shared check slot with a freshHOME and TMPDIR (
reports/PubWave-files/PubLate5/StartTrio/proof/kk-*):tests/test_precompile_handoff.py --headers <Vulkan-Headers 1.4.345>,--arch arm64and--arch x86_64(Rosetta): exit 0on both (
PASS: the precompile goes on behind the game … every other driver as before). On the base #665 (40edc9da) withthis PR's test file: exit 1 on both (
create_watched/compile_again: KosmicKrisp's failure code not read …,vk_vendor.h: compiler_service not MoltenVK's and KosmicKrisp's alone …,vk_draw.cpp: no service_failed …).test_warm_handoff,test_vendor_fixesandtest_worker_caches, arm64 and x86_64: exit 0 on all six(
test_vendor_fixesis #665's, unchanged here: the KosmicKrisp row is #698's, a sibling item).gpu/vk/vk_draw.cppcompiled whole for arm64 and x86_64 with main's renderer flags (#476's, #492's and #490's macOS compilepieces merged in a scratch tree only): exit 0 (
…/StartTrio/compile/kk-compiler-service/).macos/kk-compiler-serviceecbeefa5, on the integration branch79e2e006): the two changed testsfailed on
79e2e006and passed atecbeefa5, with 8 related checks passing (test_precompile_handoff,test_vendor_fixes,test_warm_handoff,test_loading_stall,test_retry_alone,test_giant_memory,test_worker_caches,test_index8_bind);vk_draw.cppcompiled for arm64 and x86_64 (reports/KkSlow-files/fix/).unifdef -U__APPLE__, base against head):vk_draw.cppandvk_vendor.hdiffer:service_failedis compiledeverywhere and returns every code as it is unless the driver is KosmicKrisp's, and the vendor keying names KosmicKrisp's
driver id, which no Windows or Linux device reports
(
reports/PubWave-files/PubLate5/StartTrio/offapple-kk-compiler-service.txt).a4f716dc…, build129a73de…; both routes released once by the parent, 05:02-05:03 CST):reports/KkSlow-files/kk04/score-kk04/score.json(sha256bb0b1e2747d4d20f0385a541a1b1bfeb4b1f7f85cb1815d70a4943acb9525ef7)K04-1 to K04-5 MATCH, routes
runs-kk04-kk/run.json(5d5e98d4…) andruns-kk04-mvk/run.json(8c3d0873…): the codeservice_failedreads is the one KosmicKrisp gives (K04-1), MoltenVK's is the onecompile_againalready took (K04-2), andeach cache behaves as the comments in
compile_againandservice_failedsay (K04-4, K04-5).Not tested: a game start with KosmicKrisp and this PR; Windows and Linux (no behaviour changes there: the new code returns
at its first test off KosmicKrisp): not built there; its test request covers it. KK-04 has passed, so no probe holds this PR in
WIP any more; the Testing box waits for the test requests.
Must be tested:
RX_VK_DRIVER=kosmickrispin a KosmicKrisp-only cache folder,expecting
vk: preparation: the compute programs are translated and kept …, a preparation of about #19's length, then aprecompile that hands off to the title (by hand: the parent's game run)
a4d31a59, it carries #665, #664, #652, #650 and #651) and #665's head thesame way and start each to the title, expecting every line to match #665's (no
KosmicKrisp:line, the samevendor fixesline) (by hand: test request T-XXXX)Risks
What could break: only starts on KosmicKrisp (opt-in): its compute pipelines move from the preparation to the precompile
and behind the game, as MoltenVK's did, and its failed compiles are tried again. A KosmicKrisp failure for another reason
(a program its MSL cannot express) is tried once more and then said not made, as before but one compile later. KK-03 found
KosmicKrisp 2-3.4× MoltenVK per graphics pipeline and up to 5.8× per large compute pipeline: its first start stays long;
MoltenVK stays the default.
Turning it off:
RX_VK_COMPILER_SERVICE=0, or revert the PR.Compatibility: Nothing changes for players: KosmicKrisp is opt-in, and on every other driver the code is as before.
Neither changed file is a shader-stamp input, so no program is translated again; no
MKWVK_API_VERSIONchange.Reviewer notes
40edc9da..a4d31a59, one commit:macos/kk-compiler-serviceecbeefa5picked with-x. Readservice_failedandits two calls first, then
vendor_fixes.compile_again,create_watchedwithRetry::Fresh/Laterandcompile_failed_later: the tries againthe mapping feeds, which the test exercises) and what #665 carries (#664, #652, #650, #651). Not on #666 or #669: their tries
alone and gates apply to KosmicKrisp unchanged once both land. It needs no code of #654 (KosmicKrisp's packaging): only the
driver id, from the Vulkan headers (1.4.345).
vk_vendor.h(main's and the integration branch's neighbouring fields; only thistopic's line kept),
docs/development.md(#665's text of the two rows, with this topic's words). Its code and itstest_precompile_handoff.pychanges are the topic's line for line.tests/test_vendor_fixes.py'scheck_apple_drivers: KosmicKrisp's Apple columns1000000011→1000000111(compiler_serviceon), its comment, themodule docstring and the
ok:line, as the topic has them (ecbeefa5). That check is #698's; this PR's base does not have it,so the pick leaves it out.
git merge-tree):docs/development.md'sRX_VK_COMPILER_SERVICErow with #666, #667, #669 and the PRsthat carry them (keep their text, with this PR's "MoltenVK and KosmicKrisp" and its failure-code clause);
gpu/vk/vk_vendor.hwith #784 (neighbouring fields: keep both).
35465d12): inherited from the base (vk_draw.cpp,test_pipeline_play_cache.py); none of this PR's own.reports/2026-11-14-*.md(the port's design notes), which are not in this repository.Issues
See #420
Checklist
Everyone
type(scope): description) of the status line's type.main. (On maine090cc48through #66540edc9da; main has moved since (35465d12): a delta sweep follows.)python -I -B tests/run_all.pypasses (any failure that also fails onmainis named). (On wave Sc08ae52d= #784694edb10with #7865c37ec10and this heada4d31a59merged: 586 passed, 31 failed, 18 skipped against main e090cc48's 544/32/17 on this Mac; the 31 failures are main's own and nothing that passes on main fails;test_collect_widenow passes; 41 new tests pass;reports/PubWave-files/PubLate5/wave/full-S-c08ae52d/.)third_party/untouched (a new folder with aPROVENANCE.mdinstead).When it applies
Assisted-by:/Co-Authored-By:trailers.mainand passing here. (It fails on this PR's base, #665, with this PR's test file; main has no compiler service path.)tests/that reads changed source updated in this PR, not weakened.7707c634) under the precompile hand-off c19fe5a59da4d31a5904588d5f3851Folded into #849 (fix(macos): MoltenVK's precompile and pipelines on Metal)
Pull request closed