Files
MobileGL/docs/archive/contracts/CONTRACT-P8.md
T

4.6 KiB
Raw Blame History

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);线上格式不变。