mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-10 03:23:23 +09:00
Two things land together: the plan and contract draft P6 needs before it starts, and the
working notes that until now existed on exactly one machine.
1. P6's plan and contract draft (neither started; not one line of code)
docs/Disaggregated/P6-SPAWN-PLAN.md the package plan
docs/Disaggregated/P6-CONTRACT-DRAFT.md the contract draft (moves to
MG_Remote/CONTRACT-P6.md when c6 lands)
The three findings that mattered, all written into the documents:
a. P6 is SMALLER than its roadmap cell suggests. The transport primitives are already in
the tree and already tested: SocketDoorbell including hangup detection and the two
lost-wakeup fences (Doorbell.cpp:211-360, four cases in FdPassingTest), SCM_RIGHTS fd
passing, ShmSegment::Adopt, and the SurfaceOp / WindowKind schema already defined in
protocol.fbs. inproc uses a real second shm mapping rather than an alias, and
SessionRings.h:22-28 says that was done so today is not the first time it runs. P6 is
assembly plus a control plane plus a process, not "write a socket transport".
b. The evidence for "P6 is only a transport swap" has EXPIRED. It was bought by P5c, whose
audit found 59 direct memory accesses in a tree that already looked clean. P5e changed
the tree again. So the first package, a6, is a read-only audit that writes no code, and
every contract row that depends on it is marked PENDING a6 rather than decided in
advance.
c. P6 does not get a game running on the phone. ANativeWindow* is meaningless in the child,
and protocol.fbs:186-196's own comment says Android transfers the window out of band -
that band is P12. P6 lands pbuffer / surfaceless / offscreen, which is what HeadlessGL,
the split-equivalent lane and trace replay need, and which is exactly what P6's own exit
gate measures. A real window reaching the server is a named refusal. This gets its own
section because "P6 is done" would otherwise read as "the game runs now".
The contract adds rule G: a role may not name a process-local handle. It extends P5c's
rule E (a role may not name the other role's memory) from memory to identity - EGLDisplay /
EGLSurface / EGLContext / ANativeWindow* / fd number / pid / mapped address either cross as
a token this contract defines or they do not cross, and a descriptor crosses only through
SCM_RIGHTS, where the kernel renumbers it.
What P5e left for P6 gets its own section. The latch semantics are already designed
(ARCHITECTURE.md:504) and are copied unchanged. What is new is that after run-ahead the
client no longer waits while the peer process can DIE: the client holds records that were
published and will never be applied, and Android's freezer suspends the child without
closing anything. So slow and dead must be distinguishable WITHOUT a timeout threshold.
That is P6's only new design; everything else is carriage. It shares a predicate with E1's
outstanding re-specification (ID-122), and the two should be designed together.
Two gates carried over from P5e's lessons: G2 requires integration-spawn's test-name set to
match integration-split's name for name, because a differing set means the lane is quietly
running less; and the arm-proof gate requires every entry to record the child pid and
transport=spawn in its OWN private log - ID-124 established that this kind of false green
really happens, and a spawn lane that actually ran monolith would pass every other gate.
S2's shape must be settled before it is written, and the document says why: E1 is the
cautionary case.
2. The working notes move into the repository (docs/Disaggregated/notes/, 415 .md files)
ROADMAP / CURRENT_STAGE_PROGRESS / MEASUREMENTS cite ruling numbers, audit line numbers and
the provenance of gate figures from ~/w7/notes/, a directory that exists on one machine and
is under no version control. A record cited hundreds of times that lives only locally is not
a record, so it moves in whole, with its directory structure intact.
Only .md moves. Scripts, run logs, census and gate result JSON, patches, APKs and nm dumps
stay where they are: they are evidence DATA rather than documents - large, regenerated per
run, and mostly carrying absolute paths and device serials that mean something only on the
machine that produced them. The mapping and this split are written in
docs/Disaggregated/notes/README.md.
Two exceptions are recorded there too: P6's BRIEF has been promoted to a first-class
document and keeps no copy under notes/, so the two cannot drift apart; and recovered/ holds
material salvaged from failed workflow runs, which may duplicate the like-named phase
directories and is kept because a few of those were the only complete version at the time.
CI's citation lint takes docs/Disaggregated/*.md only (non-recursive), and notes/ is
deliberately outside it: those notes' file:line citations were written against their own
code heads, and resolving them against today's HEAD would fail wholesale - which is not an
error, it is their correct state as a historical record. To check one, use the revision it
declares (--rev).
3. Inconsistencies fixed in passing
- README.md's status line still said P5e was in progress while the stage table already said
closed.
- CURRENT_STAGE_PROGRESS's next-step item 1 still listed the exit gate as pending, though
(a) and (b) were run in the previous commit; rewritten to closed plus the one item that
actually remains (E1).
- ROADMAP's P6 row still had the pre-phase plan in three of its cells; it now carries the
package order, the scope boundary and the two new gates.
Checked with check_doc_citations.py: 125 citations across docs/Disaggregated/*.md, 0 problems.
276 lines
24 KiB
Markdown
276 lines
24 KiB
Markdown
# P3a integrator decisions (feat/disaggregated, 2026-09-08)
|
|
|
|
## ID-1 The base ref is `44c2b5cf`, not the brief's `55d2af9b`
|
|
`BRIEF-P3A.md` was verified at `55d2af9b`. P2 landed four more commits before P3a started: `c73ae7d4` (pins
|
|
`MOBILEGL_PIPE_PUSH=0x7f` in the itest Handles lanes: `MG_IntegrationTest/CMakeLists.txt`), `a9778eaa` + `738b289d`
|
|
(the ABA generation-coverage fix: `MG_Backend/DirectVulkan/Renderer/{MagmaPipeArms.h, VertexInputStateFactory.cpp,
|
|
VulkanRenderer.cpp}`, `MG_IntegrationTest/Scenarios/HandleRecycleScenario.cpp` (comment), `MG_Test/Pipe/CMakeLists.txt`
|
|
+ new `MG_Test/Pipe/MagmaPipeIdentityTest.cpp`), and `44c2b5cf` (docs only). **Every P3a tree branches from `44c2b5cf`**
|
|
and `$BASE` = `44c2b5cf` in every command the brief writes as `55d2af9b`. Brief line numbers are still exact for every
|
|
file except those seven; a package touching `HandleRecycleScenario.cpp`, `MG_IntegrationTest/CMakeLists.txt` or
|
|
`MG_Test/Pipe/CMakeLists.txt` re-opens the file before editing. The `~/w7/p3a-before-*` baselines were captured at
|
|
`44c2b5cf` (2482 ctest names; pull lib; `RenderStateImpl` sha `d8fd1c48...`).
|
|
|
|
## ID-8 Landed so far (feat/disaggregated in ~/w7/pipe, pushed to origin)
|
|
- contract c0: `39722687` (tag `p3a/contract`, packages branch here) rebased onto the P2 docs commits as
|
|
**`e01c0ccc`** — pull symbols 0/0/0/0, unit 1571 x 3, +5 test names. Package branches rebase onto
|
|
`refs/heads/feat/disaggregated` (spell branch refs fully: the tag makes `p3a/contract` ambiguous);
|
|
the duplicate c0 patch drops out of the rebase automatically.
|
|
- contract review v1: ACCEPT WITH MINORS; M1 (Coverage.def target split omits DispatchIndirect/Query) and
|
|
item 9 (SetVertexBuffers Start+Count policing) go to wire's rework; M2 (GetOrCreate(MGPipeHandle) adopts a
|
|
stale generation) goes to espryt's e1; item 11 (0x7f-pinned itest lanes need a 0x1ff arm) goes to gates.
|
|
|
|
- wire v1: db0c93bb / cede041d / e9b4a263 on p3a/wire; review v1 = REWORK (C1 records wiped on every
|
|
make-current via Tracker.h:192-195's Reset; C2 serials zeroed on reset; M1; c2 zero test coverage; the
|
|
PipeLiveHostWrites control; RecordAt bound; Blob rule). Rework in flight with a **granted waiver** to touch
|
|
Tracker.h:192-195 minimally if the fix needs it (B rebases across it).
|
|
- espryt v1: 9ae4ec09 / de13c588 / 855272e5 / 469f78b8 / a9a1d0eb / 203120fa on p3a/espryt; legacy arms
|
|
461/461, default arm 202/461 red all attributed to the stub applier (expected until wire+client land);
|
|
review v1 in flight. Accepted-in-principle deviations: g_pendingFetchBaseInstance/ScopedFetchBaseInstance
|
|
stay under MOBILEGL_PIPE_LEGACY_MEMOS (deleting them is a G1 break, so C.2's "grep empty" line is not
|
|
achievable in P3a - D.5 must say so); MGPipeSetResourceOps installed from RegisterBufferBackendOps;
|
|
the fp64 stream's SyncGpuWrites stays frontend-side (D-N) - DoublePrecisionScenario is a post-rebase watch item.
|
|
espryt review v1 = REWORK: C-1 the draw-clean test replaced IsMapped() with HasLiveHostWrites (pinned false
|
|
=> mapped non-adopted buffers never resync), C-2 a cached raw hostBytes base dangles after adoption/resize
|
|
(fp64 narrowing UAF, undeclared pool gate), majors: contract M2 unaddressed, attribute walk bounded by
|
|
AttributeCount drops the disable arm, bit 8 without bit 7 advertised but non-functional, PipeLegacyMemos
|
|
ignored by the new arms, memo safety silently depends on wire's serial rule. Rework in flight (rebases onto
|
|
5cb826b0 first, ID-9/ID-10/ID-11 applied).
|
|
|
|
## ID-8b wire integrated: feat/disaggregated = `12e6bfcf` (pushed)
|
|
wire v2 (six commits: c1 45c8f1a8, c2 6eb0e675, c3 355c60b9, then the rework 56366331 / e6452ce9 / 12e6bfcf)
|
|
rebased onto 5cb826b0 and fast-forwarded; pull symbols 0/0/0/0 against the 5cb826b0 baseline, unit 1599 x 3,
|
|
G2 0, G14 0 removed / +17. Applier rule from here on: object records survive make-current; only
|
|
MGPipeApplierReleaseObjectRecords (unwired in monolith) drops them; refusals are counted; serials only advance;
|
|
one Blob rule (0 = not declared). Client's rework runs against this tree.
|
|
|
|
## ID-8d client integrated: feat/disaggregated = `31e370be` (pushed)
|
|
Between wire and client two version bumps landed on the branch (42d43af2 gradle 26.09, b9eaa474 CoreVersion
|
|
26.9), so the G1/G14 baseline was re-captured at b9eaa474 before the merge. client v2 (eight commits, rework
|
|
d9bde131 / f11e78b0 / 0c555605 / 31e370be) fast-forwarded; pull symbols 0/0/0/0, unit 1617 x 3, G2 0,
|
|
G14 0 removed / +18; client's own tree had integration-gpu 920 x 3 arms, integration-verify 832, retrace
|
|
79/79 verify-armed zero divergence. espryt v3 (verification round on this tree) in flight; gates integrates
|
|
after espryt.
|
|
|
|
## ID-8e all four packages integrated: feat/disaggregated = `3e298c9a` (pushed)
|
|
espryt v3 (`3c55e027` + the integrator's BufferTest fixture commit `83302ca2` — ID-14 below) then gates v2
|
|
rebased and fast-forwarded (`3e298c9a`). On the finished tree: pull symbols 0/0/0/0 vs the b9eaa474 baseline,
|
|
G5 ten functions byte-identical vs 5cb826b0 AND vs 44c2b5cf, G5 self-test, unit 1619 x 3, G2 0, G14 0 removed
|
|
/ +58, HandleRecycle (verify) 60/60, mpr + ResourceSubsystemControl (push) 34/34, G7 tripped naming IsBgra.
|
|
espryt v3's real-path round found and fixed three seam defects (vertex buffer resolved by GL binding point
|
|
instead of attribute index; a stale descriptor consulted for the shadow on full re-upload; the shadow base not
|
|
published for a lazily twinned store) - the verification round was load-bearing. In flight: the full
|
|
five-part gate (three retrace sweeps) on ~/w7/pipe, the final whole-diff review (5cb826b0..3e298c9a), the
|
|
pull/push trace APKs for the D.4.2 device A/B, and the P3a docs.
|
|
|
|
## ID-14 Ownership waiver: `MG_Test/Buffer/BufferTest.cpp`'s fixture
|
|
C.5 gives that file to nobody. Under a push build the backend installs both `BufferBackendOps` and
|
|
`MGPipeResourceOps` at bring-up, so `ScopedBackendOps` (which scoped only the former) let 26 of the 86
|
|
BufferBackendOps dispatch cases route into the pipe. The integrator landed the one-scope fix espryt-v3 §7
|
|
measured (`83302ca2`): the fixture now saves/nulls/restores the pipe table exactly as ResourceEmitTest's
|
|
ApplierGuard scopes the applier. It weakens nothing (the pipe-side dispatch has ResourceEmitTest's own
|
|
coverage). Follow-up for a later phase: a pipe-shaped mock so the same 86 assertions run over the handle path.
|
|
|
|
## ID-15 Final whole-diff review = REWORK; C-2 ruling supersedes ID-13's "outside any #if" sentence
|
|
Full five-part gate on 3e298c9a: all green (G1 0/0/0/0, G5 byte-identical vs 44c2b5cf and 5cb826b0 + self-test,
|
|
HandleRecycle 60/60, unit 1619 x 3, G2 0, G14 0/+58, integration-gpu 958/958 x {0x1ff, 0, 0x7f} + the
|
|
ESPRYT_DISABLE_INVALIDATE_FLUSH arm, buffer/VAO family 202/202, g7 + G7 tripped, CsoContentAddressing +
|
|
ResourceSubsystemControl 10/10, controls 64/64, integration-verify 842/842 zero Fatal, retrace verify 79/79
|
|
armed zero Fatal, retrace push 79/79). The G3b named sub-sweep matched 0 cases because `retrace_gate.py
|
|
--only` is a regex and the gate script passed a comma list (fixed in wsl_p3a_gate.sh; the five cases passed
|
|
inside the full sweeps). final-review-v1: C-1 the client-minted VertexElementsCso slot has no backend-neutral
|
|
death path (Magma installs no death ops: leak per VAO at 0x1ff, Fatal past 65536 slots); C-2 FlushPendingRangesNow
|
|
sits inside the pull-only #else, so push builds compile only FlushPendingRangesFrom and G5's text hash does
|
|
not cover the shipping ladder. **Ruling for C-2:** FlushPendingRangesFrom becomes the ELEVENTH G5 row with
|
|
its own baseline sha (captured at 3e298c9a); FlushPendingRangesNow stays byte-identical where it is (G1 is
|
|
what protects the pull build); the two-arm shape is stated at Managers.cpp:1127-1138. M-3 (the fp64 stream's
|
|
dropped SyncGpuWrites site) is a RULED deviation for P3a. The rework runs on ~/w7/p3a-final (branch p3a/final
|
|
from 3e298c9a); it lands as the last P3a commits. The device A/B and the bench are recorded against the
|
|
3e298c9a APKs (the rework is lifecycle/seam correction, not a cost change) - the docs say so.
|
|
|
|
## ID-9 dev merged mid-phase: feat/disaggregated = `5cb826b0` (pushed), baseline re-captured there
|
|
`dev@9eae9858` (two commits past our P2 base: `d7655247` rebinds VAOs when an adopted store is respecified -
|
|
a 5-line fix in Managers.cpp's immediate retire path - and `9eae9858` adds the persistent-buffer ordering
|
|
POST probe) was merged into `~/w7/pipe` as `5cb826b0` right after the contract, so every remaining package
|
|
rebases across it once. **The `~/w7/p3a-before-*` baseline is now the pull build of `5cb826b0`** (2502 ctest
|
|
names, 1582 unit); G1 for every later package is measured against that. Consequences: espryt's rebase
|
|
conflicts in Managers.cpp and the d7655247 fix must be present in BOTH the legacy and the handle arm of the
|
|
respecify/retire path (the handle arm duplicates that core); gates' rebase conflicts in
|
|
LargeArenaAdoptionScenario.cpp (dev added cases there, gates added the mpr assertions and the second arena) -
|
|
resolve by union, keep every test name from both sides. wire and client do not touch those files.
|
|
|
|
## ID-10 Ownership grant: the three `*BaseInstance` draw entry points in `MG_Impl/GLImpl/GL_Drawing.cpp`
|
|
The brief's ownership table gives `MG_Impl/GLImpl/**` to nobody, yet D-H2 needs `MGPipeSetPendingBaseInstance`
|
|
called from the three `glDraw*BaseInstance` entry points (client-v1 finding 1: no call sites, so the emitted
|
|
BaseInstance is always 0). Package B's rework is GRANTED those three one-line call sites (and nothing else in
|
|
GL_Drawing.cpp); the reset in `MGPipeLeaveVerb` stays B's. Until they land, espryt's handle arm reads a
|
|
`VertexFetchBaseInstance` of 0 - the DrawParameters / VertexAttribBinding base-instance scenarios are the gate
|
|
that must go red without the call sites and green with them, and the integrator checks both directions once
|
|
on the finished tree. client v1: 73bab3d6 / 1ae6b4f4 / 71805d59 / a0ac79cc on p3a/client; review v1 in flight.
|
|
|
|
## ID-11 G5's byte-identical set is ten functions
|
|
The brief's G5 row names nine (`IsPoolable`, `EnrollIntoPool`, `AcquireFromPool`, `TrimBufferPool`,
|
|
`ClearBufferPool`, `ProcessDeferredBufferReleases`, `CreateRingStorage`, `RingAvailable`, `RingAllocate`) but its
|
|
text (BRIEF-P3A.md:420, :1708) twice calls `FlushPendingRangesNow` G5-protected and names it as the only
|
|
mitigation of the tier-drain p99 risk. Decision: **`FlushPendingRangesNow` is the tenth**. The handle arm must
|
|
call the untouched function; a copy under `#if MOBILEGL_PIPE_PUSH` is a G5 break espryt's rework restores.
|
|
gates v1: 1ef91dec / 588d25e9 / 80f6bf1b; review v1 = REWORK (four majors: three CSO stats lanes still pinned
|
|
0x7f, the ResourceSubsystemOn/Off entries unreachable from CI's -R, the G7 script not rebuilding on its
|
|
"did not trip" exit, FlushPendingRangesNow missing from G5); rework in flight, rebasing onto 5cb826b0 first
|
|
and undoing the second-arena workaround that d7655247 makes unnecessary.
|
|
|
|
## ID-12 client review v1 = REWORK; cross-package items
|
|
B-C1: Tracker.h:373 zeroes m_pendingBaseInstance in Reset() (called on every make-current) - delete the line.
|
|
B-C2: no re-publication path for resource records after MGPipeApplierReset - **resolved together with wire's
|
|
rework C1**: the applier keeps resource/vertex-elements records across make-current and clears them only at
|
|
context destruction; the client therefore needs no re-publication on FreshlyPrimed, but must state that as
|
|
the rule (not "absence as policy") and cover context destruction (ResourceDestroy from ~BufferObject is the
|
|
only path). The client rework starts after wire-v2.md exists and reads it first.
|
|
Majors for the client rework: the three call sites at GL_Drawing.cpp:662/684/713 (ID-10); Acquire mutating the
|
|
global slot allocator on Espryt's off-thread SubData path; the sampled BindMask's DSA hole; the absent
|
|
UnmapPersistent producer (record it or add it). Cross-package: the `hostBytes` base-vs-base+offset mismatch -
|
|
B is brief-conformant, **espryt must change** (goes into espryt's post-rebase verify round, ID-13 when opened).
|
|
|
|
## ID-13 G1 vs G5 on `FlushPendingRangesNow`: one untouched definition, a separate handle-arm ladder
|
|
gates v2 (`2bafb316`, 8 commits on 5cb826b0; rebased clean, D6 undone, M1-M4 closed, G5 = ten functions) reports
|
|
G5 rc 2 against espryt (`cdbd5535`): espryt's push arm redefines `FlushPendingRangesNow` as a 3-line forwarder
|
|
onto a new `FlushPendingRangesFrom` ladder (Managers.cpp:1051-1127), the original body living only in the
|
|
`#else` copy. Decision: **`FlushPendingRangesNow` is defined exactly once, outside any `#if`, byte-identical to
|
|
5cb826b0** (that satisfies G1 for the pull build and G5 for the text). The handle arm gets its own
|
|
`FlushPendingRangesFrom(...)` under `#if MOBILEGL_PIPE_PUSH` that takes the record/twin instead of the frontend
|
|
object; duplicating the tier ladder there is accepted for P3a (the same shape espryt already used for the
|
|
respecify core; the legacy copy retires at P13 - ARCHITECTURE.md:367). The pull arm never calls the new one.
|
|
A shared template over an accessor interface is NOT acceptable: it resizes the pull symbol (G1). espryt's
|
|
post-rebase round applies this; gates' G5 must then be rc 0 against espryt's tree.
|
|
|
|
## ID-8c espryt v2 = `6a1a9bc7` (16 commits on 5cb826b0), gates v2 = `2bafb316` (8 on 5cb826b0)
|
|
espryt v2: rebased onto 5cb826b0 (trap: the three-way merge put d7655247's ++g_bufferBackendIdGeneration into
|
|
the legacy arm only; fixed, both arms symmetric), C-1/C-2/M-1..M-5 closed, ID-11/ID-13 satisfied (one
|
|
definition of FlushPendingRangesNow, ten byte-identical), legacy arms 463/463, default arm 204/463 red with
|
|
the identical failing set before and after (stub-applier attribution still expected until client lands).
|
|
Next for espryt: after client integrates, a verify round on the rebased tree (default arm, buffer/VAO family,
|
|
DoublePrecision, base-instance scenarios both directions per ID-10, retrace), then a focused re-review.
|
|
|
|
## ID-2 Integration order: contract -> wire -> client -> espryt -> gates
|
|
The brief's D.1 order with `wire` inserted after `contract`: `client`'s emissions land in the applier's records only
|
|
once `wire`'s apply bodies exist, and `espryt` reads those records. `wire` is behaviour-neutral on its own (nothing
|
|
registers `MGPipeResourceOps` until `espryt`).
|
|
|
|
## ID-3 Tool ownership
|
|
`~/w7/notes/tools/wsl_p3a_gate.sh` and `p3a_ab.sh` are written by the integrator, not by package D; package D's
|
|
deliverables are the two `scripts/p3a_*.sh` in the repo, the scenarios, the itest CMake rows and `test.yml`. Tree
|
|
creation is `wsl_tree.sh p3a <slug> <base> [verify]`, integration `wsl_integrate.sh p3a <slug>...` (generalised P2
|
|
helpers; the phase is a parameter, not a copy of the script).
|
|
|
|
## ID-4 Models and rounds
|
|
Package agents and reviewers run on opus (user rule 2026-09-08: fable only for genuinely hard single items). One
|
|
adversarial review per package, at most two rework rounds; declared minors do not block integration.
|
|
|
|
## ID-5 Durable locations
|
|
Brief `~/w7/notes/p3a/BRIEF-P3A.md`; scouts `~/w7/notes/p3a/scout-*.md`; package results and reviews
|
|
`~/w7/notes/p3a/p3a-results/<package>-v<N>.md` and `<package>-review-v<N>.md`; A/B artefacts `~/w7/notes/p3a/ab/`.
|
|
Package logs under `~/w7/p3a-<slug>-*.log` are deleted by their owner when the round ends.
|
|
|
|
## ID-6 Performance is recorded, not gated (user, 2026-09-08)
|
|
Part 4 of the five-part gate and `ROADMAP.md:19`'s "MC 26.3 在 Adreno 上 p99 不变" are measure-and-publish items
|
|
against P2's pull baseline (`MEASUREMENTS.md` §10-§12). Parts 1, 2, 3, 5 stay hard gates.
|
|
|
|
## ID-7 Working over UNC and WSL
|
|
Package agents edit their worktree through `//wsl.localhost/Arch/home/swung/w7/p3a-<slug>/...` with the Read/Edit/Write
|
|
tools (file writes work; `mkdir` does not - create directories from a WSL script). Builds and tests run through a script
|
|
file: write `<scratchpad>/wsl/<name>.sh` (LF endings) and run
|
|
`MSYS_NO_PATHCONV=1 wsl.exe -d Arch -- bash /mnt/c/<scratchpad path>/wsl/<name>.sh`; never pass `~` or `$vars` inline to
|
|
`wsl.exe`. A build or test run longer than ~8 minutes is launched with `setsid nohup ... &` inside the script and polled
|
|
through its log.
|
|
|
|
## ID-16 CI reds on 42d43af2 / b9eaa474 / 31e370be are GitHub artifact-download flakes
|
|
Every failing job is a `retrace`/`retrace verify` matrix entry whose "Download Linux runtime" / "Download trace
|
|
fixture" step died with `digest-mismatch` and `Artifact download failed after 5 retries`; no build or test
|
|
step ran red. 12e6bfcf (wire) was green on the same tree family. The failed jobs of the 31e370be run were
|
|
re-run; 83302ca2 and 3e298c9a are queued behind them. A red of this shape is not a code signal (the user's
|
|
rule: only real retrace reds after a successful download matter).
|
|
|
|
## ID-17 P2's device A/B APKs were unoptimised; the Release baseline of record is P3a's pull arm
|
|
The P3a pull APK's libMobileGL.so (Release, arm64) is 15.5 MB with a 9.4 MB .text; the P2 A/B's pull APK
|
|
(`~/w7/notes/p2/apk/trace-pull.apk`) is 43.2 MB with a 21.8 MB .text, same clang 18.0.4, no .debug_info in
|
|
either - a 2.3x larger .text is an unoptimised (Debug-flavour, -O0) build, and it replays 26.3 on the Oppo
|
|
at 42 ms/frame CPU where the Release build takes 9.7 ms. So MEASUREMENTS.md §10's absolute numbers and its
|
|
+8-18% deltas are -O0 readings (the tracker's inline-heavy code pays most at -O0). Decision: the P3a A/B on the
|
|
3e298c9a Release APKs is the two-device baseline of record; its pull arm is symbol-identical to the P2-era pull
|
|
path (G1 across P3a; only d7655247's 5 lines differ from 44c2b5cf). To re-derive P2's own cost at Release, a
|
|
supplementary arm runs the SAME push APK with `--env MOBILEGL_PIPE_PUSH=0x7f` (P2 subsystems on, P3a off) =
|
|
the device-side T2 (`p3a_ab_7f.sh`, nofinish only, its own reboot-clean session). The docs get an erratum on
|
|
§10 and the corrected table; the user is told that the "~10% is acceptable" call was made on -O0 numbers.
|
|
`wsl_build_trace_apks.sh` prints the lib size so an -O0 APK can never pass unnoticed again (Release .text ~9.4 MB).
|
|
|
|
## ID-8f final rework integrated: feat/disaggregated = `c20e2f2b` (pushed) = the P3a landing hash
|
|
p3a/final (12 commits on 3e298c9a, final-v2.md) fast-forwarded: pull symbols 0/0/0/0 vs b9eaa474, G5 eleven
|
|
functions byte-identical vs 3e298c9a AND the ten vs 5cb826b0, unit 1622 x 3, G2 0, G14 0 removed / +69,
|
|
HandleRecycle+VertexElements+Leak (verify) 76/76, Magma CrossFrameBuffer verify 13/13 locally. Open: the
|
|
CI-only teardown `double free or corruption` on DirectVulkan.Verify.CrossFrameBufferScenario.{Vertex,Index}
|
|
CopyBufferSubData (3e298c9a run and its re-run; ASan reproduction in flight on a private worktree) - whether
|
|
c20e2f2b's lifecycle fixes change it is answered by c20e2f2b's own CI run. Docs: P3ALANDHASH -> c20e2f2b;
|
|
the device A/B and the bench remain recorded against the 3e298c9a APKs (ID-15/ID-17).
|
|
|
|
## ID-18 The CI-only teardown abort is a static-destruction-order UAF at exit; fix = never-destroyed singletons
|
|
asan-doublefree-v1: `exit` -> `PipeInputs::~PipeInputs` (namespace-scope `gPipeInputs` holds a
|
|
SharedPtr<VertexArrayObject>) -> `~VertexArrayObject` -> `~BufferObject` -> `MGPipeEmitResourceDestroyAndFree`
|
|
-> `MGPipeSlotAllocator::FindByLifetimeId` on a hash table already freed by `~MGPipeSlotAllocator`
|
|
(`MGPipeSlots()` is a Meyers singleton constructed at the first buffer, so it dies first). Every case executes
|
|
the chain; only when the freed table still resolves does `Free()` write freed vectors and glibc reports
|
|
`double free or corruption` - CI's allocator layout did, ours did not (native repro: `GLIBC_TUNABLES=
|
|
glibc.malloc.tcache_count=0` makes exactly the two CI cases fail on c20e2f2b and none on the fix). Fix
|
|
(p3a/asan, rebased onto c20e2f2b as d54ec57a): `MGPipeSlots()`, `MGPipeResourceTrackerInstance()` and
|
|
`g_applier` become never-destroyed (heap-constructed, intentionally leaked at exit); the C-1 rework's second
|
|
reaching path (`MGPipeEmitVertexElementsDestroyAndFree` from `~VertexArrayObject`) is covered by the same
|
|
change. Integrated after the P3a bench finishes reading pipe's libraries.
|
|
|
|
## ID-19 P3a DriverBench (desktop, c20e2f2b libs) - recorded, not gated
|
|
mc_vanilla_draw ns/draw: Espryt pull 5115 / push(0x1ff) 6162 / push(0x7f) 5463 / push(0) 5693; Magma pull 17099 /
|
|
push 17709 / push(0x7f) 17287 / push(0) 17739. T1 = +1048 (+20.5%) / +611 (+3.6%); T2 (0x7f = P2's boundary) =
|
|
+349 / +189; **P3a itself = +699 / +422 ns/draw** - the largest boundary cost so far (per-draw vertex-input emission +
|
|
applier record + Espryt's record walk; Magma's share is pure client emission until P7). blend-toggle +5.2% / +2.8%;
|
|
pass switch ~0; CSO content addressing ~0. Goes into the optimisation-phase list (per-draw suppression of
|
|
unchanged vertex-input sets; in-place applier record updates). Device side (Release APKs, 3e298c9a): Oppo 26.3
|
|
Espryt +8% / Magma +10%, rd12 +30% / +27%, sodium ~0 (sub-ms frames), create-instancing is a 2-frame fixture
|
|
(not a benchmark). 0x7f arms and the Xiaomi pass in flight.
|
|
|
|
## ID-20 CI Test lane green at c20e2f2b
|
|
The lifecycle changes of the final rework moved the allocator layout enough that CI's two teardown aborts
|
|
(3e298c9a) no longer surface at c20e2f2b - not a fix, a layout change; the systematic exit-order closure
|
|
(ID-18 + the 21 knob-only cases) lands as the last P3a commits on p3a/exit and is proven with
|
|
GLIBC_TUNABLES=glibc.malloc.tcache_count=0 on both lanes before the docs push.
|
|
|
|
## ID-21 exit-order closure integrated: feat/disaggregated = `fde5fda3` (pushed) = the P3a landing hash
|
|
p3a/exit (6515c8e6 leak-at-exit storage for the four static PipeInputs holders; fde5fda3 the four remaining
|
|
MGPipe singletons never-destroyed) on d54ec57a, fast-forwarded. On pipe: pull symbols 0/0/0/0, G5 eleven
|
|
byte-identical, unit 1622 x 3, G2 0, G14 0/+69, and with GLIBC_TUNABLES=glibc.malloc.tcache_count=0
|
|
integration-verify 844/844 and push integration-gpu 966/966. Follow-up outside P3a: IntegerBorderColorScenario's
|
|
stack-buffer-overflow (pre-existing test bug, ASan). Docs: landing hash -> fde5fda3.
|
|
|
|
## ID-22 CI at fde5fda3: every build/test job green; the run is red only in "remove artifact clutter"
|
|
Its "Delete intermediate Linux retrace artifacts" step died on a GitHub HTTP 504 from `gh api --method DELETE`
|
|
(housekeeping after all tests passed). Not a code signal. The Test lane's authoritative jobs (pipe-gates,
|
|
include-graph-check, test, integration, build-linux-verify, integration-verify, retrace, retrace-verify,
|
|
monolith-symbol-report) all succeeded on the P3a landing hash.
|
|
|
|
## ID-23 rd12 on Magma on the Xiaomi aborts on every arm (pull included): pre-existing, excluded from the table
|
|
scudo map error inside a calloc from libMobileGL (frames 0x818b14 / 0x7e2c44, stripped) seconds after start,
|
|
with 6 GB available - a giant/negative allocation on the Adreno 830 + Magma path for this fixture, not P3a's
|
|
(the pull build is symbol-identical to the pre-P3a path). The same fixture runs on the Oppo/Magma and on the
|
|
Xiaomi/Espryt. Task chip opened (symbolize + fix). Side effect: the GPU pwrlevel pin on the Xiaomi resets after
|
|
the crash (pin_device reports "range 2..5"), so the Xiaomi's sodium and create-instancing rows after rd12 carry
|
|
a DRIFT verdict on both arms (still paired). The P2 -O0 Xiaomi table did not include rd12, so nothing is lost
|
|
against P2.
|
|
|
|
## ID-24 P3a closed: docs at `37da3c3a` (pushed); device A/B complete on both devices, three arms
|
|
Release APKs from 3e298c9a; pull / P2-only (0x7f) / P3a (0x1ff), nofinish primary. P2's boundary at Release =
|
|
+6-12% p50 on both devices and backends; P3a adds ~0 on 26.3 and sodium but +17-19 points on rd12 (Espryt
|
|
+30%, Magma +27% total) - per-draw vertex-input emission on VAO/buffer-heavy frames; MC 26.3 p99 on Adreno
|
|
pull 25.46 -> P3a 26.32 ms (+3.4%). mpr on device: 26.3 = 8 per run, sodium 1. Excluded: Xiaomi rd12/Magma
|
|
(pre-existing abort, ID-23), create-instancing (2-frame fixture), sub-ms sodium rows (noise). Artefacts:
|
|
~/w7/notes/p3a/ab (60 benchmark.json) and ab7f (15), ab3-final.md; bench ~/w7/notes/p3a/bench/driverbench.md.
|
|
Next: P4a (handle wave 2: FBO / texture / sampler / program). Optimisation-phase list carries: the per-draw
|
|
vertex-input emission cost, IntegerBorderColorScenario's ASan finding, rd12/Magma/Adreno abort, the
|
|
harness pidof single-sample kill, create-indirect on dev.
|