mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 18:13:23 +09:00
54 lines
4.6 KiB
Markdown
54 lines
4.6 KiB
Markdown
# CONTRACT-P8:server 侧仿真缺口与 split 覆盖
|
||
|
||
> P8(2026-09-29 起,重定界见 `docs/Disaggregated/notes/p8/PLAN-P8.md`)落地后的规则。每条写明:规则、代码落点、守住它的用例。包说明见 `docs/Disaggregated/notes/p8/{A,B,C,D,E,F,SE,SV,MF,S}.md`,裁定见 `INTEGRATOR-DECISIONS-P8.md`。
|
||
|
||
## 1. Espryt 生成 mip(B、SE)
|
||
|
||
- server 按记录的生成窗口 [BASE+1, min(MAX+1, 存储层数, 链长)) 生成,与 Magma 同口径:`GenerateMipmapWindowByRecord`(`DirectGLES.cpp:11759`);两条 blit 链都走这个窗口。
|
||
- RGB16F / RGB32F:先试驱动原生生成;驱动拒绝时 server 从**自己的**基级做 2×2 box,永不读 client 影子。
|
||
- 基级读不回来时,暂存 store 只在「整级、extent 相符、未被驱动写过」时可代替;否则具名拒绝 `generate-mipmap-store-declined`(`DirectGLES.cpp:13134`),生成的层保持原样。driver-written 标在本次生成自己打标之前读取。
|
||
- 用例:`GenerateMipmapServerScenario`(两后端 × monolith / Split / Spawn / Tcp;Espryt 强制 CPU 臂 `.CpuMip.`、`.CpuMipRefused.` 只上 Split / Spawn)。
|
||
|
||
## 2. Espryt server 暂存副本与 GPU 写(C)
|
||
|
||
- shader 写过的 buffer(SSBO / 原子计数、可写 buffer image、XFB)在 server 孪生体上打 `serverGpuWritten` 标。
|
||
- server 的 CPU 读者(restart 重写、multi-draw rebase、`*IndirectCount`、CPU 取用的 indirect 字段、XFB scatter、fp64 收窄)一律经 `SplitHostBytesForCpuRead`(`Managers.cpp:3613`):有标或有排队常驻写时先刷新再读;T0 store 先落写再 `glFinish`。
|
||
- 用例:`GpuWrittenDrawInputScenario`(Espryt Split / Spawn / Tcp 门控)。
|
||
|
||
## 3. Magma wire 臂的 indirect(D、SV)
|
||
|
||
- `glDraw*Indirect` / `glMultiDraw*Indirect[Count]` 从 wire store 直接录成 `vkCmdDraw*Indirect[Count]`(`DrawWireIndirectNative`,`WireDraw.inc:627`);CPU 展开只留给设备发不出的 COUNT 形态(与 monolith 同条件)。
|
||
- `glDispatchComputeIndirect` 同样原生(`WireDraw.inc:844`),无 CPU 路径。
|
||
- 屏障规则:store 被 shader 写过(`MarkWireBufferGpuWritten`)后,首个 indirect 读之前录一次 MEMORY_WRITE → INDIRECT_COMMAND_READ。
|
||
- 用例:`WireIndirectDrawScenario`、`WireIndirectDispatchScenario`(计数经 `WireIndirectPeek`:原生可发时 CPU 展开 = 0)。
|
||
|
||
## 4. 驱动拒读的纹理回读(E)
|
||
|
||
- split 的 `glGetTexImage` 只读 GPU。驱动拒绝时由 server 暂存 store 作答,条件同 §1(整级、extent 相符、未被驱动写过),否则具名拒绝 `texture-readback-store-declined`(`DirectGLES/WireTextureReadback.inc:411`)。
|
||
- store 跟随同格式、单上传目标、源可信的 `glCopyImageSubData`(`FollowCopyImageInStagedStore`,`Managers.cpp:11032`);跟不了的形状打粘性 driver-written 标。
|
||
|
||
## 5. 分类与拒绝(F、SV)
|
||
|
||
- 我们的 client 发不出的形状一律 `ProtocolCorruption`:multi-draw `CLIENT_INDICES` / `INSTANCED`(`MultiDrawShapeLatch`,`PipeApplier.cpp:779`)、Magma `client-vertex-array`。
|
||
- Magma 生成 mip 的形状 / 格式缺口是具名拒绝:`MipmapShaderFormatOrShape`、`MipmapDepthStencilAspect`(`WireFramebuffer.inc:1401`、`:1465`),判定在长链之前;3D 原生 blit 用 1 层、深度走 z 偏移。
|
||
|
||
## 6. 默认帧缓冲的 surface 发布(SE)
|
||
|
||
- push 构建里,只要 `OnSurfaceChanged` 回调在,Espryt 就发布默认帧缓冲的格式与尺寸,不再以本进程的前端占位为条件(`DirectGLES.cpp:16239`);spawn / tcp 的 client 由此拿到 server surface 的真实深度模板格式。pull 构建不变。
|
||
|
||
## 7. Espryt flush 阶梯(MF,dev `f973008c`)
|
||
|
||
- 部分范围的失效映射不得越过同一 store 上 GPU 还没跑的环形拷贝:两条阶梯(push `FlushPendingRangesFrom`、pull `FlushPendingRangesNow`)都以 `ringCopyRetireSerial` 守住(`Managers.cpp:1496`、`:1785`);整 buffer 映射除外。
|
||
- G5 两个脚本把两条阶梯的评审后正文钉在 ID-P8-14。
|
||
|
||
## 8. 覆盖与门(A、SE)
|
||
|
||
- 归一化前缀后,每个 monolith 用例要么登上 split 门控臂,要么在 `scripts/data/split_coverage_exemptions.txt` 里有原因类(mechanism / single-backend / no-records / pending-fix):`scripts/ci/split_coverage.py`。
|
||
- `MGPipeUnmigratedEmulation` 的名单与调用点一一对应:`scripts/ci/unmigrated_emulation_sites.py`。
|
||
- server 读的旋钮车道:要么独立 tcp supervisor,要么只上 split + spawn,要么证明对其他用例惰性。
|
||
|
||
## 不变量
|
||
|
||
- G1:pull 构建符号不变(整阶段 0 / 0);pull 的 `.text` 只随 dev 修复变化。
|
||
- 控制协议修订号不变(5);线上格式不变。
|