Files

18 KiB
Raw Permalink Blame History

Still-open debts (cross-phase)

2026-10-07 (P14 close): W9 closed (readout, see below); ID-P13-2 (Magma monolith) updated to the current state where traces are largely caught up but FCL still trails; three rows added: the per-item composition and structural cause of the Espryt monolith record arm, the cache-pressure inference for the driver item, and the tested-but-not-done frontend change-epoch fast path. The next phase is the draw-packet cache redesign.

2026-10-07 (P13 close), three rows closed: ID-P8-13 (9 monolith defects — after the monolith moved to the record arm, the corresponding monolith registrations all pass on the integration lane; the old monolith frontend arm was deleted in W6), ID-P8-14 (the whole-buffer readback in SyncClientSideVertexArraysForIndirectFetch and the depth mip view type in Magma monolith both belong to the deleted monolith frontend arm), MOBILEGL_PIPE_TEXEL_RETAIN_MB (W3b deleted with the pull build). Two rows added: W9 cache capacity re-tuning and Magma monolith performance, both queued for the performance round after P13, with the dev build as baseline.

The roadmap lists only "there are debts, look here". Each entry states its disposition; closed historical debts and the full debt table of that time are in git history. Open questions are in OPEN-QUESTIONS.md. Updated: 2026-09-30 (P8 second wave; reordered per the debt review. Same day: create-indirect switched to the derived fixture minecraft-1.21.1-neoforge-create-indirect-in-world-align1024 (not the original capture; the 16-byte-aligned SSBO range bindings moved to 1024 alignment), ID-P8-14 and ID-P8-19 closed — Redmi passes on both backends for monolith / spawn, and Magma spawn no longer loses the device). Disposition "needs a ruling" = waiting for the user to decide; "can proceed" = a small fix that can start anytime and does not depend on another phase.

Debt Disposition
CI coverage: test.yml / apk.yml switch MOBILEGL_CI_DISAGGREGATED and lanes by branch name (feat/disaggregated, codex/fix-github-ci); this check covers 14 places in test.yml and 4 in apk.yml; the pull build has only G1 and the monolith comparison, no integration test gate (TextureRemintPullScenario was red on pull from P9 until P11 M before it was fixed); after merging into dev, the inproc acceptance and the two APK split arms are turned off by branch name, while build-linux-split / integration-split / retrace-split are unconditional Needs a ruling: whether to add a pull integration lane before merging; the trigger conditions of each lane after merging into dev (and delete the feat/disaggregated trigger while at it)
P9 handoff: TCP_USER_TIMEOUT = 5000 ms — the kernel disconnects when the client stops reading control for more than 5 s and there are pending log bytes to send; the blocking write in PublishSessionFault waits at most the same 5 s for a client that stopped reading (ID-P9-10). Risk scenario: FCL backgrounded and paused + cross-machine TCP Needs a ruling: recommend raising it to tens of seconds and making PublishSessionFault a bounded write; the user sets the value
P11 handoff (B0 F1): HyperOS freezes the entire uid of the server app when the screen goes off. B1 is already solved by a user setting (both the server app and the app hosting the client set battery to "unrestricted", ID-P11-16); what remains is keep-alive for the same-machine FCL use case Needs a ruling: document it only / detect the power-saving policy in the app and guide the user / do nothing
P11 handoff (B2): T0 was measured only on one Redmi with an Adreno; Mali and others have only shell-domain evidence from spike B (the server self-test falls back to T2 on unsupported devices). The mutation "release the import immediately on respecify" does not turn red on Espryt (the driver probably holds its own reference, unverified); release with a fence is kept Needs a ruling (limited by device rules): bring up a Mali and retest, or accept the self-test fallback long term
P11 handoff (B1): the apply-thread policy for external clients was measured only on one Redmi (two big cores); Magma openra stalls at the server on both data planes (~285 fps), and shared memory brings no gain Same as the row above
P12 not done: TLS (open question 21 at the time said "the token is enough; TLS is kept as a P12 open item"; P12 has closed) Needs a ruling: formally drop it, or keep it as an open item
MOBILEGL_IPC_IDLE_EXIT_S unresolved (the server already exits immediately on client EOF) Needs a ruling: recommend retiring it; after approval delete design/09-build-switches-counters.md:67 and the Config.h comments and so on
P10 handoff: GL_ARB_gpu_shader_fp64 is advertised according to the server's MOBILEGL_ADVERTISE_FP64, but fp64 narrowing is in the client's compilation; under tcp, when the server's environment differs the two disagree (the similar GL_KHR_parallel_shader_compile is already fixed; the approach is in CapsMirror.cpp:72-101, ID-P10-10) Can proceed (small fix)
P11 handoff: when client and server share a log prefix, the client opens <base>.server.log with "w" to write forwarded server logs (MobileGL/MG_Util/Debug/Log.cpp:89), truncating the server's own file; two processes on the same machine with the same prefix truncate each other the same way Can proceed (small fix)
P11 handoff (B1): when the session slot is held by a slow-starting program, a second client that sends Hello within 2 s gets a named Refuse{Busy}, and a slower one only sees the send fail (that path does not read the pending refusal); already written into the contract Can proceed (small fix)
P11 handoff (B1): after a session start failure the client also reports a misleading extra Fatal{CapsBeforeFirstSnapshot} (CapsMirror.cpp:247, predates B1; every rejected helper user sees it) Can proceed (small fix)
P11 handoff (B2): the handle arm's CPU reader lands queued resident writes before reading the adoption / T0 mapping — the split half is already implemented by P8-C (SplitHostBytesForCpuRead's T0 arm: land the write + glFinish, ID-P8-9), but the host has no T0 and could not prove red Needs device verification (Redmi Android integration test + static-peek)
P11 handoff (B2): when the server grants T0 but the client chose T2, every storage's map_persistent waits 2 s and then is refused by name (in production grant and caps agree; seen only under mutation) Can proceed (small fix: one "client does not want T0" hint per session)
P9 handoff: on the Espryt re-mint retain path, imageLoad occasionally reads an old value after a framebuffer clear (host 3/30, 0/30 after adding a barrier; TextureRemintPullScenario case C pins the barrier for now), suspected llvmpipe (ID-P9-11); seen once on the push monolith arm after P11 merged dev, and ImageBindableRemintScenario also pins the barrier (ID-P11-6) Can proceed (attribute on Redmi without the barrier)
P8 handoff (D): when the application omits glMemoryBarrier, neither arm has a dependency between compute writes and vertex shader reads (undefined by GL, but real applications rely on it); the per-round barrier cost of D on device is unmeasured; create-indirect (now the derived minecraft-1.21.1-neoforge-create-indirect-in-world-align1024, same content) cannot verify these two things (ID-P8-14); a fixture is needed for "a compute write command, no application barrier, no rewrite" Pending attribution (needs a new fixture)
P8 handoff (E): the driver-written mark is applied to the whole texture (GenerateMipmap also marks it); when the driver refuses reads, even the base level is refused by name, which is conservative; cross-format copy stores are not followed; a refusal is still a session Fatal (the reply state would have to change to answer GL_INVALID_OPERATION) Small fix (mark per level); the rest as needed
P8 handoff (B): PipeCalls.def:260 GenerateMipmap is still kWaitApplied; the reason for ruling 14 (CPU filtering touches the client shadow) no longer holds, so it can become kWaitNone Performance work (protocol behavior change, needs a separate ruling)
P8 handoff (C): server SSBO marking is over-approximate (every SSBO bound in the window is marked); a buffer that stays bound to an SSBO and is also used as a restart EBO is read back on every draw Performance work
P13 handoff (ID-P13-2, P14 update): Magma monolith record arm vs dev (pull) — traces are now largely caught up: rd12 83.8 vs 87.0 fps (−4%), openra 747 vs 293 (dev waits on the GPU there); P14's largest item is 553eb86d (texture-layer uploads no longer wait on the CPU for the GPU to drain, rd12 70→83). But still behind on FCL MC: monolith 171 vs dev 232 (−26%), inproc 195; the presentation thread's CPU is only about 2.8 / 5.8 ms of the frame, the rest is waiting — another wait different from the traces First item of the next phase: off-CPU profile of FCL Magma monolith (--trace-offcpu, the same method that found the upload wait; neither capture at P14 close caught a game frame), find that 3 ms wait; numbers in git history
P13 handoff (W9): cache capacity re-tuning P14 closed (readout): MOBILEGL_PIPE_STATS on rd12 / openra shows render-state CSO steady state mints 0 new per frame, Magma pipeline memo hit rate 99.0% / 92.7%, no cache thrash, P8 capacity kept Closed (W9 section, see git history)
P14 handoff: Espryt monolith record arm vs dev (pull) rd12 91.1 vs 115.2 fps (−21%); FCL MC 198 vs 229 (−13%). Render thread CPU per frame 11.56 vs 9.07 ms: client half +1.39 (validate 0.92: EmitGlobalConstants 0.17, EmitVertexElements 0.13, Tracker::Update 0.12, CopyField 0.10, validate itself 0.10, EmitVertexBuffers 0.07; verb port about 0.2), backend +0.45 (SyncNeccessaryTextures +0.14, SyncNeccessaryBuffers +0.08, AdoptUnchangedBufferSets +0.09, BindCurrentProgramWithResources +0.07, SyncCurrentProgramByHandle +0.05), driver +0.33, applier +0.07. Each item is below 2% of frame time; together they are the record arm's structural cost: pull's backend reads frontend objects by pointer at draw time, while push must detect change (tracker), serialize (emitter, uniform span), apply (applier), and then the backend resolves again by handle through the slot table, and because the backend cannot see frontend dirty bits it does a clean check for every bound object — tens of ns per step per draw, each a separate cold cache line, multiplied by 1471 draws/frame Next phase: per-(VAO, program) draw-packet cache (design draft (see git history), estimated to recover 1.0–1.6 ms/frame for rd12 Espryt monolith, about 91→100–106 fps); first prototype and measure only the client half
P14 handoff: Espryt monolith's driver item +0.33 ms/frame (2.9%), all inside glDrawElements, with the GL call combination the same as dev. simpleperf stat (whole run, render thread): feat executes 16.6% more instructions than dev, L1D refill 56% more, L2D 23% more (IPC 3.73 vs 3.86). Inference: the record arm's larger per-draw working set (record, applier state, slot table, twin) pushes the driver's state out of cache — this is a counter inference, not measured inside the driver Verify together with the draw-packet cache: measure L1D refill and driver ms/frame before and after landing; if the driver item does not drop, the inference does not hold, and investigate separately
P14 handoff (tested, not done): frontend change-epoch fast path for Tracker / residual — bump a context epoch at every DECLARE_GL_FUNCTION_END entry (except draw, glBindVertexArray, floating-point glUniform*), as well as handwritten entries and EGL entries; when the epoch has not moved, validate only recomputes the VAO / program-derived shutter (cap about 0.07 ms), then, after auditing which residual fields depend on VAO / program binding, skips the residual copy (0.15–0.25 ms total, 1.5–2%) Each is below the 2% threshold, and missing the bump at one entry renders stale state; merge into the draw-packet design (its §3 context epoch is exactly this), do not do it separately
P13 handoff (FCL soak, user ruling: FCL is not changed for now, and MobileGL does not work around it): FCL game process can die silently (exit SIGNALED status=34, SIGRTMIN+2): the JVM signal reset after renderer selection drops libcore's AsynchronousCloseMonitor handler, and FCL's okhttp/Okio watchdog then kills the process; renderer-independent (reproduced on P12 and P13 libraries, both backends; untested with other renderers). Soak: P13 library 30 runs (Magma 22 / Espryt 8) died 18 times, P12 library 10 runs died 2; a P12 / P13 alternating control run by run (same scenario, same network period) P12 4/10, P13 2/10, the timeline (Renderer: line to MobileGL's first line about 6.2 s, the late death fixed about 9.4 s after it) identical for both libraries, with no evidence that MobileGL raises the probability; all status=34, no tombstone, no kgsl; evidence and mechanism in git history fix belongs in FCL (save/restore libcore's SIGRTMIN+2 sigaction around JVM creation); left for the user
P8 handoff (MD): dev's RingAllocateSlow drains without limit on a context in the error state (hangs in glFinish on device) Small fix (dev)
P8 handoff: LogForwardChannel.APeerThatStopsReadingCostsWarnLinesNotTheCallersTime times out under load (twice), always passes when run alone Small fix (relax the deadline or isolate)
P8 handoff (SV): gen_pipe_dirty_surface.py scans integration test sources; a test member with the same name as a GLContext member (e.g. m_parameters) silently breaks its self-check; .Mip3DValidation. is a failure rather than a skip on lanes without the validation layer Small fix / CI record
P8 handoff (MF): near the two flush ladders, a few comments still name the old freeze / pin commits (5cb826b0, 3e298c9a) Documentation small fix
P8-0 handoff: SSIM < 0.99 already present in the device baseline — 1.21.11-main-menu (Espryt 0.890, Magma 0.165), derivative-main (Espryt 0.851); present on both arms Pending attribution
P12 not done: D8 window-kind whitelist — X11 / MetalLayer / Win32Hwnd / None are still accepted (SurfaceOpCodec.cpp:138-141), HandleFromToken casts the token to a pointer (ServerLoop.cpp:1228, via UnpackWindowHandle; whether downstream hands it to EGL was not traced to the end) Can proceed (Ph-class small fix)
P12 not done: the fixed landscape server window was not retested Can proceed (Redmi read-only check)
P11 handoff (M2, to dev): dev's DirectVulkan.SplitRecording. lane has no RESOURCE_LOCK, and its cases read a literal log path — under -j they may truncate each other; the copy on the P11 line is already fixed (the duplicate fix for Magma's empty uniform was synthesized into one entry in ID-P8-17) Bring it along on the next back-merge to dev
P11 handoff (M2): large layers beyond the stage chunk budget are sent as shards, and shards not covered by a write box still carry the whole box (the server needs it to assemble the layer image), which paints the shadow over places the GPU wrote; the fix needs a "locate-only" region form that both servers skip, control protocol revision +1 (split-only, predates P11) Small package or P8
P11 handoff (M2): uploads still have two lossy shapes, each logged once — when a layer's precise write boxes exceed 4096, it is sent covered by the storage's rectangle table; when an applier entry accumulates more than 4096 regions, they are merged into a union box. When the texture has GPU writes, both paint the shadow into the gaps Small fix, no trigger reported
P10 handoff (performance): on device, of the 19.4 ms per frame of tcp loopback rd12, ~11.2 ms is the producer parking in the stream transport (send + ring / stage / ack waits), credit waiting only ~0.2 ms (see git history §2, ID-P10-13) Performance work after the roadmap completes
P11 handoff (performance): on device with MC 26.3, split T2 relative to monolith adoption p99 Espryt +37–42%, Magma about 2.5×; part of that is thread placement — the server apply thread pinned to cores 6–7, the client GL thread mostly lands on slow cores, about 2.3× CPU per frame (see git history). Half of RSS is already delivered by B2 (T0): peak memory Espryt −41–42%, Magma −18–26% (ID-P11-17) Performance work after the roadmap completes (p99 and thread placement)
P11 handoff (B2, performance): adoption of glBufferStorage(NULL) first sends the entire zeroed storage once as resource_subdata (both T2 and T0; MC 26.3 8 storages, 441.5 MiB) Performance work after the roadmap completes
P12 not done: DirectGLES g_Display / g_Surface / g_Context are still globals (not needed when there is one session per process); full handling of the cached-app freezer (the docs never defined it); multiple contexts; the server window does not forward input Wait for the need for a second session / second context
P9 handoff: Magma sends a whole-buffer OnGpuWritten for writable SSBOs / texel buffers / XFB targets on every draw (7,093 on create-indirect's first frame); the client already marks the same set itself, redundant and harmless; OnMipLevelsGenerated and OnCapsInvalidated still have no producer. OnTextureWriteback also has no producer, but do not delete it: the CPU three-channel mip fallback needs it (CONTRACT-P5B.md:255) Future narrowing / cleanup candidates (ID-P9-7)
Out-of-tree scripts: the census runner, wsl_p5_gate.sh, and so on are in ~/w7/notes/; a git merge does not propagate them; the de facto gate scripts are in git history Put them in the repository when needed

Closed historical debts (P5's 27 wrong answers, rsp residual reads, P5b's inproc dependency, the ABI fingerprint, the default staging being unable to hold a 128 MiB upload, the 184-symbol ratchet CI gate) and the full debt table of that time are in git history.