mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
[Docs] (P10): close the phase - CONTRACT-P10 sections 2-3, rulings ID-P10-1..14 with the integration gate, C-MEASUREMENTS (device fence bench, loopback credit 1/2/3, the retrace round-trip census), the roadmap row, the debts P10 hands on, design/09, the phase README and the status page
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
## 范围
|
||||
|
||||
fence 轮询不再是往返(§1)。路线图原文里已做完或前提已变的项(client 铸造 query handle、present 1:1、credit 默认 1、无 present 负载的 `SEG_STAGE` 饥饿)见计划 §1。
|
||||
fence 轮询不再是往返(§1);最后一个 class-C 与 split 覆盖(§2);credit 与往返的测量记录(§3)。路线图原文里已做完或前提已变的项(client 铸造 query handle、present 1:1、credit 默认 1、无 present 负载的 `SEG_STAGE` 饥饿)见计划 §1。
|
||||
|
||||
## 1. fence 轮询从 server 的报告作答(A)
|
||||
|
||||
@@ -36,7 +36,17 @@ fence 轮询不再是往返(§1)。路线图原文里已做完或前提已
|
||||
|
||||
### 测量
|
||||
|
||||
`PacedFrameFenceWaitsBench`(手动开启,不设门)的配对结果在 [`A-FENCE-POLL.md`](../../docs/Disaggregated/notes/p10/A-FENCE-POLL.md):Magma 走 tcp 时每帧耗时降 37%、fence 往返为 0;Espryt 在主机 llvmpipe 上没有收益,因为只有阻塞等待才能让 fence 可见。
|
||||
`PacedFrameFenceWaitsBench`(手动开启,不设门)的配对结果在 [`A-FENCE-POLL.md`](../../docs/Disaggregated/notes/p10/A-FENCE-POLL.md):Magma 走 tcp 时每帧耗时降 37%、fence 往返为 0;Espryt 在主机 llvmpipe 上没有收益,因为只有阻塞等待才能让 fence 可见。在 Adreno 830 上两后端都是 0 次往返、598 / 598 次本地作答([`C-MEASUREMENTS.md`](../../docs/Disaggregated/notes/p10/C-MEASUREMENTS.md) §1)。
|
||||
|
||||
## 2. 最后一个 class-C 与 split 覆盖(B)
|
||||
|
||||
- 发射表的 `SetSwapInterval` 槽 = server 转发器(与 `eglSwapInterval` 经 `SurfaceControlOp::SetSwapInterval` 的同一路);`SetSwapInterval_Unmigrated` 与 `BackendObject_Remote` 的覆盖删除。class C 为空:69 已实现 / 0 未迁移。单元控制:`ServerLoopTest.TheEmitTableSwapIntervalSlotCrossesAsOneDispatchedFrame`(经表调用,恰好一个控制帧到达)。
|
||||
- caps mirror 采纳 server 快照时,`GL_KHR_parallel_shader_compile` 按 **client** 的 `MOBILEGL_ASYNC_SHADER_COMPILE` 重算:编译池与 `GL_MAX_SHADER_COMPILER_THREADS_KHR` 都在 client。red-once:去掉重算 → 两后端 Tcp 的 `AsyncOff` 扩展串用例红。
|
||||
- 登记(全部进门):`AsyncCompileScenario`(`AsyncOn.` / `AsyncOff.` / `OptimisticShaderStatus.`)与 `XfbPrimitiveQueryScenario` × 两后端 × Split / Spawn / Tcp;`PrimitivesGeneratedNoXfbScenario` 只在 Magma(`PrimGen.` 三臂,`PrimGenReroute.` 仅 Split / Spawn:tcp 的共享 server 读不到改道开关)。red-once:client 查询结果加一 → 101 条里 49 条红(全部 XfbQuery / PrimGen / PrimGenReroute),同名 monolith 条目仍绿。
|
||||
|
||||
## 3. 测量(只记录)
|
||||
|
||||
见 [`C-MEASUREMENTS.md`](../../docs/Disaggregated/notes/p10/C-MEASUREMENTS.md),包括真机 fence bench、设备上 TCP loopback 的 `PRESENT_CREDIT` 1/2/3、以及主机 retrace 往返普查。在 loopback 上 credit 没有噪声以外的影响(rd12 51.4 / 51.6 / 52.4 fps),默认值保持 1。
|
||||
|
||||
## 不变量
|
||||
|
||||
|
||||
@@ -431,7 +431,8 @@ The wave-3 tail no P5b package owns, by name, so nobody discovers it by grep: `B
|
||||
`GetSyncStatus`, `BeginTimeElapsedQuery`, `EndTimeElapsedQuery`, `QueryCounterTimestamp`,
|
||||
`IsQueryResultAvailable`, `GetQueryResult64`, `DeleteBackendQuery`, `BeginOcclusionQuery`,
|
||||
`EndOcclusionQuery`, `BeginXfbPrimitivesQuery`, `EndXfbPrimitivesQuery`, `GetGpuTimestampNs`,
|
||||
`SetSwapInterval` - P9 (readbacks), P10 (queries, syncs, swap interval).
|
||||
`SetSwapInterval` - P9 (readbacks), P10 (queries, syncs, swap interval). (2026-09-29: all are
|
||||
emitted now; the last one, `SetSwapInterval`, went in P10 - `CONTRACT-P10.md` §2.)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -659,6 +659,8 @@ Negative controls, each run red once:
|
||||
7. **"The 511 class-C entries" in §11** is the P5-joint census
|
||||
(`docs/Disaggregated/notes/p6/census-classC.md`). At this head the `MGR_UNMIGRATED_*` lists are
|
||||
empty; `SetSwapInterval` (P10) and `DeleteTransformFeedback` (P9) are the two that remain.
|
||||
(2026-09-29: both are gone. P10 made the `SetSwapInterval` slot the server forwarder, so class C
|
||||
is empty - `CONTRACT-P10.md` §2.)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,32 +1,29 @@
|
||||
# 当前阶段:P9 已收官(2026-09-29);下一阶段 P10 / P8 待排
|
||||
# 当前阶段:P10 已收官(2026-09-29);下一阶段 P11 / P8 待排
|
||||
|
||||
> **更新 2026-09-29**。这一页只有摘要;裁定明细、包报告与证据在 [`notes/p9/README.md`](notes/p9/README.md)(范围重划与交接 [`HANDOFF-P9.md`](notes/p9/HANDOFF-P9.md))。上一阶段 P12 同日收官,其状态与五臂性能对比见 [`notes/p12/README.md`](notes/p12/README.md)、[`notes/perf-five-arm-20260928`](notes/perf-five-arm-20260928/README.md)。
|
||||
> **更新 2026-09-29**。这一页只有摘要;裁定明细、测量与证据在 [`notes/p10/README.md`](notes/p10/README.md)(计划与范围重划 [`PLAN-P10.md`](notes/p10/PLAN-P10.md))。上一阶段 P9 同日收官,见 [`notes/p9/README.md`](notes/p9/README.md)。
|
||||
|
||||
## 目标
|
||||
|
||||
server → client 的结果回传在 split 下不阻塞、不丢、不乱序:回读、日志、纹理重铸都不再让一方同步等另一方。
|
||||
split 下的同步对象、查询与帧节奏不再逐次往返:fence 轮询不再等 server,最后一个手写 class-C 清掉,credit 在带延迟的链路上有配对数据。
|
||||
|
||||
## 完成情况
|
||||
|
||||
| 项 | 状态 |
|
||||
|---|---|
|
||||
| W1:`glReadPixels` / `glGetTexImage` 读进 pack buffer 不等回复 | ✅ 两后端;新 op 82/83,server 经 buffer 写入口落行,client 标"GPU 写过";UNPACK 源在 split 下先同步 |
|
||||
| W2:纹理重铸 | ✅ 不需要拉取协议(Espryt 读回驱动上存在的层 + server 暂存,Magma GPU→GPU);修"只定义未上传的层"的 Fatal;`OnTexturePullRequest` 删 |
|
||||
| W3:server 日志按级别转发 | ✅ 队列 + 发送线程:≤WARN 有损计数、ERROR 无损限速、FATAL 有界;`OnLog` 删 |
|
||||
| W4:事件批处理 / 收窄 | 不做:全语料 0 丢弃、0 阻塞 |
|
||||
| W5:`OnGlError` 有序 | 保持 P5e 放宽,写进契约 |
|
||||
| 故障注入 F1(device lost 时 PBO 读还欠着)/ F2(client 停读、server 狂打日志) | ✅ 各有门,各真红过一次 |
|
||||
| 主机门与单进程构建二进制不变(G1) | ✅ 符号增 0 减 0,`.text` `0xa52203`;全部车道绿(数字见裁定 ID-P9-12) |
|
||||
| 真机 | 未做(本阶段无真机门;主机覆盖两后端,CI 兜底) |
|
||||
| A:`glClientWaitSync` / `glGetSynciv` 由 server 报告本地作答 | ✅ 两后端;`kEventFenceSignaled`(EventKind 5),present 时在归还 credit 前也报告;`MOBILEGL_IPC_POLL_ESCALATE`(64,0 = A/B 对照);零超时轮询有界退出 |
|
||||
| A 的收益 | 主机 Magma·tcp 每帧 −37%、fence 往返 598 → 0;Adreno 830 上两后端都是 0 次往返、598 / 598 次本地作答;主机 Espryt(llvmpipe)无收益,属于驱动行为 |
|
||||
| B:最后一个 class-C、split 覆盖 | ✅ `SetSwapInterval` 槽改为转发,class C 清零;`GL_KHR_parallel_shader_compile` 由 client 决定;AsyncCompile / XfbPrimitiveQuery / PrimitivesGeneratedNoXfb 在 split 各臂进门 |
|
||||
| C:`PRESENT_CREDIT` 1/2/3 | 设备 tcp loopback 在噪声内(rd12 51.4 / 51.6 / 52.4 fps),默认保持 1;跨机 +26% 仍以 P12 为准 |
|
||||
| 主机门与单进程构建二进制不变(G1) | ✅ 符号增 0 减 0,`.text` `0xa52203`;全部车道绿(数字见裁定 ID-P10-12) |
|
||||
|
||||
## 收官(2026-09-29)
|
||||
|
||||
- 契约 [`MG_Remote/CONTRACT-P9.md`](../../MobileGL/MG_Remote/CONTRACT-P9.md);回调 9 → 7;目录追加 2 个 op;控制协议修订号不变。
|
||||
- 转入 [`notes/DEBTS.md`](notes/DEBTS.md):monolith Espryt 重铸覆盖 GPU 写过的纹素(dev,已开独立任务);`TCP_USER_TIMEOUT` 5 s 与 `PublishSessionFault` 阻塞写;Espryt 保留路径 clear 后 `imageLoad` 偶读旧值(待归因);Magma 冗余 `OnGpuWritten`。
|
||||
- 契约 [`MG_Remote/CONTRACT-P10.md`](../../MobileGL/MG_Remote/CONTRACT-P10.md);`EventKind` 追加 1 个;控制协议修订号不变。
|
||||
- 转入 [`notes/DEBTS.md`](notes/DEBTS.md):fp64 宣告按 server 环境(同类的 parallel-compile 已修);loopback 上的传输停车(性能);Magma 不支持 `eglSwapInterval`(dev,已开独立任务)。
|
||||
- 收官审查沿用 P12 的做法:不派 agent / Codex,契约断言由本人对照代码核过,G1 同机复核。
|
||||
|
||||
## 下一步
|
||||
|
||||
按 [`ROADMAP.md`](ROADMAP.md):P10(同步对象、查询与帧节奏;FCL 里 Minecraft 稳态每帧约 1 次的 `FenceWait` 回包在这里)→ P11(IPC 跑道);P8(monolith 跑道);P6.5 残余(39 例 device 矩阵)与 P3b/P4b 余项并行。
|
||||
按 [`ROADMAP.md`](ROADMAP.md):P11(persistent map 与 ≥ 16 MiB 采纳,同机臂专属;前置开放问题 3);P8(monolith 跑道);P6.5 残余与 P3b/P4b 余项并行。
|
||||
|
||||
**阻塞**:没有需要决策的事项。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 路线图(索引)
|
||||
|
||||
> **2026-09-29**:P0 到 P7、P12、**P9** 已完成(P9:读进 PBO 的回读不再等回复、server 日志按级别转发不阻塞、纹理重铸不需要拉取协议,两条故障注入,契约 `MG_Remote/CONTRACT-P9.md`,G1 成立);下一阶段 **P10**(IPC 跑道)与 **P8**(monolith 跑道)。每个阶段的计划、验收结果、实测与报告在 `notes/<阶段>/`(点阶段名进入)。
|
||||
> **2026-09-29**:P0 到 P7、P12、P9、**P10** 已完成(P10:fence 轮询不再往返——server 报告完成的 fence、client 本地作答,真机两后端 0 次往返;最后一个 class-C 清零;credit 1/2/3 在设备 loopback 上量过、默认保持 1;契约 `MG_Remote/CONTRACT-P10.md`,G1 成立);下一阶段 **P11**(IPC 跑道)与 **P8**(monolith 跑道)。每个阶段的计划、验收结果、实测与报告在 `notes/<阶段>/`(点阶段名进入)。
|
||||
|
||||
## 目标
|
||||
|
||||
@@ -9,7 +9,7 @@ client(跑应用的一方)与 server(跑驱动的一方)可以在**不
|
||||
## 两条路线
|
||||
|
||||
- **单进程路线**:先把接口建起来,让单进程版本也受益(后端拥有自己的状态、可以挪到渲染线程)。P0 → P0.5 → P1 → P2 → P3a → P4a → P3b/P4b → P7 → P8 → P13。
|
||||
- **拆分路线**:在接口之上逐步拆开前后端。P5 → P5b → P5c → P5d → P5e → P5f → P6 → P6.5 → Ph → P12 → **P9** → P10 → P11。
|
||||
- **拆分路线**:在接口之上逐步拆开前后端。P5 → P5b → P5c → P5d → P5e → P5f → P6 → P6.5 → Ph → P12 → P9 → **P10** → P11。
|
||||
|
||||
## 阶段一览
|
||||
|
||||
@@ -35,7 +35,7 @@ client(跑应用的一方)与 server(跑驱动的一方)可以在**不
|
||||
| [**P12**](notes/p12/README.md) | **server 自己开窗口上屏,client 不需要窗口** | ✅ 09-29:出口门 B(跨机 TCP)✅ 09-28、A(FCL + 杀 server)✅ 09-29;契约 `MG_Remote/CONTRACT-P12.md`;G1 成立;余项进 [`DEBTS.md`](notes/DEBTS.md) |
|
||||
| [P8](notes/p8/README.md) | 把剩余的仿真路径挪到正确的一侧,补齐协议 | 待排 |
|
||||
| [**P9**](notes/p9/README.md) | **反向通道:回读、日志、重铸不再同步等待 client** | ✅ 09-29:PACK-PBO 回读 fire-and-forget(两后端)、日志分级转发、重铸无拉取(`OnLog` / `OnTexturePullRequest` 删,回调 9 → 7),F1 / F2;契约 `MG_Remote/CONTRACT-P9.md`;G1 成立;事件量批处理无实测需求不做;余项进 [`DEBTS.md`](notes/DEBTS.md) |
|
||||
| [P10](notes/p10/README.md) | 同步对象、查询与帧节奏 | 待排 |
|
||||
| [**P10**](notes/p10/README.md) | **同步对象、查询与帧节奏** | ✅ 09-29:fence 轮询由 server 报告本地作答(`kEventFenceSignaled`、`MOBILEGL_IPC_POLL_ESCALATE`;主机 Magma·tcp −37%,Adreno 830 上两后端 0 次往返);`SetSwapInterval` 转发、class C 清零;query / XFB / AsyncCompile 登记 split 各臂;credit 1/2/3 设备 loopback 在噪声内;契约 `MG_Remote/CONTRACT-P10.md`;G1 成立;余项进 [`DEBTS.md`](notes/DEBTS.md) |
|
||||
| [P11](notes/p11/README.md) | 同机大缓冲零拷贝共享 | 待排 |
|
||||
| [P13](notes/p13/README.md) | 删掉旧的"后端直接读前端"路径 | 待排 |
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ CMake:`MOBILEGL_BUILD_DISAGGREGATED`(OFF)、`MOBILEGL_BUILD_DISAGGREGATED_
|
||||
| `MOBILEGL_IPC_RUN_AHEAD` | 1 | P5e run-ahead;只是合取式的一半(server 须发布 `kCapRunAheadApply`);`0` 是 A/B 对照 |
|
||||
| `MOBILEGL_IPC_VERB_BARRIER` | 1 | `0` 只作阴性对照,且同时关掉 run-ahead |
|
||||
| `MOBILEGL_IPC_PRESENT_CREDIT` | 1 | 1..8,§14 |
|
||||
| `MOBILEGL_IPC_POLL_ESCALATE` | 64 | 未报告 fence 的零超时轮询本地答"未完成",同一 fence 连续第 N 次才往返(P10,`CONTRACT-P10.md` §1);`0` = 每次轮询都往返,是 A/B 对照 |
|
||||
| `MOBILEGL_IPC_BATCH_WAITS` | 1 | lockstep 下值类记录发布即返回;verify 强制 0 |
|
||||
| `MOBILEGL_IPC_EVENT_WAIT_MS` | 2000 | 反向事件遇满环时 server 等 client 排空的整笔预算(§11.7) |
|
||||
| `MOBILEGL_IPC_WIRE_DEFERRED_MB` | 64 | Magma wire 臂延迟回收的水位线;`0` 是 M2 阴性对照 |
|
||||
@@ -62,7 +63,7 @@ CMake:`MOBILEGL_BUILD_DISAGGREGATED`(OFF)、`MOBILEGL_BUILD_DISAGGREGATED_
|
||||
| `MOBILEGL_IPC_SPIN_US` / `MOBILEGL_IPC_SERVER_AFFINITY` | 50 / `auto` | park 前自旋预算 / apply 线程亲和(Redmi 内核忽略) |
|
||||
| `MOBILEGL_IPC_RESPAWN` | — | 具名拒绝:没有阶段实现 server 重启后的全量重推 |
|
||||
|
||||
显式不设立:`MOBILEGL_IPC_PROGRAM`(没有 relink 档)、`MOBILEGL_IPC_VALIDATE_SERVER`。计划中未接线:`MOBILEGL_IPC_POLL_ESCALATE`(P10)、`MOBILEGL_IPC_IDLE_EXIT_S`(未解析)。
|
||||
显式不设立:`MOBILEGL_IPC_PROGRAM`(没有 relink 档)、`MOBILEGL_IPC_VALIDATE_SERVER`。计划中未接线:`MOBILEGL_IPC_IDLE_EXIT_S`(未解析)。
|
||||
|
||||
## 附 B:边界计数器(`MobileGL/MG_Util/Metrics/PipeStats.h`)
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
# 仍开放的债务(跨阶段)
|
||||
|
||||
> 路线图只列"有债务、看这里"。每条写明去向;已关闭的历史债与当时的完整债务表见 [`p5b/README.md`](p5b/README.md) 末节。开放问题另见 [`OPEN-QUESTIONS.md`](OPEN-QUESTIONS.md)。更新:2026-09-29。
|
||||
> 路线图只列"有债务、看这里"。每条写明去向;已关闭的历史债与当时的完整债务表见 [`p5b/README.md`](p5b/README.md) 末节。开放问题另见 [`OPEN-QUESTIONS.md`](OPEN-QUESTIONS.md)。更新:2026-09-29(P10 收官)。
|
||||
|
||||
| 债务 | 去向 |
|
||||
|---|---|
|
||||
| 未接入内容分块的 record 类型:program archive 与 `draw_vbo` range 尾 | P6.5 sl 与 P8 共用的分片(开放问题 11) |
|
||||
| class-C 余项与仿真路径:`SetSwapInterval`(P10);multi-draw client indices、RGB CPU mip 等具名拒绝 | P8 / P10 |
|
||||
| 仿真路径的具名拒绝:multi-draw client indices、RGB CPU mip 等(class C 已于 P10 清零) | P8 |
|
||||
| P10 转出:`GL_ARB_gpu_shader_fp64` 按 server 的 `MOBILEGL_ADVERTISE_FP64` 宣告,fp64 收窄却在 client 的编译里;tcp 下 server 环境不同时两者不一致(与已修的 `GL_KHR_parallel_shader_compile` 同类,挂点 `CapsMirror::Adopt`,ID-P10-10) | 小修,无触发报告 |
|
||||
| P10 转出(性能):设备上 tcp loopback 的 rd12 每帧 19.4 ms 中 ~11.2 ms 是生产者在 stream 传输里的停车(发送 + 环 / stage / ack 等待),credit 等待只有 ~0.2 ms(`notes/p10/C-MEASUREMENTS.md` §2,ID-P10-13) | 路线图推完后的性能工作 |
|
||||
| P10 转出:Magma 没有注册 `SetSwapInterval`,monolith 与 split 下 `eglSwapInterval` 都是空操作(ID-P10-10) | dev(独立任务) |
|
||||
| `GetCaps` 的两个 blobref | 一旦运输,必须有 server → client 的 carrier rule,不能套 `SEG_STAGE` |
|
||||
| E1 对照的重定义(ID-122) | 无主(开放问题 24) |
|
||||
| `MOBILEGL_IPC_IDLE_EXIT_S` 未解析;`CONTRACT-P6.md` 仍把 `DynamicBackendParameters` 定宽记在 P7 名下(已由 P6.5 wf 落地) | 文档 / 小修 |
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## 负载
|
||||
|
||||
`FencePollScenario.PacedFrameFenceWaitsBench`(`MGITEST_FENCE_PACE_BENCH=1`):每帧 clear + `glFenceSync` + 交换,再对 N 帧前(`MGITEST_FENCE_PACE_LAG`,默认 2)的 fence 做 `glClientWaitSync(FLUSH, 1 s)`;600 帧。也就是 Minecraft 的形状,回放语料里没有 trace 带它。A/B = `MOBILEGL_IPC_POLL_ESCALATE=0`(每次都往返,P10 之前的行为)对默认 64。
|
||||
`FencePollScenario.PacedFrameFenceWaitsBench`(`MGITEST_FENCE_PACE_BENCH=1`):每帧 clear + `glFenceSync` + 交换,再对 N 帧前(`MGITEST_FENCE_PACE_LAG`,默认 2)的 fence 做 `glClientWaitSync(FLUSH, 1 s)`;600 帧。也就是 Minecraft 的形状,这里单独拿出来测(回放语料里只有 `improved-transparency-minecraft-26.3` 带 timed wait,见 [`C-MEASUREMENTS.md`](C-MEASUREMENTS.md) §3)。A/B = `MOBILEGL_IPC_POLL_ESCALATE=0`(每次都往返,P10 之前的行为)对默认 64。
|
||||
|
||||
## 结果(3 轮,ms/帧 与 600 帧里的 fence 往返次数)
|
||||
|
||||
@@ -34,4 +34,4 @@ Espryt 的 timed wait 几乎全部过线,这**不是**报告晚到:
|
||||
|
||||
结论:在这台主机的 mesa llvmpipe(ES 3.2)上,`glGetSynciv(GL_SYNC_STATUS)` 与零超时 `glClientWaitSync` 看不到早已完成的 fence,只有真正阻塞的等待才能让它变成 signaled。这是宿主驱动的行为,与传输无关。A 在这里只是**没有收益**,并没有错:过线的等待语义不变,esc=64 与 esc=0 持平。探针都已撤掉,`ReportSignaledFences` 保持门禁通过时的原样。
|
||||
|
||||
**真机上的答案归 C**:红米(Adreno 830、Espryt)FCL + Minecraft,esc 0/64 配对,读 `fence-local / round-trips` 计数。
|
||||
**真机上的答案(C,[`C-MEASUREMENTS.md`](C-MEASUREMENTS.md) §1)**:在红米(Adreno 830)上同一个 bench,Espryt esc=64 时 0 次往返、598 / 598 次本地作答,与 Magma 相同。上面的现象只出现在 llvmpipe 上。
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
# P10 C:真机测量与往返普查
|
||||
|
||||
2026-09-29。真机:Redmi `2f7cbe2e`(Adreno 830),代码 `8d0a1b6c`;CPU 定频 1555200 / 1958400 并回读核验,GPU 未定频。只记录、不设门。原始数据在 `~/w7/notes/p10/evidence/c/`(报告 `~/w7/notes/p10/c-report.md`)。
|
||||
|
||||
## 1. fence bench 在 Adreno 830 上(Split / inproc,600 帧,3 轮交错)
|
||||
|
||||
`FencePollScenario.PacedFrameFenceWaitsBench`,每帧对 2 帧前的 fence 做 timed wait。
|
||||
|
||||
| 后端 | esc=0 ms/帧 | esc=64 ms/帧 | esc=64 fence 往返 / 本地作答 | 回复槽记录 0 → 64 |
|
||||
|---|---|---|---|---|
|
||||
| Espryt | 0.163 / 0.153 / 0.145 | 0.156 / 0.140 / 0.157 | **0 / 598** | 601 → 3 |
|
||||
| Magma(tier 2) | 0.167 / 0.176 / 0.181 | 0.191 / 0.175 / 0.174 | 0 / 598 | 601 → 3 |
|
||||
| Magma(`.Fence.` 带状环境,与主机 bench 同) | 0.171 / 0.167 / 0.164 | 0.182 / 0.160 / 0.182 | 0 / 598 | 601 → 3 |
|
||||
|
||||
- 延迟 4 帧:Espryt 0 / 596;延迟 1 帧:两后端都是 0 / 599。
|
||||
- **结论:真 GPU 上 Espryt 与 Magma 一样,每次等待都在本地作答。** [`A-FENCE-POLL.md`](A-FENCE-POLL.md) 里"fence 只有阻塞等待后才可见"是主机 llvmpipe 独有的行为。inproc 的每帧耗时在噪声内不变(每次运行约 0.1 s,10% 以内的差都是噪声);收益在有往返延迟的链路上(主机 Magma·tcp −37%)。
|
||||
- Spawn 臂没跑:Android 测试框架总是画进 `ANativeWindow`,spawn 出来的 server 拒收(`Fatal{UnmigratedSurface}`)。
|
||||
- **Android 上的 itest 本身跑不了这个 bench**:`SplitRuntimePeek` 在 `__ANDROID__` 下编译掉,itest 又链接的是隐藏符号的 `libMobileGL.so`。测量用的是本地构建补丁(`-DMGITEST_ANDROID_STATIC_PEEK=ON`:Android 上改链静态库并开启 peek,库代码与编译选项不变),未提交,存为 `evidence/c/peek-patch.diff`(ID-P10-14)。
|
||||
|
||||
## 2. `MOBILEGL_IPC_PRESENT_CREDIT` 1 / 2 / 3,设备上 spawn + tcp(127.0.0.1),trace APK,Espryt,3 次交错
|
||||
|
||||
| 臂 · 负载 | credit 1 | credit 2 | credit 3 | 散布 | credit 等待 ms/帧 | 传输等待 ms/帧 | client CPU ms/帧 |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| tcp · rd12(稳态 fps) | 51.4 | 51.6 | 52.4 | 1–3% | 0.18–0.24 | 11.2 | 9.9 |
|
||||
| tcp · openra | 399.0 | 384.9 | 391.8 | 最多 8% | 0.16–0.19 | 2.1 | 1.8 |
|
||||
| shm · rd12 | 120.2 | 120.1 | — | ≤ 0.4% | 0 | 0.1 | 8.2 |
|
||||
|
||||
- **结论:loopback 上 credit 没有噪声以外的影响。** rd12·tcp 的 19.4 ms 帧由 client CPU(~9.9 ms)和生产者在传输里的停车(~11.2 ms,发送 + 环 / stage / ack 等待)组成,credit 等待只有 ~0.2 ms。五臂报告(09-28)建议 #2"credit 2"在 loopback 上没有收益;要追的是 stream 传输的停车(性能债,[`../DEBTS.md`](../DEBTS.md))。
|
||||
- 跨机(Wi-Fi)credit 1 → 2 的 +26% 仍以 P12 的数字为准([`../p12/CROSSHOST-ACCEPTANCE.md`](../p12/CROSSHOST-ACCEPTANCE.md)),那里瓶颈是往返延迟。
|
||||
- 五臂报告里 tcp-loopback rd12 的 21–23 fps(74% 在 credit 等待)是旧构建、未定频的结果,与本次不可直接比较。
|
||||
- Magma 没测:`profile_matrix.sh` / `run_matrix.sh` 在两处写死了 DirectGLES。
|
||||
- P12 同款明细(`evidence/c/m2/m2.p12style.md`):rd12 加载帧 10.6–10.8 s、稳态 73–74 MB/s;`wait_replies` 全在第 1 帧(`ResourceCreate`)。
|
||||
|
||||
## 3. 主机 retrace 往返普查(`MOBILEGL_PIPE_STATS=1`,全部 SPLIT / SPAWN 条目)
|
||||
|
||||
集成头 `47bbf5e6`,156 条(39 个 trace × 两后端 × SPLIT / SPAWN),`P65LinkMetrics` 的逐帧 `wait_replies` 按 op 分。全表在 `~/w7/notes/p10/evidence/census.md`,脚本 `~/w7/notes/p10/census.py`。
|
||||
|
||||
| 稳态(第 2 帧起)的回包等待 | 全语料 | 出处 |
|
||||
|---|---|---|
|
||||
| draw / state / upload 路径 | **0** | 没有一条 draw、状态设置或 `ResourceSubData` 记录等待回复 |
|
||||
| `ResourceCreate` | 243,172 | 每个资源一次(modernui-inventory 每帧约 6.5 次);P12 已裁定保持 `kWaitReply`([`../p12/DEVICELOST-AND-UPLOAD-WAITS.md`](../p12/DEVICELOST-AND-UPLOAD-WAITS.md) §2.4) |
|
||||
| `FenceWait` | 10,685 | **只有** `improved-transparency-minecraft-26.3` × Espryt(每帧约 4.4 次 timed wait),即 llvmpipe 的现象(ID-P10-6);同一 trace 在 Magma 上是 0 |
|
||||
| `MapPersistent` | 192 | 每个 trace 1–9 次 |
|
||||
|
||||
- 39 个 trace 里有 34 个建 fence(多数每帧一个),其中 33 个在任何一条臂上都**没有**发出 `FenceWait` / `FenceStatus` 记录,也就是轮询全部在本地作答;唯一的例外是上表中 llvmpipe 上那一条。
|
||||
- iterationrp 的 6 条 retrace 因宿主 JIT 崩溃判红,但崩溃前的帧照常计数。
|
||||
@@ -0,0 +1,20 @@
|
||||
# P10 集成者裁定日志(sync / query / present 节奏)
|
||||
|
||||
> 形式沿用 [`../p9/INTEGRATOR-DECISIONS-P9.md`](../p9/INTEGRATOR-DECISIONS-P9.md):一条裁定一个 ID,只记「定了什么、为什么、影响哪些文件」。计划与范围重划见 [`PLAN-P10.md`](PLAN-P10.md),协议见 `MobileGL/MG_Remote/CONTRACT-P10.md`。
|
||||
|
||||
| ID | 日期 | 裁定 | 理由 | 影响 |
|
||||
|---|---|---|---|---|
|
||||
| ID-P10-1 | 2026-09-29 | 范围按计划 §1 重划:client 铸造 query handle、present 1:1、credit 默认 1 已是现状,关闭;"DirectGLES fence 逐 fence 退休"与"非 present fence tick"不单独做——线上不依赖帧水位(每批后 `RetireThrough(appliedSeq)`),帧水位只喂 Espryt 自己的 buffer 池回收,与 monolith 相同;A 的"空闲时也查 fence"就是线上的非 present tick。 | 路线图行写于 09-22,逐项对照树的现状核对过。 | `PLAN-P10.md` |
|
||||
| ID-P10-2 | 2026-09-29 | A 的形状:server 按创建顺序查 fence,完成的发 `kEventFenceSignaled`(`EventKind` 追加 5,8 字节);client 已知 signaled 的轮询本地作答,不能等的未知轮询本地答"未完成",同一 fence 连续第 `MOBILEGL_IPC_POLL_ESCALATE`(默认 64)次改为一次往返;**可以等的调用(timeout > 0)仍然往返**,语义不变。旋钮为 0 就恢复 P10 之前的行为,作 A/B 控制;设备丢失后一律走往返臂。 | 本地作答只用 server 说过的事实,所以不会早报;升级保证"只轮询不发记录"的循环有界。timed wait 本地等报告需要另一套唤醒路径,往返本身就是那次等待。 | `EventRing.h`、`ServerSession.{h,cpp}`、`PipeApplier.{h,cpp}`、`ServerLoop.cpp`、`ClientSession.{h,cpp}`、`EmitTables.{h,cpp}`、`Config.h`、`ConfigLoader.cpp` |
|
||||
| ID-P10-3 | 2026-09-29 | client 记"已 signaled"的表用独立互斥锁,不用 `g_fenceMutex`。 | 事件排空发生在持有 `g_fenceMutex` 的发射函数内部(`EmitAndWait`、`PollEntry` 都排空),用同一把锁会让 GL 线程自锁。 | `EmitTables.cpp` |
|
||||
| ID-P10-4 | 2026-09-29 | server 将要空闲且有未报告 fence 时:对最老的 pending fence 做一次 `ClientWaitSync(GL_SYNC_FLUSH_COMMANDS_BIT, 0)`(两个后端都会借此提交所持命令的唯一后端无关方式),仍有未报告的就限时停车 1 ms 再查;否则照旧无限期停车。`SEG_EVENT` 满时不报告。 | red-once:去掉空闲复查 → Espryt 需 1 次升级,Magma 升级 15 次仍等不到(Magma 的 fence 不会自己提交)。每批都提交会打掉 Magma 的命令缓冲批处理,所以只在空闲时做。 | `ServerLoop.cpp`、`PipeApplier.cpp` |
|
||||
| ID-P10-5 | 2026-09-29 | `OnPresent` 在归还 present credit **之前**报告一次(状态查询,不提交)。 | credit 放行的 client 会立刻去等一两帧前的 fence;批次结束后才发的报告会输给它。实测只在 Espryt·tcp 有变化(本地作答 36–54 → 79–101 / 598)。 | `PipeApplier.cpp`、`ServerSession.{h,cpp}`(`EventRingHasRoom`) |
|
||||
| ID-P10-6 | 2026-09-29 | 主机 Espryt 上 A 没有收益:在 mesa llvmpipe(ES 3.2)上 `glGetSynciv` 与零超时 `glClientWaitSync` 看不到早已完成的 fence,只有阻塞等待才能让它变成 signaled。另外试了三种做法——空闲 / present 时冲刷最新的 fence、present 时 flush 检查、1 ns 的 timed wait——都没有效果,全部撤回,`ReportSignaledFences` 保持门禁通过时的原样。真 GPU 上的答案由 C 给出(ID-P10-11)。 | lag 1–6 的本地作答都是 0–6;server 端追踪显示队首 fence 在约 4 帧的每次检查里都是 pending,要等 client 的 timed wait 过线、server 阻塞等待之后才被报告。Magma(lavapipe)同一追踪里报告全部早于等待,tcp 每帧 −37%。 | `A-FENCE-POLL.md` |
|
||||
| ID-P10-7 | 2026-09-29 | B:`GL_KHR_parallel_shader_compile` 由 client 的编译开关决定,caps mirror 在采纳快照时重算这一项。 | 编译池与 `GL_MAX_SHADER_COMPILER_THREADS_KHR` 都在 client;Split / Spawn 之所以一致,只是因为 server 继承了 client 的环境,tcp 的共享 fixture server 不继承,于是 Tcp 的 `AsyncOff` 用例两后端都红。 | `CapsMirror.cpp`、`RemoteClientTest.cpp` |
|
||||
| ID-P10-8 | 2026-09-29 | B:发射表的 `SetSwapInterval` 槽改为 server 转发器,`SetSwapInterval_Unmigrated` 与 `BackendObject_Remote` 的覆盖删除;class C 清零(69 已实现 / 0 未迁移)。控制由单元用例 `ServerLoopTest.TheEmitTableSwapIntervalSlotCrossesAsOneDispatchedFrame` 钉住(split 车道观察不到交换间隔)。 | 路线图列为最后一个手写 class-C。原槽是一个永远到不了的具名 Fatal,实际调用一直走另一条路。 | `EmitTables.{h,cpp}`、`BackendObject_Remote.{h,cpp}`、`ServerLoopTest.cpp`、`RemoteClientTest.cpp` |
|
||||
| ID-P10-9 | 2026-09-29 | B 的登记:`AsyncCompileScenario`(`AsyncOn` / `AsyncOff` / `OptimisticShaderStatus` 三形)与 `XfbPrimitiveQueryScenario` 在两后端的 Split / Spawn / Tcp 上登记;`PrimitivesGeneratedNoXfbScenario` 只登记 Magma(Espryt 上每例都按设计跳过),其中 `PrimGenReroute` 不登记 Magma Tcp(共享 fixture server 读不到这个开关,8 例在 `spawn_lane_parity.py` 里具名列出)。 | 保证跳过的登记只会让门看上去更大。 | `MG_IntegrationTest/CMakeLists.txt`、`spawn_lane_parity.py` |
|
||||
| ID-P10-10 | 2026-09-29 | B 查出、**不在 P10 改**的两项:(1) `GL_ARB_gpu_shader_fp64` 按 server 的 `MOBILEGL_ADVERTISE_FP64` 宣告,但 fp64 收窄发生在 client 的编译里,tcp 下 server 环境不同时会不一致,属于同类问题(挂点是 `CapsMirror::Adopt`)→ 债;(2) Magma 没有注册 `SetSwapInterval`,monolith 与 split 下 `eglSwapInterval` 都是空操作 → dev 线独立任务。 | 前者无触发报告,挂点已有;后者是 dev 的缺陷,按规矩不顺手修。 | `DEBTS.md`;独立任务 |
|
||||
| ID-P10-11 | 2026-09-29 | 真机(Adreno 830,`8d0a1b6c`)上 A 成立:同一 bench 在 esc=64 时,Espryt 与 Magma 都是 0 次 fence 往返、598 / 598 次本地作答,回复槽记录 601 → 3;lag 1 / 4 也一样。ID-P10-6 的现象只出现在 llvmpipe 上,A 的实现不需要按后端区分。 | 这正是 ID-P10-6 留给 C 的问题。 | `C-MEASUREMENTS.md` §1 |
|
||||
| ID-P10-12 | 2026-09-29 | **P10 收官**。集成头(A + B,`47bbf5e6`)整套门:G1 符号增 0 减 0、`.text` `0xa52203`(同机 clang 22.1.6,与 P9 相同);fatal census 79、link ratchet 171、spawn parity 0、协议修订 3、wire-declines 53/53;卫生 12/12;unit 2644;integration-split / spawn / tcp 356 / 273 / 277;integration-magma-split / spawn / tcp / full-split 174 / 153 / 130 / 583;integration-gpu monolith / inproc 2348 / 2348。verify 构建 unit / integration-verify / integration-verify-split 2644 / 1238 / 1172。主机 retrace 230 / 236,6 项仍是 iterationrp 的宿主 llvmpipe JIT 崩溃(monolith 同挂,同 P9)。出口门"trace 上 draw / state / upload 往返读零"成立:`MOBILEGL_PIPE_STATS=1` 普查 156 条 SPLIT / SPAWN 条目,稳态回包等待只有 `ResourceCreate`(P12 已裁定保持)、`MapPersistent`,以及 llvmpipe 上 Espryt 的 `FenceWait`(`C-MEASUREMENTS.md` §3)。收官审查沿用 P12:不派 agent / Codex,契约断言由集成者对照代码核过(`kEventFenceSignaled = 5` 与 8 字节载荷、`PollEscalate` 默认 64 且范围 0..1000000、`kFenceIdlePollMs = 1`、控制协议修订 3、class C 无 `_Unmigrated` 桩)。 | — | 全阶段 |
|
||||
| ID-P10-13 | 2026-09-29 | `PRESENT_CREDIT` 默认保持 1。设备上 tcp loopback 的 credit 1 / 2 / 3 在噪声内(rd12 51.4 / 51.6 / 52.4 fps,credit 等待 ~0.2 ms / 帧,传输停车 ~11.2 ms / 帧);跨机 Wi-Fi 的 +26%(P12)是按链路调的旋钮,不是默认值问题。present credit 的直方图不另做:`P65ClientPace` 每次 present 都打 `credit_wait_ms`,分布可以直接从日志得到。loopback 上的下一个开销是 stream 传输的停车:记为性能债,等路线图推完再回头做(用户 09-08:性能只记录)。 | 路线图说"credit > 1 从未量过",现在两条链路都量过了;推翻五臂报告的建议 #2(那组数据是旧构建、未定频)。 | `C-MEASUREMENTS.md` §2 |
|
||||
| ID-P10-14 | 2026-09-29 | 让 Android itest 读到 split 运行时计数的构建补丁(`-DMGITEST_ANDROID_STATIC_PEEK=ON`:改链静态库并开启 `SplitRuntimePeek`)**不入库**,只存为证据(`~/w7/notes/p10/evidence/c/peek-patch.diff`)。 | 只是这一次测量要用;要让设备上的计数门成为一条车道,得先给 Android 框架加 pbuffer 路径(spawn 臂也缺这个),那是单独一项工作。 | 无(证据) |
|
||||
@@ -1,6 +1,16 @@
|
||||
# P10 — sync / query / present 节奏(待排)
|
||||
# P10 — sync / query / present 节奏(已收官,2026-09-29)
|
||||
|
||||
> 尚未开工。本页保存该阶段在路线图上的完整范围与出口门(2026-09-24 从 [`ROADMAP.md`](../../ROADMAP.md) 阶段表移入,原文照录);阶段开工后,计划、裁定与报告都放在本目录。
|
||||
> **2026-09-29 收官**。协议与行为:`MobileGL/MG_Remote/CONTRACT-P10.md`;裁定 [`INTEGRATOR-DECISIONS-P10.md`](INTEGRATOR-DECISIONS-P10.md);计划与范围重划 [`PLAN-P10.md`](PLAN-P10.md);测量 [`A-FENCE-POLL.md`](A-FENCE-POLL.md)、[`C-MEASUREMENTS.md`](C-MEASUREMENTS.md)。
|
||||
>
|
||||
> | 包 | 结果 |
|
||||
> |---|---|
|
||||
> | A fence 轮询 | server 报告完成的 fence(`kEventFenceSignaled`,含 present 时、归还 credit 之前),client 本地作答;第 `MOBILEGL_IPC_POLL_ESCALATE`(64)次未答的零超时轮询才往返;timed wait 语义不变。主机 Magma·tcp 每帧 −37%、fence 往返 598 → 0;主机 Espryt 无收益(llvmpipe 上只有阻塞等待才能看到 fence 完成);Adreno 830 上两后端都是 0 次往返、598 / 598 次本地作答 |
|
||||
> | B 覆盖与 class C | `SetSwapInterval` 槽改为 server 转发,class C 清零;`GL_KHR_parallel_shader_compile` 改由 client 决定;AsyncCompile / XfbPrimitiveQuery / PrimitivesGeneratedNoXfb 登记到 split 各臂(Espryt 27 条、Magma 64 条) |
|
||||
> | C 测量 | 设备上 tcp loopback 的 `PRESENT_CREDIT` 1/2/3 在噪声内(rd12 51.4 / 51.6 / 52.4 fps),默认保持 1,下一个开销是传输停车(性能债);主机 retrace 往返普查见 `C-MEASUREMENTS.md` §3 |
|
||||
>
|
||||
> 门(集成头):见 ID-P10-12。
|
||||
>
|
||||
> 下面是该阶段在路线图上的原始范围与出口门(2026-09-24 从 [`ROADMAP.md`](../../ROADMAP.md) 阶段表移入,原文照录)。
|
||||
|
||||
## 摘要
|
||||
|
||||
|
||||
Reference in New Issue
Block a user