Files
MobileGL/docs/Disaggregated/ROADMAP.md
T

144 lines
48 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MGPipe 路线图
> 状态:**P0、P0.5、P1、P2、P3a、P4a、P5 已落地;P5b 代码已落地(`feat/disaggregated@7cb29d46`),测量未收口**。当前头、逐门数字、开放项与下一步见 **[`CURRENT_STAGE_PROGRESS.md`](CURRENT_STAGE_PROGRESS.md)**(随每次落地更新)。P5b 收官仍需:新头上的完整普查、一次主机全门、APK 与红米 A/B。P6 排在四个目标 trace 的红米 `inproc` 渲染之后。设计见 `ARCHITECTURE.md`,分头证据见 `MEASUREMENTS.md` §2635。
## 通用纪律(每个 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 → P5b `inproc` verb migration → P6 → P9 → P10 → P11 → P12。这里只调整 IPC 跑道内部的先后,不把 spawn 混进 monolith 深化。
## 阶段
| 阶段 | 天 | 落地什么 | 验收门 | 依赖 |
|---|---|---|---|---|
| **P0** 卫生、度量、门、骨架 | 9–11 | ✅ 边界计数器(字节 / 动态 accessor / 六个 memo 门 / 上传形状);`PipeCalls.def` 完整目录 + payload POD + 七个生成器 + CI `pipe-gates``gen_pipe_dirty_surface.py``check_doc_citations.py`;八个 `MOBILEGL_PIPE_*` 开关;`MG_Remote/{Protocol,Transport}` 骨架(`SCM_RIGHTS` 第一优先、双 tail 双三元组的 `RingControl`、双向 doorbell、校验型 `Framing``ShmSegment``InProcessTransport`+ `protocol.fbs` + `flatc-check` + `MG_Test/Wire` 五个套件;三个严格 no-op 收益(`GetInteger64i_v`/`GetProgramiv` 退役、`RenderbufferObject::GetLifetimeId()`、D21 XFB 计数槽重键);compute 限制进 `DynamicBackendParameters`spike A、spike Bretrace 通道 `--env` 透传 | ✅ 单元/集成/40 trace 逐名不变;wire 层测试(fd 传递、doorbell、ring、封帧、inproc)绿;两台设备的字节/调用基线在案;spike A/B 出结论;citation lint 绿 | — |
| **P0.5** 值头与制品头抽取 | 6–9 | ✅(`5d99ee43``MG_Pipe/MGPipeValueTypes.h``RenderStateParameters``SamplerParameters``PixelStoreParameters``VertexAttribute`… 不 include `MG_State/GLState`);`MG_State/GLState/ProgramState/ProgramArtifacts.h`(五个反射类型,不 include `ShaderObject.h`/`SpvcSession.h`8 个 includer 零改动——类内 `using` 别名保住每一种既有拼写);`Visit()` 归档 + `sizeof` 绊线;CI `-H` include 闭包断言(`scripts/check_include_closure.py`text + clang 两模式、自带阴性对照、`--require-all` 棘轮;`scripts/symbol_report.py` 做逐符号归因)。实测落地:测试名零删除、`MG_Backend` 零 diff、`.text` 字节不变、符号 0 增 / 0 删 / 42 重命名;`DynamicBackendParameters` 未搬(含 `SizeT``TextureTarget` 成员,搬动不是纯移动),`MGPipeTypes.h` 仍 include `BackendObject.h`,闭包门 A 因此断言 `MGPipeValueTypes.h` | 全套测试逐名不变(纯搬移);两条闭包断言绿且人为加回一个 `MG_State` include 能变红;`nm`/`.text` 变化可逐符号归因 | P0;**P1 与 P7 的硬前置** |
| **P1** `PipeInputs` 替换与 verify harness | 1013 | ✅ `MG_Backend/MGPipe/PipeInputs.h`63 字段;Espryt 32 / Magma 56 访问器);**实测 277 处箭头 + 58 行非箭头**Espryt 113+9、Magma 164+49)逐条转换;逐 verb 类填充点(G5 表,~93 个边界站点);逐 verb 世代 poison;G4 影子比对器 + 第三种 CI 模式;20 处 `SyncPersistentMappedRange` + 6 处 `SyncGpuWrites` 的逐站点归属表 | pull 构建 `nm --defined-only` 不变、`.text` 差异逐行归因(空守卫/三元重写推迟到 P2);40 trace + 全部集成测试在 `MOBILEGL_PIPE_VERIFY=1` 下零分歧;故意损坏一个快照字段能让 verify 变红;故意在 `glGenerateMipmap` 的填充表漏一个字段能在**那条 verb** 上触发 poison Fatal | P0.5 |
| **P2** 渲染状态 CSO + 第一片 Track H + 残余值块 | 1826 | ✅(`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/916pull、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 +814%Oppo Espryt +818% / Magma +1011%);桌面 `DriverBench` T1 = +322 / +345 ns/drawEspryt / Magma),T1 T2 = 228 / 354(P2 比它替掉的 P1 残余填充便宜),blend-toggle +4.7% / +3.5%,见 `MEASUREMENTS.md` §9–§14 | P1 |
| **P3a** handle wave 1Espryt):buffer、VAO | 1823 | ✅(`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<BufferObject, GLESBufferResource, MGPipeKind::Buffer>``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<VertexAttributeVersion,32>`,本阶段最大的一处)/ `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 下非零、可断言。子系统位 7resources)与位 8vertex 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 例 retracepush 下 **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 2Espryt):FBO / 纹理 / sampler / program 身份与描述符 | 2634 | ✅(`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)。子系统位 **9framebuffer/ 10(纹理资源)/ 11sampler/ 12program**`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..37fc4fdb`)同一 codec 上的 `InProcessTransport`;发射表、caps/replyapply-thread contextlockstep barriertight ReadPixelspersistent-map 块推送;八包及 j0/x2/v1-r3 收尾 | 历史 jointOpenRA 双后端 2/2、SSIM 1.0。收尾头:G1 0/0/0/0、.text +0unit 1817×3 / 2086push 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(收尾中) | 按首阻塞迭代 | d1 19、i1 7、t2 6、f1 11 槽已迁移;新增具名 blit lowering、GLES mip descriptor 路径、五槽 syncP5 收官 r1/r2 已合入。合并头 `348d22a4`A=2 / B=54 / C=15 | 主机 split 107 selected = 105 passed + 2 skipped;一次全门、合并普查与审查定向修复分别记账,见 `MEASUREMENTS.md` §3234。Redmi 四 trace × 双后端正确性及四臂 A/B 尚待最终证据;256 MiB stage 为显式 profile,默认仍为 32 MiB | P5 |
| **P6** spawn transport(后移) | 5 | `SocketTransport`socketpair + fork/execveenvp 剔除 + 强制 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 | 2938 | **P4a 已经付掉的,别再排进来**`ResolvedDrawBuffers` 重键(P3a 就做了)、Tracker 的集合 hash 抑制器(三个 unit set 各自带内容 hashclientsp)、`g_unitTextureSyncList` 那条 unit-bindings epochE 的验证轮换成 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** DirectVulkanMagma)全量迁移 | 80104 | §5.5 其余 10 个子系统(子系统 1、4 已在 P2):`SetupDrawSnapshot` 探测字段塌成 dirty mask;占位纹理原生化(~120 行删除);具名 UBO host payloadD-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 |
| **P9** 反向通道 | 10 | `SEG_REPLY` slot 池;阻塞 `read_pixels`PBO 回读 fire-and-forget`OnGpuWritten` 收窄;`OnBufferWriteback` 按操作级批处理 + epoch 排序;`OnXfbScatterReady` + client scatter`OnTextureWriteback``OnMipLevelsGenerated`;纹理拉取四条缓解 + 终止符;`OnGlError` 有序 + `glBufferStorage` 的 ack`OnCapsInvalidated``OnSurfaceChanged``OnLog` 分级 + 速率限制;`SEG_EVENT` 溢出策略 | 回读/XFB 场景在 split 下绿;`TextureRemintPullScenario` 绿且含无解用例(终止符前表现为 apply 线程挂死/超时);拉取计数逐 trace 发布;故障注入:credit 阻塞时灌满 `SEG_EVENT`、日志洪泛下注入 link 失败 | P8 |
| **P10** sync / query / present 节奏 | 6 | client 铸造 sync/query handle;轮询入口成门铃点 + `MOBILEGL_IPC_POLL_ESCALATE`;fence 完成度来自真的逐 fence 退休;DirectGLES 非 present fence tick`present` 1:1credit 默认 1 + 叠加公式;roundtrip 计数器与输入延迟直方图;三个独立 `dev` monolith 修复(`glEndTransformFeedback` 无限 `ClientWaitSync` → 推迟到首次读;`glDispatchCompute` 三次 `GetIntegeri_v` 校验 → 读 `CompileEnv`D21 已落地) | query/XFB/`AsyncCompile` 场景在 split 下绿;40 个用例上 draw/state/upload 路径 roundtrip 读零,条件渲染与阻塞 query 次数逐用例发布;零 timeout 轮询在有界时间退出;`bench.sh` 配对 A/B:两侧都关采纳时 split 帧时在 monolith 10% 内,输入延迟 p50/p99 在案 | P9 |
| **P11** persistent map 与 ≥16 MiB 采纳 | 8 | POST 探针档位选择(T0 主攻,Adreno 可选 T1,T2 回退);`SEG_ADOPT` 生命周期绑 `completedFrameSerial``MOBILEGL_IPC_ADOPT_TIER` 负面对照 | `LargeArenaAdoptionScenario` 在所选档下绿;26.3 与两个 Create fixture SSIM ≥ 0.99`StorageBufferRegrowScenario` 发布 `map-persistent-roundtrips`Adreno 830 上 p99 帧时与峰值 RSS 对 monolith 采纳基线(163→21 ms / 40→115 fps / ~400 MB**回归不超过 10%**;若 T2 成为某设备的永久答案,其实测代价写进文档 | P10、spike B(已答) |
| **P12** Android 生产窗口路径 | 10 | `android:process=":mgl"` Service 收 Java `Surface``ANativeWindow_fromSurface`server 生命周期绑 ActivityFCL 用户 env 与 plugin APK V2 开关表接线 | Minecraft 经 FCL 在 spawn 模式下于 Adreno 830 双后端入世界;配对 reboot-clean bench + 输入延迟直方图;杀 server 产生干净 device-lost latchSIGKILL 故障注入 | P11 |
| **P13** 退役 pull 路径 | 812 | 删 `SnapshotFromGLContext()` 非 verify 分支、`MGB_CTX``MOBILEGL_PIPE_PUSH``MOBILEGL_PIPE_LEGACY_MEMOS`;保留 `MOBILEGL_PIPE_VERIFY`MGPipe recorder 金标模式;删 `set_residual_value_state``MG_Backend``MG_State` include 收缩到 `MGPipeValueTypes.h`;在计数器活着的情况下重调幸存缓存容量(`VaoDrawMemo` 2048、`SetupDrawSnapshot` 4、pipeline memo 8、`syncedTextureMemo` 8)并变成带 env 覆盖的调优参数;最终符号/尺寸/CPU 报告 | `static_assert(sizeof(ResidualValueBlock) == 0)` 编译通过;三道纯度门在非 verify 构建上转绿;verify 构建仍零分歧;recorder 金标在 40 trace 上建立;全套门(集成 × 2 后端 × {monolith, split}、单元、40 trace、两台设备 CTS 在 `81b17c0b` 基线 0.5 pp 内);**monolith 逐线程 CPU 在两台设备 p50/p99 上不差于 P0 基线** | P7、P8、P12 |
P5 的八个实现包(报告在 `~/w7/notes/p5/p5-results/`):
| 包 | 落地物 |
|---|---|
| c0 | wire/segment 契约、四种 build、71 槽三分类、acceptance reply-slot 与 respecify scope carrier |
| w1 | 记录 codec、blob/tail 边界检查、call/ring flag 翻译、R-10 记录上限 |
| s1 | session/ring/handshake、caps snapshot、reply pool16 MiB / 8×2 MiB)与 ABI fingerprint |
| p1 | 63 字段 + 7 sticky forward 的四类归属、poison/strict、`rsp` stamp 与生成器门 |
| b1 | persistent-map tracker、保守块推送、GPU-write 标记与 G5 第十一行重钉 |
| t1 | split 测试/CI/retrace/APK 车道、五部分 gate 与阴性控制脚手架 |
| c1 | 33 条生成路由 + 4 escape、37-row catalogue、caps 本地回答、tight readback client scatter 与 PACK-PBO 具名拒绝 |
| v1 | `ServerLoop` / `PipeApplier`、apply-thread EGL 生命周期、server shadow、12 条 forwarder 与 caps republish |
累计(低端):P0 9 → P0.5 15 → P1 25 → P2 43 → P3a 61 → P4a 87 → P5 99 → P6 104 → P3b/P4b 133 → P8 145 → P9 155 → P10 161 → P11 169 → P12 179 → P13 187P7 另 80104,单跑道累计 267。
**CTS 周转单独计价**`gl44to46` 约 56,271 例。逐阶段只跑该阶段可能影响的具名块(P4a `packed_pixels`、P3b/P4b `texture_*`/`shader_image_*`、P9 `transform_feedback*`);完整 caselist 只在五个架构边界(P0.5、P3a、P4a、P3b/P4b、P13)与每次合并 `dev` 之前跑,放 CI 不放关键路径。若周转仍主导排期,加宽估时而不是削弱门。
## 里程碑
- **第 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**:缩减路径首个 IPC 帧已经观察到;joint、落地快门、收尾头实跑分别记在 `MEASUREMENTS.md` §26/31。收尾头 `37fc4fdb` 的 E3(a) 控制因两条设计性 skip 失败;不能以早期 joint 或各包自门替代未完成的最终全门。红米 P5 四臂 A/B 的 split 均停在索引 drawbarrier tax 未测(`MEASUREMENTS.md` §30),迁移与重跑归 P5b。
- 原“第 104 天跨进程帧”后移到 `inproc` verb migration 之后;目标先是完整 separate-thread rendering,再是 separate-process transportID-66)。第 145 天全功能 split与第 187 / 267 天纯度门仍是方向,不据此伪造新日历。
- **P5b 出口(待完成)**:主机迁移与阶段门不代替 Redmi 渲染证据;唯一收官审查后的定向修复不触发第二轮全门/审查。四臂统一采用 256 MiB stage profile,原始主机门固定在 `348d22a4`,最终设备源头另记。
## 第 43 天 GO/NO-GO 清单
手上必须有(**结算:继续**2026-09-08):
- [x] P1 交付的逐 draw 逐字段语义等价证明(40 trace + 全部集成测试零分歧)
- [x] 两个后端上都已推送的渲染状态,`SyncRenderState` 693 行一行未动(`RenderStateImpl` 段 sha 与 P2 起点相同)
- [~] 两片 Track H 的实测单位成本(Espryt 0b、Magma 子系统 4)—— 产出侧在案(`ARCHITECTURE.md` §9.5 那份 21 条身份 memo 普查里,11 条直接删除 + 2 条重键全部落地,两片都零回归),日历口径(实际工作日 vs 估计的 5–7 / 2–3 天)**未记录**
- [x] 两台设备(Adreno 830 `35d0befa`、Mali `3B159D009VZ00000`reboot-clean 配对的逐线程 CPU 时间增量,p50 与 p99 —— 两机各 16 行全部在案(`MEASUREMENTS.md` §10):小米 p50 +814%Oppo Espryt +818% / Magma +1011%p99 同向
- [x] tracker 每 draw 的**绝对 ns**T1/T2)—— 桌面 `DriverBench`Espryt T1 +322 / T2 +550、Magma T1 +345 / T2 +699 ns/drawT1 T2 = 228 / 354`MEASUREMENTS.md` §12);设备侧的等价读数是配对 A/B 的 +8–14%;按下面的口径为**记录项**,不再是门
- [x] Blaze3D blend-toggle 微基准(enable/draw/disable/drawMC batch 速率)—— `mc_state_toggle`(每帧 46 对):Espryt 23753 → 24869 ns/开关对(+4.7%)、Magma 32705 → 33857+3.5%);pass switch +0.6% / +1.7%
- [x] 负面对照:关掉 CSO 内容寻址重跑,把"推送更慢"与"CSO 设计更慢"分开(`kMGPipeBehaviourNoCsoContentAddressing``CsoContentAddressing` 6/6 证明开关真的改变 mint/bind 计数)
判据与出口:
- **口径变更(用户 2026-09-08**push 比 pull 多约 10% 逐线程 CPU 可接受(该读数来自 -O0 APK,`MEASUREMENTS.md` §10 勘误;Release 数字在 §20);性能自此**对着 pull 臂基线记录**、不作阻塞门,第 43 天的绝对 ns 上限降为记录项;路线图先推完,专门的优化阶段排在其后(或首个 IPC 帧之后)。
- **继续**(本次结算):五部分门全绿,两片 Track H 按计划的产出全部落地且零回归,按两条跑道推进,下一步 P3a。原判据(两台设备 p50 与 p99 逐线程 CPU 增量都不为负;tracker 绝对 ns 在上限内)保留为后续阶段的记录口径。
- **收缩为 headless 工装用途或重新评估**:任一判据落空。**不回滚**:P0/P0.5/P1/P2 的产物(句柄基建与重键、两个头文件抽取、计数器、verify harness、渲染状态 CSO)全是自洽的 monolith 交付物,留在 `dev`MGPipe 收缩为 `MG_Test` mock 后端 → MGPipe recorder(给 trace_replay 一种记录已解析状态的录制格式)+ `inproc` 渲染线程实验;IPC 跑道搁置到出现新判据。
- 沉没成本:P0 与 P0.5 无论走哪条路都要花(后者本身是 monolith 净收益);真正只为 MGPipe 押上的是 P1 + P2 ≈ 28–39 天,NO-GO 分支下仍留下上述产物。
## 再基线检查点
| 触发 | 动作 |
|---|---|
| P3a > 27 天 | "窄句柄化"的前提错了,P4a 开始前重定基线。**未触发**:P3a 实际 **1 天**(2026-09-08,四个包全部落地),`MEASUREMENTS.md` §19 记了逐包口径 |
| P4a > 39 天 | 同上。**未触发**P4a 实际 **1 天**2026-09-08 起;六个包并行、契约七次修正 `c0b``c0g`、缝类审计一轮、终审修复一轮)。逐包口径与每一次修正的因由见 `MEASUREMENTS.md` §22 与 `~/w7/notes/p4a/INTEGRATOR-DECISIONS.md`ID-1…56 |
| P5 > 计划窗口 | **未触发重定基线**:实际日历 **2026-09-11 至 2026-09-16**。Sep 11 的模型配额 outage 中断 wave 2Sep 16 又把本地 `rereview@local` 谱系重写到用户身份并重新接到 GitHub `ff2994d9`,两项都是过程时间,不是实现规模(ID-40/45/66 |
| P7 中点(第 40–52 工作日)完成子系统 < 40% | 立即重定基线(P3a 的检查点发现不了 Magma 特有的超期) |
任一触发,先跑 `inproc` 的证伪数字再决定是否继续。
## P5/P5b 出口记录的债务
ID-65 的原始处置、ID-73 的 r1/r2 修复与 P5b 残余项如下。历史 27 条 wrong-answer 不是当前合并头计数,最终普查以 `MEASUREMENTS.md` §33 的同名比对为准。
| 债务 | 去向 / 当前口径 |
|---|---|
| P5 基线 27 个普通 inproc wrong-answer(历史) | **22**14 layered + 3 packed depth/stencil + 5 framebuffer recycle)→ P4b/P7 texture readback3 → P7 query1 inspection → P6。FBO/RBO delete 那 1 条使用 ReadPixels,完整像素因果未隔离;client-thread framebuffer death 已由 **r1 #2** 转至 apply mailbox,原 FBO/RBO delete 像素用例在 r1 定向验证中通过;合并普查决定最终计数,不能从单例外推 |
| `rsp` residual inputs | STRICT_ERRORS reduced lane 19 abort/2 skip;既有 rsp=35 只是有 stamp 读点的下界。无 verb stamp 的 sticky/non-verb forward 仍可绕过计数/strictP7/P8 补逐字段归类和自证门(r2 提议),其余按字段的 P3b/P4b/P7 phase 退役 |
| `SEG_REPLY` 2 MiB payload cap | 当前 `MaxReplyBytes = 2 MiB - 16`;更大 readback 需要 P6+ chunking 或专用 carrierID-47 |
| `GetCaps` 的两个 blobref | 目前不骑 record;一旦运输,必须有 server→client carrier rule,不能套 `SEG_STAGE`ID-48 |
| PACK-PBO readback | P5 具名拒绝;真实形状是 server 写 buffer resource、client `MarkGpuWritten`,列入 P6ID-57 |
| ABI fingerprint | 目前不混 segment sizes;改变 8/32/16 MiB + 256 KiB ledger 时仍欠这项(ID-47 |
| max record bytes telemetry | **x2 已实测** reduced/OpenRA maxrec=784 BSetVertexAttribDefaults),默认 cap=4 MiB;只代表所测负载,后续索引/indirect 尾仍须记录 |
| E2 wire 内容控制 | x2 draw-drop758 drawsSSIM 0.000036clear-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=18 MiB 对照同时红;**r1 #4 已合入** command-ring retirement 等待,重试保留两条尾与 ordinal;超大单记录仍拒绝 |
| 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**。**r1 #1 已合入** apply-role producer guard;仅取消 client pre-draw push 的两个像素控制均变红,恢复后变绿,见 `MEASUREMENTS.md` §32 |
| tight ReadPixels PACK_SWAP_BYTES | **r1 #3 已修** tight/scatter 的 component/packed-word swap;非对称 UNSIGNED_SHORT 像素在 monolith/inproc 均通过,混合 depth/stencil 按两个 32-bit word 处理 |
| P5b 收官审查三项 | **已在 `82683d4a` 修复**user-index span 长度、长 ClientWaitSync 预算、ReadPixels 非 OK 状态;包内定向 9 passed + 7 passed,均零 skip;原始审查为 0 blocker / 2 major / 1 minor,证据见 `MEASUREMENTS.md` §34 |
| CI / 控制 / 跑器 | **r2 包内已修** broad debt lane 吞掉后续控制、all-skip 绿、REQUIRE_GPU、E2 库恢复、E3 选择、陈旧/零用例普查、G5 pin 自测、c1f 旧名。外部 notes 脚本也有修改,git merge 不会自动传播;验收详见 `MEASUREMENTS.md` §31 |
| 默认 32 MiB staging 容量 | 128 MiB 单次上传不能装入默认 stageP5b 普查/Redmi 显式 profile=256 MiB,默认不改。更大 blob 的分块/专用 carrier 仍属后续设计 |
| P5b 的 inproc 依赖 | 具名 blit 使用 scoped client binding + barriermip descriptor 的 registry 身份查询仍依赖 barrier-held objectFBO death 使用 inproc mailbox。P6 需替换这些跨地址空间不成立的路径 |
| 未迁移与仿真路径 | `348d22a4` 尚有 class-C 15 槽;client vertex arrays、multi-draw client indices、RGB 三通道 CPU mip/writeback、renderbuffer copy endpoint、未绑定 named clear 等保留具名拒绝或后续阶段债务;query/texture readback 的错答仍按普查记录 |
| 临时 CI trigger | 合入 dev 前删除 `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,数字仍在补齐)**:推送**没有**在拉取基线(每 draw 6.59.3 次 accessor + memo 探测)之下净减少,而是多花约 10% 逐线程 CPU。小米 Adreno 830`35d0befa`reboot-clean、定频、配对、尾 200 帧 p50,单位 ms/帧):`minecraft-1.21.4-in-world` DirectGLES 7.39 → 8.19+10.8%)、DirectVulkan 5.23 → 5.85+11.9%);`minecraft-1.21.4-fabric-iris-bsl-in-world` DirectGLES 4.91 → 5.35+9.0%)、DirectVulkan 4.158 → 4.525`--benchmark-no-finish`+8.8%/ 4.583finish+10.2%)。bsl 用例的 p99 两臂都由着色器编译主导(~1.6 s),不承载这个问题。
小米全部 16 行(4 trace × 2 后端 × finish 开/关,p50 与 p99、钉频判定)在 `MEASUREMENTS.md` §10:p50 增量在四个 trace、两个后端上都落在 **+814%**`improved-transparency-minecraft-26.3` DirectGLES 37.26 → 42.44、DirectVulkan 61.55 → 68.12`minecraft-1.21.4-startup` 只有加载帧,不承载)。
Oppo Mali`3B159D009VZ00000`)全部 16 行同在 §10Espryt in-world **+1618%**、26.3 +89%Magma 两机一致 **+1011%**26.3 上 p99 同向放大到 +1622%。两机 32+32 次运行的 pull 臂即此后的性能基准线。
绝对 ns 的分解(T1 = push 默认位图 pullT2 = `MOBILEGL_PIPE_PUSH=0` pull`T1 T2` 正是 P2 自己的增删;桌面 `DriverBench``mc_vanilla_draw`ns/draw,全表在 `MEASUREMENTS.md` §11–§12):Espryt **T1 +322**pull 5121 的 +6.3%)、T2 +550、**T1 T2 = 228**Magma **T1 +345**+2.0%)、T2 +699、**T1 T2 = 354**——P2 的 tracker + CSO 比它替掉的 P1 残余填充便宜,剩下的 T1 是尚未句柄化的填充与 dirty 走查。无 CSO 内容寻址对照:Espryt 69(噪声内)、Magma +200(内容寻址每 draw 省 200);blend-toggle +4.7% / +3.5%pass switch +0.6% / +1.7%。
**口径**:用户 2026-09-08 接受这一代价,性能自此对着 pull 臂只记录不设门(见上文"判据与出口")。
2. **真实语料上纹理重铸拉取的发生率。** `ImageBindableHint` 预防主因,但整格式再生在普通 `glTexImage` 格式变更上就触发。若 MC/Iris fixture 上非平凡,保留 LRU 从默认 0 升为强制并拿真预算。**P4a 已答:可以忽略,保留 LRU 维持默认 0。** 计数器 `tex-remint-pulls`(汇总行 `emit[... trp=]``PipeStats``CallClass::TextureRemintPulls`,随终审修复轮落地)数的是"Espryt 重铸一份它已经持有的存储";在 79 例 retrace × 两后端、`MOBILEGL_PIPE_STATS_PERIOD=60`、push 构建(`8c458cd5`)下:**780 个统计窗口里总共 2 次**,分布在 **2 个用例**`iris-photon-v1.3b-in-world``iris-derivative-main-d24.4.14-in-world`,都只在 DirectGLES 侧,各 1 次),其余 77 例恒 0。`ImageBindableHint` 这一波也第一次有了真实的生产者(`glBindImageTexture` 与 sampler view 解析各标一位,此前两位无人写、hint 恒 0),所以这个数是"预防已经生效之后"的残量。
3. **spike B 的 `untrusted_app` 域复核。** 两台设备的分档在 `shell` 域测得;T0 的 AHB socket 交接是每个与 SurfaceFlinger 共享 buffer 的应用都在走的路径,风险在 memfd/opaque-fd 腿上。从应用进程再跑一次 `extmem_probe`spike A 的 exec 钩子已可用)。
4. **渲染状态的 wire 粒度。** **已答(P2**chunk 表冻结为 **16 个边界 / 15 个 chunk**,两半完美交替(chunk 0 dynamic、chunk 1 pipeline……),**7 个 pipeline chunk 共 396 B + 8 个 dynamic chunk 共 772 B = 1168**,每个边界都是一个 `offsetof``sizeof`,划分与总数由 `static_assert` 把关(`MobileGL/MG_Pipe/MGPipeRenderStateSpans.h:190-191`)。`set_dynamic_state` 的粒度就是这 8 个 dynamic chunk(只发变化的那些)。CSO LRU 容量取 **64**`MobileGL/MG_Impl/Pipe/CsoCache.h:53`)——这是暂定值,**在 P13 连同其余幸存缓存一起、在计数器活着的情况下重调**(P13 行的"重调幸存缓存容量")。
5. **`FramebufferSrgb` / `DepthClamp` / `TextureCubeMapSeamless` 的拍板。** **已答(P2**:无存储的是**三个**能力不是两个——`RenderState::SetCapability``default:` 分支同样吞掉 `TextureCubeMapSeamless``glEnable` 可达、零读点)。三个都在 P2 拿到真存储,落在 `ColorMasks``ClearColor` 之间那 3 字节的空洞(偏移 581/582/583`MobileGL/MG_Pipe/MGPipeValueTypes.h:303-305`),所以 `sizeof(RenderStateParameters)` 仍是 1168 且既有成员一个都没挪位。三个都划进 **pipeline 半边**(它们的 setter 都走 `BumpVersions()``DepthClamp``VkPipelineRasterizationStateCreateInfo::depthClampEnable`),chunk 表随之冻结。
6. **具名 UBO host payload 的形状(D-B8)。** 第一个数字已有:Magma 在 26.3 世界每帧重打包 331 KB 具名 UBO 字节,Espryt 为 0。要么冻结现在的第二变长尾形状,要么走备选(Magma 直接描述符绑定常驻 `VkBuffer` range,独立 `dev` PR + Iris 性能门)。
7. **`MG_Util` 的切割缝。** server 需要 SPIRV-Cross pass 流水线、ESSL 转译缓存、格式处理器、POST 探针;client 需要 glslang phase A/B 与反射层。P0.5 解决了 `ProgramObject.h` 一处,`MG_Util` 内部是否有干净的 Transpile-vs-Reflect 缝未审计。
8. **一份反射归档能否服务三个消费者**Espryt 读前端表、Magma 跑 SPIRV-Reflect、`DirectVulkan.cpp``glGetProgramResource*` 又反射一遍)。**P4a 答了 Espryt 那一半:能,而且不需要复制**——`create_shader_state` 过线的是逐 stage SPIR-V 与归档 blob 加上身份与序号,monolith 下 Espryt 仍直接读前端那份归档(D-H3),`ProgramArtifactsCodec.{h,cpp}` 只在 verify 构建里被调用,所以句柄化没有给热路径添一次编解码;换句话说"一份归档服务 Espryt"在 monolith 上已经是事实,跨进程时它就是那条 blob。**Magma 的两个消费者仍未答**(P7):`DirectVulkan.cpp``glGetProgramResource*` 重跑一遍反射这件事,P4a 没有碰。
9. **viewport-array 回放能否塞进一次 `draw_vbo`**`EndViewportRoutingPasses``InvalidateSyncedRenderState`,各遍之间观察到的状态是否与今天一致未验证。
10. **`ResidentSubData` 的不对称怎么收口。** null 项保住今天的行为;给 Magma 补真实现是行为变更,独立 `dev` PR。**P3a 的处置(仍开放)**:不对称原样保留。`MGPipeResourceOps::SubDataResident``kOptional`、允许为 null,前端检查它就像今天检查 `g_bufferBackendOps->ResidentSubData` 一样;**P3a 没有给 Magma 补实现**Magma 的 buffer 路径是 P7),`kCapResidentSubData` 也没有接线。所以这条问题原样留给 P7 / 独立 `dev` PR。
11. **`SEG_STAGE` 的上限。** P5b 目标负载已实测单次 128 MiB 上传,超过默认 32 MiB;完整 trace 普查及 Redmi 四臂统一显式设置 256 MiB。默认不变,分块路径尚未实现;P8 仍需 MC in-world / Create 的占用分布与更大 blob 的 carrier 设计。
12. **P13 之后 split-only 渲染 bug 的 server 侧第二意见。** verify 构建 + recorder 只覆盖推送内容,不覆盖后端对它的解释。
13. **烘焙后的内部 shader 能否在没有活 `ProgramObject` 的情况下表达 uniform location 与 UBO 布局。** 未做原型。
14. **推送模型改变哪些按拉取模式调过的缓存命中率。** 幸存者容量在 P13 重调。
15. **monolith 的 `*IndirectCount` 不调 `SyncGpuWrites()` 是不是潜在缺口**compute 写的 indirect buffer)。独立 `dev` 问题,拆分不得借机顺手修。
16. **索引宿主镜像的实际内存占用。** MC/Sodium/Iris 语料里 element-array buffer 总量未测;若显著超 64 MiB,退化路径的频率与代价必须实测。
17. **create-indirect fixture 在 Adreno 830 上的失败**是 `dev@81b17c0b` 就有的(基线 APK 复现),不是本分支造成;它是 P3a/P8 验收清单里的用例,需要先在 `dev` 上修。**P3a 出口的状态:仍然开放,仍是 `dev` 侧的活。** P3a 没有碰它,也不该碰(`ROADMAP.md:7` 的纪律:拆分不借机顺手修 `dev` 的 bug)。**P4a 出口的状态:设备侧照旧开放(本分支没碰,也没有新证据),但桌面侧这条 fixture 在本波中间坏过一次又被修好,值得记下来**——Espryt 的 per-draw 包把 `MGPImageView::Level` 改成从推送记录里读之后,`create-indirect` 的桌面 SSIM 从 0.999961 掉到 0.887403:根因不在那个包,而在 `Tracker.h``NewShaderImages` 快门只混了三个前端计数器,`glBindImageTexture` 用同一张纹理换一个 level 重新绑定时**一个都不动**,于是 applier 留着上一次绑定的 `Level`,第一个真去读这个字段的消费者就画错 mip(Flywheel/Create 恰好这么用,79 例里只有这一条能发现)。修法是把 `ctx.GetTextureBindGeneration()` 混进那个快门(`glBindImageTexture` 本来就会动它,不必新增计数器——新增会撑大 pull 构建的对象、G1 不允许)。这也是 P4a 之后写进 P4b brief 的那张"记录字段 → setter → 快门"表的由来。处置沿用 P2:`minecraft-1.21.1-neoforge-create-indirect-in-world` **留在桌面 79 例 SSIM 语料里**(G3/G3b 的具名扫描包含它,桌面栈上它是通过的),**排除在两台设备的 A/B 之外**(D.4.2);因此 G3b 记为"桌面全绿,设备侧因开放问题 17 而部分",不当作设备侧的通过。P8 要在这条 fixture 上断言 `roundtrips-per-frame == 0`,所以 `dev` 的修复在别人的关键路径上,不在 P3a 的。