Repository navigation
honeykrisp: M1 compute speedups and the deferred CDM barrier on G13G (stacked on #3, #4, #5) - #6
joshuaswarren wants to merge 67 commits into
Conversation
…add32 Add the opcodes and packer (byte-exact against applegpu), a NIR intrinsic bridge, the agx_nir_lower_simdmat lowering, the validator widths, and a gated advertisement of an 8x8x8 fp32 cooperative matrix shape. Everything is behind AGX_SIMDMAT; default Honeykrisp behavior is unchanged.
…le coopmat shaders
VK_KHR_cooperative_matrix on Honeykrisp only advertised 8x8x8 fp32 even
though agx_nir_lower_simdmat.c already tiles a 16x16x16 coopmat into a
2x2x2 grid of simd_matrix_fmadd ops, and the G13 matrix unit takes fp16
operands. Now advertised (subgroup scope, N in {8, 16}, NxNxN):
fp32 A/B, fp32 C/D simd_matrix_fmadd32 with 32-bit pairs
fp16 A/B, fp32 C/D simd_matrix_fmadd32 with 16-bit A/B pairs
fp16 A/B, fp16 C/D simd_matrix_fmadd16
The mixed form is the one Apple's own Metal mul_mm kernel emits
(simd_matrix_fmadd32 r15_r16, r49l_r49h, r46l_r46h, r15_r16); the generic
ALU packer already encodes the per-source size bits, so the lowering
passes A/B at their own width instead of up-converting to fp32, and the
nir intrinsic gains a 16-bit dest form that selects fmadd16.
Bug found while verifying: with fp16 A and fp32 D the register allocator's
early-kill let D (a 32-bit pair) land on top of A (a 16-bit pair inside
that pair). The hardware then produced zeros for that fmadd: 16x16x16
fp16/fp32 failed in every input/layout variant, always sub-block (1,1),
whose last fmadd was the only one with D overlapping A. Apple's compiler
only ever emits D == C, so the RA now keeps A and B live until D is
placed (D may still reuse C).
Verification on Apple M1 (G13G B1), the cmshape test program, one coopMatMulAdd
per run, exact host reference, integer-valued inputs bit-exact and random
floats within tolerance, identity/ones/randint/randf x row/col-major:
stock Mesa 26.1.7: FAIL, extension not exposed
5bb2b28 (before): 8x8x8 fp32 8/8 PASS; 16x16x16 not advertised
this commit, no RA guard: 40/48 (16x16x16 fp16/fp32: 8/8 FAIL)
this commit: 48/48 PASS, plus 48/48 randint over 4 seeds
MLX Release tests (primitive 98, reduce_ops 34, runtime 40,
matmul_family 14 cases) pass identically on the stock ICD and on this
driver with AGX_SIMDMAT=1.
Bug: (word >> s) & mask with a non-constant s returns zero on Honeykrisp
whenever s has any bit set above bit 4 (s >= 32). MLX hit this as
the "dynamic shift-then-mask byte extraction" miscompile family: bool
scatter dropping writes across word lanes, select picking the wrong
operand under broadcast conditions, reduce_general's load_truthy reading
zero, masked_scatter's scan undercounting (s_scan[255] = 32, not 128).
Root cause: agx_nir_fuse_algebraic_late rewrites
iand(ushr(a, b), (1 << bits) - 1) -> ubitfield_extract(a, b, bits)
NIR's ushr uses only the low 5 bits of its count, and by this point the
main nir_opt_algebraic has already relied on that to strip explicit masks
(ushr(a, iand(b, 31)) -> ushr(a, b); ushr(a, ishl(iand(b, 3), 3)) ->
ushr(a, ishl(b, 3))). ubitfield_extract has no such wrap: an offset >= 32
is undefined in NIR and bfeil returns 0 for it on the hardware.
lower_sm5_shift, which masks the count of every surviving shift, runs
after the fusion and never sees the ushr it consumed.
Fix: fuse directly only when the count is a constant below 32; otherwise
fuse with an explicit iand(b, 31) on the offset. Same instruction count as
the unfused shift+and, and the mask CSEs with one the shader already had.
Verification on Apple M1 (G13G B1), standalone Vulkan compute reproducer
(20 variants, 1024 lanes each, host-compared):
stock Mesa 26.1.7: 9 of 16 base variants FAIL (byte_dyn,
byte_dyn_const, byte_dyn_gid, scan_dyn, scan_dyn_const, scan_dyn_rand,
select_bcast, select_dyn, shift_dyn_mask), plus all 4 boundary
variants FAIL (count exactly 32: 1016/1024 wrong; 63: 516/1024;
uniform 40: 1020/1024; divergent 8/40: 509/1024, only the 40 lanes).
this commit: 20 of 20 PASS, 0 mismatches.
MLX suites, stock vs this commit (AGX_SIMDMAT=1), identical:
primitive 98/98 (2699373 assertions), reduce_ops 34/34 (7152),
runtime 40/40 (6307), indexing_ops 53/53 (4093), select_layout 11/11
(1908), scatter_determinism 21/21 (127).
…duction
Three fp32 rounding defects on Honeykrisp (Apple M1 G13G, Mesa 26.1.7)
that MLX patches around in its shaders:
a) GLSL "/" was lowered by nir_opt_algebraic (lower_fdiv) to
a * frcp(b), and frcp was only Newton-refined when the instruction
was `precise`. Even with an exact reciprocal a * RN(1/b) is not
RN(a/b): 80/25 and 10/25 come out one ulp low, 6.55859375/0.030016447
one ulp high. Measured on 1008 pairs: 299 mismatches (298 at 1 ulp,
1 at 2 ulp), 1/b: 204 mismatches; 1M random pairs: 305792 mismatches.
fma() itself is IEEE (0/1000 mismatches), the MLX note
blaming fma contraction was a misdiagnosis.
b) log(x) was flog2(x) * ln2 on the hardware log2, which is only
absolutely accurate: log(3) = 1.0986121892929077 instead of
1.0986123085021973, 2792/4107 mismatches on [0.5, 64] with errors up
to 357 ulp near 1 (log(1.0000001) = 1.65e-7 vs 1.0e-7); log2 had
2905/4107 mismatches.
c) sin/cos reduced the argument as fract(x / 2pi) in fp32, so the
reduced angle lost ulp(x) of precision: sin(3.0) 14 ulp off,
sin(1e5) 1.06e-3 absolute error, sin(1e8) = 0.0, sin(-1e-3) 571 ulp
off, sin(pi_f32) = 0, and the hardware sin_pt_2 core itself is 2 to
3 ulp off (cos(1e-3) 3 ulp).
The lowering moves to a new the AGX compiler pass file agx_nir_lower_math.c,
built only from the exact fp32 fma and marked no-fast-math so
nir_opt_algebraic cannot reassociate it:
- lower_fdiv is dropped from agx_nir_options; fdiv32 becomes Markstein
division (y = refined rcp, q = a y, r = fma(-b, q, a), q + r y) with
the NaN/zero guard keeping q for b = 0, overflow and signed zero.
frcp32 is always refined. fdiv16 keeps a * frcp(b).
- fmul(flog2(x), ln2) as emitted by nir_flog, and any remaining flog2,
become a double-float evaluation of log(m) = 2s + 2s^3 P(s^2) with
s = (m-1)/(m+1) kept as a pair, m folded into [sqrt(1/2), sqrt(2)),
e ln2 split hi/lo and Fast2Sum accumulation (about 40 bits before the
final rounding). Zero/subnormal/negative/inf/NaN are handled by bit
tests, not the hardware log2.
- fsin/fcos: Cody-Waite in radians with pi/2 in three pieces, the k C2
product and its subtraction as TwoProduct/TwoSum so the reduced
argument is a pair accurate to an ulp, for |x| < 2^22; an integer
Payne-Hanek (24-bit mantissa times a 128-bit window of 2/pi, 64
fraction bits kept) for |x| >= 2^22 up to FLT_MAX. The quadrant then
selects a Taylor polynomial in quadrant units (sin degree 13, cos
degree 14, leading terms as pairs, low part of the argument fed to
the derivative). The hardware sin_pt_1/sin_pt_2 core (nir_op_fsin_agx)
is no longer used by the lowering. fp16 sin/cos go through the fp32
path.
Verification (standalone Vulkan compute reproducer):
- division: 1008-pair table incl. 80/25, 10/25, 1000 random: 0
mismatches (stock 299); 1/b 0 (stock 204); 1M random pairs 0
mismatches for both a/b and 1/b; b = 0, inf, NaN, overflow, flushed
subnormal and -0/5 = -0 match host IEEE.
- log: 4107 points on [0.5, 64] plus pinned exact cases: 0 mismatches
(stock 2792), log(3) = 1.0986123085021973; log2 0 (stock 2905);
1M random on [1e-37, 1e38]: log 3 at 1 ulp, log2 14 at 1 ulp,
rest exact.
- sin/cos at 1e5, 5e5, 1e6, 5e6, 1e8: all 0 ulp from the double
reference except cos(5e6) at 1 ulp (stock: 2.8e5 to 1.06e9 ulp);
1310 mixed points max 1 ulp; 1M random over [1e-3, 1e9] and [-10, 10]:
sin 42346 and cos 41184 at 1 ulp, rest exact, max 1 ulp (stock
>= 8 ulp for 627689 / 512816 of them).
- MLX suites on the same Release tree, stock vs fixed:
primitive 98/98, eq_math 7/7, fast_ops 30/30, runtime 40/40,
reduce_ops 34/34 both; complex_ops 30/33 both with the same three
pre-existing cases (failed assertions 31 -> 29). The upstream
ops_tests log(3) pin through libmlx: FAIL on stock, PASS on fixed,
as do 80/25, 10/25 and sin/cos up to the 1e5 limit mlx enforces.
- timing: 16M-element elementwise dispatch is memory bound at ~2.45 ms
on both drivers (sin 2.474 -> 2.463 ms median, within spread). A
32-deep in-register chain shows the ALU cost: sin 6.64 -> 39.6 ms,
log 2.57 -> 34.8 ms, div 2.84 -> 7.24 ms, mul unchanged.
…it late Symptom: any shader converting fp32 to a 64-bit integer aborts in the backend with "Unhandled ALU op fdiv" (agx_compile.c agx_emit_alu); the MLX suite the copy-offset tests crashes on "dtype converting copies cover the integer family and bool". Fragment shaders with perspective-correct varyings hit the same path. Cause: "agx: correctly rounded fdiv/frcp, faithful log/log2, exact sin/cos reduction" dropped lower_fdiv from the compiler options so nir_opt_algebraic no longer splits fdiv into fmul/frcp, and only ran agx_nir_lower_fdiv in agx_preprocess_nir. nir_lower_int64 (f2u64/f2i64: fdiv by 2^32, plus the frem that lower_fmod turns into a second fdiv) and agx_nir_lower_interpolation run after preprocessing, so their fdiv reached the backend, which has no fdiv. Fix: agx_nir_lower_fdiv_late runs in agx_optimize_nir after the int64 cleanup loop and lowers only fdiv, leaving frcp alone so the reciprocals built by the first pass and by the log lowering are not refined twice. Verification: hk/precise-math driver alone reproduced the abort on the 13-inch M1; with this commit the copy-offset tests passes 25/25 .
…0 disables)
Replace the five getenv("AGX_SIMDMAT") checks (agx_preprocess_nir lowering,
the extension table, the feature bit, the supported stages, and the
properties query) with agx_simdmat_enabled(), which reads the variable through
debug_get_bool_option with a default of true. Setting AGX_SIMDMAT=0 restores
the previous behaviour.
The 25/25 MLX battery and every reproducer ran with the gate on
(AGX_SIMDMAT=1), so the default now matches the verified configuration and a
system-installed driver exposes coopmat to unmodified wheels.
|
fdiv: default-path 2.5 ULP contract pinned, with identity + performance receipts (M1 G13G) Spec: the Vulkan SPIR-V environment allows 2.5 ULP for Measured on jwm1 (M1 G13G, Coreglass ledger, 3-round crossed
The last row is the paired clean run on the same box after w71's window (e763 measured in the same run: 171.5 / 17.1 and 404.8 / 43.3); across three additional independent runs the candidate sits at 168.4-170.9 vs e763 171.0-173.5 4B prefill, i.e. the exact-division default costs ~1.3-2.2% 4B prefill against a baseline that is itself outside the spec budget. A cheaper default was tried and rejected before pinning the test: a guarded Markstein form (common 2⁻³ operand scale for d ≥ 2¹²⁶, float selects for specials) measured 8,376 over-bound results on the same 328,192 pairs - the compute pipeline preserves denormals, so any float-path special handling needs the integer flush machinery back, and nothing is left to save against the ~44-op normalized form. The normalized correctly rounded division therefore stays the default for every What 92aa3f6 adds: Library identity: fresh meson builds are byte-deterministic (two independent 29266f6 builds identical), and every number above comes from a recorded sha256; the v2 candidate lib measured earlier differs from a fresh 29266f6 build by 38 bytes - build-id + stale baked git-string only, zero code bytes. |
|
Decode regression from the fdiv fix: found and recovered, results bit-identical (head ed28f1d) Bisect. I bisected e763159..01de043 one commit at a time on an M1 Max (G13C, jw16), with MLX held fixed (bf62cfb). Each commit got its own ICD, built natively with the PKGBUILD flags. The runs alternated in 5 rounds, measuring 2B d64 decode. 43b2756 costs -6.63 tok/s and was negative in 5 of 5 rounds. 443153a recovers +2.1 tok/s. Every other commit, including the 934b barrier (+0.04), stays within noise. Mechanism. After 43b2756, every fp32 a9a668a: exact reciprocal without the division machinery. For
ed28f1d: round
d64 decode tok/s, jw16, medians of 5 alternating rounds (e763159 / 01de043 / head):
Greedy token digests do not change on these prompts. The remaining 4B gap (about 2.7%) is general division Not yet verified: G14 (M2). jw14m2-linux was unreachable all day on three routes. Please run |
|
f24b680: 7-op exact reciprocal (decode profile follow-up) Where the remaining decode gap sits, on jw16 (M1 Max, G13C), measured with d64 decode and 5 alternating rounds:
This commit lets the hardware rcp produce the edge cases: a Newton step, the hardware value where the step is NaN, then the canonical NaN. That is 7 ops instead of 16.
The 2B gap to e763159 is now about 0.4 tok/s. The 4B gap (about 2.7%) is general division. |
|
Two commits joined this layer after the description was written:
Measured on the gated build against the same tree without it, three rounds per cell, with bit-identical output on both chips (GEMM output hashes and 21 MLX matmul cases in f16, bf16 and f32; on the M1 Max also the Qwen3.8-2B 4-bit prefill logits and 32 greedy tokens):
Applied to every chip, the same fold lost 13-17 % on dense f16 GEMM on the M1 Max, which is why it is keyed per device. Receipt: https://github.com/joshuaswarren/omarchy-mlx/tree/main/receipts/2026-10-07-coopmatload-lowering-per-device Build and test on the M1 Max (aarch64, the driver's meson suite): both |
|
G14 (M2 Max,
These are the same results as on G13C (M1 Max) and G13G (M1), so the reciprocal and log() changes are now checked on all three GPU generations. |
|
Pushed bbbfa36 ( Why: a per-commit bisect of Qwen3-4B 4-bit decode on G13C (M1 Max, 64 tokens, 5 paired rounds) found two commits that slow it down. 43b2756 (division) costs -3.09 tok/s, and later division commits on this PR recover most of that. 934b7c3 costs -1.22 tok/s (0/5 rounds positive) and changes no shader. Since 934b7c3, every Results on G13C, 64edca0 vs bbbfa36, 5 paired rounds:
An earlier run of the same change (identical code, different comment) gave 4B +1.61 (5/5) and 2B +0.41 (9/10 over 10 rounds). Greedy output digests are unchanged for the 2B, 4B and 9B models. No shader changes. G13G uses the deferred CDM flush path by default; a greedy-digest check there is next. |
|
Pushed two commits on top of bbbfa36:
Why: Honeykrisp had The NIR change is needed because Results on G13C (M1 Max), driver at this commit:
IQ mat-vec kernels are 5-24x faster (MUL_MAT_ID iq2_xs 2290 -> 102 us). With |
|
Pushed 135d870 ( Why: Honeykrisp advertised fp32 and fp16 cooperative-matrix A/B only, so bf16 GEMMs had to stage every tile through shared memory and widen bf16 with ALU ops; MLX's bf16 matmul ran 1458 instructions per shader against 337 for the direct f16 route. This adds VK_KHR_shader_bfloat16 (shaderBFloat16Type, and shaderBFloat16CooperativeMatrix with cooperative matrices; no dot product) and bf16 A/B with fp32 C at 8x8x8 and 16x16x16. bf16 fragments stay 16-bit through load/store/extract/insert; MulAdd widens them exactly to fp32 and runs the fp32 A/B Correctness:
Speed, bf16 GEMM with direct bf16 cooperative-matrix loads vs the current staged kernel, output bits identical on every element:
Existing fp16/fp32 shaders compile to the same operations; MLX decode greedy outputs are unchanged. |
|
Pushed Tested on an M2 Max (G14C) only. Tracked vs per-launch barrier, same driver:
The gen-15 negative branch is not run (no hardware); it is a plain |
DivDefaultFastSequencePinned and FrcpDefaultSequencePinned counted the ALU ops of the e763159 division and reciprocal. Every exact lowering since 43b2756 emits other ops, so agx_tests has failed these three pins on the PR omacom#6 head (found by w7Q, the driver's meson suite: 61/64). The bits of division and reciprocal are pinned on hardware by tests/precise_math.py, ulp_bound.py and div_window.py. What this file can pin is the float-control contract: DenormFlushToZero emits exactly the default lowering. Compare the two op histograms for fdiv and frcp instead of fixed counts.
a6cbc83 to
66cb84f
Compare
|
Pushed It fixes 30 deterministic CTS failures on G13C (M1 Max): Results, same driver with and without the change (kernel 12.6 prerelease):
Not shown: other drivers (the NIR is identical for them, I ran none), and why G14C passes the 30 cases without the change. |
|
Pushed What it does. A compute-only pass ( Gate. On by default for Gain (build
Correctness, default vs
Earlier builds of the same rule (before the pure-operation and The same gates are being rerun on the pushed tree ( |
|
Pushed
Why the reserve. Without it, two processes that each fill the old 50% heap (7.55 GiB each on the 16 GB M1) took MemAvailable to 0 kB, Unevictable to 14.4 of 15.1 GiB, and the kernel OOM killer killed quickshell and the Hyprland unit (journal: With the reserve (G13G, 16 GB M1, desktop running; test processes in cgroup scopes with no swap and
Same pair with 32 MiB chunks, 0.90, ICD with the final reserve code: one process refused at 10.72 GiB (343 calls), minimum MemAvailable 1.03 GiB; two at once both refused at 5.34 and 5.31 GiB, minimum 1.01 GiB. All processes exited 0, no oom-kill line in On G13C (64 GB M1 Max, cgroup caps): one process holds 46.00 GiB (heap 46.78 GiB at 75%); a second process capped at MemAvailable minus 0.5 GiB was refused at MemAvailable 1.35 GiB; two more at once were both refused at 27.75 GiB with MemAvailable 1.49 GiB; 0 oom-kill lines, Hyprland unchanged.
With the reserve in place the percent is no longer what bounds a process on a quiet 16 GB host (about 11.0 to 11.25 GiB of GPU memory with the desktop holding about 3 GiB): the reserve is. A dedicated inference host can raise The per-call cost of the added |
|
Per-call cost of the reserve's
No measurable difference: the 32 MiB page population at bind time dominates (about 1.9 ms per call), and one |
|
Pushed Problem. One process could not map more than about 64 GiB of device memory, whatever Cause. The kernel reports a 512 GiB GPU address window on all three chips ( Change. Hardware proof (ICD
Not done. The G14C CTS ( |
|
Open gate on On a 16 GB M1 (G13G) I ran one MLX process (omarchy backend, 256 MiB bf16 arrays) until the free-memory reserve refused an allocation, then freed everything and called
The refusal itself is as designed (a typed error, immediate, desktop untouched). The recovery failure has not been attributed. Two causes are possible and I have not separated them: MLX's allocator keeps freed buffers pinned for one more generation, so the memory is still held when the reserve is checked (the stock arm also showed MemAvailable at 4.19 GiB after "recovery"), or the new layout or the reserve keeps memory that the old path returned. A paired run on the same wheel with Receipt: |
|
Recovery gate: fixed in Cause: freed device memory is parked in the driver BO cache and counts as used in MemAvailable. The cache is trimmed only on a later BO free or when Fix: when the check would refuse, call Evidence, 16 GB M1 (G13G), MLX with 256 MiB arrays, cgroup-capped, refusal at 11.75 GiB:
Still open before a package pin: a recipe build at this head, and the G14C MLX suites on it. |
|
Dependency order correction. Nothing here says this PR is ready. The full Vulkan conformance run of this PR against its base cannot qualify it as planned. The first chunk of the run failed on two machines (a 16-inch M1 Max and a 13-inch M1) with the same error from the comparison gate:
What this means for order. #8, #9 and #10 should merge before this PR, and #11 after it. Each of those three branches is small and independent of this PR. A merge of What runs now. A control build ( This PR stays NOT READY TO MERGE. The two M1 machines have not run the whole suite on a build of this PR yet, and the status block above lists what was measured on which build. |
|
Status, 25 Oct: this PR has been idle since 15 Oct, and that is on me. Where it stands. The source head Why it stalled. The base branch crashes in Plan:
Results: I expect the first full numbers by 27 Oct and will post them here either way. If someone on the team can review #8 in the meantime, that is the one change that unblocks the baseline. |
ulp_bound.py divided the error by np.spacing of the float64 reference. np.spacing is negative for a negative reference, so the distance came out negative and any error on a negative reference passed the > 2.5 check; for a positive reference the float64 spacing made every inexact result fail instead. Use the absolute float32 spacing of the reference. Add a --self-test mode that needs no GPU: it checks the distance for 0, 1 and 3 ULP errors in both directions on positive and negative references, that a 3 ULP error on a negative reference exceeds 2.5, and that the old expression gives a negative distance for it. MEASURED: the self test passes; the old expression gives -1610612736 for a 3 ULP error at -1.5, which passes the old check. NOT measured: the GPU run of ulp_bound.py with the corrected distance; the numbers from the old script are not to be relied on. Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
|
Update, 25 Oct: the head of this branch is now A reviewer found that the script's distance check let errors on negative references through. It divided by the float64 spacing, which is negative there. The commit uses the absolute float32 spacing and adds a MEASURED: the self test passes. NOT measured: any GPU run of the corrected script yet. The division numbers from the old script are not to be relied on until that run is done. The whole-suite results in the description were measured on earlier builds, not on this head. |
Measure positive binary32 ULPs, reject non-finite results for finite references, and add seven CPU controls. Restore unchanged public shader/runner fixtures from Joshua Warren source f144c79; provenance is recorded beside the tests. No driver code changes. Generated-by: LLM
[High impact] No reviewed code finding remains blocking, but the PR's stated GPU test gate is still pending. SummaryThis PR adds cooperative matrices, compute speedups, math fixes, and memory changes for Honeykrisp. Since the previous review:
No new actionable issue was established. This review does not replace the exact-head GPU testing still required by the PR description. Reviews (2) · Last reviewed commit: "agx: keep the sign of shared-memory cons..." · Reviewed by Greptile |
… allocated hk_upload_shader created the preamble buffer and the shader constants buffer without checking agx_bo_create, which returns NULL after its allocation retries fail. Large constant arrays take the constants path by default now, so loading such a shader under memory pressure dereferenced NULL. Return VK_ERROR_OUT_OF_DEVICE_MEMORY from hk_upload_shader and pass it back through both callers (compile and deserialize). The shader's destroy path already tolerates a NULL buffer. NOT measured: an allocation failure on hardware; the change is a null check. Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
With HK_SUBMIT_POLL_US set, the bounded poll ran for its whole budget even when the caller's deadline was zero or already past, so vkGetFenceStatus and short waits could spin for the full budget. Start the poll only while the caller's deadline is in the future and cap the poll deadline at it. The option is off by default. NOT measured: the wait latency of short waits with the option on. Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
…x case ulp_bound.py locked /tmp/m1-gpu.lock while the other harnesses lock /tmp/gpu.lock, so they did not exclude each other; use /tmp/gpu.lock. cmshape2.c created uint8_t storage buffers for the u8 element type without enabling storageBuffer8BitAccess; enable it when the element type is u8. NOT measured: the u8 case on hardware. Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
…ment before the sub-format fold Two address folds could change the address they were meant to keep. agx_peel_const read constant addends as unsigned. A 16-bit add of 0xfff0 is x - 16, but it was summed as +65520, so the shared-offset fold gave the access the index x + 65520, and the hardware index add does not wrap. Read the constants signed. The sub-format fold in agx_nir_lower_address scales a byte offset down to an element index. That equals the byte offset only when the offset is a multiple of the element size; an access that is aligned as a whole does not say so (base P + 2 with offset 2 for a 32-bit access is aligned, and the fold drops the 2). Fold only when the offset is provably a multiple (constants, shifts, multiplies, adds, masks, widenings); otherwise keep the 64-bit sum. Tests: SharedFoldKeepsNegativeAddends, SubformatFoldNeedsProvablyAlignedOffset and SubformatFoldKeepsProvablyAlignedOffset in test-lower-math.cpp. agx_nir_fold_shared_offsets is exported for them. MEASURED: not yet run. NOT measured: the performance of the cooperative matrix sub-format fold with the new guard (it was +15 % on the single-cluster M1 and -13 to -17 % on the M1 Max; a pattern the guard does not recognize loses the fold). Signed-off-by: Joshua Warren <816217+joshuaswarren@users.noreply.github.com>
|
GREEN at 9323171 Delta 5ce4451..9323171 (4 commits, 8 files) read in full.
Not checked: I did not build this head or run agx_tests (the author reports 76 of 76, with the two new tests failing on the old behaviour), no GPU run, and the speed effect of the stricter fold (the author lists it as not measured). |
|
GREEN at 9323171 Delta against 5ce4451: four commits, eight files (
Not checked: a build of this head, the test run (I did not compile Mesa), any GPU run, and the speed effect of the stricter fold. |
|
The branch is at 9323171. The six review threads are resolved. The latest code review found no new actionable issue. But the GPU test gate stays open. The results in the description belong to older builds. They do not qualify this head. I will tie any readiness claim to the source and library that were actually tested. |
DivDefaultFastSequencePinned and FrcpDefaultSequencePinned counted the ALU ops of the "hk: enable cooperative matrices by default on G14X" division and reciprocal. Every exact lowering since "agx: flush the exact quotient in precise fp32 division, not the correction step" emits other ops, so agx_tests has failed these three pins on the PR omacom#6 head (found by w7Q, the driver's meson suite: 61/64). The bits of division and reciprocal are pinned on hardware by tests/precise_math.py, ulp_bound.py and div_window.py. What this file can pin is the float-control contract: DenormFlushToZero emits exactly the default lowering. Compare the two op histograms for fdiv and frcp instead of fixed counts.
|
Partial whole-suite Vulkan CTS table for the stack, not final. Both runs are still going. Same commits, same boot, paired chunks. Control is main
What changed:
All of those changes are timing tests in the NOT measured yet: the remaining chunks (about 576 on the M1 Max, about 1,141 on the M1), and any result at the current #6 head. Remaining groups include shader_object, transform_feedback, fragment_shading_rate, pipeline and renderpasses. No GPU timeouts so far. |
|
Update on the CTS runs. It is still partial. It has two parts, for two heads. Part 1: the targeted set at the current #6 head
NOT measured at this head: everything outside those groups. The full runs below are for Part 2: the whole-suite runs of
The only changes that are not gains are in A decode benchmark A/B of the head NOT measured yet: the last 237 chunks on the 16-inch, the last 980 on the 13-inch (240 of them in |
|
Final whole-suite result on the 16-inch M1 Max, for Same boot, both arms per chunk. Control is main
1,986 tests changed:
The comparison gate says ALLOW: regressions 0, invocation errors 0, errors 0, coverage 3,253,584 of 3,253,584. No GPU timeouts. NOT measured: the 13-inch M1 run is still going. A whole-suite run at the current #6 head has not been made; the targeted set above covers its changed areas only. |
DivDefaultFastSequencePinned and FrcpDefaultSequencePinned counted the ALU ops of the "hk: enable cooperative matrices by default on G14X" division and reciprocal. Every exact lowering since "agx: flush the exact quotient in precise fp32 division, not the correction step" emits other ops, so agx_tests has failed these three pins on the PR omacom#6 head (found by w7Q, the driver's meson suite: 61/64). The bits of division and reciprocal are pinned on hardware by tests/precise_math.py, ulp_bound.py and div_window.py. What this file can pin is the float-control contract: DenormFlushToZero emits exactly the default lowering. Compare the two op histograms for fdiv and frcp instead of fixed counts.
|
Final whole-suite result on the 13-inch M1, for Same boot, both arms per chunk. Control is main
1,955 tests changed: 1,951 NotSupported to Pass, and 4 tests in The comparison gate says BLOCK for the whole run: regressions 3, errors 0, coverage complete. All three regressions are in Rerun of the two Pass to Fail cases on the 13-inch, same boot, 12 runs per arm. NOT measured: a whole-suite run at the current #6 head. The targeted set above covers its changed areas only. |
|
Status, no change to head |
|
Correction for head I withdraw the earlier 366-chunk / 361,849-case, no-Pass-to-Fail claim as qualification of this PR. Its control included #8, #9 and #10, while the candidate was PR #6 alone. That comparison changed more than #6 and does not isolate this change. CPU compiler tests and source review are not device qualification. The corrected comparison keeps the same prerequisite stack in both arms:
The controlled run is incomplete. Its selected scope is 1,367 chunk pairs / 1,346,778 cases, not the full CTS. Completion counts are not a pass: every pair's gate JSON, driver identity and same-boot binding still need to be scored. No final corrected pass count or no-regression verdict is claimed here. Valid provisional evidence is the matched prerequisite-stack check, not a result for #6, and the source-only review at this head, not GPU qualification. The old whole-suite results for Landing order remains #10, #8, #9, then #6. No merge is requested until the controlled device gates and remaining coverage/hold decisions are complete. Corrected-run provisional snapshotThe retained gate, last written at 2026-10-29T15:35:02.470819+00:00 and read at 2026-10-29T20:08:08.547446+00:00, has 669 of 1,367 chunk pairs complete: 665,231 of 1,346,778 selected cases have results in each arm. It records 1,912 status differences, zero regressions and zero invocation errors in those completed rows. The overall gate is BLOCK / INCOMPLETE, solely reporting unfinished coverage; this is not a completed no-regression result. The latest individual 1,000-case chunk is ALLOW, which does not authorize the whole run. There is no final result yet. The source ancestry was checked: the control contains the exact #10, #8 and #9 heads, and the candidate contains both that control and #6 at |
DivDefaultFastSequencePinned and FrcpDefaultSequencePinned counted the ALU ops of the "hk: enable cooperative matrices by default on G14X" division and reciprocal. Every exact lowering since "agx: flush the exact quotient in precise fp32 division, not the correction step" emits other ops, so agx_tests has failed these three pins on the PR omacom#6 head (found by w7Q, the driver's meson suite: 61/64). The bits of division and reciprocal are pinned on hardware by tests/precise_math.py, ulp_bound.py and div_window.py. What this file can pin is the float-control contract: DenormFlushToZero emits exactly the default lowering. Compare the two op histograms for fdiv and frcp instead of fixed counts.
Current checkpoint: NOT READY TO MERGE (29 October, 23:10 UTC snapshot)
The corrected frozen differential has 811 of 1,367 complete chunk pairs, covering 806,848 of 1,346,778 cases per arm on paired chunks. There are zero regressions and zero invocation errors. The 1,912 differences remain NotSupported → Pass (1,911 compute and one API case).
The score is BLOCK / INCOMPLETE, not qualification: the control also contains one extra in-flight image chunk (1,000 cases), so its raw count is 807,848 versus the candidate's 806,848. Four errors record unfinished coverage and that unpaired chunk. The paired image chunks have no differences; their shared failures are not new regressions. Approximately 556 chunk pairs remain.
Recorded source bindings are unchanged: control
59c25f62c9d9b3077160b180ee294612df3d4de7(main plus #10/#8/#9), candidate413636ccd83578a8ec9020532d16552a5a8a3551(that control plus this PR's9323171c12c5), CTS ELF550d04d3bc2b2164c3a74ae5f386f287a97bc2e3c2a311756838c994e9b50744. Each pair uses the same boot. The CTS source binding remains recorded rather than independently verified. Checkpoint JSON SHA256:61901e1fcf8a8f4e84c44b8b33fd29746120c0b5995b3823d1a4c6f3e2536d59.This run remains a valid differential of those frozen arms. It does not silently qualify a future integration with the #8 ownership correction. After that correction, a short placed/mapped-memory confirmation of the restacked tips is required, not a whole-run repeat; its exact list/count is awaiting confirmation. The prerequisite landing order and current review holds remain.
Earlier dated status and evidence
NOT READY TO MERGE
Head:
9323171c12c5aa6055f1031ea26c16c247191987.Qualification correction — 29 October
I withdraw the earlier 366-chunk / 361,849-case, no-Pass-to-Fail claim as qualification of this PR. Its control included #8, #9 and #10, while the candidate was PR #6 alone. That comparison changed more than #6 and does not isolate this change. CPU compiler tests and source review are not device qualification.
The corrected comparison keeps the same prerequisite stack in both arms:
59c25f62c9d, driver SHA-256 prefix2528f828;413636ccd835, driver SHA-256 prefix6d9b234f.The controlled run is incomplete. Its selected scope is 1,367 chunk pairs / 1,346,778 cases, not the full CTS. Completion counts are not a pass: every pair's gate JSON, driver identity and same-boot binding still need to be scored. No final corrected pass count or no-regression verdict is claimed here.
Valid provisional evidence is the matched prerequisite-stack check, not a result for #6, and the source-only review at this head, not GPU qualification. The old whole-suite results for
518212284edo not qualify the current head. The three shader-object timing regressions remain unresolved, not waived.Landing order remains #10, #8, #9, then #6. No merge is requested until the controlled device gates and remaining coverage/hold decisions are complete.
Full correction: #6 (comment)
Corrected-run provisional snapshot
The retained gate, last written at 2026-10-29T15:35:02.470819+00:00 and read at 2026-10-29T20:08:08.547446+00:00, has 669 of 1,367 chunk pairs complete: 665,231 of 1,346,778 selected cases have results in each arm. It records 1,912 status differences, zero regressions and zero invocation errors in those completed rows. The overall gate is BLOCK / INCOMPLETE, solely reporting unfinished coverage; this is not a completed no-regression result. The latest individual 1,000-case chunk is ALLOW, which does not authorize the whole run. There is no final result yet.
The source ancestry was checked: the control contains the exact #10, #8 and #9 heads, and the candidate contains both that control and #6 at
9323171c12c5aa6055f1031ea26c16c247191987. The CTS ELF SHA-256 is550d04d3bc2b2164c3a74ae5f386f287a97bc2e3c2a311756838c994e9b50744; its recorded source commit has not been independently verified.Historical source and test notes (not current-head qualification)
Status: NOT READY TO MERGE (source head
f144c7949b7d, native and package builds passed 48 of 48 targeted cases, wide suite pending; wide CTS build69bde153405c; diagnostic tail build594460915d6a)The wide Vulkan CTS found three problems in the previous head of this PR (
8b217d2f67cc). All three came from the dependency-tracked compute barrier. Those three fixes were measured on build69bde153405c(see the table). The completed wide CTS on that build also found 55 regressions. The later barrier-word fix5c8d6b910379was rerun on the 48 known cases: 48 of 48 Fail, with 0 new GPU timeout lines. Both later attempts, the barrier-word change and a query-copy batch-closure change, are reverted in this branch. The current source headf144c7949b7dkeeps a compute batch open across a barrier only when it is the tail stream. A native build of it (library SHA-256 prefixcfa40cace1eb8dfb, with asrc/tree identical to594460915d6a) passed the 48 known correctness cases, 48 of 48, on the 16-inch M1 Max. The stored control and a control rebuilt from main also passed 48 of 48, and the GPU timeout delta was 0. A package build of the same head (library SHA-256 prefix4874d533a942e052, byte-identical to the staged package library) passed the same 48, 48 of 48. A package build of main as the control also passed 48 of 48, and the GPU timeout delta was 0. That is the first result on the bytes that would be installed. The wide suite on the package pair is queued and has no results yet. A diagnostic build of a related change,594460915d6a(69bde153405cplus one hunk inhk_cmd_buffer.c), passed the 48 known correctness cases, 48 of 48, on the 16-inch M1 Max. A control rebuilt from main also passed 48 of 48, and the GPU timeout delta was 0. That build is not the head, and no wide suite has run on it. The seven timing cases have been rerun, with the sequences below; none is waived.More checks ran on all three machines. The 8 MLX suites, recovery after a refusal and
sparse_resourcesare done on the 13-inch M1 and the 16-inch M1 Max; the 8 MLX suites are done on the M2 Max. The wide CTS on the 13-inch M1 is complete: all 20 of 20 parts finished, 0 wedge-stopped, 3,284 of 3,284 chunks complete in all arms, 3,253,584 cases with a result in both arms, 1,958 status differences, 0 GPU timeout lines this boot. The wide CTS on the 16-inch M1 Max is complete: all 20 of 20 parts finished, 3,284 of 3,284 chunks complete in both arms, 3,253,584 cases compared and 2,037 status differences. Of those, 1,951 are NotSupported to Pass, 31 Fail to Pass, 53 Pass to Fail and 2 QualityWarning to Fail. Those 55 regressions were recorded on the wide CTS build. On the later combined build, the 42 multiview cases passed the targeted run and the six renderpasses cases still failed. The seven timing cases are not waived. This PR stays NOT READY.api.copy_and_blitimage-copy tests passed on the base branch and failed on the previous head. The groups arecore.image_to_image10,088,copy_commands2.image_to_image1,420,dedicated_allocation.image_to_image1,420 andbuffer_to_image16. A bisect over the 54 commits the previous head had, with exact-sha builds, names the tracked-barrier commit as the first bad one. An image copy launches one dispatch per region, and the app declares no barrier between them. The fix is inside that commit.imagegroup, threeimage.atomic_operations ... sparse_imgtests failed and the GPU timed out. The first bad commit is the same one. That commit emits a reduced barrier word on G13X. A device that has created a sparse image or buffer now keeps the full word. The fix is inside that commit.robustness.index_access.draw_indexed_pipeline_robustness_2_vert_tess_fragfailed on the M1 Max. On the 13-inch M1, the tessellationdraw_indexed_indirect_countcases hung the GPU in a 100-case chunk (Job timed out on the DRM scheduler). Of eight settings tried on the failing case with the build02765a81b1a5(the previous head's fixes without this last one), only those that includeHK_PERFTEST=alwayscdmbarriercured it. A command buffer that records rendering, a copy, or a precomp that feeds a draw now flushes every launch. That is one new commit near the top of the series.This block changes to READY TO MERGE only when every number below names the final sha and the regressions are resolved. The current source head is
f144c7949b7d960f26677b671341d5a123057ddf; its native and package builds passed the 48 targeted cases, but nothing else below, including the wide suite, was measured on it. The wide CTS builds in the table are69bde153405cf02d52b0c9810307a0c7d0085d52(treed4272dcddc2842ca775258da7fae307960262e65), not the current source head. Two earlier targeted builds were reverted:5c8d6b9103798916692efa0b80c675b507d2b5d3(48 of 48 Fail) anda5a7723d7c3b(42 Pass, 6 Fail). A diagnostic build,594460915d6ac9da1249a5075e10c6c316063900, passed 48 of 48 targeted cases. It is not the head. These results do not qualify the source head.What this PR is
One pull request with everything: 61 commits on top of
main, 62 files, +4950/-199. It replaces #3, #4 and #5 (see "Merge" below).spirv:).Results (each line names the sha it was measured on)
69bde153405cgit-69bde15340(Mesa 26.3.0-devel)69bde153405cimagechunks 0 and 3 (2,000 cases) and 12apichunks that held the earlier copy failures (12,000 cases), against the base branch69bde153405cimagewindow with the sparse-image atomics, 3 runs69bde153405c83be9b16b3d8: 3 failures in each of 3 runs and GPU timeouts)robustnesscases that hung the 13-inch M169bde153405crobustnesscases, 3 runs, and 3 runs of the base branch69bde153405c8b217d2f67cc, and a build of the previous head's fixes without the last one,02765a81b1a5; the kernel logs showJob timed out on the DRM scheduler)69bde153405cshader_object.performancethat flip on the base branch as well and are excluded from the intended count (see the next row). The remaining 1,951 are all NotSupported on the base and Pass here: 1,911 cooperative matrix tests incompute, 39 glsl bfloat16 tests and the properties query inapi. That is the intended change. No case changed in any other direction. 0 GPU timeouts.69bde153405c7cda7850edd1. 1,951 are NotSupported to Pass: 1,911 cooperative matrix tests incompute, 39 glsl bfloat16 tests and the properties query inapi. The other 86 are 31 Fail to Pass, 53 Pass to Fail and 2 QualityWarning to Fail. The 30memory_modelimage-payload cases were Fail in 90 of 90 base runs and Pass in 90 of 90 measured-build runs, with 0 within-arm variation and 0 GPU timeouts; the cause is not bisected. The 42multiviewquery-copy and 6renderpassessuballocation cases were Pass in 144 of 144 base reruns and Fail in 144 of 144 measured-build reruns, with 0 within-arm variation. The other 8 differences are inshader_object.performance: 5 Pass to Fail, 2 QualityWarning to Fail and 1 Fail to Pass. These 55 regressions were measured on this wide CTS build. Later targeted results are separate rows below; no timing waiver. The installed system library on that machine was built from the same source commit as the measured build, but the bytes differ (13,792,048 against 15,869,440 bytes), so this evidence is bound to the measured library, not to the installed package. It is not a separate stock control. Before part 1, the boot already had 8 GPU timeout lines from another job. Parts 1 to 9 each read before 8 and after 8: 0 own GPU timeouts.5c8d6b910379a5a7723d7c3b(includes5c8d6b910379)c63179b3da8e2a95. Script journal counter: before 8, delta 0. Guard counter: before 0, after 0, delta 0. These are different counters. The combined changes are not a full fix or qualification.594460915d6a(69bde153405cplus one hunk inhk_cmd_buffer.c)7cda7850edd1also passed 48 of 48, and the GPU timeout delta was 0. This is a diagnostic build, not the PR head. No wide suite, speed measurement or other case was run on it.f144c7949b7d(library prefixcfa40cace1eb8dfb, native build, not the package bytes)7cda7850edd1also passed 48 of 48, and the GPU timeout delta was 0. Not shown: any other case, speed, the M2 Max, the 13-inch M1, or the packaged library.f144c7949b7d(package library prefix4874d533a942e052)7cda7850edd1(library prefix30cf82ae3074421a) and the stored control also passed 48 of 48, and the GPU timeout delta was 0. This is the library that would be installed. Not shown: any other case, speed, the M2 Max, or the 13-inch M1.69bde153405cagainst7cda7850edd1shader_object.performancetiming cases that flipped between pre-PR main and the head in the wide CTS, rerun with 5 runs per arm and separate deqp processes (ticket at 20:50Z)69bde153405cdraw_dynamic_pipelineanddraw_indexed_dynamic_pipelineFail in all 10 runs of BOTH builds;draw_indexed_indirect_static_pipelineanddraw_static_pipelinePass in all 10 runs of both.draw_indexed_indirect_count_dynamic_pipeline(mainFail Fail Pass Pass Pass, headPass Fail Pass Pass Fail),draw_indexed_indirect_dynamic_pipeline(mainFail Fail Fail Pass Fail, headQualityWarning Pass Fail Pass Pass) anddraw_indirect_count_dynamic_pipeline(mainPass Fail Fail Fail QualityWarning, headFail Pass Fail Fail Pass) flip between runs INSIDE the base build too. These are timing tests; they flip on the base branch as well, so they are excluded from the difference count. 0 GPU timeouts.69bde153405cfast_opshas the same 8 failed assertions of about 1.38 million in both builds, so they are not new. The cooperative matrix suite runs 82.9 million assertions here against 21.1 million on the base branch, all passing.69bde153405cfast_opshas the same 8 failed assertions in both builds, so they are not new. The cooperative matrix suite runs 82.9 million assertions here against 21.1 million on the base branch, all passing. (An earlier try found no test binaries on this machine; they were copied from the 13-inch M1 with the same checksums.)69bde153405c69bde153405csparse_resourcesCTS (7,263 cases), this head against the base branch69bde153405csparse_resourcesCTS, same69bde153405c40282811c6e1, reportsgit-69bde15340) next to the exact-sha build above and the base branch69bde153405c40282811c6e1) against the earlier v3 driver, three runs per driver interleaved in one block, same wheel; every ratio below is the median of the three package runs over the median of the three v3 runs69bde153405c69bde153405c69bde153405c8b217d2f67ccwithHK_PERFTEST=alwayscdmbarrier6543eeb7df7) fails both with an out-of-device-memory error. The same earlier build with the system-memory limit set by hand (HK_SYSMEM=11000000000) runs gemma-3-12B at 31.62 and 5.35. The raw error text of the two failures was overwritten by later runs; the empty score rows remain. Measured again on69bde153405c: queued.8b217d2f67ccwithHK_PERFTEST=alwayscdmbarrier69bde153405c: queued.memory,sparse_resources, and 46 of 151 chunks ofbinding_model8b217d2f67ccapishowed the image-copy failures abovesparse_resourceson an earlier tree4c1ca73cddb(treef51deca39fbf)f144c7949b7dagainst7cda7850edd1, package buildsshader_object.performancecases, thebinding_modelrows, the full suite, the M2 or any speed.Not run: the CTS on the M2 (a separate problem, below). Speeds are ratios inside one block, because the absolute tokens per second on the M1 chips drift by 10 to 20 percent over hours. The memory rows above were not shown to prevent out-of-memory kills: a run without those commits finished without a kill. Anything not listed in this table was not run.
Every row above ran on kernel 7.1.12-2-12.6. The M2 Max rows added the compute-preemption debug word, as stated above. On the 13-inch M1 only the Ornith run on the earlier driver added that word. The other memory rows on that machine ran on a stock boot. Release kernel .15 results (kill-mid-dispatch arm on the M2 Max and the 13-inch M1) are kernel results. They are reported in omacom/linux-aurora #25 and are not part of this PR.
What still blocks READY
69bde153405c. That build had 53 Pass to Fail and 2 QualityWarning to Fail regressions. All 48 targeted correctness cases failed on build5c8d6b910379, with 0 new GPU timeout lines. The reverted combined build ata5a7723d7c3bgave 42 Pass and 6 Fail. A diagnostic tail build,594460915d6a, passed all 48. The source headf144c7949b7dhas native and package builds that passed the 48 targeted cases. No wide suite, speed measurement, M2 Max or 13-inch M1 result exists for it. PERF7 is finished on69bde153405c; the recorded sequences above are not a blanket exclusion. A passing wide suite on the exact final head, run from the packaged library bytes, is still required.69bde153405c: queued.Merge
Merge this pull request with a merge commit, not a squash, so the 61 commits and their authorship stay. It will not mark #3, #4 or #5 as merged, because their heads are not ancestors of this one. This PR holds the commits of all three. 12 of #3's 16, 19 of #4's 25 and 21 of #5's 28 are identical patches here. Later commits in this PR edited the rest. For example, the precise division work was redone. Lines that exist only in #3 to #5 are earlier versions of code that later commits here rewrite. I compared final trees but did not review every such line. After merging, close #3, #4 and #5 with a comment that their content is in this PR. Merging #3 to #5 first would not help, because their heads are not ancestors of one another.
Commits by layer
VK_KHR_cooperative_matrixon by default, bounded syncobj poll, FP_MATH_CTRL for the builder generator, regression testsubfefusion, one precise division fixFour of the #3 commits no longer count as identical. The tests commit had comment edits. The first commit dropped an experimental env-gated code block and its lab-notebook reference. The tracked-barrier commit carries the fixes above. The division work was redone.
Defaults per chip at this head
AGX_SIMDMAT=1opts in)HK_PERFTEST=trackcdmbarrieropts in)Paired fragment loads have no chip check of their own: they run wherever cooperative matrices run, so they are on for G14X as well.
AGX_HWMAT_VEC2_OFF=1turns them off.Where the barrier is dependency-tracked, some command buffers flush after every launch. These are the buffers that record rendering, an image copy or blit, or a precomp that feeds or follows a draw. A command buffer that only dispatches compute keeps the tracking. A device that has created a sparse image or buffer uses the full barrier word.
On every chip: the device heap is 90% of system memory, and an allocation of 1 MiB or more is refused when free memory would drop below the larger of 1 GiB and 2% of RAM.
Knobs
AGX_SIMDMAT=0|1cooperative matrix.AGX_HWMAT_VEC2_OFF=1,AGX_LOCAL_FOLD_OFF=1,AGX_SCHED_COMPUTE=1switch the M1 codegen defaults off or restore the scheduler.AGX_HOIST_LOADS=0|1load hoisting.HK_CDM_DEFER_FLUSH=0|1deferred barrier.HK_PERFTEST=trackcdmbarrieroralwayscdmbarrier.HK_SUBMIT_POLL_USbounded poll before blocking waits (default off).HK_LARGE_CONSTANTS=0|1.HK_SYSMEM=<bytes>overrides the system memory size the heap and the reserve are computed from (the 11,000,000,000 row above used it). The heap share is the driconf optionheap_memory_percent(this PR changes its default from 0.50 to 0.90). The compiler switches are part of the shader cache key. They areAGX_SIMDMAT,AGX_HWMAT_VEC2_OFF,AGX_LOCAL_FOLD_OFF,AGX_SCHED_COMPUTEandAGX_HOIST_LOADS.Try it on your Mac
The last line should print
driverName = HoneykrispandMesa 26.3.0-devel (git-795ae42a71). To run the CTS against it, put the sameVK_DRIVER_FILESin front ofdeqp-vk.One thing about the M2
On the M2 Max, a single long compute dispatch can return partly wrong values with no error while a window animates on the same GPU. It must run about 150 ms or longer: 87 ms was correct and 152 ms was wrong. The kernel log then shows "GPU timeout" and recovery lines from the GPU driver. It also happens with the stock distribution driver (Mesa 26.2.4) and with every build of this PR we tried, so this PR is not its cause. The M1 chips do not show it. It is a kernel matter. With compute preemption switched on through a kernel debug flag (bit 48 of the GPU driver's debug flags), the same test matched its reference in 60 of 60 animated runs. Those were 5 harness runs on 3 boots, with no GPU timeout. Without the flag, the same test showed wrong results and GPU timeouts on the stock kernel (39 timeout events in one run, 120 in another). The kernel change is not part of this PR.