Merge merge/unity (Mesa pin 60202246, gllimits=41 default, docs) into merge/unity-seed

One U head for the re-key round: 64efd78e (fjit holes, fjit.rs out of the unit key), 1bf5ba09 (seeded starts) and merge/unity a0f6a8c9 (4ed5cad3's page fixes, the Mesa pin 1d5b26d9, docs).

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_1896c5b302a54696aaa92c5f4047f20b
This commit is contained in:
velzieandClaude Opus 5.5 committed 2026-10-09 08:16:34 -04:00
commit 0ddc93909d
7 files changed
+116 -40

No files matched your search

+9 -9
View File
@@ -51,21 +51,21 @@ push** (rebased onto upstream wink 0dd84167; nothing pushed):
- replay it with `replay-run.mjs gpu TRACE --query readback=1`;
- bisect the shader variants with `shaders.mjs`;
- then re-apply e204fa1b's two web files.
2. *Grass is still dots* at GL 4.0 after the -0.0 fix (U mp27; the sea is
back). Next: the geometry-shader emulation's output for the grass program
(its source is in the Muck trace; `shaders.mjs`). It may resolve with
item 1 at GL 4.1+, where Unity's 410 source compiles natively.
2. *Grass:* fixed at GL 4.2 by GL 4.1's texture limits with mesa-wink
60202246 (U mpg3: blades, 36.6-38.1 presents/s). gex's pin is 60202246
and `?gllimits=41` is the default since U's pin commit on merge/unity
(`?gllimits=0` turns it off; 43 stays per run, item 1).
3. *Noita's world fps* is bound by its job hand-off, not by GL: the main
thread is parked about 37% waiting on job threads, and KLock is 0.14%
(stream F's area). The page's GL submit is no longer the limit
(CLIENT_ARRAY: 55.5 vs 51.1 world fps on the old path, pewasm 47.2).
4. Remaining E1: GL draw/pointer calls are on the fast path, but the page
gain is below noise.
5. *The 4-slot bind-group repro on the rebased tree* (`$G/urep5.sh`, mods
tinyu) timed out at 1200 s with no output. Rerun it the way trep2.sh ran
the earlier ones (full trace, `--query stream=1`, timeout 1500, no
maxframes) before moving gex's pin; expect 0 validation errors from
frame 1343 on.
5. *The 4-slot bind-group repro on the rebased tree:* done (U,
2026-10-09, `scratch/unity/urep-pin.sh` on edger, run like trep2.sh:
full trace, `--query stream=1`, timeout 1500): mods/tinyu replays all
2,777 frames (3,403 batches) of Noita's trace with 0 validation errors
(5f5572e6 and +6d3a4cfd had 2,668 and 2,720 from frame 1343).
Tooling (unchanged):
+67 -14
View File
@@ -2086,6 +2086,8 @@ Not yet:
| hp12 | full fjit + unit | 58e95157 (epochs only where translated) | 128 s | 158 s | 42.4-42.7 |
| **hp13** | **full fjit + unit** | **977a2236 (current JIT callees out of batches too)** | **87 s** | **119 s** | **39.6-39.9** |
| hb51 | full fjit, no unit | 58e95157 | 222 s | 270 s | 33.9 at 392 s, rising (x11 backend; was black) |
| hb52 | full fjit, no unit | merge/unity-rekey d146c248 | - | - | SIGILL at start-up (status 132) |
| hb53 | full fjit, no unit | merge/unity-rekey 64efd78e | 178 s | 225 s | 35.7 at 392 s (x11 backend) |
Native gexc's gate (unit, no fjit): menu at 406.5 s, 30.59
presents/s. hp13 against hp7: 52% more presents/s (39.9 vs 26.3),
@@ -2095,17 +2097,68 @@ Not yet:
the menu rate ranges 39.7-42.7 across these runs. By the menu hp13's
JIT has made libasound 20 MiB of wasm (947 functions), libc 4.3 MiB,
libudev 3.2 MiB, libcrypto 2.9 MiB; UnityPlayer is out of the top 12.
- **Resume (2026-10-09, HEAD after 977a2236; merge/unity has master 41917e73):**
HK in the page runs the target configuration (full fjit + the pinned
unit, `hk-bisu.sh NAME byobj=1`) to the menu: hp13 above. Fixed today: the
black screen and the libxcb crash (stale learned starts across dlclose,
763a1538), unit and current JIT callees kept out of batches (5ec43e82,
977a2236), mid-function misses to the fallback (a12da54a, 6bc61569).
Open: start-up is still ~87 s to the first frame (hp7 without fjit 55 s):
profile the main Worker again (ht2's method) to see what the JIT costs
now; libasound's 20 MiB of wasm; the native JIT has the same two holes
(learned state kept across dlclose, mid-function roots as starts),
which want a gex-xlate fix (a re-key: fjit.rs is in
GEX_CGEN_RECOVERY_INPUTS although it is runtime-only; build.rs could
leave it out, once). Muck's grass needs the mods/gpu Mesa and
`?gllimits=41` (not default; GL to decide).
- **merge/unity-rekey (64efd78e, one commit on 4ed5cad3, for its own
round):** the native JIT's two holes fixed in gex-xlate
(`Jit::retire(process, ranges)` from both hosts' on_retire; a miss's
root stays a start only if it was a strong one already) and fjit.rs out
of GEX_CGEN_RECOVERY_INPUTS (key c6014ffc... with and without an
fjit.rs edit, 855acf6a... after a func.rs edit). hb52 (d146c248) died
with SIGILL: with misses no longer starts, recovery walked over a JIT
entry inside the function, and the page's "served" test was part of
`executable`, which fetch asks of every byte, so the bytes decoded as
illegal. 64efd78e passes it as `skip` (`Jit::translate_skipping`), the
batch bound only. hb53: menu, x11, first frame 178 s, 35.7 presents/s
(hb51 on the epoch shim: 222 s, 33.9). Native: tests/fjit-remap (the
Oct 8 gexc gets 99,800 of 200,000 wrong under --fjit), fjit-procs,
x86-programs (82 ok), embed PASS, gex-xlate tests. The page's unit cache
(scratch/unity/units/cgen-page) must be rebuilt after it lands.
- **Mesa pin (1d5b26d9): mesa-wink 60202246 and `gllimits=41` by
default.** Replays gpu vs this build: Noita 92f095c5, HK 9eece5c5, 0
rejects and 0 validation errors each; GL's 4-slot repro (tinyu) 2,777
frames with 0 validation errors; browser-gui --gl x86 and x64 12 ok
each; HK hp14 (merge/unity shim, this Mesa) menu at 41.8 presents/s.
Muck with the default and no `?gllimits` (mk2, the seed shim, no unit):
"OpenGL 4.2" context, no "Shader Unsupported", grass blades in
`shots/mk2/c013.png`, 36.9 presents/s at 393 s.
- **Muck dies with SIGILL at ~25 s on merge/unity's shim (977a2236,
4ed5cad3)**, with the unit (mpg5, mk1) and without (mk4). It does not
with 64efd78e (mk3, 4 minutes, no unit) or 1bf5ba09 (mk2). The page asked
"served by the unit or the JIT" of instruction fetch (part of
`executable`); with epochs a JIT entry the current epoch has no start
for is read as non-code inside the function being recovered and decoded
as illegal. 64efd78e passes it as `skip` (batch bound only).
- **Start-up (decision 3).** hp14's main-Worker profile, 10-90 s (unit +
fjit): 61% (49.8 of 81 s) in `fjit::translate`: recover_one 27.2 s
(jump tables 16.9, discover 9.2, lift 6.9), summaries 17.7, build_runtime
8.8, emit 8.4, prepare 5.5; the per-byte `executable` 5.9 (2.3 in
elfprov::provided's locks). Audio: the page has no audio device; FMOD's
output init fails ("Unknown PCM default", tried twice), after pulse
fails to connect. libasound's 20 MiB was mostly copies: the page's JIT
had no function starts but those calls name, so a tail jump absorbed the
function it reached, and libasound's exported wrappers each carried one.
Offline (fjitrepro, all 1,698 exports): 57.2 MiB / 16.4 s unseeded, 9.7
MiB / 7.1 s seeded. ALSA with no config (hp15, ALSA_CONFIG_PATH=/dev/null)
cut libasound to 11.2 MiB but not the first frame (112 s against hp14's
110 s, both profiled), so it is not the path to cut.
merge/unity-seed 1bf5ba09 (on 64efd78e) seeds every mapped object's
starts (`Jit::add_image`) before a translation and takes the fetch
checks once per translation: no unit, hb53 (64efd78e) 178 s first
frame, 225 s 100 presents, 35.7 presents/s; hb54 (seeding) 121 s, 171 s,
39.1; hb55 (both) 121 s, 166 s, 40.1; libasound 26.0 -> 3.7 MiB.
The HK unit re-keyed for 64efd78e (key 7bd87731, byte-identical c.wasm,
1,941 s on gooner) is on edger in `units/cgen-page-rk`; Muck's is
rebuilt too (4e58f35b, 884 s), also in `cgen-page-rk`.
With the unit (target configuration, seed shim 1bf5ba09):
- hp16 (HK): first frame 56 s (hp13 87 s), 100 presents 85 s (119 s),
41.5 presents/s at 392 s (39.9).
- hp17 (HK, profiled 10-90 s): `fjit::translate` 20.7 s of 81 s (25.5%;
hp14 49.8 s, 61.5%); the main Worker now waits on its threads 31.6 s.
Profiled runs' first frame (110 s both) is held by the profile.
- mk5 (Muck): first frame 82 s, 100 presents 95 s, 34.0 presents/s at
392 s, OpenGL 4.2, no "Shader Unsupported", grass blades
(`shots/mk5/c013.png`).
Branches: merge/unity-rekey 64efd78e (own round), merge/unity-seed
1bf5ba09 on it (worktree wt/unity-rk); merge/unity 1d5b26d9 (pin).
Natively the JIT seeds only the main image too (gexc's
FjitTranslator::image); a Translator hook per mapped object would do
the same there.
+20 -1
View File
@@ -20,7 +20,26 @@ else
fi
OUT=${1:-$DEFAULT_OUT}
BUILD=$OUT/build
EMDAWN=${GEX_EMDAWN_DIR:-$($ROOT/web/fetch-emdawnwebgpu.sh)}
# emdawnwebgpu: a Mesa checkout that pins its own (the wink branch:
# wink/lib/emdawn.sh, a release matched to its Tint and patched by
# wink/tools/patch-emdawnwebgpu.py) supplies it; else gex's own fetch.
if [ -z "${GEX_EMDAWN_DIR:-}" ] && [ -f "$MESA/wink/lib/emdawn.sh" ]; then
WINK_CACHE=${GEX_MESA_WINK_CACHE:-${TMPDIR:-/tmp}/gex-mesa-wink-cache}
EMSDK_ROOT=$(CDPATH='' cd -- "$(dirname "$(command -v emcc)")/../.." && pwd)
emdawn_log=$(WINK_ALLOW_ANY_EMSDK=1 bash "$MESA/wink/build.sh" --variant=mt --until=emdawn \
--cache="$WINK_CACHE" --build-dir="$WINK_CACHE/build" --emsdk="$EMSDK_ROOT" 2>&1) || {
echo "$emdawn_log" | tail -20 >&2
exit 1
}
EMDAWN=$(echo "$emdawn_log" | sed -n 's/^\[emdawn\] \(ready\|cached\) at //p' | tail -1)
[ -f "$EMDAWN/webgpu/include/webgpu/webgpu.h" ] || {
echo "$emdawn_log" | tail -20 >&2
echo "no emdawnwebgpu from wink/build.sh" >&2
exit 1
}
else
EMDAWN=${GEX_EMDAWN_DIR:-$($ROOT/web/fetch-emdawnwebgpu.sh)}
fi
TINT_OUT=${GEX_MESA_TINT:-${TMPDIR:-/tmp}/gex-mesa-wasm/mesa-tint-pthread}
TINT_TMP=${GEX_MESA_TINT_TMP:-${TMPDIR:-/tmp}/gex-mesa-tint-build}
+1 -1
View File
@@ -1440,7 +1440,7 @@ self.onmessage = ({ data: m }) => {
canvas = m.canvas;
presentOverride = m.present ?? null;
// The compositor draws with WebGPU on the device Mesa will use.
if (m.glLimits) globalThis.GEX_GL_LIMITS = m.glLimits;
if (m.glLimits != null) globalThis.GEX_GL_LIMITS = m.glLimits;
requestGexDevice().then((gpu) => {
comp = new Compositor(m.canvas, m.channel, m.stats ? new Int32Array(m.stats) : null, gpu);
comp.setDirect(m.direct);
+5 -4
View File
@@ -137,10 +137,11 @@ export class Compositor {
// is the canvas, fitted to the viewport; compositing only when needed.
const direct = pq?.get('direct') === '1';
this.#pointerLock = pq?.get('pointerlock') === '1';
// `?gllimits=41|43`: the device asks for GL 4.1's texture limits (and
// 4.3's compute ones), raising the GL version Mesa's context earns
// (gpu-device.js). Off by default: at 4.6 Muck's 3D scene drew black.
const glLimits = Number(pq?.get('gllimits')) || 0;
// `?gllimits=40|41|43`: the device asks for WebGPU's default limits,
// GL 4.1's texture limits (the default), or 4.3's compute ones too,
// which decide the GL version Mesa's context earns (gpu-device.js). At
// 4.6 Muck's 3D scene drew black, so 43 is only per run.
const glLimits = pq?.has('gllimits') ? Number(pq.get('gllimits')) || 0 : null;
worker.postMessage(
{ kind: 'init', canvas: offscreen, channel, stats: this.#stats, present, direct, glLimits },
[offscreen],
+13 -10
View File
@@ -44,17 +44,20 @@ export function requestGexDevice() {
maxStorageBuffersInVertexStage: 16,
maxStorageBuffersInFragmentStage: 16,
maxColorAttachmentBytesPerSample: 64,
// Not by default yet: GL 4.1's texture limits and GL 4.3's compute
// ones (all of them make the context GL 4.6) drew Muck's 3D scene
// black (U, mp26); `?gllimits=` below asks for them per run.
// GL 4.3's compute limits (with them the context is GL 4.6) drew
// Muck's 3D scene black (U, mp26), so they are only per run; GL 4.1's
// texture limits are the default, below.
};
// `?gllimits=41|43` (GEX_GL_LIMITS, set by the compositor worker): GL 4.1
// wants 16384 texels a side and 2048 array layers, GL 4.3's compute
// shaders 1024 invocations a workgroup and 32 KiB of shared memory;
// WebGPU's defaults (8192, 256; 256, 16 KiB) keep the context at GL 4.0.
// Unity drops shaders whose target the context is below (Muck's grass
// geometry shader: "Shader Unsupported ... All passes removed").
const glLimits = Number(globalThis.GEX_GL_LIMITS) || 0;
// `?gllimits=40|41|43` (GEX_GL_LIMITS, set by the compositor worker;
// 41 when unset): GL 4.1 wants 16384 texels a side and 2048 array
// layers, GL 4.3's compute shaders 1024 invocations a workgroup and
// 32 KiB of shared memory; WebGPU's defaults (8192, 256; 256, 16 KiB)
// keep the context at GL 4.0. Unity drops shaders whose target the
// context is below: at 4.0 Muck's grass geometry shader ("Shader
// Unsupported ... All passes removed") left the grass as dots; at 4.2
// with mesa-wink 60202246 it draws blades (U, mpg3).
const glLimitsSet = globalThis.GEX_GL_LIMITS;
const glLimits = glLimitsSet === undefined ? 41 : Number(glLimitsSet) || 0;
if (glLimits >= 41) {
Object.assign(want, { maxTextureDimension1D: 16384, maxTextureDimension2D: 16384,
maxTextureDimension3D: 2048, maxTextureArrayLayers: 2048 });