WIP: fix(macos): keep storage image reads in program order on KosmicKrisp too #698
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!698
Loading…
Reference in a new issue
No description provided.
Delete branch "mooki/Longshot:mac/kk-tex-order"
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 (KosmicKrisp from the Vulkan SDK 1.4.363.1, MoltenVK 1.4.2), game-free at this head; GPU probe kk02 on KosmicKrisp, arm64 (history) · Needs: macOS game run on KosmicKrisp
Why
#675 keeps storage image reads in program order on MoltenVK: Metal itself can return a texel read stored before a native atomic
as the atomic's result, so each read is stored in place and an image barrier goes before each write and atomic. KosmicKrisp
(#654's opt-in driver,
RX_VK_DRIVER=kosmickrisp) has no SPIRV-Cross, but it runs on the same Metal, and the probe kk02 showed thesame reordering there: with the fix off, a whole image buffer read came back after the same invocation's later atomic (128 of 128
lanes, and 4 of 128 without the write); with it on, every case read before. This PR turns #675's fix on for KosmicKrisp too. It is
part of the macOS port. See #420.
How to reproduce
Seen on: macOS 26.7.1, Apple M4 Max, KosmicKrisp (Vulkan SDK 1.4.363.1, driver id 28), arm64
Settings and switches:
RX_VK_DRIVER=kosmickrisp(#654), or the probe's direct driver loadSteps: run a compute program that reads a texel of a whole storage image buffer, then does an atomic (and a write) on the
same texel in the same invocation, as the probe TO-01 does (
ta-texel-rax-whole,ta-texel-ra-whole), withProfile::materialize_image_readsoff, KosmicKrisp's setting on the baseExpected: the read returns the value from before the atomic
Actual: on the base, KosmicKrisp returns the post-atomic value:
ta-texel-rax-wholein 128 of 128 lanes,ta-texel-ra-wholein 4 of 128 (kk02, TO-01 with the flag off)
What changed
On Apple,
make_profilesetsProfile::materialize_image_reads(#675's stored reads and image barriers) for KosmicKrisp'sdriver id as well as MoltenVK's. No back-end code changes: the flag already covers both halves. The translator stamp's
"rord"word keys on the flag, so KosmicKrisp's programs get it with no other change. Off Apple every changed file is the base's token for
token.
gpu/vk/vk_shader.cpp: inmake_profile's#if defined(__APPLE__)block,p.materialize_image_reads = dev.driver_id == VK_DRIVER_ID_MOLTENVK || dev.driver_id == VK_DRIVER_ID_MESA_KOSMICKRISP;, itscomment giving kk02's reason; the stamp's comment says both drivers.
profile.h(materialize_image_reads),emit_spirv_image.cpp(the two TexOrder notes).docs/segmented-binding.md, TexOrder's paragraph names both drivers.tests/test_vendor_fixes.py:check_apple_drivers(new) cutsmake_profilefromvk_shader.cppandseg_variants_onfromvk_draw.cppand runs them with the realvk_vendor.hon MoltenVK, KosmicKrisp, NVIDIA's driver and RADV, as compiled andwith the Apple gates taken as true: MoltenVK keeps all 4 of its fixes this tree has, KosmicKrisp gets the stored reads alone
of them, beside segmented binding and
fetch_bounds.tests/test_amd_subgroup_profiles.py: a KosmicKrisp case (driver 28); on Apple the stored reads exactly for drivers 14 and 28,in every stage's profile.
Measurements
Verdict: fixes it on the GPU (history: kk02 on KosmicKrisp, TO-01 with the flag off read 2 shapes after the atomic, TO-03 with
it on 44 of 44 cases before, 60 of 62 predictions, the 2 misses the flag-off shapes); game-free at this head
make_profilegivesKosmicKrisp the stored reads and nothing else of MoltenVK's fixes, and the back end's 139 fixture modules are byte for byte the
base's. Speed: as #675's on MoltenVK (a store and a load after each read, a barrier before each write and atomic); not measured on
KosmicKrisp.
Hardware: macOS 26.7.1, Apple M4 Max, 64 GB, Apple clang 21 (game-free at this head; GPU results are the probe's history)
Scene: none (
make_profilecompiled out ofvk_shader.cppand run on made-up devices; the back end's fixture, emitted, validatedand run on the CPU interpreter)
Method:
tests/test_vendor_fixes.pyandtests/test_amd_subgroup_profiles.pyat this head, arm64 and x86_64 (clang++ -arch x86_64, Rosetta), and both with this PR's test files on the base, which must fail;tests/test_seg_shader.py --base-treeagit archiveof the base, arm64 and x86_64. On the GPU: the KosmicKrisp lane's kk02 (TO-03 + TO-01 flag off), one admission,arm64 (KosmicKrisp has no x86_64 slice). Exact checks: one run per route.
How to reproduce:
python -I -B tests/test_vendor_fixes.py --headers <Vulkan-Headers/include> --cxx clang++Baseline: the "before" column is this PR's base, #675 with #654 merged (
d3cce0a1), which has the fix for MoltenVK and theKosmicKrisp driver (main has neither).
d3cce0a19e5f8983materialize_image_readson KosmicKrisp (make_profile, as compiled and with the Apple gates taken as true)test_vendor_fixes(this PR's test)test_amd_subgroup_profiles(this PR's test)test_seg_shader --base-tree), arm64 and x86_64order-*among them), CPU runs 10 of 10 the base'sta-texel-rax-wholeafter the atomic in 128 of 128 lanes,ta-texel-ra-wholein 4 of 128before=128)Flags and settings
None in this PR's own commits: the stored reads follow the driver (MoltenVK and KosmicKrisp), with no switch; KosmicKrisp itself is
chosen with #654's
RX_VK_DRIVER. The diff against main also shows the switches of the PRs it stacks on, theirs to list:LONGSHOT_KOSMICKRISP,LONGSHOT_VULKAN_LOADER,RX_VK_DRIVER(#654),LONGSHOT_DARWIN_ARCHIVE_RECEIPT,LONGSHOT_DARWIN_ARCHIVE_RECEIPT_SHA256,LONGSHOT_MOLTENVK,LONGSHOT_SDL3,RX_VK_ONLY(#479),LONGSHOT_FFMPEG,LONGSHOT_FSR,LONGSHOT_NGX_SDK,RX_ARCH(#453),RX_VK_LIBRARY(#438),HOS_KEEP_FREED_PAGES,HOS_ZERO_ALL_PAGES,RX_NVN_WATCH_AFTER,RX_NVN_WATCH_ALL,RX_NVN_WATCH_TEXELS_SRC(#480),RX_VK_DLSS_ACTORS,RX_VK_GPU_DUMP,RX_VK_MESH_IND_COUNT_WORD,RX_VK_NO_UPSCALE_STUB(#658),RX_VK_TEXEL_CODECS(#649),RX_VK_SET_FOR_TABLES(#643) andRX_VK_SET_FOR_LENGTHS(#644).Testing
Tested: on macOS 26.7.1, Apple M4 Max, at
9e5f8983, this PR's head before the rebase ontoe090cc48(main6c9edffe,#675's stack with #654, this PR), game-free, every run under the shared check slot with a fresh HOME and TMPDIR:
tests/test_vendor_fixes.pywith the pinned Vulkan-Headers 1.4.345, arm64 and x86_64: exit 0, as in Measurements. With this PR'stest files on the base: fails (KosmicKrisp's
materialize_image_reads0, as compiled and with the Apple gates taken as true).tests/test_amd_subgroup_profiles.py, arm64 and x86_64: exit 0; with this PR's test files on the base: fails (the driver 28case's assertion).
tests/test_seg_shader.py --base-treethe base, arm64 and x86_64: exit 0, 139 of 139 identical.test_program_stamp_knobs(19 switches),test_program_cache_format: exit 0.emit_spirv_image.cppandvk_shader.cppcompiled whole for arm64 and x86_64 with this tree's own renderer command(
nx2/build.py'srenderer_flags(), which #479 in this stack restores; main 6c9edffe's inline flags give a macOS build nohost/posix): 4 of 4, exit 0 (scratch tree with #476, #492 and #490);emit_spirv_image.obyte for byte the KosmicKrisp lane'sat the topic's commit.
emit_spirv_image.cpp,profile.handvk_shader.cppare the base's token for token (unifdef -U__APPLE__,comments and layout aside), so Windows and Linux compile the base's code.
objects, 1,216 name/arch checks, closure 565 symbols a route, 0 undefined.
after; 16 related checks. The picked lines are the topic's line for line in
vk_shader.cpp,profile.h,emit_spirv_image.cpp,docs/segmented-binding.mdandtest_vendor_fixes.py.reports/PubWave-files/PubShader2/(proof/kk-9e5f8983-*.log) andreports/PubWave-files/PubShader3/(
compile/kk-kk-tex-order-9e5f8983/,equal-lines.txt,stamps.txt,offapple-kk-d3cce0a1-9e5f8983.txt,merge-tree.txt,wave/).e090cc48, atdbd0e14c(was9e5f8983): Sweep2's own checks of this head were stillrunning at writing (
reports/Sweep2-files/lanes/698.txt);python -I -B tests/run_all.pyon wave Sh3's merge57c9c4ab, which carries this head: 578/31/18 (passed/failed/skipped) against main e090cc48's 544/32/17 on this Mac,no new failure (
reports/2026-11-14-rebase-sweep-2.md).Not tested: the game on KosmicKrisp at this head (KosmicKrisp is opt-in and arm64 only), and no GPU run at this head: kk02 ran
#675's modules with the flag on and off on KosmicKrisp, and this PR changes no emission code (its back-end changes are comments),
so the modules KosmicKrisp now gets are those [INFERENCE: TO-03's inputs were not regenerated here]. Windows and Linux: nothing to
build differently (every changed file is the base's off Apple); the shaders are prepared once more there (a new translator stamp,
the same SPIR-V).
Must be tested:
RX_VK_DRIVER=kosmickrisp, expecting everyprogram prepared again once (
rordin KosmicKrisp's stamp) and no new error line; MoltenVK starts unchanged but for the stamp (byhand: the owner, the log's
vk:lines)Risks
What could break: on KosmicKrisp, every storage image and image buffer read is stored in place and every image write and atomic
gets a barrier, as on MoltenVK since #675: a fault would have shown on MoltenVK already; the cost is a store, a load and a barrier
per access. MoltenVK and other drivers: nothing changes; only the stamp.
Turning it off: revert the PR (no switch: the stored reads follow the driver), or run MoltenVK (the default).
Compatibility: every platform's shaders are prepared again once (the changed comments are in the translator's stamp:
ede499681d22bdcd→ec812f384d84fc76), to the same SPIR-V; on KosmicKrisp the translator stamp also gains"rord".kProgramCacheFormatstays 3. Nothing changes in saves,longshot_options.inior the vk ABI (MKWVK_API_VERSION).Reviewer notes
d3cce0a1..9e5f8983, two commits.44969f44,-xfrommacos/integrated's KosmicKrisp follow-up (fe64034a), withtwo conflicts, both in fixtures this line has without the macOS integration's other topics:
test_vendor_fixes.pytakes onlythis change's lines (the pipeline cache check beside them is #650's), and
test_amd_subgroup_profiles.pythe KosmicKrispconstant, asserts and case (the MSL bound's lines and MoltenVK case are #676's, not on this line). Then end commit
9e5f8983: the Apple drivers' check names the six fixes this tree has (the stored reads, the null stand-ins,set_for_tables,set_for_lengths,fetch_bounds, segmented binding); the topic's check also had #676'sbound_forwarded_depth, #650'sworker_cachesandpcache_no_loadand #652'scompiler_service, which this line lacks, so itsfixture did not build. Where those PRs meet this one, their columns join again (the macOS integration's form).
242ff050) and #654 (merged ind3cce0a1, clean: KosmicKrisp's driver and its package).Until they merge this PR's diff shows their commits too.
and #676 itself (
test_amd_subgroup_profiles.py: #676's MoltenVK case and comment words beside this PR's KosmicKrisp ones; keepboth, as
macos/integrated); #696 and #697 also invk_shader.cpp's Apple block (keep both lines). With#694, #696 or #697 the cut-out
make_profilefixtures need stand-ins (stage.h,subgroup_stages,table_loops_on,local_zero_loop_onintest_vendor_fixes.py;VK_DRIVER_ID_MESA_KOSMICKRISPintest_subgroup_vertex.py): whichever lands second adds them (the macOS integration's02b10861plus LocalMemBuffer's line; thewave's merge carries them as its one fixture commit). #650, #652 (and #666, #667):
test_vendor_fixes.py(#650's pipeline cachecheck beside this PR's Apple drivers' check: keep both, the columns joined); their other conflicts are the base's.
git merge-treewith #677-#681, #686: clean.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(maine090cc48; headdbd0e14c, was9e5f8983: this PR's own commits replayed one for one, old → new:d3cce0a1→76ec8933,44969f44→ce4cf672,9e5f8983→dbd0e14c; the commit names elsewhere in this description are from before the rebase).python -I -B tests/run_all.pypasses (any failure that also fails onmainis named). (On the wave's merge77333ce0: #693 on #692, #697 with #696, #694 and #695, this PR with #654, and one fixture commit for the cut-outmake_profilestubs: 565 passed, 31 failed, 18 skipped against main 6c9edffe's 531/32/17 on this Mac; the 31 failures are main's own and nothing that passes on main fails;test_collect_widenow passes; 33 new tests pass;test_vendor_fixesandtest_amd_subgroup_profilespass;test_darwin_audio_service, Darwin-only, is skipped by the runner;reports/PubWave-files/PubShader3/wave/full-77333ce0/. After the rebase onto maine090cc48(headdbd0e14c): wave Sh3's merge57c9c4ab, 578/31/18 against main e090cc48's 544/32/17, no new failure.)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 with this PR's testfiles; on
maintoo, which has no KosmicKrisp.)tests/that reads changed source updated in this PR, not weakened.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 main5e072fc8and 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]>044635ea added vma_startup_rollback (vk_vma.cpp, run after a failed replay_start), which calls vmaDestroyAllocator. vk_vma.cpp includes vk_work.h last so that RX_VK_RECORDER=defer/thread drains before its destructions, and every such boundary call in a vk_work.h file must be in RX_REC_BOUNDARIES with a drain-first macro. This one was not, and test_recorder_sync caught it ("vk_vma.cpp calls ['vmaDestroyAllocator'], which vk_work.h does not drain before"): it passes at 58c5c5aa (044635ea's parent) and fails at 044635ea. Add it to the list and to vk_work.h, next to vmaDestroyBuffer and vmaDestroyImage. With the recorder off (the default) boundary() is a relaxed load and a branch. Rollback runs before any image or buffer exists, so nothing should be held there today, but the allocator is no longer destroyed while a recorder could still hold packets. The test is unchanged (sources: 42 boundaries drained, was 41). Assisted-by: Claude Opus 5.5 Co-Authored-By: Claude Opus 5.5 <[email protected]>A guest span larger than one device allocation (the cap on MoltenVK/M4 Max is 41,747,087,360 bytes) is bound as pieces: one descriptor per allocation segment, at the descriptor's own binding (reports/2026-11-14-full-range-design.md sections 4.1-4.4). This is the shader half; the draw side (descriptors, layout, gathers) comes later. - runtime_info.h: SegEntry {Storage|Table|TexBuf|ImgBuf, desc, pieces} and RuntimeInfo::segmented. - Back end: a segmented storage buffer is an array of pieces at its binding (a table count * pieces, entry k's piece j at k * pieces + j); its loads, stores and atomics call DontInline helpers made after main, which find the piece by the pieces' OpArrayLength in order, with constant indices. The global memory fallbacks sum the pieces' lengths for a segmented descriptor's bound end and branch to its piece (single, native candidate, table written out and in the loop). Texel and image buffers are arrays too, their fetches, reads, writes and atomics through helpers that pick the piece by OpImageQuerySize, and a texel buffer's size query sums the pieces. ImageQuery was declared for every module already. With RuntimeInfo::segmented empty nothing new is made: the SPIR-V is byte-identical. - vk_shader: SegSig (entries, hash) on Program, seg_sig and seg_variant; program_segmented finds or translates the variant of a plain program with plain's texture questions and answers and checks its descriptors are plain's; program_pick, mesh_program_locked, program_find_plain, loaded_variants and portable_variant keep the plain and segmented variants apart; every stage's RuntimeInfo::segmented comes from Program::seg. - vk_progcache: a segmented variant is never written to the program cache nor listed among the loaded programs. - tests/test_seg_shader.py + tests/seg_shader_ir.cpp: synthetic IR programs through the real back end, plain and segmented; structure checks, spirv-val (Vulkan 1.3, uniform buffer standard layout), and with --base-tree a byte comparison of the plain modules against an older tree. Five source-reading checks follow the new Program field and the atomics' new branch. The translator stamp changes with this (eden/, vk_shader.cpp, sizeof(Program)): every program cache is rebuilt once. Land it in the same release as the vk_api.h change that already does so. Assisted-by: Claude Opus 5.5 Co-Authored-By: Claude Opus 5.5 <[email protected]> (cherry picked from commit b7928876dab846485f667c1c934d34d25ecef035)Carries the vk-admission pull request's commits, which the packaged driver choice needs (host/posix/darwin_vulkan.{c,h} and test_vk_darwin_admission). #479 (mac/build-complete, this branch's start) brings darwin_build.py and darwin_package.py; the two merge without a conflict. Assisted-by: Claude Opus 5.5 Co-Authored-By: Claude Opus 5.5 <[email protected]>The interfaces the four segmented-consumer lanes (SegBind, SegXfer, TexelDesc, NullShader; reports/2026-11-14-seg-consumer-plan.md section 3) code against, frozen before they fork. Inert: no caller of anything new, no SPIR-V, layout, push range or stream change, sizeof(Program) unchanged. - vk_internal.h / vk_memory.cpp, SegMem's consumer interface: gpu_span_any() (a relaxed count of the live domains, stored in seg_commit; domains are kept for the run), gpu_span (gpu_buffer's flavour of gpu_span_bind: import buffers, no written marks, no mirror), SpanLayout::bind_stamp (gpu_bind_stamp(): a segment can be imported again with its cuts kept, so cut_gen alone never keys piece buffers), span_unused_piece's semantics ({null_storage, 0, 1}), and the SegArena API (SegArenaRef, seg_arena_take, seg_gather, seg_scatter; stub bodies after stream_alloc that give no room and log, SegBind's to fill). - Review fixes in the same interface (renderer-core review P2-3, P3.2): every piece of gpu_span_bind carries its buffer's device address (the import's or the mirror's; 0 only with bufferDeviceAddress off), and its one-piece path stores the translated guest address, not a virtual one. - vk_texture.h/.cpp: texel_view_pieces / texel_piece_views, stubs that return 1 and false (TexelDesc's to fill). - vk_shader.h: Program::presence_words, in what was padding. - Back end: PRESENCE_PUSH_OFFSET (88), Profile::emulate_null_descriptors, Bindings::presence / presence_read with the bit numbering rule. - tests: test_resolver_coverage lists gpu_span_bind / gpu_span sites too (scoped to gpu/vk: gpu/render has an rx::gpu_span of its own), checks that gpu_span follows its own gpu_buffer, and splits SITES into SITES_BASE plus one block per lane. test_segmented_domains executes the contract (the count 0, 1, 2 -> 1 on a merge, 0; gpu_span's pieces; addresses with the fixture's gpu_buffer_bind returning none as the real one does; the bind stamp; a virtual address's guest). test_seg_shader accepts a base tree of this back end's generation and compares every module. - docs/segmented-binding.md: the gate (every new behaviour Apple-only, other platforms byte-identical) and one heading per lane. Conflict on this branch (not with main): tests/test_seg_shader.py's docstring, against the array_pointer_calls paragraph #P20's msl-arrayptr port added; both kept, this paragraph first. Assisted-by: Claude Opus 5.5 Co-Authored-By: Claude Opus 5.5 <[email protected]> (cherry picked from commit 95fa06d4e6526601bd2e1bc88c2f8f5720855350)The segmented single storage array's case (plan 4.3 item 5) had no negative: the check always cut its own tree. With --source <B2 archive> it fails as required ("moltenvk.segmented_single want=set got=push"). Conflict with #P28 (read_write textures; not with main): the docstring keeps #P28's paragraph with this usage line, and main() cuts from --source's vk_draw.cpp with #P28's read_write count (as in the macOS integration, Integration 17). Assisted-by: Claude Opus 5.5 Co-Authored-By: Claude Opus 5.5 <[email protected]> (cherry picked from commit 5824f6828e21cf810dcceaa6be425a9224b15994)plaine37c097da2plaina997b3629aDefineImages and DefineImageBuffers declare one image whatever the descriptor's count, while Image() indexes the variable when the count is above 1, so such a module fails spirv-val ("OpAccessChain reached non-composite type"); B2 has it already, on every platform. The null_img* and null_imgbuf* helpers take their element the same way and share it. Found while extending the fixture; declaring the arrays changes every platform's SPIR-V and is left to the owner. Assisted-by: Claude Opus 5.5 Co-Authored-By: Claude Opus 5.5 <[email protected]> (cherry picked from commit 83e7e18b4fee477f1e6901871ad37efe8f23d5bf)SPIRV-Cross (MoltenVK 1.4.2's pin 6c09849f) prints an OpImageRead's result, and a pure read helper's call, where the value is first used, and nothing orders it against the same invocation's later writes and atomics on that image: in MSL the read ran after them and returned the later value. TexOrder's TO-01 probe proved it on the GPU for LS's plain output, with and without the NullShader bit, on both CPU routes (reports/2026-11-14-tex-order.md). - Profile::materialize_image_reads, set by make_profile on Apple for MoltenVK only, with its translator stamp word ("rord") only when on. - emit_spirv_image.cpp InPlace: with the flag, every storage image and image buffer read's result (the plain read, the segmented read helper's call, a carrier codec's element reads) is stored to a Private variable at the read and loaded back; SPIRV-Cross prints a store where it stands. Private, since a Function variable must lead its function's first block; in the entry point's interface from SPIR-V 1.4. Off: no new ID, every module byte for byte as before. - tests/seg_shader_ir.cpp: order-* modules with the flag; the read-in-place rule (every read and read helper call stored at once), their flag-off twins breaking it, CPU runs equal to the modules without the flag, and the flag alone changing nothing without image reads. test_seg_shader.py: order- modules required; a base tree without the flag builds them with TEX_ORDER_BASE and they are not compared; --source against it fails. - tests/spirv_run.h runs Private variables (fresh per invocation) and OpMemoryBarrier (a no-op one invocation at a time). - docs/segmented-binding.md: a TexOrder section. Conflicts on mac/null-shader (#P33), with MslArrayPtr's tests that #P33's last commit carries, not with main; resolved as macos/integrated did (Integration 22, b08694d8): tests/seg_shader_ir.cpp keeps both sections and both calls (msl_arrayptr, then tex_read_order); tests/spirv_run.h keeps both storage classes (Uniform, then Private); tests/test_seg_shader.py keeps both docstring paragraphs and presence checks, leaves 'msl-' and 'order-' out of an older generation's set, and compares with a base in one loop (an order- module skipped for a base without the flag, identical counts as the same, a different segmented one listed under --changed-segmented, anything else fails). Assisted-by: Claude Opus 5.5 Co-Authored-By: Claude Opus 5.5 <[email protected]> (cherry picked from commit a9aad5bcd6f4cce3d9fcff8b231da9628e7da4b3)make_profile turns Profile::materialize_image_reads on (Apple only, as before) for VK_DRIVER_ID_MESA_KOSMICKRISP as well as MoltenVK. TexOrder's TO-01 with the flag off on KosmicKrisp (Mesa on Metal 4, no SPIRV-Cross) read a whole image buffer after the same invocation's later atomic: 128 of 128 lanes read-atomic-write, 4 of 128 read-atomic, the reordering TO-02 saw Metal itself make; with the flag on, all 44 cases read before. The program cache's stamp keys on the flag ("rord"), not on the driver, so KosmicKrisp's programs get the word with the flag. No other MoltenVK fix changes: bound_forwarded_depth, set_for_tables, set_for_lengths, worker_caches, pcache_no_load and compiler_service stay MoltenVK's; null stand-ins stay keyed on nullDescriptor (KosmicKrisp has it). tests/test_vendor_fixes.py runs make_profile and seg_variants_on with vk_vendor.h on MoltenVK, KosmicKrisp, NVIDIA and RADV (as compiled, and with the Apple gates taken as true): MoltenVK keeps all 8 of its fixes, KosmicKrisp gets the stored reads alone of them, beside segmented binding and fetch_bounds. tests/test_amd_subgroup_profiles.py gets a KosmicKrisp case (every stage's profile). Both fail on the tree before this change. Comments in profile.h, emit_spirv_image.cpp and docs/segmented-binding.md say both drivers. Picked onto main 6c9edffe's line (#675 mac/tex-read-order with #654 merged), two conflicts, both in fixtures this line has without the macOS integration's other topics. tests/test_vendor_fixes.py: only this change's lines (the Apple drivers' check and its call); the pipeline cache check beside them is the fast preparation's (#650), not on this line. tests/test_amd_subgroup_profiles.py: the KosmicKrisp constant, the stored-reads asserts and the KosmicKrisp case; the MSL nesting bound's asserts, its MoltenVK case and its comment words are #676's, not on this line, so the case list names drivers 1 and 28 and the KosmicKrisp case's comment leaves out the bound. The Apple drivers' check still names fixes this line has not; the next commit fits it to this tree. Assisted-by: Claude Opus 5.5 Co-Authored-By: Claude Opus 5.5 <[email protected]> (cherry picked from commit fe64034a4d97326504d32774cd626c49db02a092)9e5f89835edbd0e14c3ddbd0e14c3d8a3d7db0ceFolded into #848 (feat(vk): the SPIR-V back end on MoltenVK and guest spans past one device allocation)
Pull request closed