Files
MobileGL/docs/Disaggregated/MEASUREMENTS.md
T

45 KiB
Raw Blame History

实测记录

每张表写明设备、提交与命令。设备:35d0befa = Xiaomi 24129PN74CSM8750 / Adreno 830v2)与 3B159D009VZ00000 = Oppo PLG110MT6993 / Mali)用于 P0P3a2f7cbe2e = Redmi M332BFSM8750 / Adreno 830v2,与小米同 SoC 同定频点)是 P4a 起唯一的 A/B 设备。定频、风扇与热协议见 devices/pin-verification-2026-09-07.md

口径(用户 2026-09-08 起):性能对着 pull 臂记录、不作阻塞门;正确性门是硬门。两条读数纪律:acc/draw 是约 10 个热入口的静态计数,把读点搬走与把工作去掉在它上面长得一样,判性能只看 CPU 时间序列与六个 memo 门;ctest -V 做拒绝普查是假零(console sink 在发布配置里被编译掉),必须逐用例读私有日志。

1. P02026-09-05trace APK 7ef7c7e5spike 8a239177

1.1 Spike A — 从应用自身进程 exec 第二个原生可执行文件

设备 结果
Adreno 830 OKuntrusted_app 父进程 fork+execve <nativeLibraryDir>/libMobileGLServer.so,子进程同域同 category、exit 0、execErrno=0、零 avc denial
Mali OK,同形

主机侧已证:AGP 会把改名成 lib*.soadd_executable 打进 lib/arm64-v8a/RUNTIME_OUTPUT_DIRECTORY 重定向到 CMAKE_LIBRARY_OUTPUT_DIRECTORY);posix_spawn 在 minSdk 26 不可用;应用进程 stdout/stderr 是 /dev/null,子进程用 marker 文件证明自己活过。代码:tools/spikes/server_stub/android-plugin/app/src/trace/cpp/spawn_spike.cppMOBILEGL_BUILD_SERVER_SPIKE

1.2 Spike B — 跨进程外部内存分档(tools/spikes/extmem_probe/shell 域,4 MiB payload,每行一次真 GPU 访问 + 两侧字节校验)

路线 Adreno 830 Mali
T1-opaque-fdserver 导出 VkDeviceMemory fdclient mmap + 导入) OK 完整往返 UNSUPPORTEDVK_ERROR_INVALID_EXTERNAL_HANDLE
T1-dma-buf UNSUPPORTED UNSUPPORTED
T1-gles-memobj-fdGL_EXT_memory_object_fd FAIL:导入接受,但每次 glMapBufferRangeGL_INVALID_OPERATION UNSUPPORTED
T0-ahb-blob-transferclient 分配 AHardwareBuffer BLOB → socket 交接 → server Vulkan + GL 导入) OK 全链 OK 全链
T3-external-memory-host UNSUPPORTED PARTIAL:GPU 写对宿主映射不可见(只读档)

决定:唯一在两台设备、两个后端上都是完整读写的档是 T0Adreno 另有 T1Vulkan 路径);Mali 无任何 server 导出路线。Caveat:运行域是 shell 不是 untrusted_appROADMAP.md 开放问题 3)。

ANDROID_NDK=$HOME/android-sdk/ndk/27.3.13750724 tools/spikes/extmem_probe/build_android.sh /tmp/extmem-build
adb -s $S push /tmp/extmem-build/extmem_probe /data/local/tmp/ && adb -s $S shell "chmod 755 /data/local/tmp/extmem_probe && /data/local/tmp/extmem_probe"

1.3 边界计数器基线(MOBILEGL_PIPE_STATS=1,最后一个完整 120 帧窗口;accessor / memo 数字是软件确定的,两台设备相同)

trace(窗口内帧数) 后端 draws/f acc/draw buf B/f tex B/f(发射 box / rect ubo-global B/f ubo-named B/f memo 门(hit/miss
minecraft-1.21.4-in-world360 Espryt 91.6 9.28 13.5 K 635 K185 box / 0 rect 16.7 K 0 ers 9257/2577etl 10538/1296eub 10720/1114
同上 Magma 91.6 8.56 13.5 K 39.9 K97 box / 89 rect 16.7 K 0 mfp 0/10994mpm 9240/1754mdt 9120/1874
minecraft-1.21.4-fabric-iris-bsl-in-world120memo 冷) Espryt 23.2 21.04 32.6 K 8.8 K 1.8 K 0 ers 1958/1843etl 722/3079
同上 Magma 23.2 11.26 313 K 256 K 1.8 K 0vtxc 1.7 K mpm 1890/895mdt 1573/1212
improved-transparency-minecraft-26.31200 Espryt 1320 8.44 333 K 0 0 0 ers 156925/2791etl 148606/11110eub 148246/11470
同上 Magma 1320 6.53 173 K 0 0 331 K mfp 21360/137036mpm 134421/2615mdt 156611/1785

门缩写:ers = EsprytRenderStateetl = EsprytTextureSyncListeub = EsprytUnitBindingsEpochmfp = MagmaDrawFastPathmpm = MagmaPipelineMemomdt = MagmaDynamicTail。读法:真机稳态动态 accessor 成本是每 draw 6.59.3 次(预测区间 10–25 的下沿),推送要打败的是 ~8 次 accessor + memo 探测;Magma 在 26.3 每帧重打包 331 KB 具名 UBO 字节(D-B8);同样 185 次发射,Espryt 整 box 路径 635 K 纹素字节 / 帧、Magma rect 路径 40 K16×("server 选上传形状"的依据)。

ANDROID_SERIAL=<serial> MSYS_NO_PATHCONV=1 python3 tools/trace_replay/run_android_retrace_local.py \
  --case minecraft-1.21.4-in-world --backend DirectGLES --env MOBILEGL_PIPE_STATS=1 --env MOBILEGL_PIPE_STATS_PERIOD=120
# 数字在结果目录的 mobilegl.log 里,grep 'MGPipe stats:'

1.4 桌面数据点与语料事实

  • llvmpipe / lavapipe 动态 accessorGuiBatchScenariomemo 冷):Espryt 20.65 / Magma 15.54 次 / draw。
  • dirty-surface 面:MG_Impl/GLImpl 41 个文件、926 次 mutator 调用、73 个不同 mutatorRecordError 占 836 次);92 次位于同函数内也到达后端的即时发布点,其余由紧随的 verb 发布。
  • 读点覆盖:63 个 PipeInputs 字段;后端读点清单 → 调用映射 0 UNMAPPED
  • OOM 探测惯用法:41 个 trace fixture 中 0 例(9 次 glRenderbufferStorage 无一在 3 个调用内跟 glGetError)→ glRenderbufferStorage* 不 ack。
  • FramebufferSrgb / DepthClamp:六个后端读点消费编译期常量 false / 零读点;glEnable 落到 default: 分支既不存储也不报错;41 个 fixture 无一开启。
  • payload 尺寸(MGPipeTypes.hstatic_assertarm64 与 x86-64 一致):MGPDrawInfo 56、MGHostSpan 32、MGPBindRenderState 12、MGPResourceDesc 88、MGPFramebufferState 304、MGPProgramDesc 192、MGPSubData 72SEG_CMD 按 56 B 头定尺,MC 帧 10004000 draw 时每帧 56224 KiB 头字节。
  • persistent map 采纳的既有基线(devMC 26.3Adreno):p99 163→21 ms、稳态 40→115 fps、省 ~400 MBP11 的回归上限对着它。Mali 上传作业数悬崖:~100 个精灵 rect 对一个 union box 是 +6 ms/frame。

1.5 Harness 事实与陷阱

  • trace app 从不到达 MobileGL::DestroyImplMOBILEGL_PIPE_STATS_FILE 在设备上永远不会写;只有 mobilegl.log 的周期汇总行,MOBILEGL_PIPE_STATS_PERIOD 为此而加。
  • run_android_retrace_local.py 每棵树共用一个 .trace-work/android-retrace-result 根并 rmtree,两台设备必须从一棵树串行跑。
  • --env 值里的 /data/... 会被 MSYS 路径转换,用 MSYS_NO_PATHCONV=1
  • ColorOS 首次 adb install 卡在 InstallGuideActivity 确认页;streamed install 进行中点它会让设备掉线几秒。
  • minecraft-1.21.1-neoforge-create-indirect-in-world 在两台设备上都失败,dev@81b17c0b 基线 APK 复现——dev 侧问题(ROADMAP.md 开放问题 17)。

2. P1lavapipe / llvmpipe

2.1 规模

后端 pGLContext-> 箭头站点 277Espryt 113、Magma 164
非箭头行 58Espryt 9、Magma 49,其中 43 条是 Magma 的逐 verb MOBILEGL_ASSERT
PipeInputs 字段 / 不同访问器 63 / 62Espryt 32、Magma 56
填充点 83 条 MGP_FILL,覆盖 69 个 verb、9 个类
SyncPersistentMappedRange / SyncGpuWrites 21Espryt 9 + Magma 12P5 b1 复核,原记 20 漏了共享 helper ResolveIndirectCommandBytes/ 6

2.2 verify 通道发现的两类真问题

缺填充行(9 处)kReadbackIsTransformFeedback{Active,Paused}kTextureOpkDispatchIsCapabilityEnabledkBlitOrCopy/kTextureOp 缺着色器 blit 用到的 viewport 与顶点 / 缓冲绑定。其中 8 行是静态过近似(代码路径可达但通道未跑到),有意保留——能退役它们的证据只能是动态的(完整 CTS caselist + MOBILEGL_PIPE_POISON_OMIT,未做)。

verb 内后端改前端(3 个字段)Magma 在 draw 里写前端对象(合成回退纹理、材质化排队清除、覆写 sampler filter),8 条 DirectVulkan 用例与 2 条 trace 报 Fatal{PipeVerifyDiffer, "GetSamplingResolutionGeneration@Draw*"}。解法 push-on-mutation:前端计数器移动时用 MGP_NOTE_MUTATION(Field) 刷新推送块里那一个字段——钩子挂在三个计数器上(BumpSamplingResolutionGenerationBumpTextureBindGeneration / NoteUnitTouched、高水位分支),不挂在四十个写入点上。

2.3 验收

结果
pull 构建符号与 .text 0 增 / 0 删 / 0 改尺寸 / 0 重命名,.text 不变
MG_Backend 里的 pGLContext 0
单元(pull / push / verify 1485 × 3
integration-gpupull / integration-verify 878 / 818 零 Fatal{
79 例 retraceMOBILEGL_PIPE_VERIFY=1 79/7979/79 armed,零 Fatal{
两个阴性对照 篡改字段变红、抽掉一个填充戳记在那条 verb 上变红
测试名 0 删除,+29

verify 构建的代价:integration-verifyintegration-gpu 同量级;79 例 retrace 在 4 路下约 20 分钟。

3. P2738b289d

3.1 门

结果
G1 pull 构建符号 0 增 / 0 删 / 0 重命名;4 处认定 resizeRenderState::{RenderState, SetCapability, IsCapabilityEnabled}_GLOBAL__sub_I_DirectGLES.cpp);.text +160 B
G5 SyncRenderState RenderStateImpl 段 sha 逐字节相同
G2 / G14 名差 00 删除 / +119
单元 1566 × {pull, push, verify}
integration-gpu 916/916 × {pull, push, MOBILEGL_PIPE_PUSH=0};渲染状态敏感子集 72/72
integration-verify 828 零 Fatal{
79 例 retrace push 79/79verify 79/79 armed 零分歧
G7 setter 一致性阴性对照 变红并点名 SetColorMask
CsoContentAddressing / verify 三组对照 6/6 / 44/44PoisonOmittedVerifyCorruptedHandleRecycle

3.2 设备配对 A/B-O0 勘误)

两机 64 次运行(小米 + Oppo,四 trace × 两后端 × finish 开/关,reboot-clean、钉频、best-of-3、尾 200 帧)所用的两臂 APK 是未优化构建libMobileGL.so 43.2 MB / .text 21.8 MB,对 Release 15.5 / 9.4 MB),绝对值与差值都是 -O0 读数,不作基准线;Release 基准线以 §4.4 为准。-O0 读数:小米 p50 +814%(四 trace 两后端),Oppo Espryt +1618% / Magma +1011%,p99 同向;finish 开关两臂几乎一致(多出的是客户端 CPU);计数器两机逐字相同。原始 32 行表在 git 历史(ea34bccb 版本的本文件 §10)。harness 误杀记录:trace-replay-ci.shpidof 单次采样失败即 force-stopdev 侧跟进。

3.3 DriverBenchT1 / T2(桌面 llvmpipe / lavapipewsl_p2_bench.shRelease240 帧 × 5 次取中位数,ns_per_op

mc_vanilla_drawns/draw mc_state_togglens/开关对) mc_pass_switchns/pass
native 4771 22968 437759
Espryt pull / push / push PIPE_PUSH=0 / push 位 63 5121 / 5443 / 5671 / 5374 23753 / 24869 / 24584 / 24630 443300 / 446017 / 443807 / 435454
Magma pull / push / push PIPE_PUSH=0 / push 位 63 16900 / 17245 / 17599 / 17444 32705 / 33857 / 34082 / 34780 438406 / 446067 / 445006 / 444758
mc_vanilla_drawns/draw Espryt Magma
T1 = push pull(整个边界) +322+6.3% +345+2.0%
T2 = push(PIPE_PUSH=0) pullP1 残余填充) +550 +699
T1 T2P2 自己加的减的) 228 354
位 63 − push(CSO 内容寻址净值) 69(≈ 0 +200(内容寻址每 draw 省 200
blend-toggle / pass switch +4.7% / +0.6% +3.5% / +1.7%

读法:P2 的 tracker + CSO 比它替掉的 P1 残余填充便宜;剩下的 T1 是尚未句柄化的填充与 dirty 走查。mc_state_toggleDriverBenchStateToggle 钉住每帧 46 对开关;位 63 对照的开关 CsoContentAddressingScenario 常开(内容寻址臂 csom ≤ 4csom < csob,位 63 臂 csom == csob)。

3.4 计数器读数

resid= 已非零且棘轮压到底(1248 → 8):桌面 push retrace iris-bslresid=197.07 B/帧 = 每 draw 0.64 块;csom/csob = 8 / 1415CSO 复用比)。小米 push 臂(-O0,计数器与优化无关):

trace Espryt ers / etl / eub Magma mfp / mpm / mdt resid= B/帧 csom / csob(每 120 帧)
minecraft-1.21.4-in-world 6020/1850 · 6884/986 · 6962/908 0/7278 · 6030/1248 · 5928/1350 178.31 2 / 1719
improved-transparency-minecraft-26.3 78960/1367 · 75378/4949 · 75199/5128 10740/68928 · 67660/1268 · 78800/868 185.36 0 / 1157
minecraft-1.21.4-fabric-iris-bsl-in-world 113/133 · 85/161 · 82/164 0/177 · 86/91 · 81/96 370.67 1 / 122
minecraft-1.21.4-startup 174/185 · 305/54 · 305/54 0/118 · 0/118 · 0/118 25.08 9 / 181

CSO 内容寻址在稳态窗口里几乎不再铸造;memo 门形状与 §1.3 的拉取基线一致。未测:逐 dirty 位触发率(FireCount/WalkCount 已实现但不在汇总行)、每 draw payload 直方图(只在 teardown JSON 里)。

3.5 遗留判定

  • MOBILEGL_ESPRYT_DISABLE_INVALIDATE_FLUSH=1 的 186 条过滤不进比对器(P3a 在 push 下跑了一次 958/958;进比对器推迟到 P3b)。
  • Track H 单位成本的日历口径未记录(产出侧在案:11 条 memo 删除 + 2 条重键零回归)。
  • 句柄 ABA 对照"重键前红":修复前 HandleRecycle 28 条中 1 条红(AbaControl 期望死对象的红却看到替换对象的绿);修后 32/32,且关掉 MOBILEGL_PIPE_HANDLE_ABA_CONTROL 两臂都 observed=FRESH 并失败——污染只由被打掉的身份产生。

4. P3afde5fda3,基线 5cb826b044 个提交,37 文件 / +9273 / 230

4.1 五部分门(本地 ~/w7/pipe

结果
构建 pull / push / verify rc 0 / 0 / 0fail-fast,绝不拿陈旧二进制下判决)
A 门 include 闭包 / C 门 pGLContext / G13 4 probes 0 problem / 空 / 空
G1 .text 10806323 → 10806323+0);27811 符号 0 / 0 / 0 / 0
G5 十一函数(pool / 延迟释放 / ring / FlushPendingRangesNowFlushPendingRangesFrom 44c2b5cf5cb826b0 都逐字节相同;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, 0x7fG12 子系统关闭臂), ESPRYT_DISABLE_INVALIDATE_FLUSH=1}
buffer/VAO 族 / RenderStateSpans+Residual+VertexInputEmit+ResourceEmit 202/202 / 48/48
HandleRecycleverify / 子系统对照 / 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 / 79ssim=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 符号或改 sizeofG1 的 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=0x7fP3a = push APK 默认 0x1ffcreate-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 三臂都 SIGABRTscudo::reportMapErrordev 侧)
小米 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 下的真实代价是 +612%,两机两后端一致;(2) P3a 在 26.3 与 sodium 上几乎不再加价,但在 rd12 上把差距从 +11% 推到 +2730%——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 上的 p9925.46 → 26.32 ms+3.4%),仍在采纳基线的 2126 ms 档;(4) mpr 在设备上成立(26.3 两机都是 8,P2 臂恒 0);(5) 计数器三臂逐字相同。

小米 rd12 + Magma 三臂(含 pull)都 SIGABRTscudo::reportMapErrorscudo_callocpull 库与 P3a 前的 Magma 路径符号一致——既有 bug,dev 侧任务。

DriverBenchwsl_p3a_bench.shc20e2f2bmc_vanilla_draw ns/drawT2 = 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 nsMagma 没有句柄化的 VAO 消费者,全是 client 侧发射 + applier 记录);进优化清单:vertex-input 发射的 per-draw 抑制与 applier 记录就地更新。DriverBench 必须经 DRIVERBENCH_EGL_LIB 显式 dlopen provider,不得靠 LD_LIBRARY_PATHglvnd 会把 GPU 悄悄换成 llvmpipe)。

4.5 决定与遗留

  • ID-15Managers.cpp 的三层 flush 排水梯每个预处理臂各一份——push 构建跑 FlushPendingRangesFrompull 构建跑逐字节不变的 FlushPendingRangesNow;两个名字都是 G5 行,各对自己的 pin 比。转发函数不可行(G5 提取器不认预处理)。
  • M-3:fp64 顶点数组收窄在句柄臂上少做一处 SyncGpuWritesSyncFloat64AttributeAsFloat32ByHandle 手里只有句柄)——默认掩码下两臂唯一的行为差异(fp64 数组 + shader 写过的源 buffer + 无显式回读),P8 把拉取搬到 client 侧即关闭。
  • 整体 diff 终审抓出两个跨包接缝:client 为每个 VAO 铸的 VertexElementsCso 槽在 Magma 下泄漏(修为 ~VertexArrayObject 走后端无关的死亡路径);FlushPendingRangesFrom 在 G5 覆盖之外(→ ID-15)。
  • CI 独有的 teardown 崩溃(exit() 时静态析构顺序 UAF):MGPipeSlots() 等单例与四个持有前端 SharedPtr 的静态 PipeInputs 改为退出时泄漏(d54ec57a6515c8e6fde5fda3),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 不 scope MGPipeResourceOps,26 条被路由进 pipe——修后 86/86;给它一个 pipe 形 mock 是跟进项。
  • 峰值 RSSpush vs pull79 例):retrace_gate.py 不报,没有数。

5. P4a8c458cd5,基线 37da3c3a101 个提交,86 文件 / +30066 / 384

5.1 全门(6035c9d7 全量 + 8c458cd5 复跑)

6035c9d7 8c458cd5
G1(认定 resize 集为空) 0 / 0 / 0 / 0.text 不变 同上
G5 P3a 十一函数 rc 0P4a 17 区 / 3 文件 rc 0self-test 8 个阴性对照按名变红 同上
G2 / G14 差 0 / +275 差 02902 条)/ +314
单元 1772 × 3 1785 × 3
integration-gpu 1091/1091 × 七臂 1117/1117 × 七臂(默认 0x1fff0x1ff00x9ff0x5ff、pull、ESPRYT_DISABLE_INVALIDATE_FLUSH=1DirectVulkan 559/559
integration-verify 896/896 零 Fatal{ 920/920
retrace79 例) verify 79/79 armed 零分歧;push 79/79G3b 12/12 push 79/79
阴性对照脚本 g7_negative_control.shp3a_vertex_input_negative_control.shIsBgra)、p4a_descriptor_negative_control.shLayeredborderColorForm rc 0 同上
子系统对照套件 CsoContentAddressing + ResourceSubsystemControl + ObjectSubsystemControl 24/240x9ff 依赖拒绝臂 14/14HandleRecycleverify180/180 同上 + 184/184 controls
八族拒绝普查 0(逐用例读私有日志;ctest -V 是假零)

G9 的"落地前必须红"没能通过公共 GL 达成(回读模拟自己会设 GL_DEPTH_STENCIL_TEXTURE_MODE):改成 PipeApplyPeek 白盒断言,变异下 4/4 变红。真正红过再绿的两条来自终审:per-level respecify 丢上传(0x1fff 下读回全黑)与 delete-then-drawpure virtual method called)。CTS direct_state_access.framebuffers* / packed_pixelsG15)未跑,随 P3b/P4b 补。

5.2 缝的分类(契约七次修正 c0bc0g + 一轮缝类审计 + 一轮终审修复)

实例 症状 预防
编码没定死 MGPSubData::TargetDepthStencilModeMGPSurface::Kind、缺 TextureTarget 两侧各自发明一套;Texture1D == 0kMGPipeResourceTargetBuffer == 0 撞上 编码表放进契约
身份 vs 内容 内置 samplerclient 按身份铸、cache 按内容铸 查找永远落空 → 17 条 Iris trace 用驱动默认采样器 每 kind 两侧 handle 规则表
记录键错了维度 framebuffer 记录按"当前绑定"存,DSA 按名字来 打进从没收到附件的 FBO 记录按对象存;Named = 3
进程级单例 vs 每上下文命名 CompositeResolver 按管线 GL 名记忆 释放另一个上下文还活着的合成体 单例的键含上下文身份
破坏性客户端动作缺前置条件 按 acceptance 清 dirty,但 Magma 无消费者、依赖位只在服务端拒 上传丢失:66 条 DirectVulkan 用例、0x7ff 下 438/491 消费者门 + 依赖门都在客户端:一条不发
快门看不见自己的主体 glBindSampler、SSO 下 GetCurrentProgram()glBindImageTexture 只换 level 记录停在上一次的值(create-indirect SSIM 0.887 "记录字段 → setter → 快门"完备表;优先混入已有世代
清得太宽 resource_respecify 清掉整张待上传表 已接受的那一级永久丢失 作用域随调用走
死亡没通知发射方 六个死亡 helper 只释放 slot 已删句柄解析到已释放对象 → UAF 死亡转发给每个 emitter
门不能变红 G7 脚本永远编译不过、HighWater(ShaderCso) 取段顶、G9 红前态公共 GL 不可见 绿得毫无意义 每个门带阴性对照并真跑过一次红

方法论结论:六个包的 v1 全部通过自己的门、六份对抗性复审全部判 REWORK,最贵的两个缺陷(丢上传、delete 后 UAF)是整体 diff 终审才抓到的——它们跨包,各方自洽。终审是唯一能看见跨包契约的那一轮。

5.3 Redmi 三臂 A/B、MC 26.3 的 p99、上传形状(记录项)

设备换为 Redmi 2f7cbe2e(与小米同 SoC 同定频点,数值可比;GPU 当时钉 1050 MHz;主动风扇 level 240 个样本 40 个 PINNED)。APK 8c458cd5 Release 双臂;--benchmark-no-finish,尾 200 帧、best-of-3、逐线程 CPU p50 ms0x1ff = P2+P3a 边界,0x1fff = P4a 默认。

用例 后端 pull 0x1ff 0x1fff Δ P2+P3a Δ 合计 P4a 自己
improved-transparency-26.3 Espryt 10.716 11.754 12.124 +9.7% +13.1% +3.4 pt / +0.37 ms
improved-transparency-26.3 Magma 10.603 11.543 11.585 +8.9% +9.3% +0.4 pt(噪声)
rd12-odinlite Espryt 8.210 10.798 11.182 +31.5% +36.2% +4.7 pt / +0.38 ms
rd12-odinlite Magma 三臂全 rc=1scudodev 侧,换机仍复现)
fabric-sodium Espryt 1.312 1.406 1.454 +7.2% +10.8% +3.6 pt / +0.05 ms
fabric-sodium Magma 0.474 0.502 0.507 +5.9% +7.0% +1.1 pt(噪声)
1.21.4-in-world Espryt 2.369 2.732 2.867 +15.3% +21.0% +5.7 pt / +0.14 ms
1.21.4-in-world Magma 1.028 1.147 1.145 +11.6% +11.4% 0.2 pt(噪声)
fabric-iris-bsl Espryt 1.727 1.740 1.811 +0.8% +4.9% +4.1 pt / +0.08 ms
fabric-iris-bsl Magma 0.742 0.788 0.786 +6.2% +5.9% 0.3 pt(噪声)

读法:P4a 自己在 Espryt 上是 +3.4 +5.7 pt0.050.38 ms/帧),大头仍是 P2+P3a 的边界;Magma 两臂在四个用例上落在噪声内——消费者门在设备上的读数(Magma 一条 P4a 记录都不发);vanilla 是 P4a 占比最高的用例(draw 少、状态切换密)。MC 26.3 在 Adreno 上的 p99pull 25.297 → P4a 26.841 ms+6.1%),仍在 2126 ms 档。上传形状 pull 与 push 逐项相同79 例两臂 tex[emit/box/rect/jobs]18451/16060/2391/39926 对 18453/16062/2391/39928,唯一差异是 2 次 trp 带来的重放上传)。线索:设备上 26.3 Espryt 的 sve ≈ draw 数(9143 / 9138),桌面 ~0.07/draw——每 draw 重发一次 sampler-view 集合,进 P3b/P4b 优化清单。acc/draw 在这一波普遍下降而 CPU 上升,不是矛盾而是该计数器的定义。

5.4 DriverBenchwsl_p4a_bench.sh8c458cd5mc_vanilla_draw ns/draw

Espryt T10x1fff pull= +1076.1T20x1ff pull= +1064.7T1 T2 = +11.4Magma T1 = +629.0、T2 = +452.6、T1 T2 = +176.4。两臂绝对值在两轮之间各漂 ~200 ns 而差只有 10130 ns桌面 bench 分辨不出 P4a 这一档;可引用的是 T1 ≈ +1.1 µs/draw 的总边界(Espryt)与设备侧三臂表。Magma 的 +176 ns 不是"Magma 在跑 P4a"(消费者门让它一条不发),是 tracker 多算的快门加噪声。

6. P5joint e61d0012 → 落地 eec0e836 → 收尾头 37fc4fdb

6.1 五部分门(joint)与落地快门

部分 joint 实测
1 接口纯度 include closure 4 probes / 0 problemspull MG_Remote 符号 0、split 610G1 .text 10806611 → 10806611、27814 符号 0/0/0/0P3a/P4a G5 对 ff2994d9 byte-identical
5 覆盖 / 生成器 gen_pipe self-test 9/9dirty-surface 27/27UseProgram 一项明确 UNDECIDED);field ownership 15/15emitter/CSO 185/185verify controls 4/4
3 行为 A/B G2 差 0G14 0 / +42unit 1816×3、split 2038Wire 58/58integration-gpu pull 1128、push 1128、split-monolith 1149split-inproc 普查 426 pass / 185 skip / 511 abort / 27 failintegration-split 21/2119 run、2 design-skip);persistent arm 2/2split pmap=2160.00, mpr=1push pmap=0.00, mpr=1
2 语义 / retrace integration-verify 930/930 零 Fatal{OpenRA inproc 2/2 双后端 SSIM 1.0push retrace 79/79verify retrace 79/79 armed
4 设备 未跑(joint 禁止 adb);见 §6.4

落地快门(eec0e836ID-66):split unit 2038integration-split 22/22push integration-gpu 1128G1 0/0/0/0 .text +0

6.2 退出门 E1E6 与 27 个 wrong-answer

实测与"为什么会红"
E1 barrier reduced path 19 pass / 2 skip / 0 failMOBILEGL_IPC_VERB_BARRIER=0 选中的 14/14 全 abort,每个私有日志有自己的 Fatal{BarrierViolation, "<slot>"}
E2 OpenRA 2/2 SSIM 1.0x2:丢 29 clears 仍 SSIM 1.0(被后续地形 draw 覆盖),改为丢 758 DrawVbo 后 SSIM 0.000036r2 验证真实 CTest 顺序 baseline → pull-library control → 恢复原库 → draw-drop,并断言库身份
E3 persistent map (a) 收尾头 6 selected 中 4 pixel red、2 条 TheMapLandsInTheArmItsLaneDeclares 设计性 skip 被 j0 判红 → r2 精选默认 / SmallRing 下 4 条 pixel case 各带自己的 assertion + 私有诊断;(b) ID-42 emulated membership green → 3 red → green(e) x2 证明 wrapr2 证明真实 retirement wait1 MiB 臂 ringwraps=1 ringwaits=18 MiB 对照同时红)
E4 field ownership 生成器 15/15strict lane 19 abort / 2 skip,首条 Fatal{UnmigratedPipeInput, "GetTextureContextId@Clear"}——BARRIER-PULLED 债务的响亮读法
E5 honest inproc 19 pass / 2 skipv1-r3 的 StagedShadowProductionTest 证明 ensure 上传 server shadow(删保护会读 client A 变红),覆盖 unmapped 对象;coherent-map 的 server 侧绕过由 r1 #1 关闭
E6 phase gate 普查在 v1-r3 修掉六条过宽 whole-store 拒绝后 432 / 185 / 505 UnmigratedVerb abort / 27 failed / 0 segfault1149 项,~/w7/p5b-c0b-census-logs/results.json
27 个 wrong-answer 家族 去向
LayeredAttachmentShapeScenario 14 P4b/P7 layered texture readback
packed depth/stencil GetTexImage 3 P4b/P7 texture-shadow readback
framebuffer HandleRecycleScenario 5 P4b/P7 readback(不是已证明的 handle recycle bug
PrimitivesGeneratedNoXfbScenario 3 P7 query
TextureParamsWithoutASamplerView 1 P6 inspection forwarder
P4aFinalFixScenario FBO/RBO delete 1 读回用 ReadPixels,完整像素因果未隔离;client-thread framebuffer death 归 r1 #2

6.3 R-10、逐帧 ledger 与内存

规范 ledgerProtocolSmokeTest 钉住):SEG_CMD 8 MiB / SEG_STAGE 32 MiB / SEG_REPLY 16 MiB / SEG_EVENT 256 KiBMOBILEGL_PIPE_STATS_PERIOD=1 下 persistent-map 场景 pmap=600.00 B/帧, mpr=1, rsp=35rsp 只是有 stamp 读点的下界)。inproc 进程峰值 RSSserver accept 时 11.5 MB、client teardown 141 MB(两角色共享一个进程,不是两个独立峰值)。

max record bytesx237fc4fdb):Triangle / persistent map / OpenRA 25 帧 / SmallRing 都是 maxrec=784 B / SetVertexAttribDefaults,默认 cap 4 MiB(占 0.019%)——这些负载不需要 chunkingoversized DrawVbo 尾的 unit 具名拒绝 Fatal{RingOverrun, "DrawVbo"}

6.4 Redmi 四臂 A/Bsplit 未测)

会话 2026-09-16runner eec0e836,三份 APK 源码头 joint e61d0012;臂 = pull APK / push APK / split APK + MOBILEGL_TRANSPORT=inproc / splitctlsplit APK 不设 transport)。40 组前后 pin check 全 P/P37.239.9 °C。27 组完成 / 13 组失败:全部 10 组 split 在 benchmark 前中止improved-transparency 双后端 DrawElementsInstancedBaseVertex,其余 DrawElements),另 3 组是 rd12/DirectVulkan 的既有 scudo 崩溃。帧 p50 / p99ms):

case / backend pull push splitctl
improved-transparency / DirectGLES 10.535 / 25.415 12.106 / 26.973 12.235 / 27.131
improved-transparency / DirectVulkan 10.742 / 25.031 11.678 / 26.134 11.837 / 26.476
fabric-sodium / DirectGLES 8.314 / 9.573 8.311 / 9.701 8.303 / 9.486
vanilla 1.21.4 / DirectVulkan 1.043 / 2.293 1.159 / 2.404 1.179 / 2.426
rd12 / DirectGLES 7.999 / 22.089 11.105 / 24.865 11.261 / 24.771

splitctl 相对 push 的帧 p50 0.1% +1.6%split build 的 monolith 臂与 push 同源等价)。barrier tax 在 P5 未测得,归 P5b(§7.4)。

6.5 收尾头停止点、r1 / r2

~/w7/p5-final-gate.log37fc4fdb):构建 4 × rc 0Part 1 G1 27,814 符号 0/0/0/0、.text +0、两条 G5 byte-identicalPart 5 完成;Part 3 unit 1817×3 / split 2086、Wire 58、pull/push GPU 1128、split-monolith 1149 零失败、reduced 22 零失败、broad lane 1149 selected532 non-success,含 abort);E1 14 redE3(a) 因 2 条设计性 skip 被 j0-v3 的逐选项拒绝判失败,Part 2 / 4 未到达。j0 的 skip 拒绝是对的(不能放宽),选择器才是错的。

收官审查(p5-close-codex-review.md,只读):1 blocker / 10 major / 2 minorID-73)。r1(核心四项):apply-role 不得进入 persistent-map producerframebuffer death 转 apply mailboxPACK_SWAP_BYTES 的 component / packed-word swapcommand-ring retirement 等待与重试。r237fc4fdb..d50183cb,CI / 控制 / 跑器九项):broad debt lane 记录后继续硬门、全 skip 则 baseline 失败;E2 库身份 SHA256 恢复;E3(a) 精选 4 pixel caseringwaits 只计真正阻塞的分配;split unit 强制 MOBILEGL_ITEST_REQUIRE_GPU=1;普查跑器零执行拒绝、launch 前清私有日志;G5 pin 自测驱动生产选择路径;c1f 改用 ID-67 用例。r2 包门:split unit 2087、reduced 22、push 1128 零失败;E1 14 own reds、E3(a) 4 own redssmoke 16 core + 12 privatecensus 432/185/505/27。r2 没有新跑 pull G1(不影响 pull production code)。

过程记录(不计入实现产量):wave-1 跨族复审十项全部经独立 perturbation 确认(ring 空 wrap 算术、reply 几何差 16 B、blob 校验接受任意段、pad-bit 控制没发送该 bit、三个 CI 对照接受任意非零退出……);后续 v1 / c1 各轮的 review 计数在 ID-52/58/62/64;本地 rereview 身份污染的 81 + 58 个提交经 parent/env rewrite 接回 GitHub ff2994d9(ID-40),此后每阶段首个 commit 前先跑 git var GIT_COMMITTER_IDENT。这些数字是流程在 P5 尾声改变(ID-66)的原因。

7. P5b(主机门 348d22a4,设备源头 82683d4a

7.1 迁移与包证据

348d22a4 含 d1 / i1 / t2 / f1、r1 / r2、五槽 sync、具名 blit 与 GLES mip storage;发射表 A=2 / B=54 / C=15(目录 76 条,槽数与 opcode 数不是同一统计量)。

已落地行为与证据边界
d1 19 个索引 / 实例 / multi-draw / indirect 槽经 draw_vbo 过线;独立包普查 77 个 Minecraft 后端用例 28 passed、49 first blockers,全部越过原 draw 首阻塞(默认 stage 32 MiB
i1 七个 image / compute / barrier / copy-image / storage-block 槽;原首阻塞 239 归零;CopyImage 的 client-shadow 镜像被跳过,GetTexImage 前端回退仍可能读旧 shadow
t2 六个 XFB / 曲面细分槽;原首阻塞实测 140(BeginTransformFeedback 95 + PatchParameteri 43 + BindTransformFeedback 2);包内基线 490 / 191 / 390 / 78,原 432 passes 全保留
f1 11 个 clear / copy / mip 槽;原 34 个首阻塞归零;bound named-clear 接线,unbound 仍具名拒绝
r1 / r2 P5 收官 #113r1 定向 10 passed / 0 skippedclient-only push suppression 两个像素控制变红
具名 blit BlitNamedFramebuffer 经 scoped read/draw binding 发布,退出恢复公开绑定;两后端四个 split 像素 entry 通过 + 15 unit
GLES mip storage server 只验证 applier descriptor 的 Levels/extent;三个 mip 像素控制 3/3iris-BSL GLES 单例 SSIM 0.997496(默认 stage 32 MiB);registry 只 Find 不 mintbarrier 债);RGB 三通道 CPU fallback 保持 Fatal
sync 五条现有 opcode 接线,wire 只传句柄,native fence 归 apply 线程;原 LOCAL guard 使 trace 的 FenceSync 没真正执行,所以 d1 旧普查里没有可扣除的 FenceSync 首阻塞数

包报告:~/w7/notes/p5b/p5b-results/{d1-codex-v1,i1-v1,t2-codex-v1,f1-v1,r1-codex-v1,r2-v1,blit-codex-v1,mip-codex-v1,sync-codex-v1}.md

7.2 主机收尾门与合并普查(348d22a4~/w7/p5b-final-host-348d22a4/

车道 Selected Passed Skipped Failed
unit-linux / unit-push / unit-verify 1817 × 3 1500 / 1782 / 1795 317 / 35 / 22 0
unit-split 2132 2122 10 0
gpu-linux-monolith / gpu-push-monolith / gpu-split-monolith 1148 / 1148 / 1178 895 / 953 / 953 253 / 195 / 225 0
splitintegration-splitinproc 107 105 2 0
verify / audit 950 / 10 804 / 9 146 / 1 0

G1 27,814 符号 0/0/0/0、.text 10,806,611 → 10,806,611G5 两族 + pin 自测;生成器 / 纯度检查;G2 / G14 rc=0E1 / E3(a)(精选 4 caserc=0E2 OpenRA 2/2、draw-drop SSIM 0.000036 / 758 records、pull-library 拒绝与库 SHA 恢复一致;smoke 16 core + 12 private。retrace-push 79/79retrace-verify 在 WSL 重启前完成 4/79,其余 75 条以 SHA-256 钉住的同一 verify 库串行续跑,合并 79/79;对账无缺步、无非零退出(reconciliation-20260916.md),complete=true、exit 0。一次 shell 异常(追加 runner 行触发 -test-dir: command not found)保留在原始输出,不冒充测试失败。

合并 inproc 普查(~/w7/p5b-final-census-348d22a4/):integration lane 显式 32 MiB1267 selected = 811 passed / 203 skipped / 62 aborted / 191 failed;旧 1149 名全部保留、新增 118;旧 432 passes 全保留、零回退;旧 505 abort → 265 passed / 18 skipped / 58 aborted / 164 failed;旧 27 failed → 1 passed / 26 failed。完整 trace 显式 256 MiB(容纳单次 128 MiB 上传,不是默认容量修复):79 = 72 passed / 6 aborted / 1 failed(主跑止于 73/79,三轮续跑补齐;create-indirect DirectVulkan 在 llvmpipe 上内存膨胀 >60 GiB RSS 被守护杀死,两次复现,记 failed)。7 条未过项首阻塞:rd12 DirectGLES Fatal{InitialBytesNotCarried,"resource_respecify"}、DirectVulkan Fatal{BarrierTimeout,"Present"}iris-photoniris-derivativecreate-indirect 三个 DirectGLES Fatal{UnmigratedEmulation,"texture-remint-pull"}iris-bsl-esc-menu-854 DirectGLES InitialBytesNotCarriedcreate-indirect DirectVulkan 内存守护。通过项含 improved-transparency-minecraft-26.3 DirectGLES SSIM 1.0 / DirectVulkan 0.999914、iris-iterationrp DirectVulkan 0.995833、iris-bsl-esc-menu-854 DirectVulkan 0.998402。逐 trace 见 joint-codex-v1.md 的 census 块与 identity.json / counts.json / trace-transitions.json

7.3 唯一收官审查与定向修复

审查 p5b-close-codex-review.md348d22a4diff base 37fc4fdb,只读):0 blocker / 2 major / 1 minor

问题 处置
Major 1 user-index span 在段内但 Size 可能短于 Count × IndexSize a021e3ccencoder / decoder / sink 共用 shape/extent gate(单 range、宽度 1/2/4、Uint64(Count) × IndexSize ≤ Size),三端短 span 均拒绝、段末 exact-fit 通过;定向 9/9
Major 2 ClientWaitSync 保留 64-bit timeout 但 applied/reply 等待一律 30 s 82683d4a:预算 = ceil(timeout ns / 1e6) + 30,000 ms,有限 chunk;普通容量等待 / FenceWaitServer 仍 30 sshutdown 可唤醒
Minor 3 ReadPixels exact-size reply 的未知 status 穿过 production helper 82683d4atight 与 bounce 路径拒绝 status=3Fatal{ReplyStatusInvalid}

定向 RemoteClientTest 7/70 ns、1 ns、60 s、UINT64_MAX 预算,FenceWaitServer、shutdown、未知状态)。合并后 quickgate 里 split 单元车道仅有的 2 个失败(PipeWireCodecTest.UserIndexSpan*)是测试日志捕获缺陷(库按进程截断日志,fork 子进程增量读读空),7cb29d46 修复后 3/3。本阶段不再做第二轮全门或审查;原始全门源头仍为 348d22a4,三项修复只以定向证据补齐。

7.4 Redmi 出口与四臂 A/B82683d4aAPK p5bcodex2

Redmi 2f7cbe2e,证据根 MobileGL/.trace-work/p5b-redmi/p5bcodex2/2f7cbe2e/;全部组合显式 MOBILEGL_IPC_STAGE_MB=256钉频口径变更2026-09-11 的厂商 GPU 上限(1050 MHz)已消失,本次 deterministic pin 为 1100 MHz;与 1050 MHz 时代的活动不可比钟频,只有同场四臂配对可比。

正确性 8/8improved-transparency-minecraft-26.3minecraft-1.21.4-in-worldGLES SSIM 0.999995)、minecraft-1.21.4-fabric-sodium-in-worldminecraft-1.21.4-fabric-iris-bsl-in-world × 双后端,inproc split 臂,逐组钉频取证 + PNG / SSIM 阈值 + inproc + apply 线程 + 正 wire 记录三证,skip 即失败。四条 A/B trace 首次在 Redmi 上以独立 apply 线程渲染——P5b 出口判据达成。

四臂 A/Bbarrier tax 首测):32 组中 24 组带 200 帧尾验证全绿;三次重复取 wall-time 均值最低者、尾 200 帧(ab-tables.md)。逐线程 CPU p50

trace 后端 pushpull barrier taxsplitpush barrier tax 帧 p50
improved-transparency-26.3 DirectGLES +15.6% +10.3% +0.1%
improved-transparency-26.3 DirectVulkan +8.8% +13.1% +13.3%
minecraft-1.21.4-in-world DirectGLES +21.4% +18.2% +0.2%
minecraft-1.21.4-in-world DirectVulkan +11.8% +17.9% +19.7%
minecraft-1.21.4-fabric-sodium DirectGLES +10.9% +5.9% 0.1%
minecraft-1.21.4-fabric-sodium DirectVulkan +7.6% +8.3% +4.3%

splitctlpush 全部在 ±1.6% 内(增量来自 inproc 传输与 barrier,不是 APK / 构建差);p99 同向放大(sodium DirectVulkan 帧 p99 +107.7% 为离群尾帧)。inproc 臂 peak RSS 389 MiB 2.5 GiB,全角色映射 560.5 MiB(256 MiB × 角色视图是虚拟映射容量,不是 RSS 增量)。

fixture 受限的 8 组iris-bsl-in-world 只有 123 个 benchmark 帧,低于 200 帧尾规则,四臂 × 双后端验证全部失败(pull 同失败,是 fixture 上限不是回归);123 帧完整序列按同法折算成补充表 ab-tables-bsl-123frame-supplement.mdbarrier tax CPU p50 DirectGLES +7.1%、DirectVulkan +9.1%,不混入上表。性能仍只记录、不作阻塞门。