Repository navigation
Metal compiler workarounds after KosmicKrisp: shader_metalwa rewrites listed shaders around a ballot that sees every lane on macOS 26 (KK3) and a ballot before a loop's only break (KK9) - #2397
Open
computerguy526 wants to merge 1 commit into
Conversation
…metalwa rewrites the shaders it lists around a ballot that sees every lane on macOS 26 (KK3) and a ballot before a loop's only break (KK9) The GPU compiler of macOS 15.4 to 26 if-converts a branch whose ballot result merges after it and evaluates simd_ballot with every lane active: `if (c) m = ballot(true); else m = 2;` gives 0xffffffff where the lanes with c belong (KosmicKrisp's KK_WORKAROUND_3, FB20113490, fixed in macOS 27). A ballot waterfall then never ends once a SIMD group holds two keys, and the kernel spins until the GPU faults. The front end keeps the ballot in its branch in the AIR; the speculation happens when the running OS compiles it for the GPU, so it depends on the OS the game runs on, not the one that built the library. KK9: a ballot before the only break of a loop also sees every lane, at -O0 too; KosmicKrisp keeps that workaround on macOS 27. - dmsh_metalwa.py (new), after KosmicKrisp (Mesa, MIT): KK3 rewrites each spvSubgroupBallot as simd_or of the lane bit, with the lane id brought to the function that needs it, behind the bool function constant DMSH_MWA_FC (220, default on); KK9 puts every loop break of a function with subgroup operations behind `if ((ulong)simd_active_threads_mask())`. Vertex shaders are left alone (one-lane subgroups). Where it would leave a ballot unrewritten it raises, and the build fails that shader with "metal workaround rewrite failed". Over 24,403 translated MSL files it raised on none; 150 of the 4,594 it changed, sampled, all compile. - Profile key shader_metalwa <kk3|kk9> ... [<shader key prefix> ...]: on the listed shaders, or every shader when no prefix is listed. Without the row the MSL is unchanged; no profile has it, so no game's shaders change. - nvn_mtl.m: every set of function constant values the host specializes a game's shader with comes from fc_values, which sets DMSH_MWA_FC false on macOS 27 and later (DM_NVN_METALWA=0 / 1 overrides; iOS keeps the default). Below 27 the set stays empty, as before. - Tests: test_dmsh_metalwa.py (rewrites, lane threading, nested calls, refusals, the gate, the profile row, that every specialization goes through fc_values). t_metalwa.metal: a ballot in a branch, a ballot waterfall on seven lane patterns, a ballot before a loop's only break, all bounded; with DMSH_TEST_METAL=1 they run on the GPU. On macOS 26.6.2 (M4 Pro), as built at -O1, the branch is wrong on 1,024 of 2,048 lanes, the waterfall reaches its 4,096-round cap on every pattern with two keys or more and the break is wrong on 1,984 lanes; rewritten, every check passes. Chain 0211f0a52894. Credit: KosmicKrisp (LunarG / Mesa) found, reported and documented both bugs; the rewrite follows its workaround forms. Co-authored-by: uncraftablexd <352372032+uncraftablexd@users.noreply.github.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.
Related to the PRAGMATA bring-up, ccd834e (@seedds).
The GPU compiler of macOS 15.4 to 26 if-converts a branch whose ballot result merges after it, and evaluates
simd_ballotwith every lane active:if (c) m = ballot(true); else m = 2;gives0xffffffffwhere only the lanes withcbelong. KosmicKrisp lists this asKK_WORKAROUND_3(reported as FB20113490, fixed in macOS 27). A ballot waterfall then never ends once a SIMD group holds two keys, and the kernel spins until the GPU faults. The speculation happens when the running OS compiles the AIR for the GPU, so what counts is the OS the game runs on, not the one that built the library. KK9: a ballot before a loop's only break also sees every lane, at -O0 too; KosmicKrisp keeps that workaround on macOS 27.What changes
dm/gfx/tools/dmsh_metalwa.py(new), after KosmicKrisp's workaround forms (Mesa, MIT):spvSubgroupBallotassimd_orof the lane bit, with the lane id threaded to the function that needs it. It sits behind the bool function constantDMSH_MWA_FC(220, default on).breakof a function that uses subgroup operations withif ((ulong)simd_active_threads_mask()).metal workaround rewrite failed.shader_metalwa <kk3|kk9> ... [<shader key prefix> ...]: applies to the listed shaders, or to every shader when no prefix is given. No profile has the row, so no game's MSL changes with this PR.nvn_mtl.m: every set of function constant values the host specializes a game's shader with now comes fromfc_values. That setsDMSH_MWA_FCfalse on macOS 27 and later (DM_NVN_METALWA=0/1overrides; iOS keeps the default). Below 27 the set stays empty, as before.0211f0a52894(the new module is a chain file and part ofCODE_FP).Tests
python3 dm/gfx/tests/test_dmsh_metalwa.pycovers the rewrites, lane threading, nested calls, the refusals, the gate, the profile row, and that every specialization goes throughfc_values. None of it exists onmain.With
DMSH_TEST_METAL=1,t_metalwa.metal(a ballot in a branch, a ballot waterfall on seven lane patterns, a ballot before a loop's only break, all bounded) runs on the GPU. On macOS 26.6.2 (M4 Pro), built as is at -O1:Rewritten, every check passes.
Reference entry: A ballot under divergent control flow sees every lane (macOS 26), plus the key's row in
dm/games/README.md,env_switches.tsvand the symptom index.Regression
regress.py impactpicks The Legend of Zelda: Breath of the Wild, Pokémon Scarlet and The Legend of Zelda: Tears of the Kingdom (the profiles with a usage manifest, throughnvn_mtl.mand the chain tools). They were not run.Reach: with no
shader_metalwarow the MSL is byte-identical, so no library changes. One host-side difference: on macOS 27 and later every specialization carriesDMSH_MWA_FC = false. Metal ignores a value for a constant a function does not declare (checked through MTLDevice and MTL4Compiler). A pipeline archive recorded before this change was keyed without that value, though, so I would expect it to be looked up again rather than reused. I have no macOS 27 machine to measure that.Credit: KosmicKrisp (LunarG / Mesa) found, reported and documented both bugs.
Working with UncraftableXD