Files
MobileGL/docs/Disaggregated/ROADMAP.md
T

100 KiB
Raw Blame History

MGPipe 路线图

状态:P0、P0.5、P1、P2、P3a、P4a、P5、P5b、P5c、P5d、P5e、P5f 已收官。P5f 于 2026-09-20 完成主机门、Redmi 六个 clean-boot 臂、跨模型族审查及修复验证;最终验收代码为 WSL cfca93c7885fd8db1e881f91189ba59090ae9c52(Windows c42577a4 等价)。证据见 notes/p5f/close-report.md、close-review.md、device-report.md。P6 已收官(2026-09-22):全部包(a6 / c6 / lk / so / sm / cp / hs / dl / st / t6)已落地于 feat/disaggregated(头 77cbd176,2026-09-21),出口门第 1–6 项此前已达成;第 7 项(Redmi 2f7cbe2e 的 reboot-clean 同热窗口配对 A/B)与第 8 项(三个强制性能数)已于 2026-09-22 采齐——门 7 判读为 tie(inproc vs spawn 的 client CPU p50 差 −0.15% / +0.16%,均在臂内散布 0.2–4.2% 之内,符号随臂序翻转;monolith 基线约贵 30%),门 8 三数齐:门铃 A/B tie(clipark 略差)、SEG_STAGE 字节/帧、分块后记录/帧。证据 notes/p6/gate7-device-ab.md、notes/p6/gate8-doorbell-device.md、notes/p6/gate8-wire-counters.md。逐包状态、出口门逐项、证据见 CURRENT_STAGE_PROGRESS.md;设计见 ARCHITECTURE.md。P5e 的历史性能与 E1 对照债保留在阶段行、P5E-RUNAHEAD.md 和 MEASUREMENTS.md,不由 P5f 的新对照代为关闭。CI / inproc 功能补齐已收官(2026-09-21):拆分主产物 + inproc 主验收、完整 retrace 双 transport、18 项 CI 门、双 ABI APK / AVD 全绿并合入 feat/disaggregated(e1bf3677),(原记 CURRENT_STAGE_PROGRESS.md §2.8;该文档已为 P6.5 重写,原文在 git 历史)。2026-09-22 起进入 Ph / P3b-P4b / P7 统筹推进:三行逐项审计、判定与波次见 notes/p7/PLAN-PH-P34B-P7.md,裁定见 notes/p7/INTEGRATOR-DECISIONS-P7.md。

P5f 后续 Magma run-ahead 已完成(194382c9,2026-09-20):主机真实排队、credit、负控及 Vulkan 同步验证通过,Redmi 同包 Magma 开/关与 GLES 三臂 FCL 世界实测通过。见 报告。P6 / P7 全阶段状态不因此改变。

终局(2026-09-22 改判):client 与 server 可以在不同机器、不同 OS / 架构上,经 TCP 连接;同机的 spawn(AF_UNIX + 共享段)保留为本机形态。传输栈拆成两根独立可选的轴——控制面(ITransport:fork 继承 fd / unix:<path> / tcp://host:port)与数据面(ILink:共享段 ShmLink / 字节流 StreamLink)——由握手协商、可以混搭(同机可以控制面走 TCP、数据面走共享段以降开销),上层只见 ITransport + ILink,不得按链路种类分支。此前 P6-ENDSTATE-REVIEW.md 假设的 AVF pVM / AF_VSOCK 终局撤回(该文顶部有更正)。这一改判把 P6.5 从条件项变成 IPC 跑道的关键路径,把 wire 定宽 + 布局摘要从 P7 / hs 的"以后"变成 P6.5 的第一个包,把 Ph(含配对 / 认证)变成 P12 非 loopback 监听的前提;设计见 ARCHITECTURE.md §11.9。

通用纪律(每个 commit)

  • 默认 ALL target 必须完整构建;禁止提交热路径插桩(CI grep 门)。
  • 每个门必须能因它存在的理由变红:每个门带阴性对照并真跑过一次红(R-16);公共 GL 看不见的改白盒断言。
  • 正确性门是硬门;性能对着 pull 臂只记录、不作阻塞门(用户 2026-09-08:push 比 pull 多约 10% 逐线程 CPU 已被接受;专门的优化阶段排在路线图推完之后)。唯一不可谈判的是数字必须真的采到。
  • 每阶段出口跑一次五部分门(ARCHITECTURE.md §13.2);性能判据是逐线程 CPU 时间;设备对比走 reboot-clean + 同热窗口配对 A/B,只用 Redmi 2f7cbe2e(devices/pin-verification-2026-09-07.md);Windows 机器不是正确性门。
  • G1:pull 构建的符号集与 .text 字节对基线恒等(每阶段 0/0/0/0);G2:pull 与 push 的 ctest 名集合相同;G14:测试名只增不删;G5:保护区字节一致。
  • 拆分不借机顺手修 dev 的 bug:句柄化过程中发现的 dev 侧缺陷记成独立条目、独立 PR(开放问题 15、17)。
  • 过程(用户 2026-09-16,ID-66):不过度验证;轮次间不做对抗性审查,每个 P 阶段收官由 Codex 审一次,发现进入下一阶段首轮;只读 / 非核心任务派给 Codex;实现方与审查方错开模型族。

两条跑道分开:monolith 跑道 P0 → P0.5 → P1 → P2 → P3a → P4a → P3b/P4b → P7 → P8 → P13,每段可独立交付、可随时中止;IPC 跑道 P5 → P5b → P5c → P5d → P5e → P5f → P6 → P6.5 → Ph → P12 → P9 → P10 → P11(同机臂)。目标顺序:先完整的 separate-thread rendering(P5b,已达成),再让 inproc 变成只经 wire 交换的诚实两角色(P5c),再把它的 CPU 代价压到可接受(P5d),然后退役 draw path 上的 lockstep(P5e:client 发了就走,server 只从记录带来的句柄解析对象),然后是 separate-process transport(P6,此时只是传输替换)。P6 之后(2026-09-22 定):传输栈两轴化并能跨机(P6.5),server 能安全地接受不是它自己产生的连接(Ph),server 成为拥有显示的常驻应用(P12),异步反向通道与节奏(P9、P10)建立在 P6.5 的消息式 reply 之上,同机的 ≥16 MiB 采纳(P11)最后。

阶段

阶段 状态 落地什么 验收门 / 证据
P0 卫生、度量、门、骨架 ✅ 边界计数器;PipeCalls.def 完整目录 + payload POD + 生成器 G1–G7 + CI pipe-gates;gen_pipe_dirty_surface.py;check_doc_citations.py;MOBILEGL_PIPE_* 开关;MG_Remote/{Protocol,Transport} 骨架 + protocol.fbs + flatc-check + MG_Test/Wire;三个严格 no-op 收益;spike A / B;retrace --env 透传 单元 / 集成 / trace 逐名不变;wire 层测试绿;两台设备字节 / 调用基线在案;spike 结论。MEASUREMENTS.md §1
P0.5 值头与制品头抽取 ✅ 5d99ee43 MG_Pipe/MGPipeValueTypes.h;ProgramArtifacts.h;Visit() 归档 + sizeof 绊线;CI -H include 闭包断言(scripts/check_include_closure.py)+ scripts/symbol_report.py 测试名零删除、.text 不变、符号 0 增 / 0 删 / 42 重命名
P1 PipeInputs 替换与 verify harness ✅ MG_Backend/MGPipe/PipeInputs.h(63 字段);277 处箭头 + 58 行非箭头逐条转换;逐 verb 类填充点;逐 verb 世代 poison;G4 影子比对器 + verify CI 模式;push-on-mutation 三字段 pull nm 不变;单元 1485×3;integration-gpu 878;integration-verify 818 零 Fatal;79 retrace verify 79/79 armed 零分歧。§2
P2 渲染状态 CSO + 第一片 Track H + 残余值块 ✅ 738b289d Tracker(dirty 位、5 个聚合世代、抑制器);dirty-surface 成门;MGPipeRenderStateSpans chunk 表 + G7;CsoCache(64);create/bind_render_state + set_dynamic_state(SyncRenderState 一行不动);pixel pack / patch / attrib defaults;ResidualValueBlock 棘轮 1248 → 8;Espryt slot 表 + Magma vertex input 重键(11 条 memo 删除 + 2 条重键);MOBILEGL_PIPE_LEGACY_MEMOS;三个 capability 真存储 G1 4 处认定 resize、.text +160 B;G2 名差 0;单元 1566×3;integration-gpu 916 三臂;retrace 79/79 push + verify;对照 44/44。GO/NO-GO(2026-09-08):继续。§3
P3a handle wave 1(Espryt):buffer、VAO ✅ fde5fda3 九条 resource_* + 五条 vertex-input 调用接线到句柄形 MGPipeResourceOps;第七张 Espryt slot 表;ResourceRespecify 的 kNeedsAck 谓词;VAO twin 六条身份 memo 在句柄臂退役、四条重键;mpr 定义;位 7/8,push 默认 0x1ff 五部分门全绿:G1 0/0/0/0 .text +0;G5 十一函数;单元 1619×3;integration-gpu 958 五臂;verify 842;retrace 79/79 ×2。实际 1 天。§4
P4a handle wave 2(Espryt):FBO / 纹理 / sampler / program ✅ 8c458cd5 十四条族调用接线(framebuffer state、sampler state / view、texture params、shader images、shader state、draw / dispatch program、global constants);纹理 / renderbuffer 复用 resource_*(目录不加行);六种 kind 按 {slot, gen} 重键;CompositeResolver;Named = 3 framebuffer 记录;消费者门 + 客户端依赖表;位 9–12,push 默认 0x1fff;emulation 在 split 下具名 Fatal 全门:G1 0/0/0/0;G5 17 区;G2 2902;单元 1785×3;integration-gpu 1117 七臂;verify 920;retrace 79/79;八族拒绝普查 0;PipeApplyPeek 白盒对照。实际 1 天。§5
P5 传输 + inproc applier + 发射表 ✅ ff2994d9..37fc4fdb 同一 codec 上的 InProcessTransport;四种 build flavour;发射表三类 / caps mirror / reply mailbox;apply-thread context 终身持有;lockstep verb barrier;tight ReadPixels;persistent-map 块推送;G8 字段归属生成器;split 测试 / CI / APK 车道;八包(c0 契约、w1 codec、s1 session、p1 归属、b1 persistent map、t1 车道、c1 路由、v1 server)+ j0 / x2 / v1-r3 收尾 joint:OpenRA inproc 2/2 SSIM 1.0;integration-split 21/21;E1 14/14 红;G1 0/0/0/0。收尾头全门在 E3(a) 停止(设计性 skip 被判红),Part 2/4 未到达;收官审查 1 blocker / 10 major / 2 minor → P5b r1/r2。§6
P5b inproc verb migration ✅ 37fc4fdb..82683d4a class-C 普查决定顺序;d1 19 / i1 7 / t2 6 / f1 11 槽迁移;sync 五槽;具名 blit;GLES mip descriptor;r1 / r2;收官审查三项修复。发射表 A=2 / B=54 / C=15 主机全门 348d22a4 complete;integration-split 107/107;合并普查零回退、79 trace 72/6/1;Redmi 正确性 8/8 + 四臂 A/B、barrier tax 首测。§7
P5c inproc 共享内存读点归零 ✅ 11ac3de6..b88e8487 server 端纹理 staged shadow(StagedTextureStore,句柄为键、整段覆盖、defined-ness 追踪);SEG_EVENT 三个 producer + kEventGlError(反向通道零裸指针);sink / twin 按记录句柄解析(blit 具名臂经 verb 句柄工作区,Magma 走 G6 消费臂);applier_reset / object_death 控制记录(opcode 77/78,framebuffer 首个 wire delete);set_context_values(79)退役全部值类 BARRIER-PULLED 行,三 shutter 自答;双层 Fatal{RoleViolation} 守卫 + InBarrierWait 接线;两个具名豁免 scope(通告家族 P4b/P7、G6 registry 家族 P3b/P4b)承接未到期的债 角色守卫开启下 unit 2187/2187(strict 下同绿)、integration-split 111/111、每层守卫 red-once 按名变红;纹理 0xDD audit 在 bsl / complementary 两条 in-world trace 零 Fatal;rsp 按帧实测(bsl 948.5/帧,残留全为钉住的对象类 15 行);G1 三个认定 resize(SwapchainObject::Create / CopyTexSubImage2D / ScopedRestartIndexSubstitution,均已具名)+ .text −16 B、pull 构建零 MG_Remote 符号;G5 保护区字节一致;双生成器 --check/--self-test 绿
P5d inproc 性能专项 ✅ cb06538c、56a77348、1f8de61b 一二轮:persistent-map 推送三级臂(mprotect 脏页追踪 + 哈希抑制 + 绑定过滤 PushDrawConsumers)、barrier 批处理 MOBILEGL_IPC_BATCH_WAITS + 延期销毁队列、自旋时钟 64 合 1、零页注册 + shadow 页对齐分配。三轮(按符号化 profile 逐项切,四包 + 一份 lockstep 可行性研究):apply 空转轮询零锁(控制邮箱原子影子位)、Doorbell::Wait 校准自旋稳态不读时钟、wait/park 计数进 stats;OnApplyThread() 内联为线程指针比较、三个 scope 深度计数器退掉 thread_local;shadow 分配尺寸补页、追踪范围向外对齐、边块哈希消失、脏页排空修复;image unit 高水位、残余填充 memo、server stamp 常量表;generate_mipmap 不再免等(apply 读残余输入)、death 测试围栏 三轮设备(Redmi,CPU 定频):inproc 64.3 → 103-106 fps(p50),client 线程 CPU 15.0 → 9.2 ms/帧、apply 12.4 → 7.0-7.4;monolith 同场景 115(120 Hz vsync 封顶的运行)/ 206(一次未封顶,渲染线程 5.0 ms/帧 大核);配对比较以逐线程 CPU/帧为主,见报告"数字"节;unit 2203/2203、integration-split 111/111(两条曾 flaky 的用例复跑 6/6);双生成器、include 闭包、dirty-surface、doc 引用绿。未完成:R-1 序列化(研究结论:留给 P3b/P4b 后的 P11 gPipeInputs 版本化)、线程放置(内核忽略亲和)、SetHashSuppressor 哈希等小项。报告:P5D-INPROC-PERFORMANCE.md
P5e 退役 Espryt draw path 的 lockstep ✅ 已收官(2026-09-19),附一条具名未决:E1 对照需按 ID-114 重新定义 契约 MG_Remote/CONTRACT-P5E.md(规则 F:未设障记录的 apply 不得读任何 client 内存;ID-84 限定它只约束未设障记录);裁定 ID-80..136(~/w7/notes/p5e/INTEGRATOR-DECISIONS-P5E.md)。十二个包,三波:wave 1 c0e(契约 + 线上行:PipeCalls.def 第五列 WaitClass、set_program_bindings opcode 80、kCapRunAheadApply 位 10 仅 DirectGLES 臂、kDrawClientArrays、子系统位 13、两个旋钮)→ id(registry 按 {slot, gen} 重键、by-handle resolver、分配器守卫);wave 2 vi / sb / pg / tx2 / fb 五个 per-draw 家族 ∥ ra(等待规则、present credit、gPipeInputs 变 server 角色内存),加 fix1(设备发现的 monolith 臂回归,ID-107);wave 3 pa(program 家族离开前端)、mv(multi-draw + 五个档位的门禁条目)、gl(门禁机制本身 + 两处潜伏崩溃)、ra2(翻开关后暴露的竞态)。kMGPipeP5eRunAheadReady 与 kMGPipeP5eClientWaitRuleLanded 均已翻。最大的那次迁移(逐 draw 的 GetProgramForDraw)没有改动任何线上结构:记录早就带着逐 link 的 ProgramArchive,缺的是仍去问前端对象的读者。报告 P5E-RUNAHEAD.md 出口门已逐条跑过(BRIEF-P5E §3,2026-09-19 在集成树上,run-ahead 已武装):item 1 unit 在 strict 两臂均 2256/2256;item 2/3 integration-split 179/179、逐条普查零 Fatal{、Admitted{ 恰为八行;item 4(a) RUN_AHEAD=0 作为配对对照 179/179 绿;item 4(b) VERB_BARRIER=0 变红(车道 62/179);item 4(c) Magma 逐字记下 run-ahead requested, server does not publish kCapRunAheadApply - running lockstep,而 Espryt 对照记下 run-ahead ARMED;item 5 在集成树上重跑 red-once(ID-121 重排后的形式):倒掉 pa 的臂得 GetProgramForDraw@DrawArrays、倒掉 mv 的臂得 GetBoundVertexArray@DrawArrays,恰好各一个具名对,还原后各自转绿;item 7 MOBILEGL_IPC_AUDIT=1 179/179。唯一未过的是 E1 对照脚本本身(ID-122):已修掉它两个遮蔽性缺陷(选中了一个在本车道永远跑不起来的阳性对照用例;ctest 与日志助手对“谁被选中”意见不一致),但它索要的 Fatal{BarrierViolation} 在整次运行里 出现 0 次:BATCH_WAITS 默认值 1 下那个重叠不发生,而 run-ahead 武装后 VERB_BARRIER=0 还会顺手关掉 run-ahead(ID-114),它产生的那条臂既不是 lockstep 也不是 run-ahead。E1 需要重新定义它要证伪什么,不是再调阈值;在想清楚之前不动它的计数规则,否则只是换一种伪绿。G1 仍由 CI 断言(ID-123)
P5f 一切状态上 wire ✅ 已收官(2026-09-20);验收代码 Windows c42577a4 / WSL cfca93c7885f f0 普查、f1 双块、fc 控制帧、fe Espryt 字段、fm Magma record consumers、fs 静态世代/角色及 liveness、fr registry、fv 反向回调均已合并。字段归属 41 RECORD_SUPPLIED / 6 APPLIER_DERIVED / 0 BARRIER_PULLED / 16 FATAL;strict / dualblock 预期 marker 集合均空。控制帧与静态量工作已完成,不再列为 P6 待实现项 unit 2310 = 2300 PASS + 10 skip;GPU 1377 零失败;ordinary / strict split 180 = 176 PASS + 4 skip;双块 212 = 206 PASS + 6 精确具名 skip;双后端 RSP 门 2 PASS / 0 skip、逐帧 rsp=0。G1 .text 10806051、symbols 27815 恒等且 0/0/0/0;G2 3016 同名;G14 3646→3744 无删名。逐包与收官修复均有 red-once;Claude 异族终审 P1/P2 已修;Redmi 六 clean-boot 臂 60 PASS / 6 skip / 0 failed、36 个窗口 rsp=0。详见 close-report
P6 spawn transport ✅ 已收官(2026-09-22);全部包已落地于 feat/disaggregated(头 77cbd176,2026-09-21),出口门第 1–6 项此前已达成,第 7/8 项于 2026-09-22 采齐。收官前核出的三项:server 进程侧 PipeStats 从未初始化(srv=0 srvpark=0 是结构性零,门 8 无 server 半边)已在收尾中修好;184 符号棘轮 CI 门(契约 §12.1)与契约 §2 分给 hs 的 LinkTerms / Refuse / 指纹拆分未落地,移交 P6.5(负控 S6 随之) 十包全落地:a6 进程装配/链接边界审计 → c6 规范契约 + 数据面缝惰声明 → lk RingControl 按写者重组 → so SocketTransport(AF_UNIX SOCK_STREAM + SCM_RIGHTS,12 条契约用例)→ sm 两个独立启动的进程(非 fork,name 汇合、共享匿名段,四守卫接线)→ cp EGL 控制帧跨进程并应答(InitCapabilities wire kind 11)→ hs build stamp 显式 present 入指纹 + abiMajor/Minor 补检 + 真实 pid → dl device-lost 闩(取自描述符挂断绝不取自超时)+ Session::Fail 漏斗(FatalFamilies.def 词表 + 90 站点归一 + SessionFault 帧命名家族)+ Fatal 普查门 → st fb-slot memo 具名 Fatal → t6 integration-spawn 车道(102/102)+ 名集合结构性一致门 + per-role 日志(<base>.client.log / <base>.server.log)。Android CI 新增 spawn-acceptance 臂,App 从 nativeLibraryDir 解析 server 路径。真机 Redmi 2f7cbe2e 上 OpenRA.DirectGLES spawn ssim=1.0 连跑三次 + 6 case 绿;DirectVulkan 真机分离路径不确定分歧(inproc 与 spawn 同表现→ Magma × 真实 GPU,非 P6,桌面 lavapipe 为 1.0)。边界仍为 pbuffer / surfaceless / 离屏;真窗口归 P12。契约 MG_Remote/CONTRACT-P6.md;a6 产出 a6-audit-v1.md、a6-link-experiment.md(server 不能不链 MG_Impl:184 符号,P7 101 / P3b-P4b 14 / 共有 60 / P6 自己 6);终局重审 P6-ENDSTATE-REVIEW.md。收尾四项(2026-09-22,工作树未提交):wire 计数器——PipeStats 新增 ByteClass::StageSegmentBytes(PipeWireCodec.cpp:878 StageAllocate 唯一收口)与 CallClass::WireRecords(:1188 EncodeRecord 提交路径)+ staged-blob 直方图,汇总行新增 seg= / wrec=;ServerMain.cpp 补 PipeStats::Init() / Shutdown()(spawn server 此前从不武装计数器——修前 0 条汇总行、修后 29 条,SSIM 1.0 不变);MOBILEGL_PIPE_STATS_FILE 按角色派生 <base>.client.json / <base>.server.json(走 RoleLogPath 同一导出规则,基名不指向文件);工具入库 tools/device_bench/p6/{ab_session.py,render_ab.py,README.md} 与 tools/trace_replay/run_android_retrace_local.py(+19 行 MOBILEGL_TRACE_PACKAGE),pin_device.sh 新增 2f7cbe2e 条目(本板 GPU 钳 1050 MHz:thermal_pwrlevel 写 0 读回 1、max_gpuclk 只读 1 050 000 000;绝对值与 1100 MHz 时代的 35d0befa 行不可比)。 出口门(契约 §9)1–6 ✅:G1 pull 0/0/0/0、.text 恒 0xa52203;integration-spawn 与 split 名集合一致(可比 102==102)且同数绿;进程树运行时恰多一子进程、结束为零;每条 spawn 条目记子进程 pid 与 transport=spawn(--require-spawn 门);每包 red-once。7/8 已采(2026-09-22):门 7 真机 reboot-clean 同热窗口配对 A/B(Redmi 2f7cbe2e / M332BF / SM8750 / Adreno 830v2,CPU 定频 little 1555200 / big 1958400,GPU 钳 1050 MHz(本板 thermal_pwrlevel 写 0 读回 1、max_gpuclk 只读 1 050 000 000;绝对值与 1100 MHz 时代的 35d0befa 行不可比,只有同会话配对可比),minecraft-1.21.4-rd12-odinlite-in-world + DirectGLES,~1471 draws/帧;六臂交错 × best-of-3:18/18 runner 退出 0、36/36 pin check PINNED、0 Fatal;client CPU p50 ms/帧 inproc 7.880/7.889 vs spawn 7.876/7.869,均值 −0.15%,符号随臂序翻转,臂内散布 0.2–4.2%;第二会话 inproc/spawn 交错 × best-of-2:4/4 OK、8/8 PINNED、0 Fatal,7.987/7.989 vs 7.992/8.009 = +0.16%)——判读 tie(差值在臂内噪声内),如实记录、不设门;monolith 基线约贵 30%(−29.8% / −29.9%)。门 8① socket 门铃 vs inproc condvar:client 121.1 waits/帧、5.6–6.1 parks/帧,两传输逐字相同(run total 30 401–30 407);server inproc 10 866–11 963 waits/帧、5.0–6.2 parks/帧,spawn 10 415–10 416 waits/帧、4.66–4.90 parks/帧——socket 阻塞读既不更便宜也不更贵(契约 §9「阻塞读可能更便宜」未兑现),spawn server waits 少 8.9–12.9% 归因于 handoff 纪律而非门铃本身,唯一 socket 略差的列是 clipark/f(6.07 vs 5.60/5.75)。门 8②③(inproc,真实 trace retrace):SEG_STAGE 字节/帧 OpenRA 130.8 KB median / 8.01 MB steady mean(含启动负载 8.07 MB),rd12 816.2 KB median / 1.53 MB steady mean(含负载 10.79 MB,rd12 首帧 981 654 draws vs 稳态 ~1471,run-wide mean 约 7× 稳态,两个读法都报);分块后记录/帧 OpenRA 211 median / 206 mean,rd12 7 497 median / 7 504 mean;maxrec=1808 与分块前相同(默认 8 MiB chunk 预算在这些负载上从未被打到)。证据 notes/p6/gate7-device-ab.md / notes/p6/gate8-doorbell-device.md / notes/p6/gate8-wire-counters.md
P6.5 传输栈两轴化 + 跨机 第一波已落地(feat/disaggregated@fe28bdb5,2026-09-22):全 TCP 控制 + StreamLink 数据,WSL client ↔ Redmi server。四切片代码审查无硬缺陷 + 两修复(AcceptPair 重试 EINTR/ECONNABORTED、supervisor 自设 MOBILEGL_IPC_ROLE=server,均 MG_Remote 门内 G1 不动,见 code-review-findings.md);固定制品(两端 stamp p65-acceptfix-20260922)再验收:unit 2399、integration-tcp loopback 102、device-102 102 全 ARMED、代表性 retrace OpenRA 1.0 全 ARMED。残余(CI/后续):完整 39 例 device golden 矩阵 + 必测数。设计见本表下方「立即的下一项」节 包:wf wire 定宽与布局摘要——wireFingerprint = PipeFields.def 派生的逐成员 name / offsetof / sizeof 摘要 + 有序目录摘要 + 记录头布局 + 两个 blob codec 版本 + kOpCount + 字节序 / 指针宽度,保留 sizeof(MGPCaps) / sizeof(DynamicBackendParameters)(wire 事实)、删 sizeof(GLFunctionsTable);buildFingerprint 只在 Dial == Fork 下比较;DynamicBackendParameters / MGPCaps / RenderStateParameters 整块 blob 的定宽化(两端是不同编译器产的不同二进制,long / padding / 位域差异都是静默读错状态);Refuse{code, detail, 对端值} 控制消息,握手路径零 abort → ct 控制面端点种类(fork 继承 fd / unix:<path> / tcp://host:port;DialMode{No, Fork, Connect} 与 MGPipeShouldDial() 按契约 §3 补齐;TCP keepalive 失败作为传输层报告的挂断进 dl 的闩,不是 apply 超时)→ nd 数据面协商(LinkTerms{dataPlane, delivery, wireForm, maxReplyBytes, cmdWindowBytes, stageWindowBytes} 入 Hello / Welcome,四个尺寸由 server 陈述;dataPlane ∈ {SharedSegments, Stream};auto 的判据是段实际交付成功而不是地址判断,回落必须具名入日志与 stats;链路工厂在会话建立时选定一对,之后不变——缝是 setup-time 的,契约 §8.2)→ sd 共享段交付与控制面解耦(ShmLink 自带 AF_UNIX aux 汇合名、在 Welcome 里公布,SCM_RIGHTS 只走它;于是控制面 TCP + 数据面共享段在同机是合法配对;ITransport 收窄为纯控制帧,描述符传递归数据面)→ sl StreamLink(分块封帧;watermark 变消息且规则逐字保留——late-never-early、>= 不是 ==、倒退是 Fatal;appliedSeq 修正案 + flush-on-idle;reply 变自带 seq 的消息,本链路上删 slot 池 / 取模 / stamp 自检;SEG_STAGE 变发送窗口,三个 cursor 要么完整复活要么不用、不留中间态;program archive 与 draw_vbo range 尾分片;GetCaps 两个 blobref 变消息;每方向每进程一条专用读线程)→ t65 车道。上层纯度:SessionProducer / SessionConsumer / ServerLoop / PipeWireEncoder、ClientSession.cpp 的 kSegEvent 挂载与 ResourceTracker.h 的 writeback 解析都只经 ILink。设计 ARCHITECTURE.md §11.9 门:inproc / spawn 车道结果数与逐线程 CPU 逐字不变(ILink::ReserveRecord 虚调用代价实测,RingProducer::Reserve 失去内联是具体风险);纯度 grep——ShmLink / StreamLink / RingControl / ReplySlotPool / EventRingConsumer / m_shm. 只出现在 Transport/ 与其测试,上层零链路种类分支;2×2 矩阵车道(控制面 {unix, tcp} × 数据面 {shm, stream},loopback)名集合与 spawn 一致且同数绿,每条目记 control=… data=… 的 arm 证明(ID-124 的形状);跨机臂一条真 trace 逐像素;wf 三条 red-once(临时树里同宽成员互换 → 摘要变而 stamp 不变;wireMajor = 99 → 两端具名拒绝、server exit 0、client 不回落 monolith;仅 stamp 不同的对端在 Dial != Fork 下连接成功——正控制);必测数:逐帧 kWaitReply 次数(ResourceCreate / SetTextureParams / 纹理半边 ResourceSubData 都在此列,TCP 上每次即一个 RTT)、SEG_STAGE 字节/帧对链路带宽、PRESENT_CREDIT 1..3 配对、混搭(tcp + shm)对(unix + shm)的逐线程 CPU 差
Ph 不可信对端加固 + 配对 已审计(2026-09-22,notes/p7/PLAN-PH-P34B-P7.md §1.1):P6.5 已在 LAN 上跑 tcp://0.0.0.0,「P12 之前」的顺序陈述落后于树。必需小件(supervisor 命名子进程死亡、两处漏斗旁路、D11 五处上限、常量时间令牌 + 数据面绑定、SEG_EVENT 弃投闩)随 P7 波次推进;fuzz 臂 2 在 P7 之后;OQ-21 已裁定令牌足够(ID-P7-3)。进展(2026-09-22 深夜):supervisor 命名子进程死亡 + 两处头层漏斗旁路已随 wave 0 落地(origin@801f8eda,abort_sites 79 成下行棘轮);其余小件是簇 F 包:片 1–3 已到集成树(2026-09-22 夜,ID-P7-37)——令牌合一 / ≥16 字节具名拒绝 / 无令牌只 loopback / smoke 进 CI;Welcome.dataNonce 绑定,TCP 上 250 ms 配对窗口消失,wireFingerprint 变更;PH-8 钳制证明——片 4–6 与 PH-7 (5) 需要对端字节的 fuzz 驱动,另派 F2(原顺序:常量时间令牌 / Refuse{Authentication} / ≥16 字节 + tcp_supervisor_smoke.py 接 CI → Welcome.dataNonce 数据面绑定 → PH-8 单测 → D11 五处 + PH-2 → PH-6 drop-with-latch → PH-1 (3)(4));逐日状态见 CURRENT_STAGE_STATUS.mdF2 完成(2026-09-23,ID-P7-57):PH-1 (3)(4) 每会话闩、PH-6、PH-7 (5) fork 前认证 + 退避、fuzz 三臂进 CI——Ph 必需小件全部落地。codex closeout(p7/int3):PH-5 界改为元素最小编码字节数(finding 3);DrainRing 在每次 pop 前查闩(finding 6:控制线程闩的窗口缩窄到查闩到 pop,未关闭)。 Session::Fail 的策略翻成每会话闩(按 ID-P7-1 重定界:98 处 SessionFail + 6 处 WireLogFatal 的字面翻转拒做——≥9 处返回引用没有诚实返回值;只对对端字节可达站点 latch-and-decline;P6 dl 收口到的是两个漏斗 + 两处头层旁路(Server/StagedShadow.h、Server/StagedTextureStore.h),不是一处;P6.5 fork-per-session 已给出「下一连接照常服务」);handle slot 预算(BackendSlotTable 的两条拒绝从 MOBILEGL_ASSERT 变 release 下的具名拒绝,杜绝静默 null twin);readback 尺寸门挪 server 侧且在 resize 之前设绝对上限;StagedTextureStore 按该 level 宣告范围设界;ArchiveVector 按 count × 元素最小编码字节数 设上限(codex closeout finding 3 改自 count * sizeof(element),后者拒掉编码器自己写的紧凑归档;map / set 仍按每项 1 字节);SEG_EVENT 溢出不再能让一个不排空(或仅涓流排空)的对端在 30 秒内、乃至瞬间用 Fatal{EventRingOverflow} 打掉承载它的 server 进程(drop-with-latch,不等 PH-1,ID-P7-2;原文「60 秒」是两轮 30 s 的算术上界);配对 / 认证(Hello 带令牌与无令牌只 loopback 已由 P6.5 ct 落地;欠常量时间比较、Refuse{Authentication} 入词表、≥16 字节、数据面按 Welcome.dataNonce 绑定到已认证的控制连接(今天 AcceptPair 按到达顺序配对、从不查 peer)、fork 前认证;OQ-21 裁定令牌足够、不做 TLS);段 / 窗口尺寸由 server 钳制(P6.5 nd 已陈述,欠一条钳制单测) 非 loopback 监听在无令牌时具名拒绝(机制已在;名字入词表 + tcp_supervisor_smoke.py 接 CI 后算达成);畸形帧 / 超界计数 / 不排空对端的模糊臂下 server 不 abort、会话闩住、下一连接照常服务(臂 1 机制已在、欠端到端脚本;臂 2 = PH-1 (3)(4) + D11;臂 3 = PH-6);Session::Fail 站点普查门扩到 server 镜像且 abort_sites 变棘轮(今天只扫 MG_Remote、站点数记了不比,wave 0);契约 §12.2 五处无界分配各一条 red-once(五处全开,不是两处)
P3b / P4b 深化(Espryt) 已审计(2026-09-22,notes/p7/PLAN-PH-P34B-P7.md §1.2);Espryt 项与 P7 文件零重叠,作为 P7 的并行流(wave 2-D)推进。D1 / D2 / D3 已落地(origin@22761a69,2026-09-22):D1 = XFB 两洞(孤儿目标保留 varyings、回写事件切片)+ 回调 10→9 + 四个 resolver 具名启动期 stop + readback 家族三臂(+39/臂,readback 半边其实早已关,ID-P7-24);D2 + 返工 = TextureViewAliasScenario、TextureUploadShape 成门(散点内缩后零补丁 red-once)、espryt_memo_purity.py、SubsystemDeps.def(R-5)、12 场景 split 普查(+76/臂)(ID-P7-26/29);D3 = view 在 owner 上传后陈旧的产品缺陷修复(clean gate 读 storage record,三臂 3 红→14/14)+ D-K2 六处读者读同一张表(ID-P7-28/30)。余:R-3 另一半(MGPSamplerView::Target 谓词)、KHR-GL46.texture_view.coherency 的 split 读数、CTS AFTER(wave 4);Iris trace 普查结果(wave 3) 已有头上结果(3c80cd62,notes/p7/iris-census-1135c664.md);逐日状态见 CURRENT_STAGE_STATUS.md view/属主发射游标别名场景(代码半已由 P4a TextureEmit.h 属主键控游标 + TextureObjectView::ToOwner* + P5e tx2 落地,欠验证);g_fboTextureSyncList(分离安全——记录臂先返回、退路是具名 Fatal;四个 resolver 改启动期具名 stop,文本删除受 P5e 裁定 1 约束归 P13);memo 重键已落地(P4a/P5f),补纯度 grep 门;XFB scatter 搬到 client(P5c/P5f 以 server staged shadow + OnBufferWriteback 落地;剩两处真洞:孤儿捕获目标被静默丢弃、回写事件无界——>128 KiB 即 Fatal{EventRingOverflow});删 fragColor 重推导 workaround 与 g_broadcastMemo*(动 pull .text,归 P13,只改注释);raw-depth-fetch sampler 的 monolith 清理(可选);回读收口(pack 半已关:set_pixel_pack_state APPLIER_DERIVED + server 中性读 + client 侧 PACK-PBO 散射;readback 半开:get-tex-image-shadow / copy-image-shadow-mirror 非 monolith 下仍 abort、split 零覆盖);P4a 的 R-5(D-K2 规则合一处)/ R-11 必须,R-3 / R-4 / R-7 / R-10 可选;ProgramArtifacts.h 的 NDK 尺寸钉(P6.5 portable archive v2 + 布局指纹取代);链接实验分给它的 14 个符号(D12,棘轮落地后 Tier 1) 纹理 / program 场景(split 三臂零覆盖,先普查首阻塞再注册);CTS texture_* / shader_image_* / packed_pixels + P4a 欠的 direct_state_access.framebuffers* 在 0.5 pp 内(caselist 入库 + monolith 基线 + delta 工具,今天三者皆无);每一个 Iris trace(CI 管道 P6 已建;3c80cd62 主机结果:39 例 × 双后端 × {monolith, inproc, spawn} 231 次全活,split 与 monolith 逐字节相同 70 / 77 行,7 行分歧均过阈值、无 Fatal;texture-remint-pull 未到达,P9 例外表为空——notes/p7/iris-census-1135c664.md §3–§4);TextureUploadShapeScenario 升级成门(Mali 增量无设备,按 Adreno 记录)
P7 DirectVulkan(Magma)全量迁移 进行中;wave 0–2 已落地,40% 检查点 6/9 已过(2026-09-22,origin@b089e0de + 集成树上的 B3):审计 + 五波计划见 notes/p7/PLAN-PH-P34B-P7.md §1.3 / §3,规范 MG_Remote/CONTRACT-P7.md,裁定 notes/p7/INTEGRATOR-DECISIONS-P7.md(ID-P7-1..33)。wave 0 仪器(Magma 两进程车道三臂、link_ratchet.py 186 基线、普查门 79 站点下行棘轮 + MGPipeSessionFailHook、设备跑器 --matrix/--repeat/--archive-dir、CTS caselists)origin@801f8eda;wave 1 设备窗口 #1(门 3 分母 36、E0–E7 归因、CTS $BASE 五块);wave 2 X1(arm64 persistent-map tracker 从不认领 fault)、F1(split 起会提前)、C(StateObjectDeathOps、OQ-8、OQ-10、vertex-layout 拆分)、A(对齐 / native-range)、B(mip 半退役、深度 mip 烘焙 (A)(D)、copy-image、default-color-blit、回读 fence)、B2(multisample shape/aspect、AllocatorDebtScope ×2 删、(B′)、棘轮 186→173)、B3(OpenRA 真机分歧的真因:wire 臂 completed-frame-serial floor 在中帧 pooled-fence 提交退休时无证据上升 → 帧首次 glBufferSubData 走无序 host memcpy;计数 26→0,spawn 臂 red-once;ID-P7-33)——树上 @P7 拒绝站点归零、§3.2 六退役全成、Magma 三臂 95/74/76。真机:p7w4 门 3 AFTER 34/36 与 monolith 差 ≤ 0.0005;OpenRA p7w5 27/27 golden(ID-P7-34,项关闭);bsl-esc-menu = server 死 VkBuffer 无界累积(一帧 1.3 M 调用,ID-P7-32,M2 在修)。已到集成树(2026-09-22 夜,ID-P7-37):B2 返工 r1 + r2、B3 返工 + 修复轮、V1、F 片 1–3 已推送 origin@87584d0b(2026-09-22 夜,ID-P7-39;pipe 门全绿:magma 97 / 76 / 71、full 535、verify 构建 1140 / 1074、OpenRA split 回放 0 条 unsound;四份 fable 审查 land with fixes,修复轮已落地,ID-P7-44);M2 + M2 r2 已推送(主机 bsl spawn server 825 → 546 MiB;memo destroy-epoch 关闭 wire store 句柄复用的 ABA;第二个泄漏 = descriptor set → M3;ID-P7-46);V1 修复 r2 已推送(read 侧负控数到 2、FATAL=0 摘要在 Close 前写出,ID-P7-47);在跑:F2 待派;窗口 1b 矩阵在跑(配对窗口在直连 LAN 上同样触发,ID-P7-41)。提交尾注已按用户令改写(origin 3c80cd62)。2026-09-23 更新(ID-P7-49–54):M3 已在 7ea7ce89 推送;B4 已集成于 pipe b19297d5,源码审查 land、完整集成门全绿(ID-P7-51)。p7w6 DirectGLES × TCP 38 例对照与 Photon / D24 同 APK monolith 对照已结案(ID-P7-52/53);两项错图亦在 monolith 复现。F2 PH-4/5/PH-2 已在包分支 commits 2c6a6e25 / 51480f8c 落地并通过 Luna 审查(ID-P7-54);该矩阵不替代门 3。CI 与门 4(ID-P7-55/56):CI 自 P6.5 起的七个红因已修;棘轮 171,p7-magma 余 86 标 # P13,门 4 关闭。F2 与门 5 修复(ID-P7-57/58):Ph 余项与 fuzz 三臂落地;门 5 预演的三个 inproc CTS 缺陷修掉;窗口 2 工装与判读裁定(ID-P7-59)。余:F2 PH-6 / PH-1 (3)(4) / PH-7 (5)、fuzz 臂 2 与完整包门;wave 3 棘轮 88;wave 4 CTS AFTER 和门 3;wave 5 fuzz 三臂与整体审查。逐日状态见 CURRENT_STAGE_STATUS.md 38919d45 已补实际游戏的 server buffer consumers 和 Android 旋转 blit(报告);194382c9 又完成 Magma run-ahead、GPU 延迟退休与 VAO 身份碰撞修复(报告);ed507b1a..d56c0e83 29 个 DirectVulkan 提交的 shape 波(随 e1bf3677 合入,本行此前未记)已退役 packed-float mip 原生 blit(5310ff62)、resolve(ec4ca06d)、占位图像(WirePlaceholderImages.inc)、copy-image 端点、XFB 捕获 span、纹理回读;70fb6689 链关闭 inproc RD32 性能回归(86.85→116.73 fps)。其余工作(2026-09-22 审计改判):SetupDrawSnapshot 探测字段塌成 dirty mask 与 VertexInputStateFactory 内容寻址 CSO 本阶段拒做(SetupDraw 在非 monolith 传输下分支到 SetupWireDraw,monolith 快照机制在 split 下不跑;无性能门;ID-P7-5);占位纹理原生化已落地(缺 split 车道条目);具名 UBO host payload(D-B8)走了直绑常驻 VkBuffer range 的备选,欠一次测量 + 裁定关 OQ-6;内部 shader 烘焙半已落地(颜色 blit WireColorBlitSpirv.h,仅 split 臂),欠深度 mip 烘焙 + MOBILEGL_BAKED_INTERNAL_SHADERS 新鲜度门(0 处);D18 按 ID-P7-6 读法一句闭。新增必须项:Magma StateObjectDeathOps(六处特判)、OQ-8 归档 storageBlocks(MagmaProgramSource::EnsureStorageBlocks 每 draw 重跑 SPIRV-Reflect)、OQ-10 kCapResidentSubData 从未发布(split 下双后端退回就地 memcpy)、两处 MagmaP7AllocatorDebtScope。P6 真机发现(2026-09-22 归此):DirectVulkan 分离路径在 Redmi 上两次观测 0.988998 / 0.976494(inproc 与 spawn 同表现,pbuffer monolith 1.0;case 归属、重复次数未记录,原始证据不在树内;取自 run-ahead ARMED 下,lockstep 对照从未在 golden 口径下跑过——wave 1 的 E1)——Magma × 真实 GPU;树上 @P7 具名拒绝实为 15 处 / 4 文件(multisample-blit-shape / -aspect、depth-stencil-mipmap(已窄化到 D|S 合并)、vertex-layout、vertex-format-conversion、texel-buffer-native-format、unaligned-{texel,storage,atomic}-buffer-range、storage-buffer-native-range、uniform-block-native-range、uniform-buffer-byte-tail / -dynamic-offset、copy-image-in-place、default-color-blit-shape;外加 Magma 无 StateObjectDeathOps 与 buffer-legacy-arm),全部是绕过 Session::Fail 与普查门的裸 abort;必须退役 .6/.8/.9/.11/.12/.13,其余改 decline 即可;链接实验分给 P7 的 101 个符号(D12)。DynamicBackendParameters 定宽重写不再是 P7 的——它是跨平台 wire 的前提,归 P6.5 wf 集成 + trace 在 Magma 的 push 与 split 下全绿(inproc 半已是硬门;spawn / TCP 臂今天 DirectVulkan 条目为 0——四条 split 臂硬编码 MOBILEGL_BACKEND_TYPE=DirectGLES,wave 0 补后端维度);verify 零分歧(verify 今天只注册 monolith,verify+split 撞旧 PipeRespecifyScope 断言,先清);真机 DirectVulkan split ssim 回到 1.0(分母排除 rd12 in-world 与 create-indirect,ID-P7-4;必须带 RUN_AHEAD=0 对照臂);184 符号棘轮(契约 §12.1)下降 P7 的 101 个——原 "nm -D libMobileGLServer.so | grep glslang 为空" 不可达,D12 裁定 server 镜像就是整个 libMobileGL.so;仪器 scripts/link_ratchet.py(存符号列表、只对新增红)归 wave 0;CTS 五块(texture_* / shader_image_* / packed_pixels / direct_state_access.* / uniform_buffer_object*)先立 monolith×DirectVulkan 基线再比 inproc,≤0.5 pp 且新 crash = 0 单独硬红。再基线检查点:中点完成子系统 < 40% 立即重定基线(分母 = notes/p7/PLAN-PH-P34B-P7.md §4 的 9 项)
P8 emulation 下放 + 索引宿主镜像 + 协议广度 待排 MG_Impl/Pipe/HostResolve.cpp(client 数组范围 已由 beba0256 落地为 owned buffer;最大索引扫描、*IndirectCount 解析,逐站点 reconcile);Server/IndexHostMirror 待重裁(树里 0 处;a6 §6 实测宿主索引 span 无 producer、client 索引已是 owned buffer——按 kCapNeedsHostIndexBytes 的真实消费者重新裁定,不照抄 ARCHITECTURE.md §10.3);multi-draw client indices(MultiDrawElements+CLIENT_INDICES 仍具名拒绝);CopyImage 镜像搬到 client;viewport-array 回放验证;generate_mipmap 计划 + CPU 回退纹素;texture-remint-pull 仿真下放(15 处具名拒绝);大 blob carrier 只剩 program archive 与 draw_vbo range 尾(a6 §6;与 P6.5 sl 共用同一分片);kCapDriverOrderedXfbCapture(0 处);无 present fence tick 只记在 P10 '^DirectGLES\.Split\.' 与 '^DirectGLES\.' 逐名相同;trace split 双后端 SSIM ≥ 0.99 含两个 coherent_as_flush fixture;ClientArrayAfterComputeWriteScenario;create-indirect 上 roundtrips-per-frame 读零;index-mirror-bytes 逐用例发布
P9 反向通道 待排,P6.5 之后(2026-09-22 重定范围) 异步 reply 语义,机制建立在 P6.5 的消息式 reply 之上(不再造 SEG_REPLY slot 池——池今天就有,stream 链路会删它);2 MiB reply cap 与 chunked readback(契约 §10.2.3 从 P6 改判至此,ID-47);PACK-PBO 回读 fire-and-forget + client 侧 MarkGpuWritten(ID-57,P6 未做);十个回调里未武装的四个:OnTextureWriteback、OnTexturePullRequest、OnMipLevelsGenerated、OnLog 分级(OnXfbScatterReady 是零生产者、零消费者、无 EventKind 的死声明——随 P3b/P4b 删除,kMGPipeCallbackCount 10→9;ClientSession.cpp:429;OnBufferWriteback / OnGpuWritten / OnSurfaceChanged / OnGlError / OnCapsInvalidated 已武装);OnGpuWritten 收窄;OnBufferWriteback 批处理 + epoch 排序;OnGlError 有序(CONTRACT-P5C §4.2);纹理拉取四条缓解 + 终止符;XFB 命名空间(DeleteTransformFeedback 的 server 侧泄漏——按裁定无行、最后两个 class-C 之一)。SEG_EVENT 溢出策略 机制已由 P5e 落地(ARCHITECTURE.md §11.7),剩余的"不排空对端杀宿主"归 Ph 回读 / XFB 场景在 split 下绿;TextureRemintPullScenario(含无解用例);拉取计数逐 trace 发布;两条故障注入
P10 sync / query / present 节奏 待排 client 铸造 query handle(已是:QueryCreate 为 kWaitNone);轮询入口成门铃点 + MOBILEGL_IPC_POLL_ESCALATE(0 处;TCP 上是首要杠杆之一);DirectGLES 的 fence 完成度来自逐 fence 退休(g_completedFrameSerial 仍只在 Present 前进;Magma 那半已由 run-ahead 落地);非 present fence tick(唯一记载处);present 1:1(已是);credit 默认 1(已是默认,ConfigLoader.cpp:414);PRESENT_CREDIT > 1 从未量过(重审 §8.7)——带延迟链路上的首要杠杆,inproc 臂上即可取;roundtrip 计数器与输入延迟直方图(今天只有 MapPersistentRoundtrips);SetSwapInterval(最后一个手写 class-C,EmitTables.cpp:1665) query / XFB / AsyncCompile 场景在 split 下绿;trace 上 draw / state / upload 路径 roundtrip 读零;零 timeout 轮询有界退出;credit 1..3 在 TCP loopback 与跨机臂上的配对记录;配对 A/B 记录
P11 persistent map 与 ≥16 MiB 采纳 待排,同机臂专属、已让位(2026-09-22) T0 / T1 只对共享映射成立:dataPlane = Stream 上点名 T0 / T1 是具名拒绝并强制 T2(重审 §6 第 5 项),今天 MOBILEGL_IPC_ADOPT_TIER 0/1 已是 Fatal-at-use、kSegAdopt 只有枚举;前置开放问题 3。POST 探针档位选择(T0 主攻,Adreno 可选 T1,T2 回退);SEG_ADOPT 生命周期绑 completedFrameSerial;gPipeInputs 版本化 / 双缓冲(P5d 研究:draw barrier 延后一个 verb 的前提,须在 P3b/P4b 的句柄键控 twin 表之后)。P5e 的更正:P5e 退役 draw lockstep 没有需要它——ra2 实测证明字段值已由 SuppliedFieldMask 分区,当时那次竞态在元数据标量上,修法是让守卫测事实而非断言未来(ID-135)。本行保留采纳存储的一般版本/时序问题;契约 §3.2 的 per-role stamp 已由 P5f 落地,不再是待办 LargeArenaAdoptionScenario 在所选档下绿;26.3 与两个 Create fixture SSIM ≥ 0.99;Adreno 830 上 p99 帧时与峰值 RSS 对采纳基线(163→21 ms / 40→115 fps / ~400 MB)回归不超过 10%
P12 Android 生产窗口路径 待排,Ph 之后 按重审 §6 改小:Service 收 Java Surface 删掉 Surface 传递那一半——server app 拥有自己的 SurfaceView,client 根本没有窗口,于是 minSdk 26 没有扁平化 ANativeWindow 的 NDK API 这条约束不再成立;WindowKind::ServerOwned;两个后端各一条 CreateEGLWindowSurface 臂;m_windowHandle 四处写点 + sameHandle 去重键(a6 §6);DirectGLES g_Display / g_Surface / g_Context 去全局;kEventSurfaceChanged 的 Width / Height 缺口(Espryt 只发布格式,server 拥有显示时 client 默认 FBO 会停在 512×512 占位值);client 侧不再无条件发 SetWindowHandle(BackendObject_Remote.cpp:215——今天 FCL 里开 spawn,第一次 eglCreateWindowSurface 就在 server 进程 abort);server app 监听 unix: 与 tcp://(后者 Ph 之后);server 生命周期绑 Activity;cached-app freezer(SPAWN-PLAN §8.2);多 context(契约 §11);FCL env 与 plugin APK 开关表接线 两个门:(a) Minecraft 经 FCL 同机 spawn 在 Adreno 830 双后端入世界,杀 server 产生干净 device-lost latch;(b) 另一台机器上的 client 经 TCP 在 Redmi 上进世界(数据面 stream),并记录 P6.5 的必测数
P13 退役 pull 路径 待排 删 SnapshotFromGLContext() 非 verify 分支、MGB_CTX、MOBILEGL_PIPE_PUSH、MOBILEGL_PIPE_LEGACY_MEMOS;保留 MOBILEGL_PIPE_VERIFY;MGPipe recorder;删 set_residual_value_state;在计数器活着的情况下重调幸存缓存容量;建立模块 target 与边界(D12:SOURCE_FILES 是一张平表喂两个库 target,无模块可链) static_assert(sizeof(ResidualValueBlock) == 0);三道纯度门在非 verify 构建上转绿;recorder 金标建立;monolith 逐线程 CPU 不差于 P0 基线

CTS 周转单独计价(gl44to46 约 56,271 例):逐阶段只跑该阶段可能影响的具名块;完整 caselist 只在架构边界与合并 dev 之前跑,放 CI 不放关键路径。

立即的下一项:P6.5 第一波 —— 全 TCP 传输(client 在 WSL,server 在 adb 设备)

状态:已实现并落地推送 feat/disaggregated@fe28bdb5(2026-09-22),代码审查完成(无硬缺陷 + 两修复),固定制品代表性再验收通过。 主机 unit 2399、integration-tcp loopback 102、Redmi device-102 102 全 ARMED、代表性 retrace OpenRA 1.0 全 ARMED;G1 与真实断线门通过。完整 39 例 device golden 矩阵与余下链路必测数按「本地代表性、CI 兜底」留 CI/后续,尚未宣布阶段收官;逐项见 CURRENT_STAGE_PROGRESS.md 与 notes/p65/。目标形态:x86_64 的 WSL 进程作为 client,Redmi 2f7cbe2e(aarch64,Adreno)上的 server 进程作为 server,两者在同一局域网内经 TCP 连接;integration 全部用例与 CI retrace 的 split 子集在这条链路上跑通并对上 golden。本节是 P6.5 行的第一波,只做「控制面 TCP + 数据面 stream」这一对;同机的「TCP 控制 + 共享段数据」混搭(nd auto / sd)是第二波,本节不做。

1 设计时的树上基线(实现前快照)

以下表格保留本波开工前的缺口定位;当前实现与契约更正见 MG_Remote/CONTRACT-P65.md 和阶段进度,不以历史行号描述今天的树。

已有 出处 对本波的意义
控制面 SocketTransport:Listen / AcceptPair / ConnectTo,汇合点是一个名字,两条连接按序接受(第一条控制、第二条 aux);auxFd = -1 已是「这条链不传 fd」的诚实答案 SocketTransport.h:70-91 TCP 只是第三种名字(tcp://host:port);两条连接的规矩原样用:第一条控制,第二条从 aux 变成数据流
帧:[u32 'MGLF'][u32 len][payload],FrameReader 是真正的字节流重组器 Framing.h 数据连接复用同一重组器,只换 magic
server 主程序:endpoint 来自 argv[1] / MOBILEGL_IPC_ENDPOINT;Listen → AcceptPair → 建 backend → Accept(Welcome + 七个描述符)→ 控制泵,对端 EOF 即退出;MOBILEGL_IPC_DIAL=no 反递归 ServerMain.cpp(门 8 的收尾修改已落入该文件,本表不引行号) 单会话进程形状保留为 child;设备侧要加一个 supervisor 循环
client:StartOverSocket(transport) 已把「socket 怎么来的」与握手分开;spawn 路径 = 造 @mgl-<pid>-<this> 名 → LaunchServer → ConnectTo ClientSession.cpp:693-724 Dial = Connect 只是跳过 LaunchServer、把名字换成 tcp://
握手后 client 收 7 个 fd(4 段 + 3 个门铃)再 AdoptFromDescriptors ClientSession.cpp:832-897 stream 上这一段整体不存在:段是本地私有的,门铃是本地条件变量
数据面没有缝:ILink 只有声明,树里用到它的只有 LinkProgress(Ring.h:97);ShmLink 不存在;两端 session 直接持有 SessionSegments(SessionRings.h:130);ServerSession.h:93 自己写着「lk 把门铃挪到 ILink 后面并删掉这些访问器」——没做 Ring.h:108(RingControl 重组已做)、ILink.h、StreamLink.h 重审 §5.1 那「约一周」的 lk 主体仍然欠着,是本波第一个包,没有它 StreamLink 无处可插
wire 寻址:MGPBlobRef{Offset, Size, Seg} 只允许 kSegStage,解析集中在 ResolveOrFatal PipeWireCodec.cpp:1421(拒绝其它段::496、:1401) 两端各建一个同尺寸的本地 stage 窗口、偏移一致,codec 一行不改
reply:ReplySlotHeader{Seq, Status, Size} 16 字节、seq % slotCount(8 槽) ReplySlot.h 头已经是消息形状;stream 上删掉取模与 stamp 自检
event:四种 kind、定宽头 EventRing.h 已是 wire 形状,原样装帧
指纹:CapsAbiFingerprint() = 三个 sizeof + 协议版本 + git stamp protocol.fbs table Hello 的注释 x86_64 ↔ aarch64 两份二进制:必须换成布局摘要,否则要么永远拒绝(stamp 不同)要么静默读错
日志按角色分文件;server 角色由启动方设的 MOBILEGL_IPC_ROLE=server 决定;LogLine 已在 CtrlMsg 里、零生产者 ServerSpawn.cpp:116、ClientSession.cpp:1948 34 个读 <base>.server.log 的消费方在跨机时读不到 → 日志前送(§3.5)
车道:mgl_itest_register_split_arms 一个宏两条臂 {Split, Spawn},环境差只有 MOBILEGL_TRANSPORT=spawn + MOBILEGL_IPC_SERVER_PATH MG_IntegrationTest/CMakeLists.txt:1985-2010 加第三条臂 Tcp;名集合门(scripts/ci/spawn_lane_parity.py)与 arm 证明(scripts/ci/junit_tally.py:27)各加一臂
retrace:桌面经 MOBILEGL_TRANSPORT / MOBILEGL_IPC_SERVER_PATH 环境(run_trace_case.cmake:47-52);设备经 --env K=V;… intent extra,server 路径从 nativeLibraryDir 解析(TraceReplayActivity.java:374-386);桌面与设备共用同一套 golden(trace_cases.json),驱动差异由 SSIM 阈值吸收 — 跨机 retrace 的 golden 就是现有的,不另造
设备已能从 app 进程 exec libMobileGLServer.so(spike A、spawn-acceptance 臂) apk.yml:477-487 supervisor 就是这个可执行文件加一个 --serve
manifest 没有 INTERNET 权限 android-plugin/app/src/main/AndroidManifest.xml server 要监听 TCP,trace flavour 必须加

2 拓扑:谁监听、谁拨号、为什么

server 在手机上监听,client 从 WSL 拨出。理由不是偏好:WSL2 默认 NAT,出站到局域网直通、入站要 portproxy;手机侧无防火墙。Role × Dial 两轴(契约 §3)因此在本波是 Role=Client, Dial=Connect / Role=Server, Dial=No。备用形态:adb forward tcp:40613 tcp:40613 把 server 绑在手机 loopback、client 连 WSL 内 adb 的 loopback——要求 adb 跑在 WSL 里(adb-over-Wi-Fi:adb connect <phone>:5555),因为 Windows 侧 adb 绑的 127.0.0.1 WSL2 够不着;路由器开了 AP 隔离时用它。

3 机制

3.1 端点与握手(包 ct)。SocketTransport::Listen/ConnectTo 识别 tcp://host:port(其余仍是 AF_UNIX 路径);两条 TCP 连接按序:控制、数据。socket 选项:TCP_NODELAY(批处理由我们的 publish 点决定,不交给 Nagle)、SO_KEEPALIVE + TCP_KEEPIDLE=2s / KEEPINTVL=1s / KEEPCNT=3 + TCP_USER_TIMEOUT=5000ms——Wi-Fi 掉线不产生 FIN,这是唯一能把「半开」变成挂断的机制;它以 POLLHUP/错误进入 Doorbell::Dead(),走 dl 的闩,是传输层报告的挂断,不是 apply 超时(开放问题 23)。Hello 追加 linkTerms{dataPlane=Stream, wireForm, maxReplyBytes, cmdWindowBytes, stageWindowBytes} 与 token;Welcome 回填 server 陈述的四个尺寸;新增 Refuse{code, detail, 对端值}(CtrlMsg 只追加)。buildFingerprint(git stamp)比较策略:Dial=Fork 不匹配 → Refuse(抓陈旧 MOBILEGL_IPC_SERVER_PATH,不变);Dial=Connect 不匹配 → 警告,MOBILEGL_IPC_REQUIRE_SAME_BUILD=1 时 → Refuse(车道设它:APK 与 WSL 构建必须同一 commit)。令牌:MOBILEGL_IPC_TOKEN 两端一致;server 无令牌时只允许绑 loopback,错令牌 → Refuse 并记日志。

3.2 wire 定宽与布局摘要(包 wf)。wireFingerprint = gen_pipe.py 从 PipeFields.def 生成的逐成员 {name, offsetof, sizeof} 表的摘要 + 有序目录摘要(opcode / payload 名 / flags / WaitClass)+ 记录头布局 + MGPipeRenderStateSpans 的 offsetof 表 + 两个 blob codec 版本 + kOpCount + MOBILEGL_ABI_VERSION + 字节序 + 指针宽度 + sizeof(MGPCaps) / sizeof(DynamicBackendParameters);删 sizeof(GLFunctionsTable)。x86_64 ↔ aarch64 都是 LP64、小端、Itanium ABI,布局大概率一致,但由摘要断言、不由这句话断言;已知的真实差异是 char 的符号性(aarch64 默认无符号)——wf 普查 payload 与 blob 里裸 char 当数用的站点。DynamicBackendParameters 定宽重写(从 P7 挪来)与 RenderStateParameters 1168 字节整块的成员表在此包。三条 red-once 见 P6.5 行。

3.3 缝的主体(包 lk2,零行为变化)。SessionSegments + RingProducer/Consumer + ReplySlotPool + EventRingProducer/Consumer + 两个门铃搬到 ShmLink : ILink 后面;SessionProducer / SessionConsumer / ServerLoop / PipeWireEncoder / ClientSession.cpp 的 kSegEvent 挂载 / ResourceTracker.h 的 writeback 解析都改收 ILink*;ServerSession.h:93 说要删的访问器删掉。门:inproc / spawn 车道结果数与逐线程 CPU 逐字不变(ILink::ReserveRecord 的虚调用在 ~850–3550 次/帧上实测;若不在噪声里,答案是把 reserve/commit 做成 link 自有 arena 上的非虚函数);纯度 grep 门上线。

3.4 StreamLink(包 sl)——被消息复制的镜像段。设计原则一句话:两端各自持有一份同尺寸的私有段,链路只负责把字节搬到对面同一偏移;codec、watermark 规则、apply 线程、编码器全部不变。

  • 段:握手协商后两端各 malloc 四块:cmd 环(cmdWindowBytes)、stage 窗口(stageWindowBytes)、event 环、reply 邮箱。尺寸相同 ⇒ 偏移相同 ⇒ MGPBlobRef 与 ResolveOrFatal 原样工作。
  • 数据连接帧:[u32 'MGLD'][u32 len][u8 kind][u8×3][u64 a][u64 b][payload]。C→S:Cmd{ringOffset, bytes}(记录字节逐字、写到对面环的同一偏移)、Stage{offset, bytes}、ClientProgress{cmdHead, submittedSeq, eventTail}。S→C:Progress{appliedSeq, retiredSeq, completedFrameSerial, presentAckSerial, cmdAppliedTail, eventRingFull}、Reply{seq, status, bytes}(头即 ReplySlotHeader)、Event{ringOffset, bytes}。
  • client 侧:编码器照旧写本地 cmd 环与 stage 窗口;Flush() 把 [上次已送, cmdHead) 作为一帧 Cmd 发出(环回绕用两段 iov 一次 sendmsg),之前先发本次新 stage 的 Stage 帧——顺序由编码器「先 stage 后 reserve」保证;LinkCapabilities.PublishIsDelivery=false,所以每个等待点先 Flush(这个位就是为此设的)。C→S 背压:WaitForCmdSpace 不变(读 Progress 里的 cmdAppliedTail),send() 阻塞是第二层,没有无界缓冲。
  • server 侧:mgl-srv-io 读线程把 Cmd/Stage 拷到镜像段同偏移,再推进本地 cmdHead/submittedSeq 并敲 apply 的本地门铃;apply 线程一行不改。
  • Progress S→C 的发出时机(对 Ring.h 「appliedSeq 不得懒发布」的修正案,规则改成「最多晚一次 flush,绝不早」):(a) apply 线程即将 park 前(flush-on-idle,解决「帧内最后一条 kWaitReply 记录两端互等」);(b) 每次 PostReply 之后;(c) present ack / completedFrameSerial 变化时;(d) 每 64 条已 apply 记录或 1 ms 取先到者。接收侧对每个 watermark 做 AdvanceMonotonic,倒退是 Fatal{ProtocolCorruption}。
  • reply:kWaitReply 下同一时刻最多一条未决,client 侧是「单槽 + 条件变量 + seq 核对」;本链路上 slot 池、取模、stamp 自检删除(ShmLink 保留)。
  • event:server 的 EventRingProducer 写本地环,io 线程把新增字节装 Event 帧;client 读线程写进 client 本地环同偏移,EventRingConsumer 不变;Drained() 发 ClientProgress{eventTail};server producer 在 head − 对端 tail > capacity 时阻塞(P5e 的规则原样,eventRingFull 经 Progress 回传)。
  • 门铃:ConsumerBell() / ProducerBell() 是本地 CondVarDoorbell,由各自的读线程敲;读线程见 EOF / 错误置 Dead()。每进程数据连接一条专用读线程(写在调用线程上),控制连接的读法不变。
  • 帧上限:Cmd/Stage 单帧 ≤ kMaxFramePayloadSize(64 MiB);一条记录本来 ≤ 4 MiB。未分片的 program archive / draw_vbo range 尾在 stream 上和今天一样受 stageWindowBytes 约束,超出仍是 Fatal{RingOverrun}——不是本波阻塞项,记在开放问题 11。
  • 不做的:kSegShadow / kSegAdopt(P8 / P11 的段)在 stream 上具名拒绝;GetCaps 的 blobref 若仍走 stage 之外 → 具名拒绝,本波不发明第三条载体。

3.5 日志前送(包 lf)。server 进程的日志 sink 在 MOBILEGL_IPC_ROLE=server 且有控制传输且 MOBILEGL_IPC_LOG_FORWARD=1(Dial=Connect 默认开)时,每行同时写本地 <base>.server.log 并作为一帧 LogLine(已在 CtrlMsg 里)经控制连接发出;client 收到后写入自己的 <base>.server.log。于是 34 个消费方(PipeStatsWindow 的计数器窗口、四个 arming 场景、拒绝普查)一字不改。顺序:读者在 MarkLaneLog / ReadLaneLogSince 之前调一个导出的 MGPipeSyncPeerLog()(一次控制往返:LogFlush → server 冲刷并 ack),远端不存在时它是 no-op;导出符号一个,-fvisibility=hidden 下显式 default。若 lf 滑期,退路是这 34 处在 tcp 臂上按名 SKIP(清单文件,像 dualblock-expected-fatals.txt),不许静默通过。stats 行一帧一条,前送代价可忽略。

3.6 设备侧 supervisor 与启动(包 sv)。mobilegl_server_main tcp://0.0.0.0:40613 --serve [--max-sessions 1]:listen → 循环 { AcceptPair(控制 + 数据)→ fork() → child 关掉 listen fd、用 SocketTransport(streamFd, dataFd) 走今天的单会话路径到 _exit;parent 关掉已接受的 fd、非阻塞 waitpid、继续 accept }。每会话一进程 ⇒ eglTerminate 的进程级拆机被隔离(D9 原样);同时只服务 1 个会话,第二个连接 → Refuse{Busy}。启动:trace flavour 新增前台 MobileGLServerService(android:process=":mglsrv"),am start-foreground-service 带 --es listen、--es token、--es env "K=V;…"(复用 --env 的 K=V; 语法),它从 nativeLibraryDir exec libMobileGLServer.so(spike A 的路径)、给 child 设 MOBILEGL_IPC_ROLE=server、持 partial wake lock;am force-stop 整包停掉。后端由 client 的 Hello.backendType 请求、supervisor 的 env 可钉死,不一致 → Refuse。EGL 在 child 里是 pbuffer / surfaceless(P6 边界;真窗口归 P12)。manifest 加 INTERNET。

3.7 谓词与测试的拓扑感知。client 进程:Transport=Spawn(拓扑:两进程)、Dial=Connect、不 fork;MGPipeBackendIsLocal()=false。CountOwnChildren() 一类断言改为按 Dial 分支:Connect 下断言本地零子进程 + Welcome::serverPid 非零 + 日志 control=tcp。S2(kill server)在跨机臂上经 MGITEST_PEER_KILL_CMD 模板(adb -s <serial> shell run-as top.mobilegl.plugin.trace kill -9 {pid})真杀——不允许用协作式「请你退出」代替,那测的不是挂断。

4 包与顺序

lk2(缝主体,零行为)→ wf(定宽 + 摘要 + Refuse)→ ct(tcp 端点 + keepalive + 令牌 + Connect 拨号)→ sl(StreamLink,先在 WSL loopback 上对着 spawn 车道打平)→ lf(日志前送)→ sv(supervisor + Service + adb 脚本)→ t65(tcp 臂、跨机臂、门、数)。每包 red-once(R-16)。第二波(不在本节):nd 的 auto 与 sd 的 aux 交付(同机 TCP 控制 + 共享段数据)、P11 的 stream 具名拒绝、Windows client。

5 出口门(本波)

  1. G1 pull 0/0/0/0、.text 不变(全部新代码在 MOBILEGL_BUILD_DISAGGREGATED 下)。
  2. lk2 后 inproc / spawn 车道结果数与逐线程 CPU 逐字不变(实测,不论证)。
  3. integration-tcp(WSL loopback,server 以 --serve tcp://127.0.0.1:40613 本地起):名集合 == spawn(parity 脚本加臂)、同数绿;每条目 arm 证明 control=tcp data=stream server=<host:port> pid=N(junit_tally --require-tcp-ran)。
  4. integration-tcp-device(server 在 Redmi):同一名集合;首轮记录、不设阻塞门,每一条与 loopback 臂的差异必须具名(GPU 能力 / P7 的 Magma 分歧 / 时限);第二轮起转硬门。
  5. retrace:CI split 子集(trace_cases.json 里未 "split": false 的)从 WSL 对着手机跑,DirectGLES 的 SSIM ≥ 现有阈值、OpenRA 为 1.0(E2 的锚);DirectVulkan 记录不设门(真机分歧是 P7 的)。
  6. red-once:wf 三条(P6.5 行);ct——错令牌 → Refuse、wireMajor 不匹配 → 两端具名拒绝、adb shell svc wifi disable → 10 s 内闩住(而不是 120 s BarrierTimeout);sl——Progress 倒退 → Fatal{ProtocolCorruption}、越窗的 Stage 帧 → 拒绝、去掉 flush-on-idle 后「帧内最后一条 kWaitReply」用例必须挂住并被超时抓到;lf——关掉前送后四个 arming 场景必须按名红;sv——第二个并发连接 → Refuse{Busy}。
  7. 必测数(记录):逐帧 kWaitReply 次数与 RTT 分布(OpenRA、MC in-world 各一);SEG_STAGE 字节/帧对链路实测吞吐(车道自己量一次 64 MiB Stage 突发);PRESENT_CREDIT 1 / 2 / 3 的帧率;loopback tcp+stream 对 spawn(unix+shm)的逐线程 CPU 差。

6 两边怎么配(第一波操作手册)

手机(server)

# 1. 同一 commit 构建 trace APK(分离构建)并安装
./gradlew :app:assembleTraceDebug -Pmobilegl.buildDisaggregated=ON && adb install -r app/build/outputs/apk/trace/debug/*.apk
# 2. 手机 IP
adb shell ip -f inet addr show wlan0
# 3. 起 server(前台 Service → supervisor 监听)
adb shell am start-foreground-service -n top.mobilegl.plugin.trace/top.mobilegl.plugin.MobileGLServerService \
  --es listen tcp://0.0.0.0:40613 --es token devtoken-0123456789abcdef \
  --es env "MOBILEGL_BACKEND_TYPE=DirectGLES;MOBILEGL_PIPE_STATS=1;MOBILEGL_PIPE_STATS_PERIOD=1;MOBILEGL_LOG_FILE_PATH=/data/data/top.mobilegl.plugin.trace/files/mgl.log"
adb logcat -s MobileGL | grep -m1 'listening on tcp://'
# 停:adb shell am force-stop top.mobilegl.plugin.trace

WSL(client),在分离构建目录(今天是 ~/lk-split):

export MOBILEGL_TRANSPORT=spawn                 # 拓扑:两进程;不 fork,因为下面给了远端
export MOBILEGL_IPC_CONTROL=tcp://<phone-ip>:40613
export MOBILEGL_IPC_DATA=stream
export MOBILEGL_IPC_TOKEN=devtoken-0123456789abcdef   # ≥16 字节(PH-7 (3)):更短的令牌让 server 以 72 退出而不是监听
export MOBILEGL_IPC_REQUIRE_SAME_BUILD=1        # APK 与本地构建必须同 commit
ctest -L integration-tcp-device -j 1 --output-on-failure   # -j 1:设备同时只服务一个会话
# retrace(同一环境):
(cd build-retrace/tools/trace_replay && ctest -V -R '^MobileGLTraceReplay\.OpenRA\.DirectGLES$')

日志:client 侧 <base>.client.log 与前送来的 <base>.server.log 都在 WSL;设备本地副本用 adb shell run-as top.mobilegl.plugin.trace cat files/mgl.server.log。

备用(AP 隔离 / 没有局域网直通):adb 跑在 WSL 里——Windows 上一次 adb tcpip 5555,WSL 里 adb connect <phone-ip>:5555 && adb forward tcp:40613 tcp:40613;手机侧 --es listen tcp://127.0.0.1:40613(loopback,不需令牌),WSL 侧 MOBILEGL_IPC_CONTROL=tcp://127.0.0.1:40613。

7 风险与未决(本波)

  1. kWaitReply × RTT:ResourceCreate / SetTextureParams / 纹理 ResourceSubData 每次一个 RTT(Wi-Fi 2–5 ms);MC 加载区块的创建突发会可感知地慢。本波只量(门 7),减少这一列是 P9 / P10 的活。
  2. 带宽:SEG_STAGE 字节/帧对 Wi-Fi;单次 128 MiB 上传 = 秒级停顿(开放问题 19、20)。
  3. Wi-Fi AP 隔离:用 §6 的 adb forward 备用。
  4. DirectVulkan 真机分歧(P7)会在门 5 出现:记录,不当本波的红。
  5. MOBILEGL_IPC_ROLE:supervisor 必须替 child 设它,否则 child 的日志会当 client 写(Log.cpp 从这个 env 解析角色)。
  6. ctest 并行 vs 一设备一会话:-j 1 或 supervisor --max-sessions N(每会话一进程,N 个 EGL 上下文同时存在,Adreno 上未验证)。
  7. 同 commit:两端二进制不同是常态,指纹只保证 wire 布局;REQUIRE_SAME_BUILD 是车道纪律,不是协议要求。

历史:P5c 计划与审计(inproc 共享内存读点;审计头 a79a0af6,2026-09-17)

为什么插在 P6 之前:P5 / P5b 的 inproc 只把 verb 记录、SEG_STAGE blob、reply 与 caps 快照做成了 wire。对 a79a0af6 的只读静态审计(~/w7/notes/p5c/p5c-audit-v1.md,59 行清单,逐条在该头上重新解析)证明两个角色之间仍有一批不经任何载体的直接内存读写,靠 verb barrier 与同一地址空间才正确。它们不是传输问题:spawn 换掉的只是 ring 的传递方式,而这些读写在另一个进程里根本没有对应内存。P5c 的目标是让 inproc 诚实——两线程之间除 SEG_CMD / SEG_STAGE / SEG_REPLY / SEG_EVENT / caps 快照 / 控制帧之外零直接访问——从而 P6 只是传输替换。本节保留 P5c 启动时的计划与审计语境;P5c 已收官,后续对象类、控制帧、静态量与反向通道的收口结果以 P5f 报告为准。

审计清单(按家族;file:line 以 a79a0af6 为准,完整 59 行见报告)

# 方向 直接访问的是什么 站点 今天为何能工作 现有守卫 P5c 载体
T1 S→C 读 纹理纹素:resource_subdata 已把 level 字节放进 SEG_STAGE,但 ApplyTextureUpload 只做门与累积、把指针丢掉,Espryt 同步时从 client 的 MipmapStorage 重读纹素;纹理对象的形状与脏区也直接读前端对象 丢指针 MobileGL/MG_Pipe/PipeApply.cpp:989-1008;重读 DirectGLES/Managers.cpp:7315(MapMipmapData)、:6940、:7129、:7198;形状 :7314、:7332、:6878-6880、DirectGLES/DirectGLES.cpp:8502-8507、:8528-8529;脏区 DirectGLES/Managers.cpp:7360、:7371 barrier + 同地址空间 无:整个纹理家族不在 FieldOwnership.def,rsp / MOBILEGL_IPC_STRICT_ERRORS / MOBILEGL_IPC_AUDIT 都看不见 server 端纹理 staged shadow(buffer StagedShadowStore 的纹理半边);SyncMipmapsToBackend 改读它,形状与脏区读描述符
T2 S→C 读写 client 的 slot 分配器 MGPipeSlots():mip / CopyTex / twin 创建时按前端 GetLifetimeId() 在 client 分配器里查找甚至铸造 DirectGLES/DirectGLES.cpp:8087 → DirectGLES/SlotTables.h:392-400(HandleOf → FindByLifetimeId);铸造 DirectGLES/SlotTables.h:232(GetOrCreate)、:418、:428;DirectGLES/Managers.cpp:2708、:4293、:5627;DirectGLES/DirectGLES.cpp:6706、:8185、:8564、:8659 barrier;mip 只 Find 不 mint 无(MOBILEGL_ASSERT 在 INFO 构建失效) 记录已带句柄(MGPMipPlan::Res、MGPCopyFromFramebuffer::Dst、MGPBlit::ReadFbo/DrawFbo)→ GetOrCreate(MGPipeHandle)(DirectGLES/SlotTables.h:278)
T3 S→C 读 具名 blit:client 临时改绑自己的 read / draw 绑定槽,server 经 MGB_CTX 读绑定槽 client MobileGL/MG_Remote/Client/EmitTables.cpp:741-786;server DirectGLES/DirectGLES.cpp:7782-7785 barrier + RAII 恢复 rsp(GetFramebufferBindingSlot) 记录里的 ReadFbo / DrawFbo,sink 侧按句柄解析(MobileGL/MG_Remote/Server/PipeApplier.cpp:228-244)
T4 S→C 读 CopyTexImage2D / CopyTexSubImage2D 经纹理单元绑定槽取目的纹理 DirectGLES/DirectGLES.cpp:8561-8563、:8656-8658 barrier rsp(GetTextureUnitObject) 记录里的 Dst 句柄
T5 S→C 写 Magma 生成 mip 直接写 client 的 level 存储(Espryt 的重推导臂没有 Magma 对应) DirectVulkan/Renderer/VulkanRenderer.cpp:1562-1590(调用 :11317) barrier 无 与 GLES 同形:只按描述符验证
B1 S→C 读 BufferObject::HasDefinedContent(),每个 ensure 的 draw 都读 DirectGLES/Managers.cpp:3147-3148(EnsureBufferResourceForHandle;:3141-3146 自述为债) barrier 无 描述符旁的 live-content 位,client 发布
B2 S→C 读 HandleOfBuffer 每次 ensure 读前端 GetLifetimeId() DirectGLES/Managers.cpp:2705-2716 barrier + memo 无 记录里的句柄
B3 S→C 读 旧 buffer 臂(MappedData() / IsMapped() / GetChangeSerial())在 split 构建里位 7 清零时可达,arm resolver 只打一行 MGLOG_D DirectGLES/Managers.cpp:2586-2620;臂体 :1012-1022、:1119-1121、:2944-2949、:3281-3327 同进程 无 有传输时具名拒绝(同 Fatal{PipeLegacyMemosDisabled} 的形状)
B4 S→C 读写 XFB:SharedPtr<BufferObject> 跨整个 span 持有,结束时 WritebackFromBackend,scatter 对 client shadow 读改写 DirectGLES/DirectGLES.cpp:950、:1060、:1077、:1081、:1172、:1185 barrier 无 OnBufferWriteback / OnXfbScatterReady 事件——P9 的题材,P5c 只记账
R1 S→C 写 反向通道是 apply 线程直接调进 client 的 MG_State:OnBufferWriteback 把裸指针塞进 MGPBlobRef.Offset,client 侧再转回指针;consumer 会拒绝任何真实段 生产 DirectGLES/Managers.cpp:2339-2343(Ops_H_Readback);消费 MobileGL/MG_Impl/Pipe/ResourceTracker.h:553-572(拒绝真实段 :560-564) 同地址空间 + barrier 无 SEG_EVENT kEventBufferWriteback:consumer 已在(MobileGL/MG_Remote/Client/ClientSession.cpp:176-267),全仓零 producer(MobileGL/MG_Remote/Server/ServerSession.cpp:484-492 无调用者)
R2 S→C 写 OnGpuWritten 直接调进 client tracker;Magma 更是绕过回调直接 MarkGpuWritten() Espryt DirectGLES/Managers.cpp:2729-2752,喂入 DirectGLES/DirectGLES.cpp:568、:616、:2601;Magma DirectVulkan/Renderer/UniformManager.cpp:1075、:1231、DirectVulkan/Renderer/VulkanRenderer.cpp:11618 同地址空间 MGLOG_E_ONCE SEG_EVENT kEventGpuWritten(consumer MobileGL/MG_Remote/Client/ClientSession.cpp:227-236)
R3 S→C 写 默认 framebuffer 附件(pDefaultFramebufferInfo)由 server 在 surface 创建时写 DirectGLES/DirectGLES.cpp:11519-11620;Magma DirectVulkan/Renderer/SwapchainObject.cpp:276-335 barrier;罕见 无 SEG_EVENT kEventSurfaceChanged(consumer stub MobileGL/MG_Remote/Client/ClientSession.cpp:242-253)
R4 S→C 写 sticky forward:RecordError 写 client 错误队列;InvalidateCompileEnv 写 client 编译环境(在 stamped verb 之外静默 no-op) MobileGL/MG_Impl/Pipe/PipeFill.cpp:1753-1756、:1764-1772 barrier rsp;strict 下 Fatal RecordError → OnGlError 事件(顺序保证是 P9 的);InvalidateCompileEnv 的活已由 R-12 caps 重发布完成(MobileGL/MG_Remote/Client/CapsMirror.cpp:78-80),删 forward
R5 — MGPipeCallbacks 十个回调只装了两个,且都是 apply 线程内联调用;SEG_EVENT 段已创建、映射、握手公告、每个 reply verb 后排空,但没有任何生产者 安装 MobileGL/MG_Impl/Pipe/ResourceTracker.h:606-613;段 MobileGL/MG_Remote/Server/ServerSession.cpp:285-301;排空 MobileGL/MG_Remote/Client/ClientSession.cpp:836 — 溢出 latch 与 eventDropped 已建未用 本身就是载体
C1 S→C 读 Magma 四处直接读 client 镜像 pActiveBackendObject->GetDynamicParameters()(Espryt 已改走 server 自己的 backend);Espryt 的格式表回落臂在 server backend 为空时读 client 镜像 DirectVulkan/DirectVulkan.cpp:713-715;DirectVulkan/Renderer/VulkanRenderer.cpp:667-676;DirectVulkan/Renderer/VertexInputStateFactory.cpp:249-250、:502-503;DirectGLES/Utils.cpp:50 镜像值等于快照 无 server 自己的 Backend()->GetDynamicParameters();回落臂拒绝
G1 shared gPipeInputs:client 残余填充写、applier 写、server 的 36 行 BARRIER-PULLED 读 MobileGL/MG_Backend/MGPipe/PipeInputs.h:806;填充 MobileGL/MG_Impl/Pipe/PipeFill.cpp:2798;applier MobileGL/MG_Pipe/PipeApply.cpp:1415-1560;stamp MobileGL/MG_Backend/MGPipe/PipeInputs.cpp:103-132;rsp MobileGL/MG_Backend/MGPipe/PipeInputs.cpp:72 只靠 verb barrier 保证单写者 rsp + strict Fatal + poison 值类行(GetActiveTextureUnit、GetMaxTouchedTextureUnit、GetTouchedBufferBindingPointCount、GetCurrentVertexAttribute、XFB 六项、三个世代)→ 每 verb 一条残余值记录或按 Coverage.def 由 server 自答;对象类行(GetBoundVertexArray、GetProgramForDraw/Dispatch、GetTextureUnitObject、GetImageTextureBinding、GetFramebufferBindingSlot、GetBufferBindingSlot/Point、sticky GetTextureObject / GetProgramObject)返回前端对象指针、无法序列化,留 P3b/P4b/P7/P8 的 twin 表
G2 C→S 写 GL 线程在 FreshlyPrimed 时整体 MGPipeApplierReset() server 的 g_applier MobileGL/MG_Impl/Pipe/PipeFill.cpp:2654-2656 → MobileGL/MG_Pipe/PipeApply.cpp:1202-1299 barrier 的后置条件(validate 时无在飞记录) 无 make-current 边上的 applier_reset 控制记录
G3 C→S 写 六种前端对象死亡:栈上结构体指针经 mailbox 送到 apply 线程(framebuffer 没有 wire delete opcode) DirectGLES/Managers.cpp:206-228 阻塞 + 同地址空间 无 object_death wire 记录
G4 C→S 控制 十二个 Server* EGL forwarder 经 one-slot mailbox 传函数指针 + void* 栈局部 MobileGL/MG_Remote/Client/BackendObject_Remote.cpp:125-264;邮箱本体在 fc 前的 HEAD 上是 ServerLoop.cpp:533-568(PumpControlRequest)+ :645-707(RunOnApplyThread)——本行原引 :543-598,f0-egl F9 修正 阻塞 Fatal{ApplyThreadNotRunning} 已由 P5f 包 fc 帧化(原记 P6):SurfaceControlFrame 纯值帧走同一阻塞通道(Server/SurfaceControlFrame.h、分发 ApplySurfaceControlFrame),wire 编解码与具名拒绝在 Protocol/SurfaceOpCodec.cpp;报告 notes/p5f/fc-report.md
G5 C→S 读 ServerLoop::OnApplyThread() 每条 routed 记录读;bring-up 直接读 loop.Backend() / MGPipeGetResourceOps() MobileGL/MG_Remote/Client/WireTables.cpp:71;MobileGL/MG_Backend/Init.cpp:100、:145、:164-170、:247 同进程 — client 本地角色标志;caps 快照的 cap 位(P6 顺手)
G6 shared 前端地址 / lifetime-id 键控的 Espryt twin registry;持前端裸指针的 memo(ResolvedDrawBuffers::Entry::frontend、三张 texture sync list);server 读 pDefaultFramebufferInfo;g_rawDepthFetchSamplerState;ScopedDefaultUnpackState::s_synced 从不按 context 世代重置 DirectGLES/Managers.h:309-377、:1185;DirectGLES/DirectGLES.cpp:61-62、:1958-1987、:2846;DirectGLES/Managers.cpp:5806-5812 barrier / server 私有 — 历史移交给 P3b/P4b / P6;transport registry 与 s_synced 世代问题已由 P5f fr / fs 收口
A1 — barrier 的 client 半边断言从未接线:InBarrierWait() 零调用点,只有 ApplyThreadIsInsideApplier 在 emit 时检查 MobileGL/MG_Remote/Client/ClientSession.cpp:880、:748-753 — — 接上,或删掉契约里的这句声明

已确认 wire-clean、不进 P5c:buffer 全家族(Ops_H_* 只拿句柄 + 记录 + SEG_STAGE 字节,StagedShadowStore::Adopt 复制,Fatal{StageSnapshotTooNarrow} 六处);resource_respecify 初始字节双向拒绝;persistent map 仿真档按块过 SEG_STAGE,Fatal{RoleViolation} 挡住 apply 线程;CreateShaderState 归档是一个 blob;caps 的格式表与 renderer 字符串走 CapsSnapshot 控制帧(GetCaps 记录本身已死,只是卫生项);tight ReadPixels;DrawVbo 用户索引;fence 家族;gMGPipeSegmentResolver 与 gBackendFunctionsTable 的角色划分。

包与顺序

包 内容 关闭的行
c0c 契约 MG_Remote/CONTRACT-P5C.md:纹理 staged shadow 的所有权与覆盖规则;SEG_EVENT 记录与 blobref 约定(Seg = kSegEvent);sink / twin 按句柄解析的规则;applier_reset / object_death 记录;角色守卫的语义(有传输时 apply 线程触前端对象表面、GL 线程触 server 状态表面都是 Fatal{RoleViolation});残余值记录的字段表;把纹理家族补进 FieldOwnership.def —
tx 纹理 StagedTextureStore:ApplyTextureUpload 采纳 SEG_STAGE 字节到 server 侧 level shadow;SyncMipmapsToBackend、形状读、脏区改读描述符与 shadow;Magma mip 改按描述符;MOBILEGL_IPC_AUDIT 的 0xDD 覆盖纹理 T1、T5(T2 的 mip 半边随之)
ev 反向通道 ServerSession::PublishEvents 接三个 producer(writeback / gpu-written / surface-changed),consumer 的段臂改为解析 kSegEvent;Magma MarkGpuWritten 改走回调;RecordError 进事件(顺序仍 P9);删 InvalidateCompileEnv forward;溢出策略沿用 ARCHITECTURE.md §11.7 R1–R5
hd 句柄解析 blit / mip / CopyTex / HandleOfBuffer 的 sink 与 twin 按记录里的句柄解析(GetOrCreate(MGPipeHandle)),server 不再触 MGPipeSlots();HasDefinedContent 改读描述符的 live-content 位;Magma 四处 caps 读改 server backend,Utils.cpp 回落臂拒绝 T2、T3、T4、B1、B2、C1
ct 控制记录 applier_reset 与 object_death 两条 wire 记录(framebuffer 首次有 delete opcode);mailbox 只剩 EGL forwarder 给 P6 G2、G3
rv 残余值 值类 BARRIER-PULLED 行改为每 verb 的残余值记录(或 server 自答),gen_pipe_field_ownership.py 把它们改成 RECORD-SUPPLIED;对象类行保持 BARRIER-PULLED 并逐行标注归属阶段 G1 的值类半边
gt 门 角色守卫(两层 Fatal{RoleViolation},仅 split 构建、有传输时生效);InBarrierWait 接线;旧 buffer 臂传输拒绝;rsp 按帧进 stats 行并在四条 A/B trace 上测得;CI 加一条 MOBILEGL_IPC_STRICT_ERRORS=1 + 角色守卫的 integration-split 车道 A1、B3,以及所有行的红一次证据

顺序:c0c → tx / ev / hd 并行 → ct / rv → gt 收口。每包自带 red-once(R-16),阶段末一次 Codex / Kimi 审查(ID-66)。

出口门(E-P5c)

  1. 角色守卫下全绿:守卫开启时 integration-split(107)、broad inproc 车道对 348d22a4 普查零回退、79 trace 无新增首阻塞;关掉任一层守卫必须能在一条具名用例上变红。
  2. 纹理字节不再回读 client:MOBILEGL_IPC_AUDIT=1 对纹理 staged 字节的 0xDD 填充在四条 A/B trace 上无失败;把采纳改回丢指针必须变红。
  3. SEG_EVENT 有生产者:三条事件的往返单元与集成用例;排空点上 eventDropped == 0;把 producer 改回裸指针必须变红。
  4. rsp 分类完成:四条 A/B trace 每帧 rsp 已测;剩余读全部是对象类行,名单由 FieldOwnershipTest 钉住,值类行为 0。
  5. Redmi 四臂复测(记录,不设门):writeback / gpu-written 改走事件后 barrier tax 重新记录。
  6. G1 0/0/0/0、G2 / G14、G5 照旧。

历史移交项(P5c 当时不碰)

P5c 当时移交的对象类 BARRIER-PULLED、transport registry 前端键、EGL 控制面、s_synced / g_syncedRenderStateParameters 世代与反向通道跨角色访问,已在 P5f 收口。P9 的异步化/排序、P8/P9 的协议广度与仿真功能仍按各阶段推进;不要把这份历史清单重新当成 P6 的帧化或静态量施工单。

里程碑

  • P2 出口(2026-09-08):GO/NO-GO 判定继续——五部分门全绿,逐线程 CPU 代价约 +10% 被接受;tracker 绝对 ns 上限降为记录项。
  • P3a / P4a 出口(2026-09-08):各 1 天,远低于 27 / 39 天的再基线绊线,未触发重定基线。
  • P5 出口(2026-09-16):缩减路径首个 IPC 帧;最终全门在 E3(a) 停止;红米四臂的 split 均停在索引 draw,barrier tax 未测(归 P5b)。
  • P5b 出口(2026-09-16,已达成):主机全门 348d22a4 complete;79 trace 72/6/1;设备源头 82683d4a(APK p5bcodex2)Redmi 正确性 8/8——四条 A/B trace 双后端首次在设备上 inproc 渲染;barrier tax 首测 split−push 逐线程 CPU p50 +5.9% – +18.2%。
  • P5f 出口(2026-09-20):双块和 strict 空棘轮、逐帧 rsp=0、零 BARRIER_PULLED、主机全门、异模型族审查修复和 Redmi 六 clean-boot 臂全部完成;P6 前提解除,实施未开始。
  • CI / inproc 收尾出口(2026-09-21):feat/disaggregated 主产物拆分编译 + inproc 主验收全绿——unit 2328 零失败、integration-gpu 双 transport 各 1455 零失败、retrace 77 例 monolith 77/77 且 inproc 的唯一间歇项(bsl-esc-menu-854 DirectVulkan,lavapipe 固有 texture-handle 注册停顿越过旧 30 s barrier 预算)在预算修正为 120 s 后隔离 10/10 绿、18 项 CI 门全绿、双 ABI APK 与 AVD 生命周期验证通过;合入头 e1bf3677,最终矩阵以远端 CI 为准。
  • P6 收官(2026-09-22):a6/c6/lk/so/sm/cp/hs/dl/st/t6 十包于 2026-09-21 合入 feat/disaggregated(头 77cbd176);三种传输(monolith/inproc/spawn)桌面与真机两进程 retrace 逐像素对上 golden;device-lost 闩把杀 server 从 123 s 错误 BarrierTimeout 变 5.7 s 正确 DEVICE LOST;Session::Fail 漏斗把裸 abort 93→4。出口门 1–6 ✅;门 7 / 8 于 2026-09-22 采齐:真机 reboot-clean 同热窗口配对 A/B 六臂 18/18 runner 退出 0、36/36 PINNED、0 Fatal,inproc vs spawn 的 client CPU p50 差 −0.15%(第二会话 +0.16%)——判读 tie(臂内散布 0.2–4.2%),monolith 基线约贵 30%;门 8 三数齐(门铃 A/B tie、SEG_STAGE 字节/帧、分块后记录/帧);G1 符号 0/0/0/0 且 .text 逐字节相同。P6 就此收官,未设性能门(只记录)。逐项见 CURRENT_STAGE_PROGRESS.md。
  • 终局改判(2026-09-22):AVF pVM / AF_VSOCK 终局撤回,改为 TCP 跨机跨平台 + 控制面 × 数据面两轴传输栈;P6.5 上关键路径,Ph 前置于 P12 的非 loopback 监听;P6 核出三项漏项(server 进程 PipeStats 结构性零——收尾中已修、184 棘轮门、hs 的三行契约未落地)与 CURRENT_STAGE_PROGRESS.md 里一条错误的 S6 陈述(已改);class-C 已归零到两个(SetSwapInterval、DeleteTransformFeedback)。
  • P7 wave 2 落地(2026-09-22):X1 / F1 / C / A / B / D1 / D2 / D3 / B2 / B3 十包合入 feat/disaggregated(origin@b089e0de,B3 在集成树上待推),每包八车道全绿、G1 恒等、每包一条两进程臂 red-once、每包一次 fable 聚焦审查;子系统分母 6/9 于 B2 落地时越过 40% 中点,不触发重定基线。真机 p7w4:门 3 34/36 与 monolith 同;OpenRA 的两个历史点值(0.976494 / 0.988998)被证明是同一帧一次 draw 的顶点前缀撕裂——wire 臂的 frame-serial floor 不健全,B3 关闭;bsl-esc-menu 是 server 死 VkBuffer 无界累积,M2 + r2 已落地(主机 spawn server 825 → 546 MiB;真机验收待 p7w6)。
  • 仍是方向、不据此伪造新日历:全功能 split(P8 之后)、纯度门在非 verify 构建上转绿(P13)。

再基线检查点仅剩一条:P7 中点完成子系统 < 40% 立即重定基线(P3a 的检查点发现不了 Magma 特有的超期)。

P5 / P5b 出口记录的债务

债务 去向 / 当前口径
P5 的 27 个普通 inproc wrong-answer(历史计数) 已结(2026-09-22,3c80cd62 同名重跑,MEASUREMENTS.md §7.2;inproc 与 spawn 逐名相同):原「22 → P4b/P7 texture readback」→ 19 绿(14 layered、3 packed depth/stencil、2 framebuffer recycle),余 3 条 framebuffer recycle 由错答变为具名停止——三条都是 integration-monolith-control 里 MOBILEGL_PIPE_PUSH=0 的对照臂(DG Legacy → Fatal{PipeLegacyMemosDisabled};DV Legacy / AbaControl → Fatal{UnmigratedVerb, "Magma:clear-framebuffer-record"}),旋钮在 split 下没有臂,不是 readback 欠账;原「3 → P7 query」→ 3 绿;1 inspection(TextureParamsWithoutASamplerView)→ 绿,「待核」关;1 FBO/RBO delete → 绿。同一重跑的 1267 名合并 lane 普查 811/203/62/191 → 1051/172/37/7,44 条非绿全是钉了非默认 MOBILEGL_PIPE_PUSH 的对照臂
rsp residual inputs P5f 已关闭残余读取:字段归属 41 record / 6 derived / 0 barrier / 16 fatal;strict 与双块 marker 表均为空,双后端逐帧 RSP 门 2 PASS / 0 skip,Redmi 36 个统计窗口 rsp=0。P5e 的“rsp 只计被采纳设障 pull”是历史计数规则,八对 admitted 的历史观察不再是当前允许集合
SEG_REPLY 2 MiB 单槽 payload cap → P9(契约 §10.2.3 改判,ID-47);stream 链路上 reply 本就是消息,cap 变成 P6.5 nd 的 maxReplyBytes 窗口
GetCaps 的两个 blobref 目前不骑 record;一旦运输,必须有 server→client carrier rule,不能套 SEG_STAGE
PACK-PBO readback P5 曾具名拒绝;70df57bb(2026-09-20)起 client 侧已实现(bounce 紧凑 reply + 按 PACK 步长逐行 UploadSubData,EmitTables.cpp;glGetTexImage 同形且按 MaxReplyBytes 分块);剩余只是 fire-and-forget(MarkReadPixelsPackBuffer 全仓无生产调用者)→ P9(ID-57)
ABI fingerprint 已由 P6.5 wf / nd 落地(fe28bdb5):wireFingerprint 布局摘要 + buildFingerprint 拆分(只在 Dial==Fork 或 MOBILEGL_IPC_REQUIRE_SAME_BUILD=1 下比较)、LinkTerms 四个尺寸由 server 陈述、DynamicBackendParameters 定宽;CONTRACT-P6.md:666 仍把定宽记在 P7 名下,待改
默认 32 MiB staging 目标负载单次 128 MiB 上传装不进默认 stage;内容侧分块已落地(buffer 范围走查 1e7c372e、纹理整宽 slab 9469d48e,预算 MGPipeStageChunkBytes() = 默认 segment/4 = 8 MiB),故普查 / Redmi 的显式 256 MiB profile 不再是这两条路径的必需;未接入分片的 record 类型与专用 carrier 仍归 P8(开放问题 11)
P5b 的 inproc 依赖 历史的 scoped client binding、mip registry 查询与 FBO death mailbox 已经 P5c/P5f 改为记录、句柄和控制/事件路径;P6 核验并装配已有载体,不再重做这些迁移
未迁移与仿真路径 class-C 已归零到两个(2026-09-22 核):EmitTables.cpp 的 MGR_UNMIGRATED_* 列表全空,只剩手写的 SetSwapInterval(P10)与按裁定无行的 DeleteTransformFeedback(P9);契约 §11 / SPAWN-PLAN §8 的"511 class-C entries"是 P5 joint 树上的旧普查(notes/p6/census-classC.md),不是当前数;client vertex arrays(已实现:beba0256 起 wire 复制到 owned buffer 并保留 baseVertex/baseInstance/drawID,本轮补齐 monolith 臂 62bfe461..e258a822)、multi-draw client indices、RGB 三通道 CPU mip、renderbuffer copy endpoint、未绑定 named clear、texture-remint-pull 仿真保留具名拒绝 → P8 / P9;Magma split compute / image 的“82 个错答”是 P5b 历史普查计数,不是当前失败清单;P5f 后续已补应用 buffer consumers 与 Android 旋转 blit,Magma inproc 已能运行所测 MC 世界;后续 run-ahead 已完成(报告);XFB、部分不对齐范围、placeholder/native-format 及进一步性能工作仍归 P7(报告)
E2 wire 内容控制 draw-drop 是 OpenRA 的有效控制(758 draws,SSIM 0.000036);clear-drop 被全屏 overdraw 掩盖,不能作控制
max record bytes 实测 reduced / OpenRA maxrec=784 B,默认 cap 4 MiB;只代表所测负载,后续索引 / indirect 尾仍须记录
树外脚本 普查跑器、wsl_p5_gate.sh、Redmi 定频行都在 ~/w7/notes/,git merge 不会传播
临时 CI trigger 合入 dev 前删除 test.yml / apk.yml 的 feat/disaggregated TEMPORARY trigger

开放问题

P0 已回答的不再列出(spike A 的域、spike B 的分档、posix_spawn 不可用、OOM 探测惯用法、GetInteger64i_v/GetProgramiv 退役、D21 与 RenderbufferObject lifetime id、动态 accessor 基线)。

  1. client 侧 dirty 走查的真实每 draw CPU 代价。 已答(P2–P4a):推送没有在拉取基线之下净减少;Release 下 P2 边界 +6–12%,P3a 在 VAO 切换密的 rd12 上再加 +17–19 pt,P4a 在 Espryt 上 +3.4–5.7 pt(MEASUREMENTS.md §3–§5)。用户 2026-09-08 接受,性能自此只记录。
  2. 真实语料上纹理重铸拉取的发生率。 已答(P4a):可忽略,保留 LRU 维持默认 0——79 例 × 两后端 780 个统计窗口里共 2 次(iris-photon、iris-derivative 各 1,只在 DirectGLES)。但 P5b 下这条路径是具名 Fatal,正是这两条 trace 加 create-indirect GLES 的首阻塞(P9)。
  3. spike B 的 untrusted_app 域复核。 两台设备的分档在 shell 域测得;从应用进程再跑一次 extmem_probe(spike A 的 exec 钩子已可用)。P11 前做。2026-09-22 降级:只对同机臂的 T0 / T1 有意义,stream 数据面不需要。
  4. 渲染状态的 wire 粒度。 已答(P2):16 个边界 / 15 个 chunk,7 pipeline 396 B + 8 dynamic 772 B;CSO LRU 64 暂定,P13 重调。
  5. 无存储的 capability。 已答(P2):FramebufferSrgb、DepthClamp、TextureCubeMapSeamless 三个都补了真存储,sizeof(RenderStateParameters) 仍 1168。
  6. 具名 UBO host payload 的形状(D-B8)。 Magma 在 26.3 世界每帧重打包 331 KB 具名 UBO 字节,Espryt 为 0。要么冻结第二变长尾形状,要么走备选(Magma 直接描述符绑定常驻 VkBuffer range,独立 dev PR)。P7。
  7. MG_Util 的切割缝。 server 需要 SPIRV-Cross / ESSL 转译缓存 / 格式处理器 / POST 探针,client 需要 glslang 与反射层;MG_Util 内部是否有干净的 Transpile-vs-Reflect 缝未审计。P7。
  8. 一份反射归档能否服务三个消费者。 Espryt 那一半已答(P4a):能且不需要复制。Magma 的第一个消费者已由 P5f fm 答:MagmaProgramSource 全部从 wire ProgramArchive 取,无前端对象、无复制。第二个(storage block 表)今天是否且变差了:split 下 MagmaProgramSource::EnsureStorageBlocks 每 draw 重跑 SPIRV-Reflect(monolith 臂 DirectVulkan.cpp:177-200 至少有持久缓存);答案是往 LinkArtifacts 加有序 storageBlocks(数据已在 blockReflection 里),两个消费者都改读它。已答(P7 wave 2-C,dce9953d..cf7ca59f):storageBlocks 入归档、两个消费者改读、每 draw SPIRV-Reflect 4→0;g_programResourceCaches 的 monolith 半边归 P13(G1)。
  9. viewport-array 回放能否塞进一次 draw_vbo:各遍之间观察到的状态是否与今天一致未验证。P8。
  10. ResidentSubData 的不对称。 已答一半(2026-09-22 核):Magma 的实现已补(VkBufferManager.cpp:123 monolith 表、:148 wire 表,fff9d639f)。仍未答:kCapResidentSubData 从未被 server 发布——MG_Backend/Init.cpp:192-219 是全树唯一的 SetCapabilityBits 生产调用点,只 OR 了 XFB、三个 query 位与 run-ahead 位;于是 PipeFill.cpp:848 在 split 下恒 false,两个后端在拆分模式下都退回 BufferObject.cpp:711-716 的就地 memcpy,Magma 的实现在 split 里是死代码。已答(P7 wave 2-C,ID-P7-20):InitServerRoleCommon 按 server 自己的 wire 资源表发布 kCapResidentSubData,镜像收到即验收;白盒「发出的是 opcode 49」在 P11 采纳档落地前不可达(§5.4 债)。
  11. SEG_STAGE 的上限。 内容侧已答(2026-09-20):分块已实现——buffer 范围走查(1e7c372e)与纹理整宽 slab(9469d48e)按 MGPipeStageChunkBytes()(默认 32 MiB 的 1/4 = 8 MiB)切成多条 resource_subdata,所以单次 128 MiB 上传不再需要显式 MOBILEGL_IPC_STAGE_MB=256;单片仍超 arena 或该 record 类型未接入分片时仍是 Fatal{RingOverrun, "SEG_STAGE"} 兜底。仍未答(2026-09-22 收窄):a6 §6 实测没走查的只剩 program archive(唯一无界 blob)与 draw_vbo 的 NumDraws*12 range 尾;宿主索引 span 无 producer(划掉),set_global_constants 有走查。二者的分片是 P6.5 sl 与 P8 共用的同一件事,stream 发送窗口对着它们定尺。MC in-world / Create 的占用分布仍未量(门 8 已给出两条负载的字节/帧与记录/帧,逐 blob 分布只在 integration 车道取到)。
  12. P13 之后 split-only 渲染 bug 的 server 侧第二意见。 verify 构建 + recorder 只覆盖推送内容,不覆盖后端对它的解释。
  13. 烘焙后的内部 shader 能否在没有活 ProgramObject 的情况下表达 uniform location 与 UBO 布局。 颜色 blit 已答(P5f fv:WireColorBlit.{vert,frag} 用 push constant,WireColorBlitSpirv.h 签进树);窄化到深度 mip 程序(今天在 split 下被编译掉、其 split 路径是具名 Fatal)与直通 TCS(ProgramFactory.cpp:4060-4262,第三个未盘点的内部 shader 生成器)。已答(P7 wave 2-B / B2):深度 mip 烘焙 (A)(D)(WireDepthMipmap.*,push constant,MOBILEGL_BAKED_INTERNAL_SHADERS 新鲜度门表驱动)与 (B′)(disaggregated 构建的 monolith 臂改用烘焙模块)落地;multisample resolve 第三套烘焙 shader 随 B2;直通 TCS 仍未盘点。
  14. 推送模型改变哪些按拉取模式调过的缓存命中率。 幸存者容量在 P13 重调。一条线索:设备上 26.3 Espryt 的 sve ≈ draw 数(每 draw 重发一次 sampler-view 集合),桌面只有 ~0.07/draw;列入 P3b/P4b 优化清单。
  15. monolith 的 *IndirectCount 不调 SyncGpuWrites() 是不是潜在缺口。 独立 dev 问题,拆分不得借机顺手修。
  16. 索引宿主镜像的实际内存占用。 MC / Sodium / Iris 语料里 element-array buffer 总量未测;若显著超 64 MiB,退化路径的频率与代价必须实测。P8。
  17. create-indirect fixture 在 Adreno 830 上的失败是 dev@81b17c0b 就有的(基线 APK 复现),不是本分支造成;rd12 + Magma 在两台 Adreno 830 上的 scudo::reportMapError 崩溃同样是 dev 侧。两者排除在设备 A/B 之外、留在桌面语料里;P8 要在 create-indirect 上断言 roundtrips-per-frame == 0,所以 dev 的修复在别人的关键路径上。
  18. split 两侧的负载平衡。 P5e 解锁出来的新问题:VD32(~3550 draws/帧)下 apply 线程 11-12 ms、client 15.7 ms,client 是瓶颈且打满 ~94%。把工作从 client 挪到 apply 会直接降瓶颈——这在 lockstep 下毫无意义(两侧串行相加),run-ahead 才使它成为一个杠杆。供选:编码侧的 emitter、tracker 走查、持久映射的脏页追踪(change_protection 在侧写里占 1.3%)。需先重新侧写:等待消失后尾部各项的分母都变了。排在 P5e 之后;无主,2026-09-22 建议挂在路线图推完后的优化阶段,P6.5 的 2×2 矩阵车道顺带重新侧写
  19. 链路带宽预算与压缩。 TCP 终局下 SEG_STAGE 字节/帧对的是 Wi-Fi / USB(量级 30–100 MB/s),不是内存;ARCHITECTURE.md §14 的 ~1 MB/帧预算在 60 fps 是 60 MB/s,已贴着 Wi-Fi 上限。是否对 stage 载荷做 LZ4 类压缩、纹理上传是否按内容哈希在 server 侧去重,要等门 8 的分布出来再定。P6.5 契约写下第一行之前必答。
  20. 大单次上传的停顿。 128 MiB 一次上传在 50 MB/s 上是 2.5 s;内容侧分块解决的是"装不装得下",不是"要等多久"。跨机臂上要么接受并记录,要么给上传做异步化(与 P9 的语义一起想)。不假装解决。
  21. 配对 / 认证的形式。 已裁定(ID-P7-3,2026-09-22):令牌足够,不做 TLS。 威胁模型是「任何人都能连的远程代码路径」而不是窃听:令牌常量时间比较、≥16 字节、无令牌只 loopback、数据面以 Welcome.dataNonce 绑定到已认证的控制连接、fork 前认证。TLS 作为 P12 的开放项保留。
  22. client 平台范围。 默认先 Linux + Android(现有 CI 能验),Windows client 第二批(ShmSegmentWin32 在;pipe: 具名拒绝作废、TCP 替代),macOS 仍不拆分。这决定 ARCHITECTURE.md §15.3 "Windows 机器不是正确性门"要不要改。
  23. 半开连接的检测。 Wi-Fi 掉线不产生挂断事件;dl 的闩取自描述符挂断,TCP 上需要 keepalive / 心跳超时并由传输层报告为挂断——这与"绝不取自 apply 超时"不矛盾,写清楚免得重吵。P6.5 ct。
  24. E1 对照的重定义(ID-122)无主。 建议并入 P6.5 的门设计:S8 的好路径断言(SessionFaultCount() == 0)已是它想表达的形状,缺的是一个能被证伪的负控。