Step 3b code is wired across UIRenderer + GlyphCache + UIPipeline +
chess game (gpu_mode = .metal on iOS, MetalGPU bound via the GPU
protocol). macOS GL chess, iOS-sim GLES chess, and iOS-sim Metal
triangle (63-metal-clear.sx) all still render.
iOS-sim Metal chess crashes inside replaceRegion uploading the 1MB
font atlas. Bisecting that crash exposed several sx-language issues
where mid-bisect tracers (NSLog inside if/else branch bodies) didn't
produce output, blocking further investigation.
Filing each finding as examples/issue-NNNN.sx rather than working
around piecemeal:
Bugs:
- 0024 NSLog/foreign-call inside if/else body not producing output
- 0025 C-ABI param coercion incomplete for composites >16B
(combined direct-call abiCoerceParamType TODO + call_indirect
path that doesn't apply C-ABI coercion at all)
- 0026 replaceRegion 1MB upload crash (likely downstream of 0025)
Features needed for step 4 + cleanup:
- 0027 Obj-C block bridge (^{...}) for animateWithDuration:
- 0028 Optional protocol box (?GPU = null) replaces T = ---; has_T: bool
- 0029 destroy_texture/buffer/shader on GPU protocol
- 0030 extern cross-file globals
Library-side: renderer.sx + glyph_cache.sx + pipeline.sx gain a
`gpu: GPU = ---; has_gpu: bool` field pair + branches that route every
GL touchpoint through the protocol when has_gpu. glyph_cache.init
saves/restores those fields around its memset. pipeline.set_gpu()
propagates to renderer + font. Renderer's MSL shader source added as
UI_MSL_SRC using packed_float2/packed_float4 to keep the 12-float
interleaved vertex layout tight (48 bytes).
metal.sx: dual-phase init (init(null, 0, 0) for eager device+queue,
re-init with the layer once UIKit installs the SxMetalView).
setStorageMode:.shared on every texture descriptor to ensure CPU-
writable atlas pixels on Apple Silicon iOS-sim.
Regression suite: 68 passing, 0 failed. WASM chess build currently
broken under step 3b state (silent compiler crash); documented in
CHECKPOINT.md, likely fallout from one of the filed issues (probably
0028 — the verbose protocol-box pattern). Step 3b resumes after
0024-0030 land.
69 lines
3.8 KiB
Plaintext
69 lines
3.8 KiB
Plaintext
// issue-0026: Chess game on iOS-sim with `plat.gpu_mode = .metal` crashes
|
||
// inside `[MTLTexture replaceRegion:mipmapLevel:withBytes:bytesPerRow:]`
|
||
// when uploading the 1024×1024 R8 font atlas. The 1×1 RGBA8 white tex
|
||
// through the SAME code path (metal_update_texture_region_ios in
|
||
// library/modules/gpu/metal.sx) works.
|
||
//
|
||
// Blocked on issue-0024 (NSLog inside if/else not firing — or unified-log
|
||
// buffer loss on crash; investigation pending) — without a trustworthy
|
||
// tracer we can't reliably bisect which arg arrives wrong. Most likely
|
||
// cause: this is downstream of issue-0025's ABI gaps (MTLRegion is 48
|
||
// bytes and goes through `xx objc_msgSend` cast, which is the
|
||
// call_indirect path that issue-0025 part B covers).
|
||
//
|
||
// ── Reproduction recipe ───────────────────────────────────────────────────
|
||
//
|
||
// cd /Users/agra/projects/game
|
||
// /Users/agra/projects/sx/zig-out/bin/sx build --target ios-sim main.sx \
|
||
// --bundle sx-out/ios/SxChess.app --bundle-id co.swipelab.sxchess \
|
||
// -F ~/Library/Frameworks
|
||
// cp -R assets sx-out/ios/SxChess.app/
|
||
// codesign --force --sign - --timestamp=none sx-out/ios/SxChess.app
|
||
// xcrun simctl install booted sx-out/ios/SxChess.app
|
||
// xcrun simctl launch --terminate-running-process booted co.swipelab.sxchess
|
||
// sleep 4 && xcrun simctl io booted screenshot /tmp/sx-chess.png
|
||
//
|
||
// Expected (after fix): chess board renders via Metal.
|
||
// Observed: app launches, returns immediately to home screen, no screen
|
||
// touched. The simpler examples/63-metal-clear.sx demo still renders the
|
||
// colored triangle on the same sim, so the Metal pipeline itself works
|
||
// for small uploads.
|
||
//
|
||
// ── Candidate root causes (in priority order) ─────────────────────────────
|
||
//
|
||
// 1. issue-0025 fallout (most likely): MTLRegion (48 B by value) passed
|
||
// via the *MTLRegion workaround. The call_indirect path (issue-0025
|
||
// part B) doesn't ABI-coerce, so the pointer-shaped declaration may
|
||
// not actually pass the address in the right register slot for that
|
||
// call site shape (6 args, including the indirect aggregate).
|
||
//
|
||
// 2. iOS-sim Metal-driver limitation: `setStorageMode:.shared` may not be
|
||
// honored for r8 textures of this size; default may be `.private`
|
||
// which precludes CPU-side replaceRegion. Workaround would be to
|
||
// upload via `MTLBuffer` + `MTLBlitCommandEncoder` (newBufferWithBytes
|
||
// + copyFromBuffer:sourceOffset:sourceBytesPerRow:...:toTexture:...).
|
||
//
|
||
// 3. sx-side `xx` cast bug: bytes_per_row : u64 = xx (u32_expr) may
|
||
// truncate or sign-extend incorrectly. Less likely (the math comes
|
||
// out to 1024, which fits in any width).
|
||
//
|
||
// ── How to resolve ────────────────────────────────────────────────────────
|
||
//
|
||
// After issues 0024 + 0025 are landed:
|
||
// 1. Re-add the trace NSLog markers ("[metal] U1..U5" in
|
||
// metal_update_texture_region_ios) — now they should actually print.
|
||
// 2. Re-build + relaunch chess on iOS-sim.
|
||
// 3. If U5 fires after U4 (no crash inside msg_replace), the bug was
|
||
// ABI-related; declare success and rename this file to
|
||
// examples/NN-metal-large-region-upload.sx (next free NN).
|
||
// 4. If U4 → crash persists, fall back to the MTLBuffer + blit
|
||
// encoder path in metal.sx's create_texture (when pixels != null,
|
||
// allocate a temporary MTLBuffer with newBufferWithBytes:length:options:
|
||
// then run a one-shot command buffer with a MTLBlitCommandEncoder
|
||
// copying the buffer into the texture). This is the Apple-recommended
|
||
// approach for large texture initial-uploads.
|
||
|
||
#import "modules/std.sx";
|
||
|
||
main :: () -> s32 { 0; }
|