WIP: fix(macos): draw-path emulation on MoltenVK #850

Draft
mooki wants to merge 60 commits from mooki/Longshot:mac/topic-draw-path into main
Member

Type: fix · Risk: medium · Tested on: macOS 26.7.1, Apple M4 Max (arm64; x86_64 under Rosetta) · Needs: Windows and Linux, any GPU

Why

On a Mac, LS's draws go through MoltenVK (Vulkan on Metal), and MoltenVK 1.4.2 draws several kinds of draw differently from
every other driver, or not at all. Loading the first scene ran the GPU out of memory (53 GB of 64) and lost the device, because
MoltenVK widens 8-bit indices to the end of the bound buffer. Count draws were dropped without a word (MoltenVK's count calls
are empty). A buffer update could lose its first word, and a direct draw that reads the draw index read a stale one (MoltenVK
writes the draw index to the wrong word). A triangle fan could be drawn as a list, or a list converted as a fan, depending on
which draw built the pipeline first; an indirect fan of several records could garble its own triangles. And every primitive took
its flat values from its first vertex, where NVN and LS everywhere else take the last. This PR draws each of these the way the
game asks on MoltenVK, counts what the game does where a fix was not yet known to be needed, and documents the MoltenVK build
the port recommends. 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
Settings and switches: defaults (the macOS port's stack without this PR: main does not start on macOS)
Steps: start the game and load the field-dawn save (START, then A), sampling the GPU's memory (ioreg -r -c AGXAccelerator -d 1); for each other gap, the members' standalone MoltenVK probes (commands in their reports, named under Measurements): MT-01 and CD-01 (count draws), CR-01 (buffer updates), DI-01 (draw index), FK-01 (fan key), FI-01 (indirect fans), PV-02 (flat values)
Expected: the load reaches play within a few GB of GPU memory; every probe draw covers its own pixels with NVN's values, as on every other driver
Actual: the GPU's memory reaches about 53 GB and the device is lost in the load (kIOGPUCommandBufferCallbackErrorOutOfMemory); a count draw draws nothing; 1,010 CR-01 trials lose the update's first word; 1,688 of 3,744 DI-01 draws read a stale draw index; 96 of 288 FK-01 draws take the wrong topology; every packed multi-record FI-01 fan is wrong; every PV-02 pixel holds the first vertex's value

What changed

On MoltenVK (on macOS, or where the device lacks a feature only MoltenVK lacks), draw() binds 8-bit indices with their size,
rewrites count draws on the GPU, copies buffer updates from the stream, draws direct draw-index readers as one indirect record,
keys fans apart, splits multi-record indirect fans into a call a record, and draws triangles with their last vertex first. Every
other driver records what it did before. Two Apple-only censuses count polygon modes, restart-off strips, fans and provoking-vertex
draws (log-only). One commit per original PR, in order:

  • feat(macos): count NVN's polygon modes and restart-off strip draws on Apple, log-only (gpu/vk/mode_census.h, the census in
    vk_draw.cpp, its report in vk_replay.cpp). Was: #677
  • fix(macos): bind a direct draw's 8-bit indices with their size on MoltenVK (vk_vendor.h index8_size, RX_VK_INDEX8_SIZE;
    VK_KHR_maintenance5 asked for only then in vk_main.cpp; vkCmdBindIndexBuffer2KHR through bind_index). Was:
    #678
  • fix(macos): count draws rewritten where MoltenVK has no drawIndirectCount (gpu/vk/count_draws.h, the compute shader
    count_draws.comp), and buffer updates copied from the stream on MoltenVK (cmd_update_buffer). Was:
    #679
  • fix(macos): direct draws that read the draw index drawn as one indirect record on MoltenVK (gpu/vk/drawid_direct.h,
    drawid_indirect). Was: #680
  • docs(macos): MoltenVK main 5189f8de with the argbuf-slots patch as the recommended MoltenVK input, and how to build it
    (docs/macos-moltenvk.md, the patch, the LONGSHOT_MOLTENVK row, gpu/vk/VULKAN.md). Was:
    #691
  • fix(macos): fans keyed apart from the other triangle topologies on MoltenVK (gpu/vk/fan_key.h, the pipeline key and the
    program cache's stamp in vk_progcache.cpp; a fan census). Was: #701
  • fix(macos): an indirect fan of more than one record drawn a call a record on MoltenVK (gpu/vk/fan_indirect.h,
    fan_indirect_split). Was: #702
  • fix(macos): take flat values from each primitive's last vertex on MoltenVK, as NVN does, for direct triangle draws and the
    mesh fallback (gpu/vk/provoking.h, provoking_list / provoking_write, the fallback's rotation list). Was:
    #703
  • test(macos): test_fan_indirect's cut of the indirect block ends at draw()'s next branch (c2cfee0f): where #702 met #703,
    the cut took in #703's branch and its fixture stopped building; the line Integration 37's eb4d0204 has. A test only.
  • The base, topic shader-backend, merged at 70cc5ba1 (its test-fixture fix).
  • fix(macos): draw_index8_report's closing brace (67fd90bc): where #701's fan census report met #678's 8-bit report, the
    brace was dropped and vk_draw.cpp stopped compiling from there; it goes back where Integration 41 has it.

Measurements

Verdict: each gap fixed where it was measured: the game reached play and held it at 9.3 GB of GPU memory at most (lost at
53 GB before), and in each member's MoltenVK probe the fixed path drew exactly what the game asks (count draws, buffer updates,
draw indices, fans, indirect fans, flat values), at no cost the probes could tell from their noise except where a member says.
The censuses answered their questions: the game draws FILL only, its restart-off strips hold no all-ones index.

Baseline: main does not start on macOS, so nobody could run main against this PR in the game. The before column is what main
records (MoltenVK's own calls, the class key, the raw bind and draws), run in each member's standalone MoltenVK 1.4.2 probe or in
the integration build just before the member's commit; the after column is this PR's code as each member measured it, in the
probe or the integration build its row names (#678: run #23 552cc3d4 against run #24 e7730869; #691: starts #26 6962f8fb,
#28 b8170e55, #31 b4732392).

Hardware: macOS 26.7.1, Apple M4 Max (40-core GPU), MoltenVK 1.4.2 (#691's start #31: MoltenVK main 5189f8de + argbuf-slots), 16-core CPU, 64 GB
Scene: the probes' steps (16×16 targets; each member's arms, both orders, 3 to 264 trials); the game: the title, the field-dawn save's load and 900 s held in play (runs #21-#26, #28, #31)
Method: each probe's result.json and each run's longshot_log.txt lines, one run each, as each member's PR states them: MT-01 and CD-01 (reports/2026-11-14-count-draws.md), CR-01 (2026-11-14-copy-race.md), DI-01 (2026-11-14-drawid-direct.md), FK-01 (2026-11-14-fan-key.md), FI-01 (2026-11-14-fan-indirect.md), PV-02 (2026-11-14-provoking-first.md), runs #21-#26 (2026-11-14-mac-startup-2x.md), MS-01 and starts #28/#31 (#691)
How to reproduce: each probe's driver.py run command in its report; in the game, a macOS build of the port's stack, the field-dawn save, and the vk: lines named below

Before: main @ aa95d35f (as main records it; main does not start on macOS) After: this PR @ 67fd90bc (each member's code, measured where its row says)
GPU memory loading the first scene (#678, runs #23/#24) 53.1 GB, then out of memory, device lost; 385 128 MB regions 9.3 GB in play, 1 such region the whole run; #25: 900 s in play, 9.2-9.8 GB
count draws (#679, MT-01, CD-01) vkCmdDraw*IndirectCount: nothing drawn rewritten: exact in 41 of 45 steps (the 4 others lost the probe's own count update to CR-01's cause)
count draw cost, one submit (#679, CD-01) 0.15-0.41 ms (direct reference) maxDrawCount 4096: 0.74-1.9 ms; 65536: 9.6-16.1 ms
buffer updates before a draw-index draw (#679, CR-01) 1,010 trials lost the first word 0 lost of 3,440
direct draws reading the draw index (#680, DI-01) 1,688 of 3,744 stale 0 of 3,744; record/submit cost within the noise floor (about 0.1 µs)
fans and other triangle topologies (#701, FK-01) 192 of 288 draws right 288 of 288
indirect fans of 2, 3, 7 records (#702, FI-01) packed arms wrong in every trial 429 of 429 records right
flat values (#703, PV-02) the first vertex's on every pixel the last vertex's (NVN's) on every pixel; coverage and depth unchanged; 130 of 130 as predicted
polygon modes, restart-off strips (#677, runs #21-#26) not counted FILL only (LINE 0, POINT 0); up to 154 restart-off strips, none holding the all-ones index; +0.385 ns a draw
MoltenVK input (#691, starts #26/#28/#31) 1.4.2: count draws rewritten by LS; MoltenVK main alone: 39 pipelines lost (no free slot) main + argbuf-slots: 0 lost, 0 skipped draws in 174 hold groups, count draws native; GPU 20.25 ms a frame (23.1 on 1.4.2)
#24 L196: vk: 8-bit indices: a direct draw's bound with their own size, so MoltenVK widens only those (VK_KHR_maintenance5): yes
#26: vk: no drawIndirectCount: a count draw's records are rewritten on the GPU, then drawn as a plain indirect draw of maxDrawCount records (multiDrawIndirect 1, maxDrawIndirectCount 1073741824, shaderDrawParameters 1)
#21 L33858: vk: polygon modes (at present 1320; NVN's, set per draw: dynamic polygon mode): graphics pipelines built FILL 30330, LINE 0, POINT 0; draws FILL 4282, LINE 0, POINT 0
DI-01 result.json: fix_exact_on_moltenvk 1; FK-01: all_as_predicted 1 (48 of 48), fix_exact_on_moltenvk 1; FI-01: all_as_predicted 1 (176 of 176), alone_exact 1; PV-02: all_as_predicted 1 (130 of 130), fix_exact_on_moltenvk 1

Flags and settings

Two new switches, both macOS or MoltenVK only, and the recommended MoltenVK input named in an existing build switch's row.

Flag What it is Before this PR After this PR Effect Helps / doesn't help / untested Recommendation
RX_VK_INDEX8_SIZE=0 or 1 (#678) a direct draw's 8-bit indices bound with their own size (VK_KHR_maintenance5) no switch: the bind reaches the pool's end on for MoltenVK's driver, off elsewhere; 0 off, 1 on where the device has maintenance5 and 8-bit indices MoltenVK widens only the draw's indices helps: MoltenVK (runs #23/#24, MT-01); no change elsewhere by default; untested forced on other drivers default (on for MoltenVK only)
RX_VK_COUNT_REWRITE=1 (#679) the count-draw rewrite on a Mac whose device has drawIndirectCount too no switch unset: the rewrite only without the feature (MoltenVK 1.4.2); set: always on macOS compares the rewrite with the driver's count draw untested in the game (the game made no count draws in #26) off; for testing
LONGSHOT_MOLTENVK (#691, docs only) the MoltenVK dylib a macOS build packages an approved dylib; 1.4.2 the same switch; its row names MoltenVK main 5189f8de + argbuf-slots as the recommended input (pending the maintainers' approval), built by docs/macos-moltenvk.md; 1.4.2 still accepted none in code helps: start #31 (0 lost pipelines, 0 skipped draws) the recommended input, once approved

Testing

Tested: on macOS 26.7.1, Apple M4 Max, game-free, at this PR's head 67fd90bc:

  • The members' own tests (their commands deduplicated), at 67fd90bc: 23 test files, 45 runs, all exit 0. 19 ran on arm64 and on x86_64 under Rosetta separately (test_count_draws also in its default form), test_macos_build_flags and test_macos_package both arches in one run (and build_flags' default), test_check_pr_description once (no x86_64 form). Among them shader-backend's test_vendor_fixes and test_subgroup_vertex, whose fixtures the base fixed at 70cc5ba1.
  • The whole game-free suite (python -I -B tests/run_all.py --jobs 6) on this Mac against main's (543 passed, 33 failed, 17 skipped): 611 passed, 15 failed, 17 skipped; no check that passes on main fails here. By name: this PR's eight new tests pass, as do the stack's (the topics it carries add 42 more), 17 of main's failures here pass (the macOS host's), one becomes a declared macOS skip, and one skip runs and passes. The 15 failures are main's own on this Mac, and the same 15 as the macOS host topic's suite.
  • The renderer's link check (every mkwvk:: name one gpu/vk file declares and another defines; each defining file compiled with the tree's own flags, arm64 and x86_64, and every symbol an object leaves undefined defined by one of them): 0 of 637 declared names without a definition, 66 of 66 objects compiled, 1,250 name/arch checks with 0 failures, and on each arch 581 cross-file symbols all defined. vk_draw.cpp and vk_replay.cpp also compiled whole with nx2/build.py's own macOS commands: 4 of 4 exit 0.
  • What Windows and Linux compile (unifdef -U__APPLE__ of every changed C/C++ file against the base): the macOS fixes are runtime-gated, not #ifdef'd, so the text off Apple changes in vk_draw.cpp, vk_draw.h, vk_internal.h, vk_loader.h, vk_main.cpp, vk_progcache.cpp, vk_recorder.h, vk_replay.cpp, vk_vendor.h, vk_work.h and seven new headers (mode_census.h, count_draws.h and its shader header, drawid_direct.h, fan_key.h, fan_indirect.h, provoking.h). Each change returns at once off MoltenVK or off __APPLE__ (dev.driver_id == VK_DRIVER_ID_MOLTENVK, provoking_first(), count_rewrite_on()): the census and report calls; vkCmdBindIndexBuffer2KHR declared in the loader and recorder lists and recorded only with index8_size (MoltenVK's vendor fix), VK_KHR_maintenance5 asked for only then; vkCmdUpdateBuffer through cmd_update_buffer (the same call off MoltenVK); the fan key class and the program cache's stamp word on MoltenVK only.
  • In the game, integration builds that hold this topic's members (earlier revisions of some): E9a on I41 78ec1c47 (arm64, MoltenVK main + argbuf-slots): 1,197 s held in play, 12 of 12 must-shows, a clean end, 0 skipped draws; run #34 on I38 3f872b0c (x86_64 under Rosetta): 16 m 52 s, every draw drawn, 19 of 19 checks, a clean exit.

Not tested: Windows and Linux (no PC here): every change there is a runtime gate that should leave what is built, recorded and
drawn as main's, but nobody has built or started this stack off the Mac.

Must be tested:

  • Windows and Linux, any GPU: build this PR (head 67fd90bc) and main (aa95d35f) the same way and run python -I -B tests/run_all.py on each, then start each to the title, expecting this PR's new tests to pass, no other check to change status against main, the same vk: lines in longshot_log.txt as main's (no census, 8-bit, count-draw, draw-index, fan or provoking-vertex line) and no program translated again (Test Farm: @Beanstalk windows and linux: build unchanged, run_all, start to the title)

Risks

What could break: on MoltenVK or macOS only: a count draw now draws (a pass break, and one Metal draw a record: 10-16 ms a
submit at maxDrawCount 65536); buffer updates and converted draws take room in the recording's stream (without room, drawn or
recorded as before and logged); one more pipeline for each program drawn both as a fan and as another triangle topology, and the
first start remakes the program cache once (the stamp word); an indirect multi-record fan costs MoltenVK's per-call dispatch a
record; a converted triangle draw reads its indices on the CPU and writes a list into the stream. Elsewhere: the runtime gates
above; nothing recorded differently.

Turning it off: RX_VK_INDEX8_SIZE=0 for the 8-bit binds; the rest by reverting the PR (no other switch turns them off).

Compatibility: on macOS the program cache is rebuilt once (fan key stamp). Elsewhere nothing changes: no save, options key,
shader cache or vk ABI change.

Issues

See #420. The macOS topic PRs, merged in this order; "topic N" in each description means these: 1 #845 (macos-host), 2 #846 (vulkan-on-metal, on 1), 3 #847 (mvk-descriptor-limits), 4 #848 (shader-backend, on 2, 3 and #431), 5 #849 (precompile-metal, on 4), 6 #850 (draw-path, on 4), 7 #851 (draw-path-quads-mesh, on 6, #705 and #707), 8 #852 (mac-perf, on 7).

Checklist

Everyone

  • One topic.
  • The title is a Conventional Commit (type(scope): description) of the status line's type.
  • Why gives the reason plainly and links the issues that fit (the tracker searched).
  • Measurements has a verdict, or one line saying why there is nothing to measure.
  • Testing names what was tested, what wasn't, and what must still be tested, where and how.
  • Rebased on current main.
  • python -I -B tests/run_all.py passes (any failure that also fails on main is named).
  • 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.

When it applies

  • AI assistance recorded with Assisted-by: / Co-Authored-By: trailers.
  • Switches documented (docs/development.md; the README for a menu row) and shipped at their recommended value.
  • The SPIR-V headers regenerated with glslang (a shader changed).
  • 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.
  • Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths.
  • Docs updated.
**Type:** fix · **Risk:** medium · **Tested on:** macOS 26.7.1, Apple M4 Max (arm64; x86_64 under Rosetta) · **Needs:** Windows and Linux, any GPU ## Why On a Mac, LS's draws go through MoltenVK (Vulkan on Metal), and MoltenVK 1.4.2 draws several kinds of draw differently from every other driver, or not at all. Loading the first scene ran the GPU out of memory (53 GB of 64) and lost the device, because MoltenVK widens 8-bit indices to the end of the bound buffer. Count draws were dropped without a word (MoltenVK's count calls are empty). A buffer update could lose its first word, and a direct draw that reads the draw index read a stale one (MoltenVK writes the draw index to the wrong word). A triangle fan could be drawn as a list, or a list converted as a fan, depending on which draw built the pipeline first; an indirect fan of several records could garble its own triangles. And every primitive took its flat values from its first vertex, where NVN and LS everywhere else take the last. This PR draws each of these the way the game asks on MoltenVK, counts what the game does where a fix was not yet known to be needed, and documents the MoltenVK build the port recommends. 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 **Settings and switches:** defaults (the macOS port's stack without this PR: main does not start on macOS) **Steps:** start the game and load the field-dawn save (START, then A), sampling the GPU's memory (`ioreg -r -c AGXAccelerator -d 1`); for each other gap, the members' standalone MoltenVK probes (commands in their reports, named under Measurements): MT-01 and CD-01 (count draws), CR-01 (buffer updates), DI-01 (draw index), FK-01 (fan key), FI-01 (indirect fans), PV-02 (flat values) **Expected:** the load reaches play within a few GB of GPU memory; every probe draw covers its own pixels with NVN's values, as on every other driver **Actual:** the GPU's memory reaches about 53 GB and the device is lost in the load (`kIOGPUCommandBufferCallbackErrorOutOfMemory`); a count draw draws nothing; 1,010 CR-01 trials lose the update's first word; 1,688 of 3,744 DI-01 draws read a stale draw index; 96 of 288 FK-01 draws take the wrong topology; every packed multi-record FI-01 fan is wrong; every PV-02 pixel holds the first vertex's value ## What changed On MoltenVK (on macOS, or where the device lacks a feature only MoltenVK lacks), draw() binds 8-bit indices with their size, rewrites count draws on the GPU, copies buffer updates from the stream, draws direct draw-index readers as one indirect record, keys fans apart, splits multi-record indirect fans into a call a record, and draws triangles with their last vertex first. Every other driver records what it did before. Two Apple-only censuses count polygon modes, restart-off strips, fans and provoking-vertex draws (log-only). One commit per original PR, in order: - `feat(macos)`: count NVN's polygon modes and restart-off strip draws on Apple, log-only (`gpu/vk/mode_census.h`, the census in `vk_draw.cpp`, its report in `vk_replay.cpp`). Was: [#677](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/677) - `fix(macos)`: bind a direct draw's 8-bit indices with their size on MoltenVK (`vk_vendor.h` `index8_size`, `RX_VK_INDEX8_SIZE`; `VK_KHR_maintenance5` asked for only then in `vk_main.cpp`; `vkCmdBindIndexBuffer2KHR` through `bind_index`). Was: [#678](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/678) - `fix(macos)`: count draws rewritten where MoltenVK has no `drawIndirectCount` (`gpu/vk/count_draws.h`, the compute shader `count_draws.comp`), and buffer updates copied from the stream on MoltenVK (`cmd_update_buffer`). Was: [#679](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/679) - `fix(macos)`: direct draws that read the draw index drawn as one indirect record on MoltenVK (`gpu/vk/drawid_direct.h`, `drawid_indirect`). Was: [#680](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/680) - `docs(macos)`: MoltenVK main 5189f8de with the argbuf-slots patch as the recommended MoltenVK input, and how to build it (`docs/macos-moltenvk.md`, the patch, the `LONGSHOT_MOLTENVK` row, `gpu/vk/VULKAN.md`). Was: [#691](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/691) - `fix(macos)`: fans keyed apart from the other triangle topologies on MoltenVK (`gpu/vk/fan_key.h`, the pipeline key and the program cache's stamp in `vk_progcache.cpp`; a fan census). Was: [#701](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/701) - `fix(macos)`: an indirect fan of more than one record drawn a call a record on MoltenVK (`gpu/vk/fan_indirect.h`, `fan_indirect_split`). Was: [#702](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/702) - `fix(macos)`: take flat values from each primitive's last vertex on MoltenVK, as NVN does, for direct triangle draws and the mesh fallback (`gpu/vk/provoking.h`, `provoking_list` / `provoking_write`, the fallback's rotation list). Was: [#703](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/703) - `test(macos)`: test_fan_indirect's cut of the indirect block ends at draw()'s next branch (`c2cfee0f`): where #702 met #703, the cut took in #703's branch and its fixture stopped building; the line Integration 37's `eb4d0204` has. A test only. - The base, topic shader-backend, merged at `70cc5ba1` (its test-fixture fix). - `fix(macos)`: draw_index8_report's closing brace (`67fd90bc`): where #701's fan census report met #678's 8-bit report, the brace was dropped and `vk_draw.cpp` stopped compiling from there; it goes back where Integration 41 has it. ## Measurements **Verdict:** each gap fixed where it was measured: the game reached play and held it at 9.3 GB of GPU memory at most (lost at 53 GB before), and in each member's MoltenVK probe the fixed path drew exactly what the game asks (count draws, buffer updates, draw indices, fans, indirect fans, flat values), at no cost the probes could tell from their noise except where a member says. The censuses answered their questions: the game draws FILL only, its restart-off strips hold no all-ones index. Baseline: main does not start on macOS, so nobody could run main against this PR in the game. The before column is what main records (MoltenVK's own calls, the class key, the raw bind and draws), run in each member's standalone MoltenVK 1.4.2 probe or in the integration build just before the member's commit; the after column is this PR's code as each member measured it, in the probe or the integration build its row names (#678: run #23 `552cc3d4` against run #24 `e7730869`; #691: starts #26 `6962f8fb`, #28 `b8170e55`, #31 `b4732392`). Hardware: macOS 26.7.1, Apple M4 Max (40-core GPU), MoltenVK 1.4.2 (#691's start #31: MoltenVK main 5189f8de + argbuf-slots), 16-core CPU, 64 GB Scene: the probes' steps (16×16 targets; each member's arms, both orders, 3 to 264 trials); the game: the title, the field-dawn save's load and 900 s held in play (runs #21-#26, #28, #31) Method: each probe's `result.json` and each run's longshot_log.txt lines, one run each, as each member's PR states them: MT-01 and CD-01 (`reports/2026-11-14-count-draws.md`), CR-01 (`2026-11-14-copy-race.md`), DI-01 (`2026-11-14-drawid-direct.md`), FK-01 (`2026-11-14-fan-key.md`), FI-01 (`2026-11-14-fan-indirect.md`), PV-02 (`2026-11-14-provoking-first.md`), runs #21-#26 (`2026-11-14-mac-startup-2x.md`), MS-01 and starts #28/#31 (#691) How to reproduce: each probe's `driver.py run` command in its report; in the game, a macOS build of the port's stack, the field-dawn save, and the `vk:` lines named below | | Before: main @ aa95d35f (as main records it; main does not start on macOS) | After: this PR @ 67fd90bc (each member's code, measured where its row says) | |---|---|---| | GPU memory loading the first scene (#678, runs #23/#24) | 53.1 GB, then out of memory, device lost; 385 128 MB regions | 9.3 GB in play, 1 such region the whole run; #25: 900 s in play, 9.2-9.8 GB | | count draws (#679, MT-01, CD-01) | `vkCmdDraw*IndirectCount`: nothing drawn | rewritten: exact in 41 of 45 steps (the 4 others lost the probe's own count update to CR-01's cause) | | count draw cost, one submit (#679, CD-01) | 0.15-0.41 ms (direct reference) | maxDrawCount 4096: 0.74-1.9 ms; 65536: 9.6-16.1 ms | | buffer updates before a draw-index draw (#679, CR-01) | 1,010 trials lost the first word | 0 lost of 3,440 | | direct draws reading the draw index (#680, DI-01) | 1,688 of 3,744 stale | 0 of 3,744; record/submit cost within the noise floor (about 0.1 µs) | | fans and other triangle topologies (#701, FK-01) | 192 of 288 draws right | 288 of 288 | | indirect fans of 2, 3, 7 records (#702, FI-01) | packed arms wrong in every trial | 429 of 429 records right | | flat values (#703, PV-02) | the first vertex's on every pixel | the last vertex's (NVN's) on every pixel; coverage and depth unchanged; 130 of 130 as predicted | | polygon modes, restart-off strips (#677, runs #21-#26) | not counted | FILL only (LINE 0, POINT 0); up to 154 restart-off strips, none holding the all-ones index; +0.385 ns a draw | | MoltenVK input (#691, starts #26/#28/#31) | 1.4.2: count draws rewritten by LS; MoltenVK main alone: 39 pipelines lost (`no free slot`) | main + argbuf-slots: 0 lost, 0 skipped draws in 174 hold groups, count draws native; GPU 20.25 ms a frame (23.1 on 1.4.2) | ``` #24 L196: vk: 8-bit indices: a direct draw's bound with their own size, so MoltenVK widens only those (VK_KHR_maintenance5): yes #26: vk: no drawIndirectCount: a count draw's records are rewritten on the GPU, then drawn as a plain indirect draw of maxDrawCount records (multiDrawIndirect 1, maxDrawIndirectCount 1073741824, shaderDrawParameters 1) #21 L33858: vk: polygon modes (at present 1320; NVN's, set per draw: dynamic polygon mode): graphics pipelines built FILL 30330, LINE 0, POINT 0; draws FILL 4282, LINE 0, POINT 0 DI-01 result.json: fix_exact_on_moltenvk 1; FK-01: all_as_predicted 1 (48 of 48), fix_exact_on_moltenvk 1; FI-01: all_as_predicted 1 (176 of 176), alone_exact 1; PV-02: all_as_predicted 1 (130 of 130), fix_exact_on_moltenvk 1 ``` ### Flags and settings Two new switches, both macOS or MoltenVK only, and the recommended MoltenVK input named in an existing build switch's row. | Flag | What it is | Before this PR | After this PR | Effect | Helps / doesn't help / untested | Recommendation | |---|---|---|---|---|---|---| | `RX_VK_INDEX8_SIZE=0` or `1` (#678) | a direct draw's 8-bit indices bound with their own size (`VK_KHR_maintenance5`) | no switch: the bind reaches the pool's end | on for MoltenVK's driver, off elsewhere; `0` off, `1` on where the device has `maintenance5` and 8-bit indices | MoltenVK widens only the draw's indices | helps: MoltenVK (runs #23/#24, MT-01); no change elsewhere by default; untested forced on other drivers | default (on for MoltenVK only) | | `RX_VK_COUNT_REWRITE=1` (#679) | the count-draw rewrite on a Mac whose device has `drawIndirectCount` too | no switch | unset: the rewrite only without the feature (MoltenVK 1.4.2); set: always on macOS | compares the rewrite with the driver's count draw | untested in the game (the game made no count draws in #26) | off; for testing | | `LONGSHOT_MOLTENVK` (#691, docs only) | the MoltenVK dylib a macOS build packages | an approved dylib; 1.4.2 | the same switch; its row names MoltenVK main 5189f8de + argbuf-slots as the recommended input (pending the maintainers' approval), built by `docs/macos-moltenvk.md`; 1.4.2 still accepted | none in code | helps: start #31 (0 lost pipelines, 0 skipped draws) | the recommended input, once approved | ## Testing **Tested:** on macOS 26.7.1, Apple M4 Max, game-free, at this PR's head `67fd90bc`: - The members' own tests (their commands deduplicated), at `67fd90bc`: 23 test files, 45 runs, all exit 0. 19 ran on arm64 and on x86_64 under Rosetta separately (`test_count_draws` also in its default form), `test_macos_build_flags` and `test_macos_package` both arches in one run (and build_flags' default), `test_check_pr_description` once (no x86_64 form). Among them shader-backend's `test_vendor_fixes` and `test_subgroup_vertex`, whose fixtures the base fixed at `70cc5ba1`. - The whole game-free suite (`python -I -B tests/run_all.py --jobs 6`) on this Mac against main's (543 passed, 33 failed, 17 skipped): 611 passed, 15 failed, 17 skipped; no check that passes on main fails here. By name: this PR's eight new tests pass, as do the stack's (the topics it carries add 42 more), 17 of main's failures here pass (the macOS host's), one becomes a declared macOS skip, and one skip runs and passes. The 15 failures are main's own on this Mac, and the same 15 as the macOS host topic's suite. - The renderer's link check (every `mkwvk::` name one `gpu/vk` file declares and another defines; each defining file compiled with the tree's own flags, arm64 and x86_64, and every symbol an object leaves undefined defined by one of them): 0 of 637 declared names without a definition, 66 of 66 objects compiled, 1,250 name/arch checks with 0 failures, and on each arch 581 cross-file symbols all defined. `vk_draw.cpp` and `vk_replay.cpp` also compiled whole with nx2/build.py's own macOS commands: 4 of 4 exit 0. - What Windows and Linux compile (`unifdef -U__APPLE__` of every changed C/C++ file against the base): the macOS fixes are runtime-gated, not `#ifdef`'d, so the text off Apple changes in `vk_draw.cpp`, `vk_draw.h`, `vk_internal.h`, `vk_loader.h`, `vk_main.cpp`, `vk_progcache.cpp`, `vk_recorder.h`, `vk_replay.cpp`, `vk_vendor.h`, `vk_work.h` and seven new headers (`mode_census.h`, `count_draws.h` and its shader header, `drawid_direct.h`, `fan_key.h`, `fan_indirect.h`, `provoking.h`). Each change returns at once off MoltenVK or off `__APPLE__` (`dev.driver_id == VK_DRIVER_ID_MOLTENVK`, `provoking_first()`, `count_rewrite_on()`): the census and report calls; `vkCmdBindIndexBuffer2KHR` declared in the loader and recorder lists and recorded only with `index8_size` (MoltenVK's vendor fix), `VK_KHR_maintenance5` asked for only then; `vkCmdUpdateBuffer` through `cmd_update_buffer` (the same call off MoltenVK); the fan key class and the program cache's stamp word on MoltenVK only. - In the game, integration builds that hold this topic's members (earlier revisions of some): **E9a on I41 `78ec1c47`** (arm64, MoltenVK main + argbuf-slots): 1,197 s held in play, 12 of 12 must-shows, a clean end, 0 skipped draws; **run #34 on I38 `3f872b0c`** (x86_64 under Rosetta): 16 m 52 s, every draw drawn, 19 of 19 checks, a clean exit. **Not tested:** Windows and Linux (no PC here): every change there is a runtime gate that should leave what is built, recorded and drawn as main's, but nobody has built or started this stack off the Mac. **Must be tested:** - Windows and Linux, any GPU: build this PR (head `67fd90bc`) and main (`aa95d35f`) the same way and run `python -I -B tests/run_all.py` on each, then start each to the title, expecting this PR's new tests to pass, no other check to change status against main, the same `vk:` lines in longshot_log.txt as main's (no census, 8-bit, count-draw, draw-index, fan or provoking-vertex line) and no program translated again (Test Farm: @Beanstalk windows and linux: build unchanged, run_all, start to the title) ## Risks **What could break:** on MoltenVK or macOS only: a count draw now draws (a pass break, and one Metal draw a record: 10-16 ms a submit at maxDrawCount 65536); buffer updates and converted draws take room in the recording's stream (without room, drawn or recorded as before and logged); one more pipeline for each program drawn both as a fan and as another triangle topology, and the first start remakes the program cache once (the stamp word); an indirect multi-record fan costs MoltenVK's per-call dispatch a record; a converted triangle draw reads its indices on the CPU and writes a list into the stream. Elsewhere: the runtime gates above; nothing recorded differently. **Turning it off:** `RX_VK_INDEX8_SIZE=0` for the 8-bit binds; the rest by reverting the PR (no other switch turns them off). **Compatibility:** on macOS the program cache is rebuilt once (fan key stamp). Elsewhere nothing changes: no save, options key, shader cache or vk ABI change. ## Issues See #420. The macOS topic PRs, merged in this order; "topic N" in each description means these: 1 #845 (macos-host), 2 #846 (vulkan-on-metal, on 1), 3 #847 (mvk-descriptor-limits), 4 #848 (shader-backend, on 2, 3 and #431), 5 #849 (precompile-metal, on 4), 6 #850 (draw-path, on 4), 7 #851 (draw-path-quads-mesh, on 6, #705 and #707), 8 #852 (mac-perf, on 7). ## Checklist ### Everyone - [x] One topic. - [x] The title is a Conventional Commit (`type(scope): description`) of the status line's type. - [x] Why gives the reason plainly and links the issues that fit (the tracker searched). - [x] Measurements has a verdict, or one line saying why there is nothing to measure. - [x] Testing names what was tested, what wasn't, and what must still be tested, where and how. - [x] Rebased on current `main`. - [ ] `python -I -B tests/run_all.py` passes (any failure that also fails on `main` is named). - [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. ### When it applies - [x] AI assistance recorded with `Assisted-by:` / `Co-Authored-By:` trailers. - [x] Switches documented (docs/development.md; the README for a menu row) and shipped at their recommended value. - [x] The SPIR-V headers regenerated with glslang (a shader changed). - [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. - [ ] Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths. - [x] Docs updated.
Every scan down vk_memory.cpp's import table by start (pool_lookup's
covering import and merge plan, bg_drain, prefetch_chunks,
import_in_background, memory_note_gpu_write and memory_guest_imported)
stopped once an import ended more than 1 GiB below its address, on the
belief that no import is larger than that. pool_lookup's own merge escape
leaves an import above 1 GiB over the smaller ones inside it ("left
overlapping"), and the device allows imports up to max_import_size: a scan
stopped at a small import inside a large one, missed the large one, and
the same bytes were imported again, two memories over the same bytes.

import_reach.h counts the live imports by span class; its bound is above
every live span, within twice the largest. imported_add and imported_take,
now the table's only ways in and out, keep the count. A scan stops only
where no import further down can reach its address, so it also stops
sooner than before when the imports are small. The covering-import checks
in pool_lookup and import_in_background look past the last import at or
below the range for the same reason.

Tests: test_import_reach.py runs the actual scans with a 4 GiB import over
a 16 MiB chunk, left by the merge escape (imports are recorded ranges: no
payload, no Vulkan, no game). Its lookup, query, note, drain, background
and prefetch cases fail on main 5e072fc8 and pass here, and a source check
keeps every change to the table in the two helpers. test_import_windows
runs pool_lookup with the helpers; test_mirror_gpu_only names the new
publication point.

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
test(vk): the readback refresh fixture runs memory_note_gpu_write with the import table's helpers
Some checks failed
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) Has been skipped
CI / Conventional Commit title (pull_request) Successful in 4s
CI / Workflow lint (actionlint) (pull_request) Successful in 7s
Guide screenshots / Guide images and local UI source review (pull_request) Failing after 6s
Third-party parts / As their notes say (pull_request) Successful in 10s
PR description / Description follows the template (pull_request_target) Successful in 5s
497be2d480
test_parallel_rb_refresh cuts memory_note_gpu_write out of vk_memory.cpp,
whose scan now stops at the live imports' reach: the fixture includes
import_reach.h, cuts live_reach, imported_add and imported_take beside it,
and puts its pool in the table through imported_add. It failed to build
at 11e9ee44 ("use of undeclared identifier 'import_reach'").

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #454 (#454), branch mac/run-all at 264f826a7c (Sweep3, on main aa95d35f).

Its own commits, squashed:
- test: teach the game-free runner about macOS (45c54bc6f)
- test: skip main's new Windows-only guard check on macOS, and undo the SDK's vsnprintf macro in a fixture (264f826a7)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #477 (#477), branch mac/arm64-host at 0f021f29c1 (Sweep3, on main aa95d35f).

Its own commits, squashed:
- fix(runtime): compile host jumps and pause hints on macOS arm64 (0f021f29c)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #478 (#478), branch mac/guest-memory at dfb71ec850 (Sweep3, on main aa95d35f).

Its own commits, squashed:
- fix(runtime): preserve guest pages when discarding on macOS (b668404c8)
- fix(runtime): retain guest-page rounding in Darwin memory wrappers (e9c77d9f3)
- test(runtime): cut main's int hos_commit in the Darwin guest-memory test (7e737ce0f)
- test(runtime): follow main's HLE call counts in the Darwin guest-memory fixture (dfb71ec85)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #436 (#436), branch mac/fault-contexts at bccfd1c2e9 (Sweep3, on main aa95d35f).

Its own commits, squashed:
- fix(runtime): translate macOS fault contexts on both CPU routes (08940fb3d)
- test(runtime): keep Darwin fault checks native by default (7d7f99dcb)
- test(runtime): classify the fault bridge's fatal _exit in main's exit inventory (bccfd1c2e)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #437 (#437), branch mac/waits at beb8a2881a (Sweep3, on main aa95d35f).

Its own commits, squashed:
- fix(runtime): port Win32 waits and deadlines to macOS (2f05d007f)
- test(runtime): link Darwin waits into the pointer fixture (ef081688d)
- fix(macos): share address wait state through the executable (186a461c5)
- docs(runtime): describe the executable-owned macOS address-wait state (beb8a2881)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #438 (#438), branch mac/vk-admission at 681e37081d (Sweep3, on main aa95d35f).

Its own commits, squashed:
- feat(vk): add macOS Vulkan loader and device admission (6f34d00bc)
- test(vk): use semantic admission contracts (fdd161190)
- test(vk): follow main's LoadLibraryA and float-add choice in the admission fixture (3e088644f)
- test(vk): pin the admission ABI at main's version 23 and macOS 24 (4f4ca3c73)
- fix(macos): a window without Vulkan extensions ends as a clean exit, as main's exit inventory asks (681e37081)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #490 (#490), branch mac/darwin-host at 162a39dcd3 (Sweep3, on main aa95d35f).

It was stacked on #436, #437, #438, #454, #477, #478; their changes are the earlier commits here.

Its own commits, squashed:
- feat(macos): complete Darwin host lifecycle and diagnostics (71a9ed0bb)
- fix(macos): integrate profile consumers and joined-thread shutdown (f420761ab)
- docs(macos): describe Darwin profile symbol loading (04e40191a)
- test(macos): integration fix: cut the tagged HThread in the waits fixture (9c18e64c4)
- test(macos): integration fix: stub the kept startup in the display fixture (5f8d511e6)
- test(macos): integration fix: prof symbols run on macOS, not a skip (a1e73d31e)
- test(macos): the memory-notice fixture runs the Darwin query (f4d7aaf76)
- fix(macos): a failed swap query still shows the low-RAM notice (28ed288a2)
- test(macos): the Darwin LoadLibraryA keeps dlerror()'s text for hos_load_error (52faf1d3d)
- fix(macos): integration fix: main's process affinity for new threads is Linux-only (61ec2411b)
- fix(macos): the POSIX main's end after the game's thread marks the clean end, as main's exit inventory asks (162a39dcd)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #453 (#453), branch mac/build-flags at 8ca4bff7a4 (Sweep3, on main aa95d35f).

Its own commits, squashed:
- build(macos): discover dual-architecture toolchains and form Mach-O commands (499e3853a)
- test(macos): default real link fixtures to the process architecture (f6f6f042c)
- test(macos): isolate synthetic command paths from the test host (7c846ae91)
- build(macos): keep third_party/a64-kit as it is; nx2/darwin_toolchain.py makes its commands Mach-O (88054c966)
- build(macos): follow main's one-way renderer build and CPU target in the moved build code (a5b02633d)
- test(macos): the frozen Windows/Linux build arrays are main e090cc48's (c3009e01c)
- test: main's third-party objects test reads build.py with this PR's macOS names (8ca4bff7a)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #479 (#479), branch mac/build-complete at 1bd269c7e2 (Sweep3, on main aa95d35f).

It was stacked on #437, #453; their changes are the earlier commits here.

Its own commits, squashed:
- build(macos): complete strict standalone dependency packaging (9424b4886)
- fix(macos): bind SDL3, imports and archive members to their real formats (8ad0e3265)
- fix(macos): keep the lazy-bind library ordinal across DONE (48f6ec02b)
- build(macos): take the architecture and SDK from darwin_toolchain when packaging (5ce85548c)
- build(macos): no prebuilt renderer on macOS either, as main has none (1bd269c7e)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #455 (#455), branch mac/mem-gate at 82c2e10341 (Sweep3, on main aa95d35f).

Its own commits, squashed:
- fix(builder): account for available memory and compiler children on macOS (8f8e03b7f)
- fix(builder): avoid stale Darwin available-memory snapshots (5240e431a)
- fix(builder): keep Darwin RSS behind the shared tree backend (82c2e1034)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #456 (#456), branch mac/control-sockets at fc2f104050 (Sweep3, on main aa95d35f).

Its own commits, squashed:
- fix(runtime): support control bridge Unix sockets on macOS (5fc3fe390)
- test(control): link the bridge's macOS socket helpers into test_oot_state_tap's fixture (fc2f10405)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #457 (#457), branch mac/control-quit at fe3e8c9178 (Sweep3, on main aa95d35f).

It was stacked on #456; their changes are the earlier commits here.

Its own commits, squashed:
- test(control): quit's parent waits for its bridge to listen, and a failed check ends the bridge it forked (fe3e8c917)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #476 (#476), branch mac/cache-files at 7e561fbb53 (Sweep3, on main aa95d35f).

Its own commits, squashed:
- fix(vk): preserve cache file reservations on macOS (7e561fbb5)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #480 (#480), branch mac/guest-16k at 657b780359 (Sweep3, on main aa95d35f).

It was stacked on #436, #478; their changes are the earlier commits here.

Merged with the topic's earlier commits by hand where they met (Consolidate-files/hand-resolutions.md).

Its own commits, squashed:
- fix(macos): serialize guest backing and native-page watch lifetimes (d7d999b92)
- fix(macos): retain pending watch faults across protection changes (a6a3e9e98)
- fix(macos): make the guest-memory changes Apple-only; Windows and Linux keep main's code (126d7bd67)
- docs(macos): describe the guest window's one owner, import pins and native-page watches (657b78035)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #492 (#492), branch mac/renderer-compile at 59f750aa38 (Sweep3, on main aa95d35f).

Its own commits, squashed:
- fix(macos): the renderer's last two files compile on Darwin (7ee5fd584)
- fix(macos): the debug tools are compiled on Darwin too (82b2d6606)
- test(macos): the debug tools check reads hos_oot_player_seen's body too (59f750aa3)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #511 (#511), branch mac/crash-records at c4d95017aa (Sweep3, on main aa95d35f).

It was stacked on #436; their changes are the earlier commits here.

Its own commits, squashed:
- fix(runtime): take the macOS report run id from getentropy (d3e86ddd7)
- fix(runtime): read crash-record memory and modules without /proc on macOS (aa039e142)
- test(runtime): build the crash-record fixture on macOS (adebf9dbb)
- test(runtime): link the macOS fault bridge into the crash-record fixture (c4d95017a)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
fix(control): keep command-line sessions alive on macOS
Some checks failed
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 14s
CI / Workflow lint (actionlint) (pull_request) Successful in 19s
Guide screenshots / Guide images and local UI source review (pull_request) Failing after 19s
Third-party parts / As their notes say (pull_request) Successful in 30s
PR description / Description follows the template (pull_request_target) Successful in 19s
40c1c5f5f8
Was: #516 (#516), branch mac/longshot-ctl-darwin at 3b9d3cfa2a (Sweep3, on main aa95d35f).

Its own commits, squashed:
- fix(control): tell macOS processes apart by their sysctl start time (56f4ca876)
- test(control): compare launch's data folder with the resolved run folder (3b9d3cfa2)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #491 (#491), branch mac/renderer-correctness at 695f6859dc (Sweep3, on main aa95d35f).

It was stacked on #438, #480; their changes are the earlier commits here.

Its own commits, squashed:
- fix(macos): pin renderer imports through final resource ownership (db82a0f23)
- test(macos): cut the non-Apple Pool and import route in three more fixtures (6cee76eb1)
- fix(vk): drain the recorder before startup rollback destroys the allocator (18c05be52)
- test(macos): follow main's #324 and #250 in the Darwin renderer fixture (c099f5da6)
- test(vk): follow the moved Pool in test_mirror_gpu_only's cut (165bf7e61)
- fix(macos): the import pin callbacks are macOS host API version 25 (fa691b55b)
- fix(macos): vk_memory.cpp compiles on macOS: #324's evicted_pools declaration is not Apple's (695f6859d)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #642 (#642), branch mac/gpu-budget at 09978824a0 (Sweep3, on main aa95d35f).

Its own commits, squashed:
- feat(vk): read the Mac's system memory for the renderer (gpu/vk/system_memory.h) (ba1952096)
- fix(macos): on unified memory the GPU's allowance is what the Mac's RAM leaves, not Metal's working set (632636ee0)
- fix(macos): vk_work.h stays vk_vma.cpp's last include (0e63a1dc1)
- fix(macos): the unified budget reads the system's memory at its first ask (5240eade7)
- docs(macos): RX_VK_UNIFIED_BUDGET in the switch table (09978824a)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #653 (#653), branch mac/metal-cache at db50cf3d26 (Sweep3, on main aa95d35f).

It was stacked on #438; their changes are the earlier commits here.

Its own commits, squashed:
- feat(macos): Metal's shader cache in a folder the caller names (db50cf3d2)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #643 (#643), branch mac/mvk-push at ca17df3be6 (Sweep3, on main aa95d35f).

Its own commits, squashed:
- fix(macos): storage buffer tables get descriptor sets on MoltenVK (ca17df3be)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
feat(macos): ship the Vulkan loader with KosmicKrisp and MoltenVK, MoltenVK the default
Some checks failed
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 14s
CI / Workflow lint (actionlint) (pull_request) Successful in 19s
Guide screenshots / Guide images and local UI source review (pull_request) Failing after 17s
Third-party parts / As their notes say (pull_request) Successful in 31s
PR description / Description follows the template (pull_request_target) Successful in 22s
7df74b124d
Was: #654 (#654), branch mac/kosmickrisp at 9d34f9a1c8 (Sweep3, on main aa95d35f).

It was stacked on #438, #479; their changes are the earlier commits here.

Merged with the topic's earlier commits by hand where they met (Consolidate-files/hand-resolutions.md).

Its own commits, squashed:
- feat(macos): ship the Vulkan loader with KosmicKrisp and MoltenVK, chosen at startup (fbd562421)
- test(macos): the driver package fixture takes the architecture and SDK from darwin_toolchain (3472d670c)
- fix(macos): type the driver manifest's ICD record for Pyright (296b5347b)
- fix(macos): MoltenVK is the default Vulkan driver on every macOS (86c017e42)
- test(macos): the display fixture counts longshot_env.txt's loads on Apple only (9d34f9a1c)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #644 (#644), branch mac/mvk-sizes at f08eb70206 (Sweep3, on main aa95d35f).

It was stacked on #643; their changes are the earlier commits here.

Its own commits, squashed:
- fix(macos): programs reading storage buffer lengths get descriptor sets on MoltenVK (f08eb7020)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #645 (#645), branch mac/mvk-rwtex at b8b1ba998a (Sweep3, on main aa95d35f).

It was stacked on #644; their changes are the earlier commits here.

Its own commits, squashed:
- fix(macos): stages with more than 8 read_write textures get descriptor sets on MoltenVK (b8b1ba998)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
fix(vk): use update-after-bind sets past Metal's per-stage limits on MoltenVK
Some checks failed
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 15s
CI / Workflow lint (actionlint) (pull_request) Successful in 16s
Guide screenshots / Guide images and local UI source review (pull_request) Failing after 12s
Third-party parts / As their notes say (pull_request) Successful in 14s
PR description / Description follows the template (pull_request_target) Successful in 16s
792a7d8a32
Was: #646 (#646), branch mac/mvk-pushlimits at 374c55a031 (Sweep3, on main aa95d35f).

It was stacked on #645; their changes are the earlier commits here.

Its own commits, squashed:
- fix(macos): stages past a Metal function's buffer, texture or sampler table get descriptor sets on MoltenVK (6c9e3c9fa)
- fix(macos): MoltenVK's descriptor sets are update-after-bind layouts, within Vulkan's limits for them (3e7d8d3d3)
- test(vk): recording_admission's device stub has the fixes make_pool now reads (374c55a03)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The topic needs it (as the stacks merged it before).
The topic needs it (as the stacks merged it before).
Was: #647 (#647), branch mac/seg-plan at 52def6832c (Sweep3, on main aa95d35f).

Its own commits, squashed:
- feat(vk): plan where an oversize guest span is cut into import segments (601c00ccd)
- feat(vk): let the segment planner add segments that pay for themselves (52def6832)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #648 (#648), branch mac/seg-shader at 9b73e82942 (Sweep3, on main aa95d35f).

Its own commits, squashed:
- feat(vk): descriptors bound as pieces in the SPIR-V back end and program variants (1f9183c2a)
- fix(vk): MslArrayPtr: no pointer into a storage buffer array is passed to a function (9b73e8294)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #649 (#649), branch mac/texel-codec at c5cbd39d26 (Sweep3, on main aa95d35f).

It was stacked on #648; their changes are the earlier commits here.

Its own commits, squashed:
- feat(vk): texel codecs in the SPIR-V back end and program variants (c5cbd39d2)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #658 (#658), branch mac/renderer-core at f8d4e51ad5 (Sweep3, on main aa95d35f).

It was stacked on #431, #491, #647; their changes are the earlier commits here.

Merged with the topic's earlier commits by hand where they met (Consolidate-files/hand-resolutions.md).

Its own commits, squashed:
- fix(vk): join #431's import table helpers with #491's macOS Pool (a1d08d92a)
- fix(macos): import NOACCESS guest pages and name a missing audio service (e6e92a90d)
- feat(vk): admit an operation's guest buffers before it binds them (alias isolation, macOS) (a27bee681)
- feat(vk): import a span past one device allocation as segments (SegMem, alias isolation) (dd4f13047)
- test(vk): follow the renderer-core merge's moved code in three extractions (6e77a383f)
- fix(vk, macos): admit a parallel batch's uniform updates in order, and keep its own updates out of its handoff (3fbfca08d)
- fix(vk, macos): keep every byte the page table reached mapped when an admission retires imports (616eacb83)
- fix(vk, macos): one view per byte of an Apple spare backing, and no endless retry of a failed view (04e00832b)
- fix(vk, macos): bg_drain publishes no background import over this epoch's retired memory or across a domain (a3913a646)
- fix(vk, macos): admission merges no import past 1 GiB again, so mirror_make can still mirror it (b8d16a20b)
- fix(vk, macos): a segment keeps a crossing import's bytes as leftovers clipped at the cuts, not as whole segments (aab3fd8a6)
- fix(vk, macos): each new import over a retired import's bytes inherits its share of that import's VRAM mirror (73bbb89ad)
- test(vk): the admission fixtures follow main's #250 sparse mirrors (6fa302cce)
- fix(vk, macos): the actor motion's resolver follows #59: a pose read at its draw is not copied (e0941ccc0)
- test(vk): test_split_ub_flush follows flush_ub_updates' end parameter (f8d4e51ad)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #662 (#662), branch mac/seg-contract at 0401eeb237 (Sweep3, on main aa95d35f).

It was stacked on #649, #658; their changes are the earlier commits here.

Its own commits, squashed:
- feat(vk): the segmented consumers' frozen contract (C0) (0401eeb23)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #663 (#663), branch mac/seg-consumers at 5400f1a0b6 (Sweep3, on main aa95d35f).

It was stacked on #645, #662; their changes are the earlier commits here.

Its own commits, squashed:
- feat(vk): texel codecs' views, texel piece views, null-descriptor stand-ins and presence words (TexelDesc, L3) (da741bdb2)
- test(vk): the texel ownership fixture names the case that failed (39d6490dd)
- feat(vk): SegBind's descriptor core, gathers and arena (L1) (7d5d51276)
- fix(vk): a draw reusing its descriptors drops an earlier build's refusal (SegBind) (7104d8324)
- test(vk): SegBind's gathers and notes fixtures, its parts of three checks, and its docs section (31d52778f)
- test(vk): test_set_for_tables reads its cut from --source (4462202ff)
- test(vk): test_mesh_fallback's topology anchor follows draw()'s `plain` (0f743f0b9)
- test(vk): test_set_for_lengths' layout fixture takes SegBind's seg_layout_count and presence_words (3b5f3b477)
- feat(vk): SegXfer, the transfer consumers of a range across a segment's cut (L2) (3200ff464)
- fix(vk): dispatch()'s compute-variant path (#252) names SegBind's pre-seam `plain` (c13540fc5)
- test(vk): the seg_gathers fixture stubs #162's rec::OwnSlot (8089dc409)
- test(vk): SegXfer's fixture and resolver sites follow #59's actor motion (1ab6beb2b)
- test(vk): SegXfer's gpu_write checks follow #329's ordered inline writes (5400f1a0b)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #674 (#674), branch mac/null-shader at b7683077e6 (Sweep3, on main aa95d35f).

It was stacked on #663; their changes are the earlier commits here.

Its own commits, squashed:
- feat(vk): null-descriptor emulation in the SPIR-V back end (NullShader, L4) (71003696f)
- docs(vk): NullShader: image and image buffer arrays share a known gap (17667bea3)
- fix(vk): NullShader: two source-cutting checks the wip commit broke (f53eda6cd)
- fix(vk): MslArrayPtr's NullShader half: a descriptor bound whole calls its loop function, and the loops' CPU runs (b7683077e)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #675 (#675), branch mac/tex-read-order at c5c6a853a8 (Sweep3, on main aa95d35f).

It was stacked on #674; their changes are the earlier commits here.

Its own commits, squashed:
- fix(vk): TexOrder: store each image read in place on MoltenVK (fb51f7807)
- test: test_amd_subgroup_profiles: the MoltenVK driver id in make_profile's stand-in (8d5fc5373)
- fix(vk): TexOrder: an image memory barrier before each image write and atomic on MoltenVK (c5c6a853a)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #676 (#676), branch mac/msl-depth at f8e18c953b (Sweep3, on main aa95d35f).

It was stacked on #675; their changes are the earlier commits here.

Its own commits, squashed:
- fix(macos): MoltenVK's Metal source nests no deeper than 32 forwarded instructions (71d2498c4)
- test(vk): the subgroup profile fixture knows MoltenVK's driver id (f8e18c953)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #686 (#686), branch mac/rosetta-import at 6ec9629e59 (Sweep3, on main aa95d35f).

It was stacked on #658; their changes are the earlier commits here.

Its own commits, squashed:
- fix(macos): Rosetta host imports: whole hardware pages, refused imports asked again only when their backing changes (ae91338ae)
- fix(macos): the backing generation is Apple host API version 26, after #491's import pins at 25 (6ec9629e5)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #692 (#692), branch mac/msl-depth2 at a67e1934ec (Sweep3, on main aa95d35f).

It was stacked on #676; their changes are the earlier commits here.

Its own commits, squashed:
- fix(macos): the nesting bound counts only the reads SPIRV-Cross certainly makes (a67e1934e)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #693 (#693), branch mac/compile-gaps at 5ceed495b2 (Sweep3, on main aa95d35f).

It was stacked on #692; their changes are the earlier commits here.

Its own commits, squashed:
- fix(vk): bound the control-flow nesting of SPIRV-Cross's Metal source on MoltenVK (46b5810a9)
- perf(vk): parse the module in place when the scope bound has nothing to move (5ceed495b)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #694 (#694), branch mac/subgroup-vertex at a3e8a51faf (Sweep3, on main aa95d35f).

It was stacked on #676; their changes are the earlier commits here.

Merged with the topic's earlier commits by hand where they met (Consolidate-files/hand-resolutions.md).

Its own commits, squashed:
- fix(vk): MoltenVK's vertex stages run the guest's warp operations as one-lane warps (a2b3b0578)
- test(vk): test_subgroup_vertex: the base tree's own checks unprinted, and one failure message per cause (e20482fa9)
- test(vk): test_subgroup_vertex: SPIRV-Cross drops a subgroup barrier in a vertex function (a3e8a51fa)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #695 (#695), branch mac/spv-size at 43d1a23420 (Sweep3, on main aa95d35f).

It was stacked on #676; their changes are the earlier commits here.

Its own commits, squashed:
- feat(vk): RX_VK_SPV_PROFILE, what the big SPIR-V modules are made of (3d7b1f5f6)
- docs(vk): spirv_profile.h's store names where the line is printed (ebf1854b4)
- docs(vk): RX_VK_SPV_PROFILE's text names the slow compile line as the precompile hand-off's (43d1a2342)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #696 (#696), branch mac/gm-loop at 231115f14c (Sweep3, on main aa95d35f).

It was stacked on #694, #695; their changes are the earlier commits here.

Merged with the topic's earlier commits by hand where they met (Consolidate-files/hand-resolutions.md).

Its own commits, squashed:
- feat(vk): MoltenVK and KosmicKrisp search storage buffer tables in loops in every global memory fallback (39a40fed6)
- test(vk): gm_loop_ir --gpu: the loop forms first, then the written-out ones, smaller first (99616b7ab)
- test(vk): stub table_loops_on where make_profile is compiled cut out (231115f14)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #697 (#697), branch mac/local-mem-buffer at a526c34c9f (Sweep3, on main aa95d35f).

It was stacked on #696; their changes are the earlier commits here.

Its own commits, squashed:
- feat(vk): MoltenVK zeroes local memory at computed offsets by a loop, not a written-out initializer (a526c34c9)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #698 (#698), branch mac/kk-tex-order at 8a3d7db0ce (Sweep3, on main aa95d35f).

It was stacked on #654, #675; their changes are the earlier commits here.

Its own commits, squashed:
- fix(macos): TexOrder's stored image reads on KosmicKrisp too (27d566b45)
- test(macos): the Apple drivers' check names the fixes this tree makes (8a3d7db0c)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #787 (#787), branch mac/giant-shape at 96b51b55b5 (Sweep3, on main aa95d35f).

It was stacked on #697; their changes are the earlier commits here.

Its own commits, squashed:
- test: giant mesh fallbacks' shape through the real SPIR-V back end (tests/giant_shape_ir.cpp) (96b51b55b)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The Mac-only part of fix/async-safe-frees-i40 (c151fcea, MvkAsyncFix's F5) that #788 does not carry, because
null_dummies_make (#663, macOS: MoltenVK has no nullDescriptor) exists only on the macOS stack. The stand-in images' clear
waits 5 s for its fence; when that wait ran out, the fence and the command pool were destroyed while the GPU might still be
clearing (a destroyed pool under a pending command buffer). Now a clear submitted and not seen done in 5 s is waited for
without a limit first, as #788 does for the read-back. The clear is still reported as not done in time (the "may read
garbage" line), as before.

tests/test_null_dummies.py: case make-slow-clear (the fixture's fence wait runs out once): one unbounded wait after the 5 s
one, before the fence and the pool are destroyed. Fails before this commit (one wait, none unbounded), passes after, on arm64
and x86_64 under Rosetta.

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #677 (#677), branch mac/mode-census at d2fd7a90ff (Sweep3, on main aa95d35f).

It was stacked on #663; their changes are the earlier commits here.

Merged with the topic's earlier commits by hand where they met (Consolidate-files/hand-resolutions.md).

Its own commits, squashed:
- feat(vk): count polygon modes and restart-off strip draws on Apple, log-only (d2fd7a90f)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #678 (#678), branch mac/mvk-temp at 989a6423d9 (Sweep3, on main aa95d35f).

It was stacked on #677; their changes are the earlier commits here.

Merged with the topic's earlier commits by hand where they met (Consolidate-files/hand-resolutions.md).

Its own commits, squashed:
- fix(macos): bind a direct draw's 8-bit indices with their size on MoltenVK (ca6b27fdd)
- docs(macos): RX_VK_INDEX8_SIZE in the switch table (989a6423d)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #679 (#679), branch mac/count-draws at 2028d598e6 (Sweep3, on main aa95d35f).

It was stacked on #677; their changes are the earlier commits here.

Merged with the topic's earlier commits by hand where they met (Consolidate-files/hand-resolutions.md).

Its own commits, squashed:
- fix(macos): draw count draws through a record rewrite where the device has no drawIndirectCount (4d9de1004)
- fix(macos): the count draw report in its own block; SegBind's fixture cuts the rewrite (ce7388bf0)
- fix(macos): buffer updates copied from the recording's stream on MoltenVK (574597e08)
- fix(macos): the count-draw rewrite on macOS only; Windows and Linux give count draws to the driver as before (791fe3a75)
- docs(macos): RX_VK_COUNT_REWRITE in the switch table (e4a7ab285)
- test(vk): test_inline_write_order (main's, #329) has gpu_write's cmd_update_buffer (2028d598e)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #680 (#680), branch mac/drawid-direct at 6c0204eb98 (Sweep3, on main aa95d35f).

It was stacked on #679; their changes are the earlier commits here.

Merged with the topic's earlier commits by hand where they met (Consolidate-files/hand-resolutions.md).

Its own commits, squashed:
- fix(macos): direct draws that read the draw index drawn as one indirect record on MoltenVK (4876f2615)
- fix(macos): tessellated direct draws reading the draw index counted, not logged as errors (32a83be13)
- test(macos): the three recording fixtures stand in stream_usage (6c0204eb9)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #691 (#691), branch mac/moltenvk-main at ebd6b127e2 (Sweep3, on main aa95d35f).

It was stacked on #654, #679; their changes are the earlier commits here.

Merged with the topic's earlier commits by hand where they met (Consolidate-files/hand-resolutions.md).

Its own commits, squashed:
- docs(macos): a MoltenVK built from main as the MoltenVK input (546102abe)
- docs(macos): MoltenVK main 5189f8de with the argbuf-slots patch as the recommended MoltenVK input, and how to build it (ebd6b127e)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #701 (#701), branch mac/fan-key at cd1ce0b214 (Sweep3, on main aa95d35f).

It was stacked on #680; their changes are the earlier commits here.

Merged with the topic's earlier commits by hand where they met (Consolidate-files/hand-resolutions.md).

Its own commits, squashed:
- feat(macos): count fans against their pipelines' static topology on MoltenVK, log-only (773588160)
- fix(macos): fans keyed apart from the other triangle topologies on MoltenVK (cd1ce0b21)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #702 (#702), branch mac/fan-indirect at d7878c9d1a (Sweep3, on main aa95d35f).

It was stacked on #701; their changes are the earlier commits here.

Merged with the topic's earlier commits by hand where they met (Consolidate-files/hand-resolutions.md).

Its own commits, squashed:
- feat(macos): count indirect fans and their records on MoltenVK, log-only (927ed3de1)
- fix(macos): an indirect fan of more than one record drawn a call a record on MoltenVK (3a743b80f)
- test(macos): the indirect fans' census checked right after FanKey's, not as draw()'s last statement (62a089ad7)
- test(macos): the segment gathers' fixture stands in FanIndirect's way and split (d7878c9d1)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Was: #703 (#703), branch mac/provoking-first at 73d4bc9bd4 (Sweep3, on main aa95d35f).

It was stacked on #701; their changes are the earlier commits here.

Merged with the topic's earlier commits by hand where they met (Consolidate-files/hand-resolutions.md).

Its own commits, squashed:
- feat(macos): count the draws that depend on the provoking vertex where the device has no provokingVertexLast (8276aa94d)
- fix(macos): direct draws that depend on the provoking vertex drawn with each primitive's last vertex first, without provokingVertexLast (ac8416c59)
- fix(macos): adjacency draws that depend on the provoking vertex drawn as plain lists with each primitive's last vertex first (1977f19f5)
- fix(macos): the mesh fallback's draws that depend on the provoking vertex drawn with each primitive's last corner first (6493717b6)
- fix(macos): lines that depend on the provoking vertex counted only, not reversed (e702fd96e)
- fix(macos): a converted draw's list written into the stream of the recording it is drawn in (4f9891106)
- test(macos): draw()'s fixtures stand in ProvokingFirst's list and count its index binds (e42bf6e87)
- test(macos): test_fan_key reads draw()'s count lines with ProvokingFirst's count on them (531fd13ec)
- test(macos): a converted fan is drawn with a pipeline built as a list under FanKey's key (523d0696e)
- fix(macos): the provoking-vertex count and lists on macOS only; Windows and Linux record as before (73d4bc9bd)

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Hand resolution on topic/draw-path, where #702 (FanIndirect) met #703 (ProvokingFirst), siblings on #701 that only this topic
combines. test_fan_indirect (#702) cuts draw()'s indirect block up to "} else if (d.indexed) {"; #703 puts its own branch,
"} else if (pv.made) {" (the list written into the stream and drawn as an indexed draw), between the two, so the cut took it in and
the fixture no longer built (pv, ProvokingWrite, game_topo, drawid_direct undeclared). The cut now ends at draw()'s next branch,
whichever it is, as Integration 37's eb4d02046 has it (its tests/test_fan_indirect.py line only). The check keeps what it requires;
no source changes.

test_fan_indirect: failing at 5efbe9d8 on arm64 and x86_64, passing with this commit; passing at #702's Sweep3 head d7878c9d.

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
test: make_profile's cut-out fixtures know KosmicKrisp, SubgroupVertex, GmLoop and LocalMemBuffer
Some checks failed
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 7s
CI / Workflow lint (actionlint) (pull_request) Successful in 11s
Guide screenshots / Guide images and local UI source review (pull_request) Failing after 9s
Third-party parts / As their notes say (pull_request) Successful in 11s
PR description / Description follows the template (pull_request_target) Successful in 16s
70cc5ba1cb
In this topic #698 (KosmicKrisp's TexOrder, its Apple drivers' fixture in test_vendor_fixes) meets #694/#696
(SubgroupVertex: make_profile reads dev.subgroup_stages and Shader::Stage) and #697's two switches (GmLoop's
table_loops_on, LocalMemBuffer's local_zero_loop_on), and test_subgroup_vertex's stub meets KosmicKrisp's
VK_DRIVER_ID_MESA_KOSMICKRISP in make_profile. Each member passes at its own Sweep3 head; at the topic's tip the
fixtures did not build. This takes I41's fixes 02b10861 and 560923891's stub line:
- test_subgroup_vertex: the KosmicKrisp driver constant (28, the Vulkan headers' value);
- test_vendor_fixes' Apple drivers' fixture: subgroup_stages (all stages), stage.h, and table_loops_on and
  local_zero_loop_on stubs; its columns are unchanged.

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
(cherry picked from commit 02b108611 and the local_zero_loop_on line of 560923891)
The base's fixture fix 70cc5ba1 (test_vendor_fixes' Apple-drivers fixture and test_subgroup_vertex's stub, #698 with #694/#696/#697). Merged after c2cfee0f, which was in before the fix was named: the tree is the same in either order (the two touch different tests).

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
fix(macos): draw_index8_report's closing brace, lost where #701's fan census report met #678's 8-bit report (#678 with #701)
Some checks failed
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 5s
CI / Workflow lint (actionlint) (pull_request) Successful in 9s
Guide screenshots / Guide images and local UI source review (pull_request) Failing after 8s
Third-party parts / As their notes say (pull_request) Successful in 17s
PR description / Description follows the template (pull_request_target) Successful in 24s
67fd90bc88
Hand resolution on topic/draw-path. #701's resolution (chain commit 21e6ec79) placed draw_fan_census_report after #678's
draw_index8_report and dropped the closing } of draw_index8_report, so gpu/vk/vk_draw.cpp stopped compiling from there ("function
definition is not allowed here" at draw_fan_census_report, then every later definition), on arm64 and x86_64, at every commit from
21e6ec79 to this one. The } goes back after the report's logf, as Integration 41 (78ec1c47, vk_draw.cpp 5087) has it, without
#782's widen8_report line (topic mac-perf). No other change.

Found by the whole-file compile of vk_draw.cpp at this topic's tip and at the topics on it.

Assisted-by: Claude Opus 5.5
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Some checks failed
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 5s
CI / Workflow lint (actionlint) (pull_request) Successful in 9s
Guide screenshots / Guide images and local UI source review (pull_request) Failing after 8s
Third-party parts / As their notes say (pull_request) Successful in 17s
PR description / Description follows the template (pull_request_target) Successful in 24s
This pull request has changes conflicting with the target branch.
  • docs/development.md
  • gpu/vk/vk_draw.cpp
  • gpu/vk/vk_memory.cpp
  • gpu/vk/vk_shader.h
  • gpu/vk/vk_texture.cpp
  • nx2/build.py
  • nx2/make_game.py
View command line instructions

Manual merge helper

Use this merge commit message when completing the merge manually.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u 'mac/topic-draw-path:mooki-mac/topic-draw-path'
git switch 'mooki-mac/topic-draw-path'
Loading…
Add table
Add a link

Hint: With a URL in your clipboard, you can paste directly into the editor to create a link.

No reviewers
No milestone
No project
No assignees – Assign to me
1 participant
Notifications
Time tracker
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!850
No description provided.