diff --git a/docs/Disaggregated/MEASUREMENTS.md b/docs/Disaggregated/MEASUREMENTS.md index ab09a2ea..f393761e 100644 --- a/docs/Disaggregated/MEASUREMENTS.md +++ b/docs/Disaggregated/MEASUREMENTS.md @@ -637,7 +637,7 @@ P4a 的契约改了七次(`c0b`…`c0g`),外加一轮缝类审计与一轮 ## 26. P5 五部分门(joint `e61d0012`)与 landed quick gate(`eec0e836`) -P5 的完整记录来自 `~/w7/notes/p5/p5-results/joint-v1.md` §2 与 ID-63;脚本按 **1 → 5 → 3 → 2 → 4** 的顺序跑。`e61d0012` 是 joint scratch head,随后同一组 landed 代码进入 `feat/disaggregated@eec0e836`;landing 后按 ID-66 只跑 quick gate,不把 quick gate 写成第二次 full gate。 +P5 的历史 joint 记录来自 `~/w7/notes/p5/p5-results/joint-v1.md` §2 与 ID-63(其中设备部分未运行);脚本按 **1 → 5 → 3 → 2 → 4** 的顺序跑。`e61d0012` 是 joint scratch head,随后同一组 landed 代码进入 `feat/disaggregated@eec0e836`;landing 后按 ID-66 只跑 quick gate,不把 quick gate 写成第二次 full gate。 | 部分 | joint 实测 | |---|---| @@ -649,16 +649,18 @@ P5 的完整记录来自 `~/w7/notes/p5/p5-results/joint-v1.md` §2 与 ID-63; landed quick gate(ID-66):split unit **2038/2038**;`integration-split` inproc **22/22**(比 joint 多 `SplitLogPaths`);push integration-gpu **1128/1128**;G1 **0/0/0/0、`.text +0`**。这组数证明 landing 没丢 joint 的 reduced path,不声称重跑了 Part 2/4。 -## 27. P5 退出门 E1–E6:门、阴性控制与处置 +## 27. P5 退出门 E1–E6:历史读数与后续修正 + +本表保留 joint 的历史基线,并明确写出 x2、v1-r3 和 r2 的后续证据。收尾头 `37fc4fdb` 的实跑边界另见 §31;表内不同头的结果不能合并成一次全门。 | 门 | 实测与“为什么会红” | |---|---| | **E1 barrier** | default reduced path 三次均 **19 pass / 2 skip / 0 fail**;`MOBILEGL_IPC_VERB_BARRIER=0` 选中的 **14/14** 全 abort,且每个 private lane file 都有自己的 `Fatal{BarrierViolation, ""}`(ID-53/65,`joint-v1.md` §3) | -| **E2 OpenRA** | baseline **2/2、SSIM 1.0**;pull library + `inproc` 的 transport control 会红。`MOBILEGL_IPC_E2_DROP_CLEAR=1` 已武装但仍 **1/1、SSIM 1.0、mismatchPixels=0**,所以 clear-drop 控制**没有**因自己的理由变红,pending x2;不能据此反推 wire bypass(ID-65) | -| **E3 persistent map** | (a) block KB=0:**6 selected / 4 red / 2 skip**,红在第二次无 GL 宣告写的 pixel assertion;(b) 该无宣告写在场景内;ID-42 的 emulated membership 经 green → `return false` **3 red** → restored green,已 VERIFIED;(c) counting lane `pmap=2160.00 / mpr=1`,push `0.00 / 1`;(d) split apply 恒 decline,不返回 host pointer;(e) SmallRing entry 跑过,但无 wrap/wait counter,pending x2(ID-42/63/65) | +| **E2 OpenRA** | joint baseline **2/2、SSIM 1.0**。x2 在 DirectGLES 实测丢 **29 clears** 仍 SSIM 1.0:目标帧被后续地形 draw 全面覆盖;换为丢 **758 DrawVbo** 后 SSIM **0.000036**、mismatchPixels **295296**,并要求正的丢弃计数。r2 又验证真实 CTest 顺序:baseline → pull-library control → 恢复原 split 库 → draw-drop;先放入 pull 库会在 replay 前被 `MG_Remote=0` 拒绝(§31) | +| **E3 persistent map** | joint (a) **6 selected / 4 pixel red / 2 design-skip**;x2 补每进程一次 disabled-push 私有诊断,报告中的“6 red”更正为上述口径。j0 的逐选项 skip 拒绝使 `37fc4fdb` 全门停止;r2 精选默认/SmallRing 下两条 pixel 场景,共 **4 own pixel + private-log reds**。(b) ID-42 emulated membership 经 green → 3 red → restored green;(c) 历史 pmap=2160.00/mpr=1,push 0.00/1;(d) split apply decline;(e) x2 已测 wrap,r2 再证明真实 retirement wait,数字见 §28。pmap 或 block-zero 红都不能单独证明 server 不会重入 client producer(r1 #1) | | **E4 field ownership** | generator **15/15** own-message controls;strict lane **19 abort / 2 skip / 0 pass**,首条具名 `Fatal{UnmigratedPipeInput, "GetTextureContextId@Clear"}`。这是 BARRIER-PULLED 债务的响亮读法,不是 default regression(ID-65) | -| **E5 honest inproc** | `MOBILEGL_IPC_AUDIT=1`:**19 pass / 2 skip / 0 fail**;production SubData copy 与 `0xDD` poison 两条 shipped test 通过。五条机制已在代码门上覆盖,但“corrupt staged upload 再 draw”这个 R-16 半边未执行,**pending v1 round 3**,不把 audit-green 扩写成它已自证(ID-65) | -| **E6 phase gate** | G1 **0/0/0/0**、G2 name diff **0**、G14 **0 removed / 42 added**;verify **930/930**;push/verify retrace **79/79**。broad inproc census是 **426/185/511/27/0**,其 attribution 如下;reduced path 与记录债务分开结算(ID-63/65) | +| **E5 honest inproc** | joint audit **19 pass / 2 skip / 0 fail**。v1-r3 的 `StagedShadowProductionTest.TheEnsurePathUploadsTheServerShadowNotTheClientObjectsBytes` 用 client A/server B 两份数据,真实 ensure 后 driver READ map 得 B;删 transport-only shadow 保护则因读到 client A 而红。它覆盖 **unmapped** BufferObject,不能扩写为 coherent-map 的 wire-only 证明;收官审查确认该绕过,归 r1 #1 | +| **E6 phase gate** | joint G1 **0/0/0/0**、G2 name diff **0**、G14 **0 removed / 42 added**;verify **930/930**;push/verify retrace **79/79**。历史 census **426/185/511/27/0** 在 v1-r3 修掉六条过宽拒绝后变为 **432/185/505/27/0**;这些是分头证据,`37fc4fdb` 最终门并未全部完成(§31) | E6 的 27 个普通失败逐条复跑均 `rc=1`、private log **0 Fatal**;8 个争议项又各跑三次,无 flake。归属不是从测试名猜的,而是 `joint-v1.md` §4 的 probe: @@ -669,9 +671,11 @@ E6 的 27 个普通失败逐条复跑均 `rc=1`、private log **0 Fatal**;8 | framebuffer `HandleRecycleScenario` | 5 | P4b/P7 readback;不是已证明的 handle recycle bug | | `PrimitivesGeneratedNoXfbScenario` | 3 | P7 query / primitive accounting | | `TextureParamsWithoutASamplerView` | 1 | P6 shared-backend inspection forwarder | -| `P4aFinalFixScenario` FBO/RBO delete | 1 | P6 shared-backend lifetime after transported delete | +| `P4aFinalFixScenario` FBO/RBO delete | 1 | 原记 P6 lifetime;实际读回用 ReadPixels,完整像素因果未隔离。收官确认 framebuffer death 的 client-thread 驱动调用另归 r1 #2,不断言此条已证明与 server 改动无关 | -511 个 abort 只**计数**,没有逐条诊断;抽样两条分别是 `DrawElements` 与 `BeginTransformFeedback` 的 class-C `Fatal{UnmigratedVerb}`。因此“511 全是 class C”不作为测量结论(`joint-v1.md` §4)。 +joint 当时只计数 511 个 abort,抽样了 `DrawElements` / `BeginTransformFeedback`,并未证明“511 全是 class C”。v1-r3 的逐项复查随后辨明:**505 UnmigratedVerb + 6 StageSnapshotTooNarrow**;后六条是 P5 的 whole-store coverage 过宽拒绝,修复后六条由 abort→pass,其余逐名状态不变。c0b 与 r2 的新鲜私有日志再次给出 **432 passed / 185 skipped / 505 UnmigratedVerb abort / 27 failed**(1149 项)。证据:`v1-v3.md` §2 item 6、`~/w7/p5b-c0b-census-logs/results.json`、`~/w7/p5b-r2-census-logs/results.json`。 + +27 条 wrong-answer 中只有 **22** 是上述 texture-shadow/readback 家族,另有 3 query、1 inspection、1 FBO/RBO lifetime。阶段接纳没有消除这些错误;“全部 27 条都是纹理读回”或“均非 v1 的问题”均不受证据支持。 ## 28. R-10、逐帧 ledger 与内存口径 @@ -691,7 +695,20 @@ E6 的 27 个普通失败逐条复跑均 `rc=1`、private log **0 Fatal**;8 `inproc` 两角色共享一个进程,所以上表是**进程**峰值,不是两个独立 physical peak;server 只在 accept 时取样,不能声称 full-run server peak,也没有 N-frame RSS slope。日志另报 `roleMapped=58,990,592 B`、`allRolesMapped=117,981,184 B`。规范 ledger 由执行过的 `ProtocolSmokeTest` 钉住:**SEG_CMD 8 MiB / SEG_STAGE 32 MiB / SEG_REPLY 16 MiB / SEG_EVENT 256 KiB**(ID-47/65)。 -**max record bytes:没有场景测量,pending x2。** encoder 有 `MaxRecordBytesSeen`,但 scenario telemetry 未发布;单元只证明它远小于 half-ring,不提供这两个场景的数。这里不从 struct size 或 ring capacity 反推(`joint-v1.md` §5)。 +**x2 后续实测 max record bytes**(`p5/x2@579118a1`,经 x2m 合到 `37fc4fdb`;`x2-v1.md` §2、`x2m-v1.md`): + +| workload | maxrec / row | cap | cmd bytes / records | +|---|---|---:|---| +| Triangle redraw | **784 B / SetVertexAttribDefaults** | 4,194,304 B | 4,040 B / 48 | +| Persistent map write-after-frame | **784 B / SetVertexAttribDefaults** | 4,194,304 B | 4,904 B / 59 | +| OpenRA DirectGLES,25 帧 | **784 B / SetVertexAttribDefaults** | 4,194,304 B | 未发布 run 总量 | +| SmallRing triangle,1 MiB SEG_CMD | **784 B / SetVertexAttribDefaults** | 524,288 B | 1,314,880 B / 24,323 | + +默认 cap 下占 **0.019%**,这些负载不需要 R-10 chunking;更大的后续 draw tail 不能由这个结果保证。stats 上的 maxrec/maxcap/wrap/wait 是 **run totals**,不是窗口内计数。oversized DrawVbo 尾的 unit 具名拒绝 `Fatal{RingOverrun, "DrawVbo"}`,证明 half-ring 上限能红。 + +x2 SmallRing 实测 `ringwraps=1, ringpads=0, ringwaits=1`,其中 **wrap 已自证,旧 wait 数只说明发生 reclaim**,不能称阻塞等待。r2 改为立即 reclaim 仍不够、确实被未退休发布记录阻塞的 allocation 才计一次;普通 GL 768 KiB uploads 配合只延迟退休的 hook,1 MiB 臂得到 `maxrec=784 cap=524288 cmdbytes=1315256 ringwraps=1 ringpads=0 ringwaits=1 emitseq=24328`。把 command/staging 都增至 8 MiB,同一门分别因 `NEVER WENT ROUND` / `producer NEVER WAITED` 变红(`r2-v1.md` #8、`p5b-r2-ring-{1,8}.{out,log}`)。这是 r2 包头的 staging-wait 证据;r1 的完整 command-ring/shutdown 处置另计。 + +`rsp=35` 等历史值仅是当前有 stamp 的计数下界:未盖 verb stamp 的 sticky/non-verb frontend reads 仍有未计数/未 strict 拒绝的路径,见收官审查与 r2 债务表;不能据此称全部 residual reads 已纳入 ledger。 ## 29. 复审作为过程测量:跨族发现、轮次与身份修复 @@ -718,20 +735,69 @@ wave-1 跨模型族复审的十项全部经独立 perturbation **CONFIRMED(10/ | ID-58(c1 round 2) | **3 blockers / 8 majors / 6 minors** | round 3;若仍有 blocker 才拆包 | | ID-62(v1 round-2 review) | **7 closed / 7 partial / 1 not closed**,新增 **5 majors** | round 3;E1 skip-false-green 转 j0 | | ID-64(c1 round-3 review) | **8 closed / 6 partial / 1 not closed**,新增 **0 blockers / 5 majors / 4 minors** | 判 MERGEABLE;剩余 gate debt 转 c1f | +| ID-73(P5 收官 Codex) | **1 blocker / 10 major / 2 minor**,只读 source-confirmed,确认扰动未在审查中执行 | #1–4 转 r1,#5–13 转 r2;包内执行结果与剩余债务见 §31 | 这些数字解释了流程为何在 P5 尾声改变:用户要求不再在轮次中做过度验证;以后 package 自门 + quick gate 落地,每阶段末只做一次 Codex adversarial review,发现进入下一阶段首轮(ID-66)。 另一个过程事实是 identity rewrite(ID-40):Sep 8 以后 WSL repo-local `rereview ` 污染了 **81** 个被 Windows 重写的提交与 **58** 个 wave-1 提交;本地谱系经 parent/env rewrite 接到 GitHub `ff2994d9`,验证 **59** 个重写提交全部是 `Swung0x48 `,tree/patch 等价。自此每阶段首个 commit 前必须先跑 `git var GIT_COMMITTER_IDENT`。这是过程修复,不计成 P5 实现产量。 -## 30. P5 four-arm A/B on the Redmi(pending `ab-v1.md`) +## 30. P5 Redmi 四臂 A/B(已记录,split 性能仍不可测) -本节只冻结协议,不填数字。设备是项目指定 Redmi;四臂用同一 native code 对照: +证据:`~/w7/notes/p5/p5-results/ab-v1.md`、`ab-v1-tables.md`,构建身份见 `ap-v1.md`。设备 Redmi `2f7cbe2e`,会话 **2026-09-16 10:31:20–11:10:05 UTC−04**;runner head **eec0e836**,三份 APK 的源码头是 **joint e61d0012**,不能当成 `37fc4fdb` 的 APK。三份 APK 有独立 application ID;split 与 splitctl 共用同一 split APK。 | arm | APK / env | 回答的问题 | |---|---|---| | pull | pull APK | 既有 pull 基线 | | push | push APK | monolith push 边界 | -| split-inproc | split APK + `MOBILEGL_TRANSPORT=inproc` | 第二 apply 线程的 barrier / codec / copy 总成本 | -| split-no-env control | 同一 split APK,不设 transport env | Gradle flavour 本身是否改变 monolith;应与 push 对照 | +| split | split APK + `MOBILEGL_TRANSPORT=inproc` | 第二 apply 线程的 barrier / codec / copy 总成本 | +| splitctl | split APK,不设 transport env | split build 的 monolith 对照 | -沿用设备协议:reboot-clean、同一风扇档与已验证定频、四臂交错配对;每个 trace 记录尾 200 帧 p50/p99、逐线程 CPU、`pmap/mpr/rsp`、进程 `VmHWM`,并保留 pin check 与 private log。A/B 后台运行、不阻塞 landing(ID-66);在 `~/w7/notes/p5/p5-results/ab-v1.md` 出现前,本节保持 **pending**,不从 desktop gate 或旧 APK 推算。 +reboot-clean、风扇 level 2、同热窗口与定频、四臂交错。每臂三次,取最低平均墙钟时间那次的尾 200 帧;所有 **40 组** 前后 pin check 都为 **P/P**,采样温度 **37.2–39.9 °C**。五个 case × 两后端 × 四臂,**27 组完成 / 13 组失败**,每次失败只重试一次;第五个 iris-BSL 用例一并保留在报告中。 + +所有 **10 组 split** 都在 benchmark 前中止:improved-transparency 双后端为 `DrawElementsInstancedBaseVertex`,rd12 / fabric-sodium / vanilla 1.21.4 / iris-BSL 双后端为 `DrawElements`。其余三次失败是 rd12/DirectVulkan 的 pull、push、splitctl 均复现既有 `scudo::reportMapError`(dev 侧)。因此 **每个 case 的 barrier tax 都未测得**,不能从 splitctl 或启动后的 RSS 推算。 + +关键帧时摘要(单位 ms,p50 / p99;完整逐线程 CPU、repeat、计数器与私有日志见上述报告): + +| case / backend | pull | push | splitctl | split | +|---|---:|---:|---:|---| +| improved-transparency / DirectGLES | 10.535 / 25.415 | 12.106 / 26.973 | 12.235 / 27.131 | 索引 draw 中止 | +| improved-transparency / DirectVulkan | 10.742 / 25.031 | 11.678 / 26.134 | 11.837 / 26.476 | 索引 draw 中止 | +| fabric-sodium / DirectGLES | 8.314 / 9.573 | 8.311 / 9.701 | 8.303 / 9.486 | 索引 draw 中止 | +| vanilla 1.21.4 / DirectVulkan | 1.043 / 2.293 | 1.159 / 2.404 | 1.179 / 2.426 | 索引 draw 中止 | +| rd12 / DirectGLES | 7.999 / 22.089 | 11.105 / 24.865 | 11.261 / 24.771 | 索引 draw 中止 | + +在 push 与 splitctl 都完成的组合里,splitctl 相对 push 的帧 p50 为 **−0.1%…+1.6%**,p99 **−3.0%…+1.4%**。这只描述 split build 的 monolith 臂。举例 improved-transparency/DirectGLES 的逐线程 CPU p50/p99 为 pull **10.447/25.213**、push **12.011/26.775**、splitctl **12.135/26.936 ms**;它不提供 apply 线程成本。P5b 索引 draw 迁移后用新 APK 重跑,直到四个目标 trace 在设备上渲染;性能仍只记录、不阻塞 landing。 + +## 31. P5 收尾实跑的停止点、j0/v1-r3 与 r2 修正 + +`~/w7/p5-final-gate.log` 明确钉在 **37fc4fdb**,不是 §26 的 joint head。首次启动曾被 WSL 会话杀死;重启后的保留日志给出了以下结果,最后一行为 E3(a) 的 skip 拒绝,没有全门成功终止标记: + +| 已执行部分 | 该次实跑结果 | +|---|---| +| 配置/构建 | pull / push / verify / split 都 rc=0 | +| Part 1 纯度与 G1/G5 | include closure 4 probes/0 problems;27,814 symbols,0/0/0/0;.text 10,806,611 B (+0);两条 G5 byte-identical | +| Part 5 | emitter/CSO 185/185,verify controls 4/4;生成器检查完成 | +| Part 3 单元与 monolith | unit 1817×3 / split 2086;Wire 58;pull/push GPU 1128,各零失败;split-monolith 1149 零失败 | +| Part 3 inproc | broad lane 1149 selected,CTest 报 532 non-success(含 abort,不等于 532 wrong-answer);reduced 22 selected 零失败,含两条设计性 skip | +| E1 | 14 selected 全部按 BarrierViolation 变红;逐项私有日志控制通过 | +| E3(a) | 6 selected 中 4 条 pixel assertion 红、2 条 `TheMapLandsInTheArmItsLaneDeclares` 设计性 skip;控制以 `the knob killed the pre-flight, not the entry - 2 selected entries skipped` **失败** | +| Part 2 / Part 4 | **该次执行未到达**;§26 joint retrace 与 §30 旧 APK A/B 是独立证据 | + +j0-v3 的 `cc20de37` 加了 fresh JUnit 逐选项检查:skip、未运行、缺失/重复条目都拒绝,E1 每条必须有自己的 Fatal。它正确暴露了 E3(a) 选择器把设计性 body skip 纳入像素控制的问题;不能通过放宽 j0 的 skip 检查修复。x2/x2m 的包内 smoke、OpenRA drop-draw 与 SmallRing 读数也不等于此最终门成功。日志里 broad census 的旧 name/status diff 含分类问题,不作为逐条归因依据;采用 §27 新鲜私有日志的 census。 + +v1-r3 已完成并需保留的事实:native EGL bind 在 reduced lane 实测每进程 **1/1/1**、release **0**;真实 EGL 四套件 **33/33、0 skip**,36 个定向扰动因自己的诊断变红;`HasDefinedContent`/coverage 修复使六个过宽 whole-store 拒绝归零。各读数来自 `v1-v3.md` 所列包头/共同测试头,不能替代 `37fc4fdb` 的门。unmapped shadow 控制的边界见 §27 E5。 + +收官审查 `p5-close-codex-review.md` 在 `37fc4fdb` 只读确认 **1 blocker / 10 major / 2 minor**(ID-73),不宣称当场执行了 proposed perturbations。r1 负责 coherent-map server re-entry、framebuffer death 驱动线程、PACK_SWAP_BYTES、RingOverrun 等待;r2 的 `37fc4fdb..d50183cb`(`6fa6a925` + `d50183cb`)完成 #5–13 并执行各自的具名 red-once: + +| 修正 | r2 包内证据与限制 | +|---|---| +| broad debt lane 与 runtime baseline | 普查 exit code/JUnit 记录后继续硬门;全部 runtime skip 则 baseline 失败,metadata 不能使其变绿。仅删掉 exit 捕获会再次阻断控制 | +| E2 库身份/恢复 | frozen split path + SHA256 恢复;真实 CTest 连续运行 baseline/pull/drop,baseline SSIM 1.0、drop 0.000036,758 records;故意换成 pull 库在 replay 前被拒绝 | +| E3(a) 选择 | 精选默认/SmallRing 的两条 pixel case,共 4 条自己的 assertion+disabled-push 私有诊断;恢复旧 broad selection 重现收尾错误,pre-flight skip 仍拒绝 | +| ringwaits | 只有真正等未退休发布记录才计数;lazy reclaim 单元为 0,GL SmallRing 的 1/8 MiB 对照同时证明 wrap 与 wait;完整 transport policy 与 r1 对齐 | +| REQUIRE_GPU / zero-run / stale evidence | split unit 强制 GPU,invalid EGL 从可选 skip 变 required failure;两份 census runner 零执行拒绝为 harness-error,launch 前清空私有日志,旧 Fatal 不可冒充新证据 | +| G5 pin / c1f mutation | 删 production pin-selection 后各自具名红;c1f 改用 ID-67 的 different-tuple case,15/15 RED 后 restored GREEN,旧 case 名证据不沿用 | + +r2 最终包门:split unit **2087 selected**、reduced **22 selected**、push **1128 selected** 均零失败(selected 包含已注明 skip);E1 **14 own reds**、E3(a) **4 own reds**;smoke **16 core + 12 private**;census **432/185/505/27**,零 segfault/harness-error。r2 **没有新跑 pull G1 binary comparison**,只说明修改不影响 pull production code;不能把继承的 0/0/0/0 当它的新测量。日志 `~/w7/p5b-r2-final-gate.log` 的 `UNIT_OK SPLIT_OK CONTROLS_OK SMOKE_OK CENSUS_OK PUSH_OK` 只认证 r2 包头,不认证后续合并头。 + +r2 还更新树外 `~/w7/p5b-c0b-census.{sh,py}`、`~/w7/notes/tools/p6_census_lane.py`、`~/w7/notes/tools/wsl_p5_gate.sh`;git merge 不会把它们自动带到别处。仍未关闭的债务包括 r1 四项、无 stamp 的 residual reads、ReadPixels 正确大小但非法 status=3 的接受路径,以及 §27 的 27 条 wrong-answer。完整归属/退休门见 `ROADMAP.md`;实现与证据索引为 `~/w7/notes/p5b/p5b-results/r2-v1.md`。本节只汇总现有证据,没有追加轮次审查或重复全门。 diff --git a/docs/Disaggregated/README.md b/docs/Disaggregated/README.md index 3d7f2da4..bdd14af1 100644 --- a/docs/Disaggregated/README.md +++ b/docs/Disaggregated/README.md @@ -1,6 +1,6 @@ # MGPipe:MobileGL 前后端拆分 -> 状态:**P0、P0.5、P1、P2、P3a、P4a、P5 已落地**(`feat/disaggregated@eec0e836`)。P5 已在完整门上跑出缩减路径首个 IPC 帧:`Clear` / `DrawArrays` / `ReadPixels` / `BlitFramebuffer` / `Present` 经同一套 wire codec 到同进程第二个 apply 线程,OpenRA 在 `inproc` 下两后端 2/2、SSIM 1.0。其余 64 个 class-C 槽仍具名 `Fatal{UnmigratedVerb}`;下一阶段先按 census 迁移它们,把真实负载完整搬上 apply 线程,再做 spawn。见 `ROADMAP.md`。 +> 状态:**P0、P0.5、P1、P2、P3a、P4a、P5 已落地,P5b 正在进行**。P5 代码收尾头为 `37fc4fdb`;缩减路径的五个 verb 经 wire codec 到第二个 apply 线程,历史 joint 门已测 OpenRA `inproc` 双后端 2/2、SSIM 1.0。该收尾头的全门实跑停在 E3(a) 的设计性 skip,**没有完成最终五部分门**;r2 已在自己的包头修正控制选择并验证。P5b 按普查迁移真实负载的后续首阻塞,出口是四个 A/B trace 在 Redmi 上 `inproc` 渲染,之后再做 P6 spawn。各头的证据与欠债见 `MEASUREMENTS.md` §26–31、`ROADMAP.md`。 > > 性能纪律(2026-09-08 起):逐线程 CPU 与 tracker 绝对 ns **对着 pull 臂基线记录**,不再作阻塞门(push 比 pull 多约 10% 逐线程 CPU 已被接受;该读数出自 -O0 APK,Release 基准线见 `MEASUREMENTS.md` §20),专门的优化阶段排在路线图推完之后。 @@ -16,7 +16,7 @@ MGPipe 是 MobileGL 前端(`MG_State` + `MG_Impl`)与后端(`MG_Backend` 应用 GL 调用 → MG_Impl(GL 语义、错误、shadow) → MG_Impl/Pipe/Tracker:在每条 verb 之前 validate,把变化推成 MGPipe 调用 - → MGPipeScreen / MGPipeContext(两张函数指针表,71 条调用,单一真相源 PipeCalls.def) + → MGPipeScreen / MGPipeContext(两张函数指针表,76 条调用(P5b 契约头),单一真相源 PipeCalls.def) monolith:直调 backend 函数 split:发射器写 SEG_CMD ring → server applier → server 对象表(按 {slot, gen} 句柄索引的数组)+ PipeInputs(后端被推送的状态块) → MG_Backend(Espryt / Magma),两个后端的 ring / pool / memo / lowering pass 原样不动 @@ -34,7 +34,7 @@ MOBILEGL_TRANSPORT=inproc ctest --test-dir build-split -L integration-split --ou MOBILEGL_TRANSPORT=inproc ctest --test-dir build-split -L integration-gpu --output-on-failure ``` -缩减路径的具名入口是 `DirectGLES.Split.*`;每条 entry 都带独立的 `MOBILEGL_LOG_FILE_PATH`,日志不共享,阴性控制也只读被选 entry 的私有文件。常用运行时旋钮: +`integration-gpu` 在 inproc 下仍是带已知 abort/wrong-answer 的普查车道;它的失败不会免除缩减路径和阴性控制的硬门。缩减路径的具名入口是 `DirectGLES.Split.*`;每条 entry 都带独立的 `MOBILEGL_LOG_FILE_PATH`,日志不共享,阴性控制也只读被选 entry 的私有文件。常用运行时旋钮: | 变量 | 默认 | 用途 | |---|---:|---| @@ -52,7 +52,7 @@ Android 有三份 APK flavour:pull、push 与 split-inproc;构建映射分 |---|---| | `ARCHITECTURE.md` | 已定稿的设计与架构:句柄与世代、调用目录、记录约定、tracker、纹理路径、shader 制品、反向通道、后端改造、传输、persistent map 分档、进程/EGL/平台、构建与纯度门、验证策略 | | `ROADMAP.md` | P0…P13 阶段表、两条跑道、GO/NO-GO 清单、再基线检查点、仍然开放的问题 | -| `MEASUREMENTS.md` | 逐阶段实测:P0(spike A/B、双设备边界计数器基线、桌面数据点、语料事实)、P1(verify harness 门)、P2(五部分门、两机配对 A/B、DriverBench T1/T2、计数器)、P3a(门、接缝缺陷、Track H 普查、两机 A/B)、P4a(门、契约七次修正与两轮终审修复、缝类审计、三臂设备 A/B、DriverBench T1/T2/T3)与复现命令 | +| `MEASUREMENTS.md` | 逐阶段实测:P0(spike A/B、双设备边界计数器基线、桌面数据点、语料事实)、P1(verify harness 门)、P2(五部分门、两机配对 A/B、DriverBench T1/T2、计数器)、P3a(门、接缝缺陷、Track H 普查、两机 A/B)、P4a(门、契约七次修正与两轮终审修复、缝类审计、三臂设备 A/B、DriverBench T1/T2/T3)、P5(分头门证据、R-10、红米四臂 A/B、收官失败与 r2 修正)与复现命令 | 代码地图(P0 已落地的部分): diff --git a/docs/Disaggregated/ROADMAP.md b/docs/Disaggregated/ROADMAP.md index 8fda5655..d592150b 100644 --- a/docs/Disaggregated/ROADMAP.md +++ b/docs/Disaggregated/ROADMAP.md @@ -1,12 +1,12 @@ # MGPipe 路线图 -> 状态:**P0、P0.5、P1、P2、P3a、P4a、P5 已落地**(`feat/disaggregated@eec0e836`)。P5 的完整五部分门已经观察到“缩减路径首个 IPC 帧”:OpenRA `inproc` 两后端 2/2、SSIM 1.0(ID-63)。下一阶段先在 `inproc` 下按 class-C 普查迁移 verb,把真实负载完整搬上 apply 线程;spawn transport 后移。设计见 `ARCHITECTURE.md`,实测见 `MEASUREMENTS.md`。 +> 状态:**P0、P0.5、P1、P2、P3a、P4a、P5 已落地,P5b 进行中**。P5 收尾头 `37fc4fdb` 的缩减路径已有 IPC 帧;历史 joint OpenRA 双后端 2/2、SSIM 1.0。该头的最终全门在 E3(a) 的两条设计性 skip 处停止,r2 已修正选择并完成包内控制验证,不能把它写成合并头全门通过。当前先让四个 A/B trace 在 Redmi 的 `inproc` 下渲染,再做 P6 spawn。设计见 `ARCHITECTURE.md`,实测与证据边界见 `MEASUREMENTS.md` §26–31。 ## 通用纪律(每个 commit) 默认 ALL target 必须完整构建;禁止提交热路径插桩(CI grep 门);**每个门必须能因它存在的理由变红**;Windows 机器不是正确性门;设备对比走 reboot-clean + 同热窗口配对 A/B,CPU 定频按项目协议;每阶段出口跑一次五部分门;每阶段性能判据是**逐线程 CPU 时间**;**拆分不借机顺手修 `dev` 的 bug**——句柄化过程中发现的 `dev` 侧缺陷记录成独立条目、独立 PR,不混进本分支(下文课题 15、17 各是一例)。 -两条跑道仍然分开:**monolith 跑道** P0 → P0.5 → P1 → P2 → P3a → P4a → P3b/P4b → P7 → P8 → P13,每段可独立交付、可随时中止;**IPC 跑道** P5 → `inproc` verb migration → P6 → P9 → P10 → P11 → P12。这里只调整 IPC 跑道内部的先后,不把 spawn 混进 monolith 深化。 +两条跑道仍然分开:**monolith 跑道** P0 → P0.5 → P1 → P2 → P3a → P4a → P3b/P4b → P7 → P8 → P13,每段可独立交付、可随时中止;**IPC 跑道** P5 → P5b `inproc` verb migration → P6 → P9 → P10 → P11 → P12。这里只调整 IPC 跑道内部的先后,不把 spawn 混进 monolith 深化。 ## 阶段 @@ -18,9 +18,9 @@ | **P2** 渲染状态 CSO + 第一片 Track H + 残余值块 | 18–26 | ✅(`738b289d`)`MG_Impl/Pipe/Tracker`(dirty 位、5 个聚合世代、抑制器骨架);`gen_pipe_dirty_surface.py` 首轮映射成门(73 个 mutator 全映射,45 条 render-state 答案 + 8 条 (mutator, bit) 答案逐字段导出,0 COARSE / 0 UNDECIDED,`.github/workflows/test.yml:1601-1604`);`MGPipeRenderStateSpans` chunk 表 **7 个 pipeline chunk / 396 B + 8 个 dynamic chunk / 772 B = 1168**(`MobileGL/MG_Pipe/MGPipeRenderStateSpans.h:190-191`)+ G7 setter 一致性测试;`CsoCache`(**64 项**,键 = pipeline 子集,`MobileGL/MG_Impl/Pipe/CsoCache.h:53`);`create/bind_render_state` + `set_dynamic_state`(Espryt `SyncRenderState` 一行不动;Magma `ComputePipelineStateHash`/`GetOrCreatePipeline`/`ApplyDynamicDrawStateTail` 改从 CSO 与动态 payload 取);`set_pixel_pack_state`、`set_patch_state`、`set_vertex_attrib_defaults`;`set_residual_value_state` + `ResidualValueBlock` 绊线(**棘轮 1248 → 8**,`MobileGL/MG_Pipe/MGPipeTypes.h:546`);**第一片 Track H**:Espryt 0b(`SlotAllocator` + 6 个 registry → slot 数组 + 删 `TwinLookupMemo`×3/`OwnerEquals`/`g_fbSlotCache`/GC)与 Magma 子系统 4(`VertexInputStateFactory`/`VaoDrawMemo` 重键,删前端 VAO 里的后端裸指针)——共 **11 条身份 memo 直接删除 + 2 条重键**(`ARCHITECTURE.md` §9.5 的普查),pre-handle 臂在 `MOBILEGL_PIPE_LEGACY_MEMOS` 下并存到 P13;`MOBILEGL_PIPE_LEGACY_MEMOS`(`CMakeLists.txt:36`);补**三个** capability 存储 `FramebufferSrgb`/`DepthClamp`/`TextureCubeMapSeamless`(`MobileGL/MG_Pipe/MGPipeValueTypes.h:303-305`) | ✅ 集成 × 2 后端 × {pull, push} 逐名相同(名差 0);pull 构建符号 0 增 / 0 删 / 0 重命名、四个已认定 resize、`.text` +160 B;`RenderStateImpl` sha 不变;单元 1566 × {pull, push, verify};`integration-gpu` 916/916(pull、push、`MOBILEGL_PIPE_PUSH=0` 三臂);79 例 retrace push 下 79/79、verify 下 79/79 零分歧;`integration-verify` 828 条零 `Fatal{`;verify 构建的三组对照(`PoisonOmitted`、`VerifyCorrupted`、`HandleRecycle`)44/44,且 ABA 对照关掉句柄身份即红;G7 负面对照按设计变红并点名 `SetColorMask`;`CsoContentAddressing` 6/6;测试名 0 删除 / +119。设备(小米 Adreno 830,配对、定频、尾 200 帧 p50):push 比 pull 多约 10% 逐线程 CPU——**用户 2026-09-08 决定接受**(**勘误**:这批 APK 是 -O0 构建,见 `MEASUREMENTS.md` §10 勘误;Release 基准线以 §20 的 P3a 表为准),性能自此对 pull 基线只记录不设门;两机各 16 行在案(小米 p50 +8–14%,Oppo Espryt +8–18% / Magma +10–11%);桌面 `DriverBench` T1 = +322 / +345 ns/draw(Espryt / Magma),T1 − T2 = −228 / −354(P2 比它替掉的 P1 残余填充便宜),blend-toggle +4.7% / +3.5%,见 `MEASUREMENTS.md` §9–§14 | P1 | | **P3a** handle wave 1(Espryt):buffer、VAO | 18–23 | ✅(`fde5fda3`,44 个提交,`git diff --stat 5cb826b0 3e298c9a` = 37 文件 / +9273 / −230)**九条 `resource_*` 调用**接线:`ResourceCreate`、`ResourceRespecify`、`ResourceSubData`、`BufferSubDataResident`(`kOptional`,Magma 仍不注册)、`ResourceFlushRange`、`ResourceReadback`、`ResourceDestroy`、`MapPersistent`、`UnmapPersistent`——全部在 GL 调用时刻从 `BufferObject` 的十一处分发点发射(`ARCHITECTURE.md:157` 的唯一例外),落到新的句柄形后端表 `MGPipeResourceOps`(`MobileGL/MG_Pipe/PipeApply.h`,签名里没有任何 `MG_State` 类型);Espryt 的 `Ops_*` 行为逐条不变,只换了读输入的地方。**五条 vertex-input 调用**:`CreateVertexElements`/`BindVertexElements`/`DeleteVertexElements`(blob 两个视图都带,`MGPVertexAttribWire[]` + `MGPVertexBindingPointWire[]`,`ARCHITECTURE.md:132`)、`SetVertexBuffers`(`BaseInstance` 显式字段,取代 `g_pendingFetchBaseInstance` 那个 ambient 全局)、`SetIndexBuffer`。**第七张 Espryt slot 表**:`GLESBufferResource` 搬出 `PipeResource::m_backend`,进 `BackendSlotTable`(`MobileGL/MG_Backend/DirectGLES/Managers.h:691-692`)——第一张按 client 铸造、随调用过线的句柄索引的表。`kNeedsAck` 首次落到目录里(`ResourceRespecify`,逐记录谓词 `MGPipeResourceRespecifyNeedsAck(desc) == (desc.Immutable != 0)`,`MobileGL/MG_Pipe/MGPipeTypes.h:680`)。pool、延迟释放与三条 ring 原样搬(G5 十个函数逐字节相同);Adreno 禁用属性 SIGSEGV workaround 保留。**memo 普查(`ARCHITECTURE.md` §9.5)**:句柄臂上**退役 6 条身份 memo 成员**——VAO twin 的 `m_hasSyncedConfigVersion` / `m_syncedConfigVersion` / `m_syncedAttributeVersions`(`Array`,本阶段最大的一处)/ `m_syncedIndexBufferVersion` / `m_syncedIndexBufferObject`(裸前端指针),加 `ConvertedFloat64Stream::sourceLifetimeId`(即普查里 11 条直接删除的最后一条,`ConvertedVertexStreamKey` 的 `sourcePin`)。六条都**仍在 `MOBILEGL_PIPE_LEGACY_MEMOS` 下编译**(`Managers.h:1109-1130`、`:1067-1075`),pull 构建强制该开关 ON,所以 `sizeof` 一处不动——G1 的 0/0/0/0 就是这条的度量,真正的删除随 pull 路径在 P13 发生;**4 条重键** —— twin 的同步门(config version + 32 组逐属性版本 → `{elementsHandle, elementsSerial}` + `VertexBuffersSerial`)、twin 的索引槽 memo(回绕 `Uint16` + 裸 `BufferObject*` → 一个 `Uint64 m_syncedIndexSerial`)、`ResolvedDrawBuffers`(`configVersion` → `{elementsHandle, elementsSerial, buffersSerial}`,`Entry` 与 `iboFrontend` 各加 `MGPipeHandle`)、`ConvertedFloat64Stream`(前端 lifetime id + change serial → buffer `{slot, gen}` + applier `Serial`),另 `GLESBufferResource::syncedChangeSerial` 从镜像 `BufferObject::GetChangeSerial()` 改为镜像 applier 的 `Serial`;**保留不删** —— `g_pendingFetchBaseInstance` / `SetPendingFetchBaseInstance` / `GetPendingFetchBaseInstance` / `ScopedFetchBaseInstance` 与它的三个 scope 仍在 `MOBILEGL_PIPE_LEGACY_MEMOS` 下编译(`Managers.h:1189-1200`、`DirectGLES.cpp:5293`),因为真删会从 pull 构建移走两个符号 = 直接的 G1 破坏,计划里"grep 为空"那条在 P3a **不可达**;`PipeResource::m_backend` / `SetBackendResource` / `ReleaseBackend` / `BackendBufferResource` 同理(D-K,`ARCHITECTURE.md:286`),push 下只是不再被写,随 pull 路径在 P13 退役。**`map-persistent-roundtrips`(`mpr`)**:定义为**每一次 `MapPersistent` 发射,铸成或拒绝都算**(`ARCHITECTURE.md:485`),所以 monolith 下非零、可断言。子系统位 7(resources)与位 8(vertex input),push 默认 `0x7f` → **`0x1ff`**(`kMGPipeSubsystemsMigratedAtP3a`) | ✅ 五部分门(本地 `~/w7/pipe`):**G1** pull 符号 0 增 / 0 删 / 0 重命名 / **0 resize**、`.text` 10806323 字节不变(P3a 的认定 resize 集为空);**G5** 十个 pool / 延迟释放 / ring / flush-drain 函数对 `44c2b5cf` **与** `5cb826b0` 都逐字节相同,self-test 两个阴性对照(`ClearBufferPool`、`FlushPendingRangesNow`)都按名变红;`RenderStateImpl` sha 仍不变;**G2** pull 与 push 逐名相同(名差 0);**G14** 测试名 0 删除 / **+58**;单元 **1619** × {pull, push, verify};`integration-gpu` **958/958** × {pull、push、`MOBILEGL_PIPE_PUSH=0`、`0x7f`(G12 的子系统关闭臂)、`MOBILEGL_ESPRYT_DISABLE_INVALIDATE_FLUSH=1`};buffer/VAO 族 **202/202**;`RenderStateSpans`/`Residual`/`VertexInputEmit`/`ResourceEmit` **48/48**;`HandleRecycle`(verify)**60/60**,含新的 buffer 用例三臂;`CsoContentAddressing` + `ResourceSubsystemControl` **10/10**,controls **64/64**;**G7** 两个阴性对照都按设计变红,vertex-input 那个**点名 `IsBgra`**;`integration-verify` **842/842**,零 `Fatal{`;`gen_pipe` 与 `gen_pipe_dirty_surface`(scan root 已扩到 `MG_State/GLState`,75 个 mutator 全映射、0 COARSE / 0 UNDECIDED)`--check` + `--self-test` 全绿。79 例 retrace:push 下 **79/79**,`MOBILEGL_PIPE_VERIFY=1` 下 **79/79 全部 armed、零分歧、零 `Fatal{`**;G3b 的具名五条都在这两次扫描里通过,**但单独那次具名扫描因门脚本把正则写成了逗号清单而选中 0 例**,且设备侧仍按开放问题 17 排除 `create-indirect`,所以 G3b 记为"桌面全绿、设备侧部分"——详见 `MEASUREMENTS.md` §16。**性能只记录不设门(用户 2026-09-08 规则 (a))**:MC 26.3 在 Adreno 上的 p99 对与两机 p50/p99 表见 `MEASUREMENTS.md` §20。**再基线检查点 1:实际日历 1 天(2026-09-08,四个包),远低于 27 天,不触发重定基线** | P2 | | **P4a** handle wave 2(Espryt):FBO / 纹理 / sampler / program 身份与描述符 | 26–34 | ✅(`8c458cd5`,101 个提交,`git diff --stat 37da3c3a 8c458cd5` = 86 文件 / +30066 / −384)**十四条族调用接线**:`set_framebuffer_state`、`create/delete_sampler_state`、`create/delete_sampler_view`、`set_texture_params`、`set_sampler_views`、`bind_sampler_states`、`set_shader_images`、`create/delete_shader_state`、`set_draw_program`/`set_dispatch_program`、`set_global_constants`;纹理与 renderbuffer 的 create/respecify/subdata/destroy **复用 P3a 的四条 `resource_*` 行**(D-D1),所以目录仍是 **71 条,P4a 一行未加**。**六种 kind 按 `{slot, gen}` 重键**:Texture、Renderbuffer、Framebuffer、SamplerCso、SamplerViewCso、ShaderCso——其中 sampler **state** 内容寻址(容量 256、引用计数防 LRU 驱逐掉仍被 `MGPTextureParams::BuiltinSampler` 指着的项),sampler **view** 按纹理对象身份寻址(D-F2),framebuffer 只有句柄没有 wire 生命期(D-I2)。子系统位 **9(framebuffer)/ 10(纹理资源)/ 11(sampler)/ 12(program)**,`MOBILEGL_PIPE_PUSH` 默认 `0x7f`→`0x1ff`→**`0x1fff`**。`CompositeResolver` 落地(program pipeline 解析成保留段里的一条 shader CSO,按 `(ContextId, 管线名)` 记忆——进程级单例配每上下文 GL 名,是复审在真实 make-current 序列上打出来的)。**契约改了七次才对**(`c0b`…`c0g`):birth 半边 hook 与发布 latch、`wants()` 看 wired 常量、四个缝的编码一次性写死(`MGPSubData::Target` 低字节资源目标 + 高字节上传目标、`DepthStencilMode` 0/1、`MGPSurface::Kind`、`Pad0`→`TextureTarget`)、Tracker 两个看不见自己主体的快门(`glBindSampler` 只动位 12 的世代、SSO 下 `GetCurrentProgram()` 恒 null)、`MGPipeFramebufferTarget::Named = 3`(**记录改按 framebuffer 句柄存**:原设计只存两个"当前绑定"记录,于是 `BlitNamedFramebuffer` / `ClearNamedFramebuffer*` 在句柄臂上打进一个从没拿到附件的 FBO)、**消费者门**(四族必须"某后端注册了 `MGPipeResourceOps`"才发射——Magma 没有 P4a twin,客户端却按 acceptance 清了 dirty,直接让 66 条 DirectVulkan 用例丢上传)、**客户端侧 D-K2 依赖表**(位 10 要位 7 和位 11,位 9 要位 10;只在服务端拒绝时客户端已经把标记清了)。emulation 在 split 下显式 Fatal 直到 P8(`MGPipeUnmigratedEmulation` 在 `Managers.cpp` 2 处、`DirectGLES.cpp` 4 处) | ✅ 全门(`6035c9d7` 全量 + `8c458cd5` 上复跑):**G1** pull 符号 0 增 / 0 删 / 0 重命名 / 0 resize、`.text` 字节不变(P4a 认定 resize 集为空;Espryt 侧靠预处理器宏而非 lambda/局部量改写——插一个 lambda 就会把同函数里九个既有 `$_N` 全部重编号);**G5** P3a 的十一函数 + P4a 自己的 **17 个区**(`scripts/p4a_untouched_regions.sh`,8 个阴性对照全部按名变红);**G2** pull 与 push 逐名相同 **2902**;**G14** 0 删除 / **+314**;单元 **1785 × 3**;`integration-gpu` **1117/1117 × 七臂**(默认 `0x1fff`、`0x1ff`、`0`、`0x9ff`、`0x5ff`、pull、`ESPRYT_DISABLE_INVALIDATE_FLUSH=1`),其中 DirectVulkan **559/559**;`integration-verify` **920/920 零 `Fatal{`**;79 例 retrace 在 verify 臂 **79/79 全 armed 零分歧**、push 臂 **79/79**、G3b 具名 **12/12**;**八族拒绝普查 = 0**(按族逐条 grep 服务端拒绝句,工具 `wsl_p4a_refusal_census.sh`;`ctest -V` 的普查是假零——console sink 被编译掉了,必须逐用例取自己的日志)。**G9 的"落地前必须红"没能通过公共 GL 达成**:回读模拟自己会设 `GL_DEPTH_STENCIL_TEXTURE_MODE`,`IsDrawSyncClean` 又在首次采样时推参数,所以该场景改成**白盒断言**(新增 `MG_IntegrationTest/Harness/PipeApplyPeek.{h,cpp}` 直接读 applier 的参数记录 + Espryt 已应用状态,变异下 4/4 变红),D 的 `SanityTest` 另加一条覆盖"推迟到首次取视图"的那半。真正红过再绿的是终审抓出的两条:per-level respecify 丢上传(`L0; draw(other); L1; draw(T)` 在 `0x1fff` 下读回全黑、`0x1ff` 下正常)与 delete-then-draw(`glTexImage2D; glDeleteTextures; draw` 在句柄臂 SIGABRT `pure virtual method called`)。**CTS `direct_state_access.framebuffers*` / `packed_pixels`(G15)未跑**,判在关键路径外,随 P3b/P4b 补。**再基线检查点 1b:实际 1 天(2026-09-08 起,六包并行 + 契约七修 + 两轮终审修复),远低于 39 天,未触发** | P3a | -| **P5** 传输 + inproc applier + 发射表 | 12 | ✅(`ff2994d9..eec0e836`,**128 files / +26161 / −594**)同一 G3 codec 上的 `InProcessTransport`;client 发射表、caps mirror 与 reply mailbox;`mgl-srv-apply` 终身持有 native context;lockstep verb barrier;诚实 host/blob 审计;tight `ReadPixels`;persistent-map 块推送;私有 lane 日志与 split CI/APK 接线。八个实现包见下表 | ✅ 完整门上 OpenRA `inproc` 2/2、SSIM 1.0;split unit 2038/2038;`integration-split` 21/21;E1/E3/E4 的具名阴性对照、G1 0/0/0/0、G2 名差 0、G14 0 删除。27 个普通 wrong-answer 与两个尚不能自证的控制按债务记录,不伪装成已绿。**缩减路径首个 IPC 帧已观察到**(ID-63/65) | P4a | -| **P5.5** `inproc` verb migration(下一阶段) | 待普查 | 先由 `~/w7/notes/p6/census-classC.md` 按 slot / family / Minecraft trace 统计 class-C abort(文件若尚未生成则本项保持 pending),再按命中次序迁移 subsystem;同时消减 `rsp` 指向的 P3b/P4b/P7 输入债 | `inproc` lane 的 abort 数只降不升,直到四个设备 trace 在 Redmi 上全程由 apply 线程渲染;每个迁移族以自己的 class-C Fatal 消失为门 | P5 | -| **P6** spawn transport(后移) | 5 | `SocketTransport`(socketpair + fork/execve,envp 剔除 + 强制 monolith 双保险);`ServerMain`;`MOBILEGL_IPC_SERVER_PATH` + `dladdr` 兜底;有界重试握手;EOF 即时退出;device-lost latch | P5.5 的完整渲染路径在 `spawn` 下绿;进程树只多一个子进程;`HeadlessGL` fork 预检无孤儿;OpenRA 在 Adreno 830 上 split SSIM ≥ 0.99 | P5.5 | +| **P5** 传输 + inproc applier + 发射表 | 12 | ✅(`ff2994d9..37fc4fdb`)同一 codec 上的 `InProcessTransport`;发射表、caps/reply;apply-thread context;lockstep barrier;tight ReadPixels;persistent-map 块推送;八包及 j0/x2/v1-r3 收尾 | 历史 joint:OpenRA 双后端 2/2、SSIM 1.0。收尾头:G1 0/0/0/0、.text +0,unit 1817×3 / 2086,push 1128、split-monolith 1149、reduced 22(含 2 skip)均零失败;**最终全门在 E3(a) 停止,Part 2/4 未到达**。收官审查 1 blocker / 10 major / 2 minor 转 r1/r2;证据见 `MEASUREMENTS.md` §31 | P4a | +| **P5b** `inproc` verb migration(进行中) | 按首阻塞迭代 | c0b 契约已落地;按 class-C 普查迁移 d1 索引/实例、多 draw,i1 image/compute/barrier,t2 XFB/曲面细分,f1 clear/copy/mip;r1/r2 修收官发现。基线为 432 passed / 185 skipped / 505 UnmigratedVerb abort / 27 failed | 各包负责的 slot abort 归零,逐场景/trace 报下一个 first blocker;合并后重普查。四个 A/B trace 在 Redmi 上由 apply 线程渲染后收官,全门一次、Codex 审查一次;期间只有包门与集成快门 | P5 | +| **P6** spawn transport(后移) | 5 | `SocketTransport`(socketpair + fork/execve,envp 剔除 + 强制 monolith 双保险);`ServerMain`;`MOBILEGL_IPC_SERVER_PATH` + `dladdr` 兜底;有界重试握手;EOF 即时退出;device-lost latch | P5b 的完整渲染路径在 `spawn` 下绿;进程树只多一个子进程;`HeadlessGL` fork 预检无孤儿;OpenRA 在 Adreno 830 上 split SSIM ≥ 0.99 | P5b | | **P3b / P4b** 深化(Espryt) | 29–38 | **P4a 已经付掉的,别再排进来**:`ResolvedDrawBuffers` 重键(P3a 就做了)、Tracker 的集合 hash 抑制器(三个 unit set 各自带内容 hash,clientsp)、`g_unitTextureSyncList` 那条 unit-bindings epoch(E 的验证轮换成 sampler set serial,顺带重键四条下游 memo)、`MGPSubRegion` 的跨步描述符(P4a 的 `resource_subdata` 已经逐区携带 `SrcOffset`/`SrcRowStride`/`SrcSliceStride`)。**仍然欠着**:按存储属主键控的发射游标与 index 重映射(dirty 归属反转,P4a 只落了 drain list);`g_fboTextureSyncList`;`ResolvedTextureBindingMemo` / `SamplerPassMemo` / image sweep / program registry 的重键;XFB scatter 搬到 client;删 fragColor 重推导 workaround 与 `g_broadcastMemo*`;**raw-depth-fetch sampler 原生化**(`g_rawDepthFetchSamplerState` 至今是 `MG_Backend` 里的一个前端 `SamplerObject`,是句柄臂上唯一一处有意保留的前端读——P4a 终审的 R-6);回读 / pack state;外加 P4a 记下的 R-3(三处只活在包头里的编码收进契约)、R-4(`UseProgram`/`BindVertexArray` 两行的 G9 推导)、R-5(D-K2 依赖表两侧各一份,要合成一处)、R-7(三通道 CPU mipmap 重武装缺口)、R-10(六种新 kind 的 ABA 对照目前是惰性的,缺一个消费者 `if`)、R-11(`TextureUploadShapeScenario` 仍是"只记录不设门") | ~25 个纹理场景、21 个 program 场景 + `MG_Test/ShaderTranspiler`;两台设备 `KHR-GL46.texture_*`/`internalformat.texture2d.*`/`shader_image_*`/`packed_pixels` 在 pull 基线 0.5 pp 内;每一个 Iris trace;**`TextureUploadShapeScenario`**(形状金标,Mali 帧时增量必须发布);view/owner 发射游标别名场景;verify 保留模式下 subdata 形状逐项相等;XFB 场景 + `capture_special_interleaved_test` | P4a | | **P7** DirectVulkan(Magma)全量迁移 | 80–104 | §5.5 其余 10 个子系统(子系统 1、4 已在 P2):`SetupDrawSnapshot` 探测字段塌成 dirty mask;占位纹理原生化(~120 行删除);具名 UBO host payload(D-B8,`kCapNeedsHostUboBytes`);blit/depth-mipmap 内部 shader 烘焙 + 新鲜度测试;`VertexInputStateFactory` 裸指针写回删除;D18 容器纪律原样保留 | 集成 + 40 trace 在 Magma 的 push 与 split 下全绿;verify 零分歧;**`nm -D libMobileGLServer.so | grep glslang` 为空**;Iris trace 上 `stage-ubo-named` 逐帧字节发布;两台设备 CTS 0.5 pp 内。**再基线检查点 2:中点(第 40–52 工作日)完成子系统 < 40% 立即重定基线** | P0.5、P2;可与 P5/P6/P8 并行 | | **P8** emulation 下放 + 索引宿主镜像 + 协议广度 | 12–16 | `MG_Impl/Pipe/HostResolve.cpp`(client 数组范围、最大索引扫描、`*IndirectCount` 解析,各带逐站点 reconcile);`MGHostSpan` split 填法;`Server/IndexHostMirror`;CopyImage 镜像搬到 client;`draw_vbo` 收编 multi-draw 族(分档仍在 server);viewport-array 回放验证;`generate_mipmap` 计划 + CPU 回退纹素;G3 分块路径;无 present fence tick + 无 present split 用例;`kCapDriverOrderedXfbCapture` | `'^DirectGLES\.Split\.'` 与 `'^DirectGLES\.'` 逐名相同(DirectVulkan 同);40 trace split 双后端 SSIM ≥ 0.99 含两个 `coherent_as_flush` Create fixture;`ClientArrayAfterComputeWriteScenario` 绿(去掉等待必须见几何缺失);`create-indirect` 上 `roundtrips-per-frame` 读零;`index-mirror-bytes`/`index-bytes-shipped` 逐用例发布。**第 145 天:全功能 split** | P6、P3b/P4b | @@ -52,7 +52,7 @@ P5 的八个实现包(报告在 `~/w7/notes/p5/p5-results/`): - **第 25 天(P1 出口)**:verify harness 逐 draw 逐字段证明"推送等价于拉取"。零产品风险,**不是** GO/NO-GO。 - **第 43 天(P2 出口):GO/NO-GO —— 判定继续**。P2 的五部分门全绿(逐名相同、零分歧、负面对照能红),逐线程 CPU 代价约 +10% 被接受,下一步立即开 P3a。 - **P3a 出口(2026-09-08)**:五部分门全绿,pull 构建仍 0/0/0/0,`resource_*` 与 vertex-input 两个家族在 Espryt 上换到句柄寻址。**实际日历口径:1 天**——contract / wire / client / espryt / gates 四个包(五轮)全部在 2026-09-08 内完成、集成并跑完门,对着"P3a > 27 天"的绊线是 **1 / 27**,不触发重定基线,也不需要 `inproc` 的证伪数字(`:70`)。Track H 单位成本的完整普查见 `MEASUREMENTS.md` §19。 -- **P5 出口(2026-09-16)**:完整五部分门在 scratch joint head 上观察到首个 `inproc` IPC 帧;同一代码随后落到 `feat/disaggregated@eec0e836`,quick gate 为 split unit 2038/2038、`integration-split` 22/22、push 1128/1128、G1 0/0/0/0(ID-63/66)。 +- **P5 出口(2026-09-16)**:缩减路径首个 IPC 帧已经观察到;joint、落地快门、收尾头实跑分别记在 `MEASUREMENTS.md` §26/31。收尾头 `37fc4fdb` 的 E3(a) 控制因两条设计性 skip 失败;不能以早期 joint 或各包自门替代未完成的最终全门。红米 P5 四臂 A/B 的 split 均停在索引 draw,barrier tax 未测(`MEASUREMENTS.md` §30),迁移与重跑归 P5b。 - 原“第 104 天跨进程帧”后移到 `inproc` verb migration 之后;目标先是完整 separate-thread rendering,再是 separate-process transport(ID-66)。第 145 天全功能 split与第 187 / 267 天纯度门仍是方向,不据此伪造新日历。 ## 第 43 天 GO/NO-GO 清单 @@ -87,21 +87,25 @@ P5 的八个实现包(报告在 `~/w7/notes/p5/p5-results/`): ## P5 出口记录的债务 -这些行是 ID-65 的处置,不是把 broad `integration-gpu` 的红偷换成 P5 reduced-path 的绿: +ID-65 的原始处置与 ID-73 收官审查/r2 的更正如下。阶段接纳不等于这些路径正确;包内证据不替代最终合并头门。 | 债务 | 去向 / 当前口径 | |---|---| -| 27 个普通 inproc wrong-answer | 14 layered + 3 packed depth/stencil + 5 framebuffer recycle → **P4b/P7 texture readback**;3 primitive-generated → **P7 query**;`TextureParamsWithoutASamplerView` → **P6 shared-backend inspection forwarder**;`P4aFinalFixScenario` FBO/RBO delete lifetime → **P6 shared-backend lifetime** | -| `rsp` residual inputs | 逐帧基线已记录;按字段声明的 P3b/P4b/P7 retirement phase 清零,不能以 barrier 永久遮住 | +| 27 个普通 inproc wrong-answer | **22**(14 layered + 3 packed depth/stencil + 5 framebuffer recycle)→ P4b/P7 texture readback;3 → P7 query;1 inspection → P6。FBO/RBO delete 那 1 条使用 ReadPixels,完整像素因果未隔离;收官确认的 client-thread framebuffer death 驱动调用另归 **r1 #2**,不得把所有 27 条统称纹理读回或断言均与 v1 无关 | +| `rsp` residual inputs | STRICT_ERRORS reduced lane 19 abort/2 skip;既有 rsp=35 只是有 stamp 读点的下界。无 verb stamp 的 sticky/non-verb forward 仍可绕过计数/strict;P7/P8 补逐字段归类和自证门(r2 提议),其余按字段的 P3b/P4b/P7 phase 退役 | | `SEG_REPLY` 2 MiB payload cap | 当前 `MaxReplyBytes = 2 MiB - 16`;更大 readback 需要 P6+ chunking 或专用 carrier(ID-47) | | `GetCaps` 的两个 blobref | 目前不骑 record;一旦运输,必须有 server→client carrier rule,不能套 `SEG_STAGE`(ID-48) | | PACK-PBO readback | P5 具名拒绝;真实形状是 server 写 buffer resource、client `MarkGpuWritten`,列入 P6(ID-57) | | ABI fingerprint | 目前不混 segment sizes;改变 8/32/16 MiB + 256 KiB ledger 时仍欠这项(ID-47) | -| max record bytes telemetry | encoder 有计数而场景 stats 不发布;**pending x2** | -| E2 clear-drop control | baseline 2/2 绿,但 clear-drop 保持 SSIM 1.0,未因自己的理由变红;**pending x2** | -| E3 small-ring wait telemetry | 小 ring 场景运行过,但没有 wrap/wait 数;**pending x2** | -| E3(a) 具名 block-zero diagnostic | 目前靠 pixel assertion 变红;**pending x2** | -| E5 corrupt-staged-upload → draw 控制 | audit lane 绿不等于该控制已自证;**pending v1 round 3** | +| max record bytes telemetry | **x2 已实测** reduced/OpenRA maxrec=784 B(SetVertexAttribDefaults),默认 cap=4 MiB;只代表所测负载,后续索引/indirect 尾仍须记录 | +| E2 wire 内容控制 | x2 draw-drop:758 draws,SSIM 0.000036;clear-drop 被全屏 overdraw 掩盖,不能作 OpenRA 控制。**r2 已在包头验证 pull-library → 恢复原库 → draw-drop 顺序及 split 库身份** | +| E3 small-ring wait telemetry | x2 已证明 wrap,旧 ringwaits=1 只证明 reclaim。**r2** 改为等待 outstanding retirement 后才计数,1 MiB 时 wrap=1/wait=1,8 MiB 对照同时红;command-ring 等待与 shutdown 策略仍须与 r1 #4 合并 | +| E3(a) block-zero control | x2 补私有 disabled-push 诊断;j0 逐选项拒绝 skip。旧 6 selected 实为 4 red/2 skip,收尾全门因此停下;**r2** 精选 4 pixel case,每条必须自己的 assertion+私有诊断,且仍拒绝 pre-flight skip | +| E5 staged shadow 与 coherent map | v1-r3 的 unmapped 双 shadow 控制证明 ensure 上传 server pattern B,删保护会读 client A 并变红;**不能证明 coherent-map wire-only**。server re-entry 读 client MappedData/写 tracker 的绕过归 **r1 #1 blocker**,以仅取消 client pre-draw push 的具名控制退休 | +| tight ReadPixels PACK_SWAP_BYTES | 多字节 client scatter 丢 swap 语义,**r1 #3**;非对称 UNSIGNED_SHORT 像素与 monolith 对照 | +| ReadPixels reply 状态校验 | 正确长度但 status=3 仍可接受;P5b reply-protocol follow-up(r2 提议),须具名拒绝非 0/1/2;生产是否会发 3 未证实 | +| CI / 控制 / 跑器 | **r2 包内已修** broad debt lane 吞掉后续控制、all-skip 绿、REQUIRE_GPU、E2 库恢复、E3 选择、陈旧/零用例普查、G5 pin 自测、c1f 旧名。外部 notes 脚本也有修改,git merge 不会自动传播;验收详见 `MEASUREMENTS.md` §31 | +| 临时 CI trigger | 合入 dev 前删除 `feat/disaggregated` 的 TEMPORARY trigger;不能随阶段遗留 | ## 仍然开放的问题