Files
MobileGL/docs/Disaggregated/design/04-reverse-channel.md
T

53 lines
4.8 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.
# 反向通道(原 ARCHITECTURE §8)
> 设计细节。设计要点与全部章节的索引见 [`../ARCHITECTURE.md`](../ARCHITECTURE.md)。章节编号沿用原 `ARCHITECTURE.md`,代码注释里的 `ARCHITECTURE.md §N` 按编号在这里找到。
## 8. 反向通道
### 8.1 `MGPipeCallbacks`(`MG_Pipe/MGPipeCallbacks.h`)
七个具名回调,取代后端直接 poke 前端对象的 95 个调用点(具名化是有意偏离 D8)。monolith 下直调,split 下是 `SEG_EVENT` 上的记录。
| 回调 | 作用 |
|---|---|
| `OnGlError` | 延迟的 GL 错误;**必须对命令流有序** |
| `OnGpuWritten` | GPU 写过的 buffer 范围(收窄 client 保守自建的 pending 集) |
| `OnBufferWriteback` | PBO 回读、XFB 捕获结果;必须与 epoch bump 有序 |
| `OnTextureWriteback` | CPU 回退生成 mip 的纹素 |
| `OnMipLevelsGenerated` | 只带形状 |
| `OnSurfaceChanged` | 默认帧缓冲的格式与尺寸(server 拥有显示时 client 靠它得知窗口尺寸) |
| `OnCapsInvalidated` | 取代 `InvalidateCompileEnv` |
`OnLog` 已删除(P9 W3;与 W2 删除的 `OnTexturePullRequest` 合计,回调 9 → 7):零生产者、零消费者、无 `EventKind`。server 日志走控制面 `LogLine`(带 `level`),由 `MG_Remote/Transport/LogForward.h` 的队列 + 发送线程转发:≤WARN 有损(队列满即丢、计数、流内 `LogForward{Dropped}` 标出缺口),≥ERROR 无损 + 限速(超速排队延迟;超出错误字节上限时合并成一条 `LogForward{Coalesced}`),FATAL 有界等待写出;日志线程永不等 socket。
后端凭空造的前端对象(Magma 占位纹理、swapchain 默认 FB 占位)改为 server 原生;pull 构建里的 `m_backend` 类成员真删会动 `sizeof`(G1),随 P13 退役(D-K)。
### 8.2 有序性是正确性要求
每次 writeback 之后的 epoch bump 必须在任何后续读该 handle 的命令之前被 server 应用。**反向通道需要与正向通道相同的有序保证。**
### 8.3 错误、ack 与日志
- **唯一允许同步 ack 的入口是 `glBufferStorage`**:`ResourceRespecify` 的 `kNeedsAck` 由逐记录谓词收窄到"不可变 **buffer**"(D-A2),纹理 OOM 在 monolith 里本来就推迟到 sync 时刻。respecify 带逐 level 作用域与"只换元数据"的形式,不误丢已接受的待上传。
- 其余错误一律晚到,走有序的 `OnGlError`。
### 8.4 纹理重铸:字节全在 server 手里,没有拉取(P9 W2 撤销原「唯一的新停顿类」D-B6)
原设计假设 server 不保留纹素、重铸要把 level 从 client 拉回来。P5c 之后 server 有 `StagedTextureStore`,GPU 写过的层本来就在 GPU 图像里——**两个后端的重铸都不需要 client 的任何字节**:
| | split 下重铸的字节来源 | monolith |
|---|---|---|
| Espryt | `RequireImageBindableStorageByHandle`:驱动上确实存在的层逐层读回旧 GPU 纹理,pending 盒用 store 合并;驱动没有的层(最后一次 sync 之后才定义)不读,store 覆盖就重放 store,否则跳过;驱动拒读而 store 覆盖时退回 store;已 immutable 且无需加宽的原样保留 | 前端臂重放 client 影子 |
| Magma | 重建带 `STORAGE` 的 VkImage,`PreserveTextureContentsOnRecreate` GPU→GPU 拷贝 | 同左 |
- 只改读 store 不够:GPU 写过的层 store 里是旧字节或没有字节;语料里 Espryt 的两次重铸(`iris-photon`、`iris-derivative`)都是 store 无字节的渲染目标。
- 「整格式再生」两臂都只上传 pending 层、不回读也不拉取;「view 源重铸」只剩源需要加宽,走同一条 ByHandle 路径。
- 删除:`OnTexturePullRequest`(与 W3 删除的 `OnLog` 合计,回调 9 → 7)、`texture-remint-pull` 标记。op 50 `ResourceSubDataComplete` 只追加不删,留作退役行(解码拒收)。`MOBILEGL_PIPE_TEXEL_RETAIN_MB` 已无消费者,但在 pull 构建里,随 P13 删(G1)。
- `ImageBindableHint` 仍是预防:hint 在第一次 sync 前到达就直接按 image-bindable 分配,省掉一次 server 回读 + 重传。
- 已知 dev 缺陷(非 P9):monolith Espryt 的前端臂重放 client 影子,覆盖 GPU 写过的纹素。
- 普查、覆盖矩阵、门与 red-once:[`notes/p9/W2-REMINT.md`](../notes/p9/W2-REMINT.md)。
### 8.5 XFB scatter 留在 server
补丁循环需要"捕获前的字节",而拆分后权威影子归 server(`StagedShadow`),所以 scatter 在 server 原地跑完;回程只有一条 `OnBufferWriteback`,载补好的整段,按 `SEG_EVENT` 容量的四分之一切片(`MGPipeBufferWritebackSliceBytes`),最后一片落地即蕴含之前每一片。孤儿目标(`HasDefinedContent == 0`)零填充后照常散射。`OnXfbScatterReady` 已删除(回调 10 → 9)。落地论证见 [`notes/p34b/README.md`](../notes/p34b/README.md)(espryt D1)。