P3a — handle wave 1(Espryt):buffer、VAO(fde5fda3)
本页是该阶段的阶段汇总:阶段表行、实测与落地形状的完整文本(2026-09-24 从上层索引移入,原文照录)都在这里;上层只留摘要——
ROADMAP.md、MEASUREMENTS.md、ARCHITECTURE.md。文中file:line与"今天""当前"按各段写成时的头理解;文中的MEASUREMENTS.md §N/ARCHITECTURE.md §17.x编号保留,对照表见../README.md。
摘要
- 落地:九条
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-gpu958 五臂;verify 842;retrace 79/79 ×2。实际 1 天(绊线 27 天)。 - 记录项:rd12(VAO 切换密)上 P3a 把 Release 帧 p50 差距从 +11% 推到 +27–30%;DriverBench 每 draw 多 Espryt 699 / Magma 422 ns。
阶段表行(原 ROADMAP.md)
- 阶段: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-gpu958 五臂;verify 842;retrace 79/79 ×2。实际 1 天。§4
实测:P3a(fde5fda3,基线 5cb826b0,44 个提交,37 文件 / +9273 / −230)(原 MEASUREMENTS.md §4)
4.1 五部分门(本地 ~/w7/pipe)
| 门 | 结果 |
|---|---|
| 构建 pull / push / verify | rc 0 / 0 / 0(fail-fast,绝不拿陈旧二进制下判决) |
A 门 include 闭包 / C 门 pGLContext / G13 |
4 probes 0 problem / 空 / 空 |
| G1 | .text 10806323 → 10806323(+0);27811 符号 0 / 0 / 0 / 0 |
G5 十一函数(pool / 延迟释放 / ring / FlushPendingRangesNow 与 FlushPendingRangesFrom) |
对 44c2b5cf 与 5cb826b0 都逐字节相同;self-test 两个阴性对照按名变红 |
integration-verify / 79 retrace verify |
842/842 零 Fatal{ / 79/79 armed 零分歧 |
| G2 / G14 | 差 0 / 0 删除 +58 |
| 单元 | 1619 × 3 |
integration-gpu |
958/958 × {pull, push, PIPE_PUSH=0, 0x7f(G12 子系统关闭臂), ESPRYT_DISABLE_INVALIDATE_FLUSH=1} |
buffer/VAO 族 / RenderStateSpans+Residual+VertexInputEmit+ResourceEmit |
202/202 / 48/48 |
HandleRecycle(verify) / 子系统对照 / verify 对照组 |
60/60 / 10/10 / 64/64 |
| G7 vertex-input 阴性对照 | 变红并点名 IsBgra |
| 79 retrace push | 79/79 |
| G3b 具名五条 | 桌面全绿(都在 79 例扫描内),但单独的具名扫描因门脚本把正则写成逗号清单而选中 0 例;设备侧按开放问题 17 排除 create-indirect → 记为"桌面全绿、设备侧部分" |
gen_pipe / gen_pipe_dirty_surface(扫描根扩到 MG_State/GLState) |
self-test 7 / 21 个阴性对照全部触发;75 个 mutator 全映射,0 COARSE / 0 UNDECIDED |
4.2 "重键前红"与验证轮找到的三个缝隙缺陷
buffer 类的红前证据(package C 尚未注册 MGPipeResourceOps 时):HandleRecycle 的 .AbaControl 臂通过(它断言的就是被污染的内容)、.Legacy 通过、.Handles 可见地 skip;C 注册后两条 skip 转为断言,最终 60/60。
| # | 缺陷 | 表现与修法 |
|---|---|---|
| F1 | vertex buffer 条目按属性的 GL 绑定点解析,而不是按属性下标 | 两者只在 KHR-GL43.vertex_attrib_binding 题材上分叉;VertexAttribBindingScenario 6 → 3 |
| F2 | ensure 路径读 MGPResourceDesc::HasDefinedContent(上一次 respecify 时的事实)判断影子有无字节 |
glBufferData(size, NULL) + glBufferSubData 后应用字节被静默丢掉;改为持有前端对象时读 HasDefinedContent() |
| F3 | 惰性生成的 twin 从不发布影子基址,fp64 收窄拒绝每个 draw | hostBytes 终身 null → Adreno workaround 禁用属性;在算出基址处补发布,只对非采纳资源 |
方法学:包 worktree 里 tools/trace_replay/fixtures 是 LFS 指针,对着指针跑 retrace 报 passed 2 / 79、ssim=None——假红;base-instance 对照在 llvmpipe 上要先关掉原生 GL_EXT_base_instance 才可证伪。
4.3 Track H 单位成本
日历:四个包(contract/wire、client、espryt、gates)各一轮实现 + 对抗性评审 + 至多两轮返工,全部在 2026-09-08 一天内,对 27 天绊线 1/27。memo 账:直接删除普查 11 条里的最后一条(ConvertedVertexStreamKey::sourcePin);句柄臂上退役 VAO twin 五个同步 memo 成员;重键 VAO twin 索引槽 memo、ResolvedDrawBuffers、twin 同步门、ConvertedFloat64Stream;保留(MOBILEGL_PIPE_LEGACY_MEMOS 下仍编译):以上全部成员、g_pendingFetchBaseInstance 族、D-K 那组——真删会移走 pull 符号或改 sizeof,G1 的 0/0/0/0 就是这条的度量,随 P13 退役。
4.4 两机 Release 配对 A/B、MC 26.3 的 p99、DriverBench(记录项)
协议:reboot-clean、pin_device.sh 钉频并前后 check、两臂背靠背、--benchmark-repeats 3 --benchmark-tail-frames 200、best-of-3、--benchmark-no-finish 主臂;APK 都是 3e298c9a 的 Release trace 构建(.text 9.4 MB)。臂:pull = pull 库;P2 = push APK MOBILEGL_PIPE_PUSH=0x7f;P3a = push APK 默认 0x1ff。create-indirect 排除(开放问题 17)。单位 ms/帧。
| 设备 | trace | 后端 | pull p50 | P2 p50 | P3a p50 | pull p99 | P3a p99 | 备注 |
|---|---|---|---|---|---|---|---|---|
| 小米 | improved-transparency-minecraft-26.3 |
Espryt | 10.810 | 11.485(+6.2%) | 11.697(+8.2%) | 25.457 | 26.322 | |
| 小米 | 同上 | Magma | 10.675 | 11.473(+7.5%) | 11.459(+7.3%) | 25.014 | 26.035 | |
| 小米 | minecraft-1.21.4-rd12-odinlite-in-world |
Espryt | 8.220 | 9.117(+10.9%) | 10.650(+29.6%) | 21.895 | 24.487 | |
| 小米 | 同上 | Magma | — | — | — | — | — | 三臂都 SIGABRT(scudo::reportMapError,dev 侧) |
| 小米 | minecraft-1.21.4-fabric-sodium-in-world |
Espryt | 1.292 | 1.349(+4.4%) | 1.382(+7.0%) | 2.418 | 2.443 | |
| 小米 | 同上 | Magma | 0.485 | 0.504 | 1.010 | 1.469 | 2.187 | 亚毫秒帧,噪声 |
| 小米 | create-instancing |
Espryt / Magma | 944.4 / 1003.9 | 945.2 / 1019.5 | 949.9 / 1015.6 | — | — | 两帧 fixture |
| Oppo | improved-transparency-minecraft-26.3 |
Espryt | 9.741 | 10.570(+8.5%) | 10.542(+8.2%) | 26.312 | 27.022 | |
| Oppo | 同上 | Magma | 8.162 | 8.920(+9.3%) | 8.973(+9.9%) | 22.851 | 23.638 | |
| Oppo | minecraft-1.21.4-rd12-odinlite-in-world |
Espryt | 9.938 | 11.009(+10.8%) | 12.963(+30.4%) | 27.137 | 29.765 | |
| Oppo | 同上 | Magma | 8.001 | 8.933(+11.6%) | 10.161(+27.0%) | 24.723 | 27.355 | |
| Oppo | minecraft-1.21.4-fabric-sodium-in-world |
Espryt / Magma | 1.896 / 0.399 | 1.770 / 0.431 | 1.841 / 0.437 | 2.993 / 1.206 | 3.079 / 1.409 | 噪声内 |
| Oppo | create-instancing |
Espryt / Magma | 1075.1 / 758.3 | 1045.1 / 731.0 | 1060.1 / 760.0 | — | — | 两帧 fixture |
读法:(1) P2 边界在 Release 下的真实代价是 +6–12%,两机两后端一致;(2) P3a 在 26.3 与 sodium 上几乎不再加价,但在 rd12 上把差距从 +11% 推到 +27–30%——rd12 每帧 VAO/buffer 绑定切换远多于 26.3,每次切换走一遍 set_vertex_buffers 构造 + ContentHash + applier 记录 + 逐属性走查(P4a 补的 csob-blob 计数器给了字节口径:rd12 1.06 MB/帧,其余用例中位数 2.9 KB/帧;DirectVulkan 恒 0);(3) MC 26.3 在 Adreno 上的 p99:25.46 → 26.32 ms(+3.4%),仍在采纳基线的 21–26 ms 档;(4) mpr 在设备上成立(26.3 两机都是 8,P2 臂恒 0);(5) 计数器三臂逐字相同。
小米 rd12 + Magma 三臂(含 pull)都 SIGABRT:scudo::reportMapError ← scudo_calloc,pull 库与 P3a 前的 Magma 路径符号一致——既有 bug,dev 侧任务。
DriverBench(wsl_p3a_bench.sh,c20e2f2b,mc_vanilla_draw ns/draw;T2 = 0x7f 臂):
| Espryt | Magma | |
|---|---|---|
T1 = push(0x1ff) − pull |
+1048(+20.5%) | +611(+3.6%) |
T2 = push(0x7f) − pull |
+349 | +189 |
| T1 − T2 = P3a 自己加的 | +699 | +422 |
| 位 63 − push | −6 | +20 |
| blend-toggle / pass switch | +5.2% / ≈ 0 | +2.8% / ≈ 0 |
读法:P3a 的 buffer/VAO 句柄路径每 draw 多花 Espryt 699 / Magma 422 ns(Magma 没有句柄化的 VAO 消费者,全是 client 侧发射 + applier 记录);进优化清单:vertex-input 发射的 per-draw 抑制与 applier 记录就地更新。DriverBench 必须经 DRIVERBENCH_EGL_LIB 显式 dlopen provider,不得靠 LD_LIBRARY_PATH(glvnd 会把 GPU 悄悄换成 llvmpipe)。
4.5 决定与遗留
- ID-15:
Managers.cpp的三层 flush 排水梯每个预处理臂各一份——push 构建跑FlushPendingRangesFrom,pull 构建跑逐字节不变的FlushPendingRangesNow;两个名字都是 G5 行,各对自己的 pin 比。转发函数不可行(G5 提取器不认预处理)。 - M-3:fp64 顶点数组收窄在句柄臂上少做一处
SyncGpuWrites(SyncFloat64AttributeAsFloat32ByHandle手里只有句柄)——默认掩码下两臂唯一的行为差异(fp64 数组 + shader 写过的源 buffer + 无显式回读),P8 把拉取搬到 client 侧即关闭。 - 整体 diff 终审抓出两个跨包接缝:client 为每个 VAO 铸的
VertexElementsCso槽在 Magma 下泄漏(修为~VertexArrayObject走后端无关的死亡路径);FlushPendingRangesFrom在 G5 覆盖之外(→ ID-15)。 - CI 独有的 teardown 崩溃(
exit()时静态析构顺序 UAF):MGPipeSlots()等单例与四个持有前端SharedPtr的静态PipeInputs改为退出时泄漏(d54ec57a、6515c8e6、fde5fda3),ASan 10/10 干净;复现钥匙GLIBC_TUNABLES=glibc.malloc.tcache_count=0。 dev侧跟进(拆分不顺手修):g_uploadRing不被OnBackendContextDestroyed重置(良性,RingAvailable自愈);ScopedDefaultUnpackState::s_synced没有失效路径。MG_Test/Buffer/BufferTest.cpp的 fixture 只 scope 了BufferBackendOps不 scopeMGPipeResourceOps,26 条被路由进 pipe——修后 86/86;给它一个 pipe 形 mock 是跟进项。- 峰值 RSS(push vs pull,79 例):
retrace_gate.py不报,没有数。
里程碑记录(原 ROADMAP.md)
- P3a / P4a 出口(2026-09-08):各 1 天,远低于 27 / 39 天的再基线绊线,未触发重定基线。
本目录
| 文件 | 内容 |
|---|---|
BRIEF-P3A.md |
P3a implementation brief — handle wave 1 (Espryt): buffers and VAOs behind the resource_* / vertex calls |
INTEGRATOR-DECISIONS.md |
P3a integrator decisions (feat/disaggregated, 2026-09-08) |
scout-docs-spec.md |
1. The P3a row of the phase table |
scout-espryt-buffers.md |
P3a scout — Espryt (MobileGL/MG_Backend/DirectGLES) buffer surface |
scout-espryt-vao.md |
P3a scout — Espryt's vertex-array surface |
scout-pipe-and-tests.md |
P3a scout — the MGPipe scaffolding and the gates |
ab/ |
3 个文件:两机 Release 配对 A/B |
bench/ |
1 个文件:DriverBench |
p3a-results/ |
19 个文件:各包的实现、评审与终审稿 |