mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-14 21:43:24 +09:00
- review round 4 nit: the second gate of the flipped multisample resolve case read `!SplitLane::IsSplitLane() && !PeekSplitRuntime().transportResolved`; the marker term is dead - with the marker set and no transport resolved, the fixture's SetUp already skipped through SplitLane::SkipReasonForSplitOnlyAssertions() -> SplitRuntimeSkipReason(), so Ready() is false and the gate is never reached; in every reachable state it equals `!PeekSplitRuntime().transportResolved`, which is what it now says (the SplitLane.h include goes with it), and the comment no longer describes an unreachable branch; behaviour unchanged - monolith entries still Skipped with the same text, the Full entries still Passed - review round 4 nit: magma-b2.md §6 items 1, 2, 3 cited WireFramebuffer.inc by line numbers that round 3 had already moved; they now name the arm inside BlitWireFramebuffers's `blit` lambda and the MGLOG_E_ONCE / RecordTextureCopyError text, and the monolith cross-reference names VulkanRenderer::BlitFramebuffer's vkCmdResolveImage + vkCmdBlitImage instead of pipe line numbers - §2.11 records the round: the should-fix (window primed magenta/0.625, the one-shot wrong-surface demonstration and its readings), the two nits, and a round 4 line under §7 with this tree's readings - test and docs only; no backend source touched (G1 unaffected)
695 lines
53 KiB
Markdown
695 lines
53 KiB
Markdown
# P7 wave 2-B2:Magma blit / copy / mip 簇里包 B 没有走完的部分(分支 `p7/magma-b2`)
|
||
|
||
> 规范见 [`CONTRACT-P7.md`](../../../../MobileGL/MG_Remote/CONTRACT-P7.md) §0(规则 I / J)、
|
||
> §3.2(`multisample-blit-shape` / `-aspect` 行)、§4.2(棘轮目标与 (B′) 路线)、§5.2;
|
||
> 前一包见 [`magma-b.md`](magma-b.md)。基线 = `feat/disaggregated` 上 `~/w7/pipe` 的头
|
||
> `09ba88e7`(X1、F1、C、A、B 全部落地)。
|
||
>
|
||
> 主机口径与包 B 相同:WSL Arch + lavapipe(`/usr/share/vulkan/icd.d/lvp_icd.json`),
|
||
> `build-split` = Release / clang / ccache / `DISAGGREGATED=ON` `INPROC=ON` `PIPE_PUSH=ON`
|
||
> `BUILD_INTEGRATION_TEST=ON`。**本树的 TCP 端口是 `40917`**(`MOBILEGL_ITEST_TCP_ENDPOINT`):
|
||
> 包 B 用 40913、pipe 用默认的 40613,兄弟树同时在跑时端口会撞,`TcpServer.Start` 整条车道红。
|
||
>
|
||
> 基线门读数(本树实测,非引自包 B):`integration-magma-split` **88**、`-spawn` **67**、
|
||
> `-tcp` **69**、`integration-magma-full-split` **521**、`ctest -L unit` **2420**,全绿。
|
||
> 包 B 的报告写的是 84 / 63 / 65,差的四条**不是**「包 A 在它之后落地」——那句是错的,
|
||
> 审查round 已更正:包 A 在 B **之前**落地(`450d3075..2207b6d9` 在 `c4be3800` 之前)且只有 +2
|
||
> (`magma-a.md:151-153`),另外 +2 是包 C(`magma-c.md:59-61`)。本树的基线因此是
|
||
> 73 + 11(B)+ 2(A)+ 2(C)= **88 / 67 / 69**。
|
||
|
||
## 0. 每片一条提交,每片至少一次 red-once
|
||
|
||
| 片 | 名 | 退役 / decline | 提交 |
|
||
|---|---|---|---|
|
||
| 1 | `multisample-blit-shape@P7` | 缩放/翻转的多重采样颜色 blit **退役**;多重采样目的地 **decline** | `c77c4f29` |
|
||
| 2 | `multisample-blit-aspect@P7` + 烘焙 (A) 第三对 | 无 resolve 扩展的深/模板 **退役**(烘焙 pass);改采样数 **decline** | `aba21e26` |
|
||
| 3 | `MagmaP7AllocatorDebtScope` ×2 | **删除**(先证明它们在非 monolith 传输下从不武装) | `4bee1313` |
|
||
| 4 | (B′):棘轮的 `p7-magma` 桶 | monolith 臂在 disaggregated 构建里改走烘焙模块 | 见 §4 |
|
||
|
||
**`grep -rn "@P7" MobileGL/ --include=*.cpp --include=*.inc --include=*.h` 在片 2 之后只剩注释**
|
||
(19 行,全部是「某某退役了」或 red-once 的散文)。树上没有任何一条拒绝再带这个标记。
|
||
|
||
---
|
||
|
||
## 1. 片 1:`multisample-blit-shape@P7`
|
||
|
||
### 1.1 一个名字下面的两半,问题不是同一个
|
||
|
||
**有臂的那一半**:多重采样颜色 blit 的目的矩形与源矩形尺寸不同。`vkCmdResolveImage` 每侧只带
|
||
**一个 extent 和一个 offset**,既表达不了缩放也表达不了翻转——而这条臂**本来就**为了翻转先
|
||
resolve 进一张单采样 scratch、再对 scratch 做 `vkCmdBlitImage`。两个 `width != |dx1-dx0|` 子句
|
||
是唯一把缩放挡在同一条路线之外的东西,而 monolith 臂走的正是这条路线
|
||
(`VulkanRenderer.cpp` 的 `regionWasTransformed` 分支)。子句去掉;scratch 仍按**源**矩形定尺寸,
|
||
所以只有第二段看得见缩放。
|
||
|
||
**顺带的一件事**:filter 是**从这次缩放起才有意义的**——1:1 时 LINEAR 与 NEAREST 读同一个 texel,
|
||
所以在此之前没有人问过这个格式能不能被过滤。对 `optimalTilingFeatures` 缺
|
||
`SAMPLED_IMAGE_FILTER_LINEAR` 的格式传 `VK_FILTER_LINEAR` 是未定义行为;GL 本来也说多重采样
|
||
resolve 忽略 filter,所以回落是 NEAREST 而不是拒绝。
|
||
|
||
**没有臂的那一半**:**多重采样目的地**。`vkCmdCopyImage` 是唯一能写多重采样图像的命令,它只带一个
|
||
extent,而 GL 4.6 core 18.3.1 说任一侧多重采样时两个矩形尺寸不同就是 `INVALID_OPERATION`。
|
||
没有「正确结果」可言,所以按规则 I (a):`MGLOG_E_ONCE` 写出两个矩形与两个采样数、记 GL 错、
|
||
目的地原样不动、会话留下。
|
||
|
||
### 1.2 场景与车道
|
||
|
||
`F1WireScenario.MultisampleColorBlitScalesAndFlipsThroughTheResolveScratch` 与
|
||
`…MultisampleBlitOntoAMultisampleDestinationDeclinesAndKeepsTheSession`,三臂各两条,前缀 `MsBlit.`。
|
||
|
||
**split-only**,理由和包 B 的 in-place copy 一样、而且更强:monolith 臂对缩放的多重采样 blit 走
|
||
`vkCmdResolveImage` 1:1 落在目的偏移上——**缩放被丢掉**——所以没有可对照的 `DirectVulkan.` 读数,
|
||
两臂相等的断言等于断言 wire 臂也一样错。
|
||
|
||
**缩放与翻转在同一条用例里、同一个源上**,因为它们坏的方式不同:丢了缩放会把 8×4 的带子塞进 4×2 的
|
||
附件(驱动直接拒命令),丢了翻转会把对的两个颜色按错的顺序返回。第二次 blit 的期望就是第一次的
|
||
期望把两行调过来,所以谁也通不过对方的断言。
|
||
|
||
### 1.3 测出来的一件事:decline 的 GL 错**晚到**
|
||
|
||
decline 在**执行 blit 的地方**记错,也就是 server 的 apply 线程,而那个错是**跟着后一次 reply**
|
||
回到 client 队列的,不是跟着 blit 调用。第一次跑的时候它挂在二十行之下那次 1:1 resolve 上——
|
||
一次没有任何毛病的调用。用例里的 `glFinish()` 因此是承重的,不是礼貌。
|
||
|
||
### 1.4 red-once(R-16,两条,均已执行并还原)
|
||
|
||
1. 把两个尺寸相等子句放回去 → `…ScalesAndFlipsThroughTheResolveScratch` 死于
|
||
`Fatal{UnmigratedVerb, "Magma:multisample-resolve-region"}`;
|
||
2. 把 `MagmaWireFatal("multisample-blit-shape@P7")` 放回去 → `…DeclinesAndKeepsTheSession`
|
||
死于该名。
|
||
|
||
还原后三臂 6/6 绿。
|
||
|
||
### 1.5 门
|
||
|
||
`integration-magma-split` **90**(+2)、`-spawn` **69**(+2)、`-tcp` **71**(+2)、
|
||
`integration-magma-full-split` **523**(+2)、`ctest -L unit` **2420**,全绿;
|
||
`fatal_census` 79 abort 站点 / 44 家族词 / 0 无标记;`link_ratchet --assert-monotone` 186 不变;
|
||
G1 pull `.text` **`0xa52203`**、`nm --defined-only` 与 `~/w7/p7-before/pull-syms.txt` 逐行相同
|
||
(30570 行,0 差异)。
|
||
|
||
---
|
||
|
||
## 2. 片 2:`multisample-blit-aspect@P7` 与第三对烘焙模块
|
||
|
||
### 2.1 `vkCmdResolveImage` 只做颜色
|
||
|
||
Vulkan 里不用 shader 把深度或模板 aspect resolve 下来的**唯一**办法,是带 depth/stencil resolve
|
||
附件的 render pass,它要 `VK_KHR_create_renderpass2` 和 `VK_KHR_depth_stencil_resolve`。两个都没有
|
||
的设备,在应用第一次
|
||
`glBlitFramebuffer(GL_DEPTH_BUFFER_BIT)`(**这就是 GL 里每一次多重采样深度 resolve**)时会死于
|
||
`Magma:multisample-depth-resolve-capability`。§3.2 的 aspect 行点了两条臂的名,这一片补上第二条。
|
||
|
||
`WireMultisampleResolve.inc` + 三个烘焙模块(一个顶点阶段,每个 aspect 一个片元阶段),取
|
||
**样本零**——和扩展臂要的 `VK_RESOLVE_MODE_SAMPLE_ZERO_BIT` 同一个样本,所以两条臂在同一台设备上
|
||
互换不会改变像素,车道也才断言得动。GL 4.6 core 18.3.1 对模板本来就要求**选一个**样本,对深度要求
|
||
结果落在该像素的 min/max 之间——样本零两边都满足,而平均**不满足**后者的精神(四个深度的均值是一个
|
||
哪里都不存在的表面)。
|
||
|
||
**这条 pass 什么都不带。** scratch 与源同尺寸、同坐标系(两张都是原生图像,彼此不翻转),所以片元
|
||
阶段直接用 `gl_FragCoord` 取址,矩形交给 scissor。没有 push constant,没有 varying,没有前端对象。
|
||
|
||
**模板那一半要扩展才存在**:片元着色器没有 `VK_EXT_shader_stencil_export` 根本写不了模板 aspect。
|
||
没有它就 decline 模板(§3.2 原话),而且**模块本身不创建**——把带不支持 capability 的 SPIR-V 交给
|
||
`vkCreateShaderModule` 是未定义行为,不是一个能接住的错误。
|
||
|
||
**两个能力判据不是同一个判据**,差别是结构性的:subpass resolve 的是**格式**拥有的每一个 aspect,
|
||
所以每个都要有 mode;而上面这条 pass 只写这次 blit 要的那一个 aspect,scratch 其余部分留成未定义
|
||
——安全,因为随后的 copy 读的正是那一个 aspect。
|
||
|
||
### 2.2 没有臂的那一半
|
||
|
||
采样数不同、且**目的地**是多重采样的那一侧:一个样本铺成 N 个,或 N 个降成 M 个。
|
||
`vkCmdResolveImage` 只写单采样目的地,`vkCmdBlitImage` 两侧都拒绝多重采样,`vkCmdCopyImage` 要求
|
||
两个数相等。decline。
|
||
|
||
### 2.3 场景与车道
|
||
|
||
**用例是提拔来的,不是新写的。** `DepthStencilReadbackMatrixScenario.AResolvedMultisampleDepth…`
|
||
本来就拥有这个可观测(清一张 4× `DEPTH24_STENCIL8`、用 `glBlitFramebuffer` resolve 进单采样、两个
|
||
aspect 都读回、并检查只做深度的 resolve 没动目的地的模板、反之亦然),而且**本来就在三条 Magma 臂
|
||
的信息档(`…Full.`)里跑**。缺的只是一条 gating 条目。
|
||
|
||
`MsResolve0.` 在三臂都注册;`MsResolve1.` **只在 split 和 spawn**(审查 round 的修正,见 §2.7)。
|
||
第二条是那条臂在此唯一可达的方式:lavapipe 两个 resolve 扩展都有,扩展臂会接下本机的每一次
|
||
resolve。`MGITEST_MAGMA_FORCE_SHADER_DEPTH_RESOLVE` 丢掉扩展臂。
|
||
**它在本机不 skip**:lavapipe 也带 `VK_EXT_shader_stencil_export`,所以 shader 臂深度和模板都走通了。
|
||
新增的 F1 用例是那条 decline。
|
||
|
||
> 集成者交代里写的「可能在 lavapipe 上 SKIP(分离的 D24/S8 不支持)」本树**没有发生**:
|
||
> 提拔的这条用例用的是**合并**的 `DEPTH24_STENCIL8`,分离 D24/S8 是同一文件里另一条用例
|
||
> (`SeparateDepthAndStencilAttachmentsAreBothReadable`)的事,没有提拔。
|
||
|
||
`MOBILEGL_BAKED_INTERNAL_SHADERS` 的表从 8 行涨到 **11 行**。
|
||
|
||
### 2.4 red-once(R-16,三条,均已执行并还原)
|
||
|
||
1. **shader 臂**:把 `MagmaWireFatal("multisample-depth-resolve-capability")` 放回非扩展臂 →
|
||
`DirectVulkan.Split.MsResolve1.…` 死于该名,而 `MsResolve0`(扩展臂)**仍然绿**——这同时是旋钮
|
||
确实改道的证明;
|
||
2. **aspect decline**:把 `MagmaWireFatal("multisample-blit-aspect@P7")` 放回去 →
|
||
`DirectVulkan.Split.MsBlit.…FromASingleSampleSourceDeclines…` 死于该名;
|
||
3. **新鲜度门**:把 `WireMultisampleStencilResolve.frag` 的取样索引从 0 改成 1(**不需要重建**——
|
||
门在运行时读源)→ `WireMultisampleStencilResolveFragment` 在**第 158 个字**变红,并指名符号、
|
||
头文件与重新生成的命令。
|
||
|
||
还原后三臂 15/15 绿、新鲜度门 11/11 绿。
|
||
|
||
### 2.5 门
|
||
|
||
`integration-magma-split` **93**(+3)、`-spawn` **72**(+3)、`-tcp` **74**(+3)、
|
||
`integration-magma-full-split` **524**(+1)、`ctest -L unit` **2423**(+3),全绿;
|
||
`bake_internal_shaders.py --check` 五个头全新鲜;`fatal_census` 79 / 44 / 0;
|
||
`link_ratchet --assert-monotone` 186 不变;G1 `.text` `0xa52203`、符号表逐行相同。
|
||
|
||
> 上面这三个 `+3` 是**片 2 落地当天**的读数,那时 `MsResolve1.` 还注册在 tcp 上。审查 round
|
||
> 把它从 tcp 摘掉了(§2.7),tcp 的最终读数在 §7。
|
||
|
||
### 2.6 欠设备核对
|
||
|
||
shader resolve 臂正是**手机**在没有 `VK_KHR_depth_stencil_resolve` 时会走的那条,而本机只能经旋钮
|
||
到达它。它的几何要在 Redmi 上看一眼。
|
||
|
||
**`MsFlip.` 在格式分叉的设备上会红**(审查 round 2 补记):场景的多重采样源是 **renderbuffer**
|
||
`DEPTH24_STENCIL8`,目的地是 **texture** `DEPTH24_STENCIL8`。本机两者都映射到
|
||
`VK_FORMAT_D24_UNORM_S8_UINT`,所以 Y 翻转走同格式的逐行 copy-out。一台把 renderbuffer 与 texture 的
|
||
D24S8 映射到**不同** `VkFormat` 的设备(例如 texture 侧退到 `D32_SFLOAT_S8_UINT`)会在
|
||
`DeclineWireDepthStencilResolveShape` 的**跨格式 Y 镜像** decline 上拿到 `INVALID_OPERATION`,
|
||
`MsFlip.` / `MsFlip1.` 因此变红——那不是回归,是 §6 第 5 条那笔债在该设备上可见了。上 Redmi 前先看它的
|
||
两种映射是否相同。
|
||
|
||
### 2.7 审查 round:一个 server 端旋钮**没有** tcp 臂
|
||
|
||
`MGITEST_MAGMA_FORCE_*` 三个旋钮都由 **server** 读(`WireFramebuffer.inc` 的三个 `std::getenv`
|
||
跑在 apply 线程上),而 ctest 的 `ENVIRONMENT` 属性只到达 ctest 启动的那个进程,也就是 **client**。
|
||
三条臂的 server 来处不同:
|
||
|
||
| 臂 | server 从哪来 | 旋钮到得了吗 |
|
||
|---|---|---|
|
||
| inproc | 同进程的一个线程 | 到 |
|
||
| spawn | `ServerSpawn.cpp:106` 把 `::environ` 复制进子进程 | 到 |
|
||
| tcp | **车道级** `TcpServer.Start` fixture,由 `scripts/ci/tcp_server_fixture.py` 用**它自己的** `os.environ` 在任何用例之前启动一次,每个 Hello fork 一个会话子进程 | **到不了** |
|
||
|
||
所以一条 tcp 的旋钮条目跑的是**默认**臂,名字却宣称不是——对 ShaderMip 而言,这正是那条用例自己的
|
||
skip 文案说不许发生的事(「would assert the native blit twice over」)。
|
||
|
||
**实测,不是推导**:在三个 reader 里各放一个临时 fatal,五条 knob=1 条目在 split **全死**、在
|
||
spawn **全死**、在 tcp **五条全绿**;五条 knob=0 的孪生条目三臂全绿。
|
||
|
||
修法用的是 ID-P7-14 `MAGMA_INPROC_ONLY` 的先例:`scripts/ci/spawn_lane_parity.py` 新增
|
||
`MAGMA_SERVER_ENV_KNOB_NO_TCP`,并给 `compare_arms` 加一个 `no_tcp=` 参数。它和 `inproc_only=`
|
||
**不是**同一个形状,这一点是承重的:`inproc_only` 把键从**每一条**非 split 臂的比较里拿掉,而这五条
|
||
必须在 spawn 上**仍然被要求**——spawn 才是它们干活最多的地方。受影响的五条是
|
||
`.ShaderMip1.` `.ShaderMip2.` `.DepthMip.` `.DefaultBlitShape1.` `.MsResolve1.`;knob=0 的
|
||
`.DefaultBlitShape0.` / `.MsResolve0.` 留在三臂,因为零就是默认值,那两条在三臂含义相同。
|
||
|
||
其中三条(`ShaderMip1/2`、`DepthMip`、`DefaultBlitShape1`)是**包 B 既有的**同种空转,一并修。
|
||
|
||
**这是一笔债而不是一个结论**:要让 tcp 车道也能带这些条目,fixture 得接受**每用例的 server 环境**
|
||
——那是一个 supervisor 控制项,不是一个 ctest 属性。记在 §6。
|
||
|
||
### 2.8 审查 round:翻转和缩放的深/模板 resolve 不再带走会话
|
||
|
||
`ResolveWireDepthStencil` 的区域判据要求 `sx1 > sx0` 且 `sy1 > sy0`,否则
|
||
`Magma:multisample-depth-resolve-region` 带走会话。于是
|
||
|
||
```
|
||
glBlitFramebuffer(0, h, w, 0, 0, 0, w, h, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
|
||
```
|
||
|
||
从一个多重采样 framebuffer 出发时,**颜色 blit 正确完成**(颜色臂自 P5f 起就会翻转,本包又给了它
|
||
缩放),**然后死在深度上**。GL 4.6 core 18.3.1 要求的是**尺寸**相同而不是角点相同(Mesa 比的是
|
||
`abs()`),所以翻转是一次合法的 blit,欠一张镜像的图。
|
||
|
||
拆成三块:
|
||
|
||
1. **缩放** → 规则 I (a) 具名 decline。18.3.1 说尺寸不同就是 `INVALID_OPERATION`,没有「正确结果」。
|
||
2. **Y 翻转、同格式** → **退役**:copy-out 那一步本来就是「image → buffer → image」,而 buffer copy
|
||
是按**行**寻址的,所以每行一个 `VkBufferImageCopy`、倒着走,就是一次垂直镜像。(round 1 让
|
||
`bufferRowLength` 保持 0、行紧贴;那违反深/模板 copy 的 4 字节 `bufferOffset` 对齐,round 2 把行距
|
||
补齐到 4 字节,见 §2.9。)
|
||
3. **X 翻转**,以及**跨格式的 Y 翻转** → 具名 decline。横向镜像要一个 region 一个 **texel**,那已经
|
||
不是 copy 了;跨格式重编码走 `BlitDepthAcrossFormats`(与 monolith 臂共用),它也没有翻转。
|
||
两条都进 §6。
|
||
(round 1 的这两条 decline 与第 1 条的缩放 decline 都是在颜色 aspect **已经写完之后**才决定的——
|
||
一次部分生效,GL 不允许。round 2 把决定提到任何 aspect 之前,见 §2.9 第 3 条。)
|
||
|
||
span 从此是**有符号**的,下游一律用 min 角(`sxMin/syMin/dxMin/dyMin`),render pass 的 renderArea、
|
||
shader 臂的 scissor、buffer copy 的 imageOffset、`BlitDepthAcrossFormats` 的四个角全部跟着改。
|
||
|
||
**场景**:`DepthStencilReadbackMatrixScenario.AFlippedMultisampleResolveMirrorsTheBandsAndAScaleDeclines`,
|
||
三臂各一条,前缀 `MsFlip.`,**不需要旋钮**(两种形状都在能力问题之前由矩形决定)。
|
||
**颜色和深度在同一次调用里**,因为那正是让这件事显形的形状;两条带子深度不等(下 0.25 / 上 0.75),
|
||
并且颜色也断言了同一个方向——一次「假翻转」(比如只是把读回顺序倒过来)会让颜色和深度不一致。
|
||
|
||
**red-once(R-16,三条,均已执行并还原,split + spawn 各一遍;审查 round 的第二个会话又亲手各跑了一遍)**:
|
||
|
||
1. 把旧判据放回去(`spanX <= 0 || spanY <= 0 || spanX != dstSpanX || spanY != dstSpanY` → Fatal)
|
||
→ 两臂都死于 `Fatal{UnmigratedVerb, "Magma:multisample-depth-resolve-region"}`;
|
||
2. 只把**缩放**那条 decline 换回旧 Fatal(翻转路径不动)→ 翻转那一半通过,两臂都在缩放那一步死于
|
||
同一个名字——证明缩放 decline 是承重的,而不是被翻转那条红顺带盖住;
|
||
3. 把 copy-out 的 `if (!mirrorY)` 改成恒真(即拿掉逐行倒序,其余一律不动)→ 两臂都**活着**但深度
|
||
带子上下颠倒:`flipped resolve: the destination's bottom band: 768 of 768 depth values differ
|
||
from 0.75; first bad value 0.25`(顶带反之)。这一条才是对**新代码**的断言——它证明那张镜像的图
|
||
是逐行倒序产生的,不是别处的副作用。
|
||
|
||
### 2.9 审查 round 2:在哪些臂上断言、行距、以及「一次调用一个答案」
|
||
|
||
**1. 用例只在 Magma wire 臂上断言。** `DepthStencilReadbackMatrixScenario` 整套被 monolith
|
||
`DirectVulkan.` 臂和每一条 DirectGLES 臂发现,于是 round 1 的新用例在它们上面全红:monolith 拒绝
|
||
翻转的深度 blit(`VulkanRenderer.cpp:9594`「depth blits with flipped rectangles are not supported
|
||
yet」,目的地保持清屏值、无错误)并**缩放**一次 GL 说是 `INVALID_OPERATION` 的多重采样深度 blit
|
||
(`:9608`);Espryt(monolith 与 split 一样)翻转时什么也不写、也不报错,缩放时也不报错。用例先按
|
||
`Gl().BackendName() != "DirectVulkan"` 跳过(Espryt 文案,P3b/P4b),再按
|
||
`SplitLane::IsSplitLane()` 跳过(monolith 文案,P13/G1)。实测:
|
||
`DirectVulkan.DepthStencilReadbackMatrixScenario.AFlipped…` 与
|
||
`DirectGLES.{,ForcedDepthStencilEmulation.}DepthStencilReadbackMatrixScenario.AFlipped…` 均为
|
||
`Skipped`,理由即上;三条 `DirectVulkan.{Split,Spawn,Tcp}.MsFlip.` 仍然武装并通过。两笔差异进 §6
|
||
第 6、7 条。(行号是落地树上的。)
|
||
**round 3 修正**:第二道门改按**进程解析到的传输**跳过(§2.10 第 1 条),因为 `MGITEST_SPLIT_LANE`
|
||
标的是精选车道而不是传输——`DirectVulkan.{Split,Spawn,Tcp}.Full.` 与 `DirectVulkan.VerifySplit.`
|
||
故意不带它。现在**运行**这条用例的条目是:`DirectVulkan.{Split,Spawn}.{MsFlip,MsFlip1}.`、
|
||
`DirectVulkan.Tcp.MsFlip.`、`DirectVulkan.{Split,Spawn,Tcp}.Full.`(三条由 Skipped 变 Passed)、以及
|
||
落地树上的 `DirectVulkan.VerifySplit.`;仍 `Skipped` 的只有 monolith `DirectVulkan.` 与 DirectGLES 条目。
|
||
|
||
**2. copy-out 的行距补齐到 4 字节。** 深/模板目的地的 buffer→image copy 要求每个 `bufferOffset`
|
||
是 4 的倍数(`VUID-vkCmdCopyBufferToImage-dstImage-07978`,旧层叫 `pRegions-07978`)。§2.8 的逐行
|
||
镜像把第 r 行放在 `r * width * texelSize`:模板 aspect(1 字节)宽度不是 4 的倍数、或 D16(2 字节)
|
||
宽度为奇数时,第一行之后的每一行都违规——而 `BlitWireFramebuffers` 的 scissor 裁剪恰好产生任意宽度。
|
||
改为 `paddedWidth = AlignUp(width, 4 / texelSize)`,buffer 取 `paddedWidth * height * texelSize`,
|
||
两次 copy 都以 `paddedWidth` 作 `bufferRowLength`,第 r 行从 `r * paddedWidth * texelSize` 开始。
|
||
场景加一条**模板**腿:源的模板带 11 / 99,一次 29×32、从 (5, 8) 到 (20, 4) 的翻转
|
||
`GL_STENCIL_BUFFER_BIT` blit,目的地每个模板值都按镜像带或原封的 3 核对。
|
||
|
||
red-once(split + spawn,`VK_LOADER_LAYERS_ENABLE=*khronos_validation`):lavapipe 不强制这条 VU,
|
||
未补齐的代码读回的模板字节**是对的**,所以红的是校验层——每臂 10 条
|
||
`pRegions[1].bufferOffset (29) must be a multiple 4 if using a depth/stencil format
|
||
(VK_FORMAT_D24_UNORM_S8_UINT)`;补齐之后校验层**零**错误(任何 VUID)。
|
||
|
||
**3. 一次调用一个答案。** 颜色 lambda 先跑,所以 round 1 的形状 decline 是**逐 aspect** 决定的:
|
||
一次缩放的 `COLOR|DEPTH` 多重采样 blit 先把颜色缩放写进去,**然后**在深度上记
|
||
`INVALID_OPERATION`;一次 X 镜像的则镜像了颜色、留下深度不动、再报一个 GL 本不会报的错。18.3.1
|
||
说出错的 blit 什么也不写。修法(本 round 做了,不是记债):形状判据搬进
|
||
`DeclineWireDepthStencilResolveShape`,`BlitWireFramebuffers` 在**任何 aspect 之前**对 mask 里每个
|
||
会走多重采样 resolve 臂的深/模板 aspect 问一次,decline 则整个调用返回;`ResolveWireDepthStencil`
|
||
为其它调用者也问一次。默认 read framebuffer 留给 lambda(它从不是多重采样)。round 2 把默认 **draw**
|
||
framebuffer 也留给了 lambda,理由是「默认 draw 在多重采样 read 后面本就是 region Fatal」——那句是
|
||
错的,round 3 改正(§2.10 第 2 条):默认 draw 与用户 framebuffer 一样进预检,以 `isWriteTarget=false`
|
||
解析,写索引不动。
|
||
**这句「整个调用什么也不写」只对形状 decline 成立**(round 3 收窄措辞):`ResolveWireDepthStencil`
|
||
里的**能力** decline(无 `VK_KHR_depth_stencil_resolve` 也无 `VK_EXT_shader_stencil_export` 的设备上
|
||
的 stencil-only resolve)仍是逐 aspect 决定的,一次 `COLOR|STENCIL` 调用在颜色写完之后才 decline
|
||
模板;规则 I (a) 接受这一点,见 §2.10 第 3 条。
|
||
顺带:X 与跨格式 Y 两种 decline 各有自己的 `MGLOG_E_ONCE`(原来共用一个,首次 X 之后跨格式 Y 不再
|
||
留痕);只有一侧为空的矩形(64×48 → 0×48)走缩放 decline 报 `INVALID_OPERATION`,不再静默返回。
|
||
|
||
**4. `MsFlip1.`。** 无旋钮时 lavapipe 的每次 resolve 都走扩展臂,shader 臂在翻转下的 min 角矩形
|
||
从未执行。`DirectVulkan.{Split,Spawn}.MsFlip1.` 带 `MGITEST_MAGMA_FORCE_SHADER_DEPTH_RESOLVE=1`,
|
||
只在 split + spawn(§2.7 的理由),列入 `MAGMA_SERVER_ENV_KNOB_NO_TCP`;`spawn_lane_parity.py`
|
||
现在要求每个 tail **恰好**命中一条 split 键,死 tail 或过宽 tail 都让门失败。
|
||
|
||
red-once(均已执行并还原,split + spawn,外加 tcp 的 `MsFlip.`):
|
||
|
||
1. 关掉预检 → 五条 `MsFlip.`/`MsFlip1.` 全红:`the declined COLOR|DEPTH scale must not have
|
||
written its colour either`(读到 {255,0,0,255},要 {0,0,255,255});
|
||
2. 放回 round 1 的「一侧为空就静默返回」→ 五条全红在空目的地腿上(错误 0,要 1282);
|
||
3. 给 shader 臂传 `sx0/sy0` 而不是 min 角 → 只有 `MsFlip1.` 两臂红(`768 of 768 depth values differ
|
||
from 0.75`;`928 of 3072 stencil values are wrong; first at (20, 4): got 255, want 99`),
|
||
`MsFlip.` 保持绿——证明这条孪生条目确实走到了 shader 臂的矩形;
|
||
4. 往 tail 表里加一个死的 `.MsFlip2.` → parity RC 1,`matches 0 split entrie(s)`。
|
||
|
||
两个拆开的 once 站点没有车道级 red-once:跨格式 Y decline 需要 renderbuffer 与 texture 的 D24S8
|
||
映射到不同 `VkFormat` 的设备(§2.6),lavapipe 不是。
|
||
|
||
### 2.10 审查 round 3:按传输跳过、默认 draw framebuffer 也进预检、两处措辞
|
||
|
||
**1. 跳过判据是进程解析到的传输,不是车道标记。** round 2 的第二道门按 `SplitLane::IsSplitLane()`
|
||
跳过,而 `MGITEST_SPLIT_LANE=1` 标的是**精选车道**,不是传输:`DirectVulkan.{Split,Spawn,Tcp}.Full.`
|
||
(整二进制普查)与 `DirectVulkan.VerifySplit.`(verify 构建上的 split 臂,`integration-verify-split`
|
||
作业的门)**故意不带**它却跑在 inproc / spawn / tcp 上——各自的 CMake 块写明了为什么:标记会武装
|
||
fixture 的「记录序数必须移动」断言,对只查询的用例是误报。于是这条用例在它们上面全部 `Skipped`,文案
|
||
还说「monolith 臂(MGITEST_SPLIT_LANE unset)」——而 round 2 之前它在这些条目上是跑过并通过的。
|
||
改为 `!SplitLane::IsSplitLane() && !PeekSplitRuntime().transportResolved`
|
||
(`Harness/SplitRuntimePeek.h`,即 `MG_Config::Transport != Monolith`;round 4 删掉了 `IsSplitLane()`
|
||
那一项——它到不了,§2.11 第 2 条)——这正是
|
||
`VulkanRenderer::BlitFramebuffer` 分到 `BlitWireFramebuffers` 的那个分叉;文案改说「monolith
|
||
transport」。标记单独仍然有效:一条要了 split 的精选车道照常跑这条用例,它拿没拿到传输由 fixture 的
|
||
武装断言说。
|
||
|
||
实测(`build-split`):
|
||
|
||
- `DirectVulkan.DepthStencilReadbackMatrixScenario.AFlipped…` 仍 `Skipped`:「the monolith
|
||
DirectVulkan transport (this process resolved no split transport, so BlitFramebuffer takes the
|
||
monolith arm) refuses a flipped depth blit …」;
|
||
`DirectGLES.{,ForcedDepthStencilEmulation.}DepthStencilReadbackMatrixScenario.AFlipped…` 仍
|
||
`Skipped`(Espryt 文案);
|
||
- `DirectVulkan.{Split,Spawn,Tcp}.Full.…AFlipped…` 三条由 `Skipped` 变 **`Passed`**;
|
||
- `DirectVulkan.{Split,Spawn}.{MsFlip,MsFlip1}.` 与 `DirectVulkan.Tcp.MsFlip.` 仍 `Passed`。
|
||
|
||
**`VerifySplit.` 在本分支上量不到,原因写明。** 那条车道由 verify-split 包注册,不在 `p7/magma-b2`
|
||
上。本树按同样的 split 选项另配了 `build-verify`(`-DMOBILEGL_PIPE_VERIFY=ON`):monolith 的
|
||
`DirectVulkan.Verify.` 条目绿,但**每一条** split 条目——包括与本包无关的
|
||
`DepthStencilReadbackScenario.DefaultFramebufferDepthClearIsVisibleToReadPixels`——都在 EGL 启动的
|
||
pre-flight 子进程里 SIGABRT(`MOBILEGL_ITEST_REQUIRE_GPU=1` 把它变成 `ScenarioFixture.h:112` 的
|
||
Failure),环境里有没有 `MOBILEGL_PIPE_VERIFY=1` 都一样。gdb 跟进子进程:`mgl-srv-apply` 线程在
|
||
`MGPipeApplyResourceRespecify` 处 abort(`PipeWireDecoder::ApplyChecked` ← `PipeApplier::ApplyOne`
|
||
← `ServerLoop::DrainRing`)——这就是 `PLAN-PH-P34B-P7.md` 写的「verify+split 撞旧
|
||
`PipeRespecifyScope` 断言」,由 verify-split 包放宽,本分支没有它。本分支自己能证明的是同一道门在
|
||
同样的形状(无标记、传输已解析)上放行,即三条 `Full.`。
|
||
`VerifySplit.` 本身则在一棵**一次性的分离 worktree** 上量了:落地树的头 + 本 round 的提交 a
|
||
cherry-pick 上去,同样的 split 选项 + `-DMOBILEGL_PIPE_VERIFY=ON`(不碰任何既有 worktree,量完即删):
|
||
`DirectVulkan.VerifySplit.DepthStencilReadbackMatrixScenario.AFlipped…` **`Passed`**(round 2 的门下
|
||
它是 `Skipped`),`DirectVulkan.DepthStencilReadbackMatrixScenario.AFlipped…` 仍 `Skipped`
|
||
(monolith transport 文案),`DirectGLES.VerifySplit.…AFlipped…` 仍 `Skipped`(Espryt 文案)。
|
||
落地后的正式读数仍由 integrator 的 `integration-verify-split` 门给出。
|
||
|
||
**2. 默认 draw framebuffer 也进预检。** round 2 的预检把默认 DRAW framebuffer 留给 lambda,理由是
|
||
「默认 draw 在多重采样 read 后面本就是 `ResolveWireDepthStencil` 的 region Fatal,形状无关」——
|
||
**不成立**:那条臂先调 `DeclineWireDepthStencilResolveShape`,**后**才到 `destination.isDefault` 的
|
||
Fatal。于是「MSAA FBO → 窗口,`COLOR|DEPTH`,缩放(或 X 镜像)」这一形状下:颜色 lambda 先跑
|
||
(`BlitWireColorToDefault` 把 swapchain 图像写了),深度再记 `INVALID_OPERATION` 返回——正是 §2.9
|
||
第 3 条与 §6 第 1、5 条宣称已关的部分生效,只是换了一种目的地。
|
||
修法:守卫去掉 `!draw->IsDefault`;`declines` lambda 两侧都按 `isWriteTarget=false` 解析——这里只看
|
||
`.format` / `.samples`,而 `DefaultFramebufferReadIndex` 是 `const`(`VulkanRenderer.h`),写索引
|
||
不动;`ResolveWireImage` 对非默认 framebuffer 根本不看这个参数。
|
||
场景加一条腿:窗口清成蓝色、深度 0.5,把多重采样源(下红上绿)放大铺满整个 128×96 的窗口、
|
||
`COLOR|DEPTH`,要求 `INVALID_OPERATION`,并在 (1, 1)、(64, 48)、(126, 94) 三点用 `glReadPixels`
|
||
核对颜色仍是蓝、深度仍是 0.5。harness 的 pbuffer 默认 framebuffer 只有 `glReadPixels` 一种看法,
|
||
所以两个 aspect 都由它断言。
|
||
|
||
red-once(split + spawn,已还原):把 round 2 的 `&& !draw->IsDefault` 放回守卫 →
|
||
`DirectVulkan.{Split,Spawn}.MsFlip.` 两臂都红在新腿上:`the declined COLOR|DEPTH scale onto the
|
||
window must not have written its colour at (1, 1)`,读到 {255,0,0,255}(源的下带),(64, 48) 与
|
||
(126, 94) 读到 {0,255,0,255},要 {0,0,255,255};而 `INVALID_OPERATION` 的断言**照样成立**——这正是
|
||
「一半效果」的样子。修后 107 条多重采样 blit/resolve 与深/模板读回条目(三臂的
|
||
`MsFlip / MsFlip1 / MsBlit / MsResolve0 / MsResolve1`、三臂 `Full.` 的两套读回场景、monolith 的
|
||
`DirectVulkan.DepthStencilReadback*`)全绿,既有 skip 不变。
|
||
|
||
**3. 两处措辞。** `VulkanRenderer.h` 对 `DeclineWireDepthStencilResolveShape` 的说明与 §2.9 第 3 条
|
||
说的「declined call 不动任何附件」只对**形状** decline 成立:`ResolveWireDepthStencil` 里的**能力**
|
||
decline(无 `VK_KHR_depth_stencil_resolve` 也无 `VK_EXT_shader_stencil_export` 的设备上的
|
||
stencil-only resolve)仍是逐 aspect 决定的,一次 `COLOR|STENCIL` 调用在颜色写完之后才 decline
|
||
模板。规则 I (a) 接受这一点,两处措辞已收窄到形状 decline。§6 第 4 条与 §7 的 knob 条目数:落地树是
|
||
**七**条 tail(B3 合入时 `.StaleSerial.` 进了表),本分支没有 B3、它的门量到的是六条;两处都已写明。
|
||
§6 新增第 8、9、10 条(审查 round 3 点出、本 round 不改的三笔债:合法同尺寸 MSAA→默认 framebuffer
|
||
深/模板 blit 的 Fatal、scissor 裁空的静默返回、MS→MS 的逐 aspect decline)。
|
||
|
||
### 2.11 审查 round 4:窗口腿的底色、一个到不了的合取项、按符号引用
|
||
|
||
**1. 窗口腿的底色不能与别的表面相同(should-fix)。** round 3 的窗口腿把默认 framebuffer 清成蓝色、深度
|
||
0.5——与用户 framebuffer `resolved.fbo` 的底色**相同**,而那张 FBO 在自己那条被 decline 的 blit 之后也还是
|
||
蓝 / 0.5。于是若 `glBindFramebuffer(GL_FRAMEBUFFER, 0)` 落在了用户 framebuffer 上,或 wire 的默认
|
||
framebuffer 读回解析到了错的表面,三个探针读到的仍是蓝 / 0.5,这条腿**空过**。改为清成品红 `(1, 0, 1, 1)`、
|
||
深度 0.625——测试里没有第二张表面持有这对值(用户 FBO 蓝 / 0.5,源下红上绿 / 0.25 与 0.75)——三个探针要求
|
||
的就是这对值。
|
||
一次性证明(已还原):把探针前的绑定改成 `resolved.fbo`,`DirectVulkan.{Split,Spawn,Tcp}.MsFlip.` 三臂在
|
||
(1, 1) 两个 aspect 都红:`the declined COLOR|DEPTH scale onto the window must not have written its colour
|
||
at (1, 1)`,读到 `{0,0,255,255}`、要 `{255,0,255,255}`;`must have left its depth alone at (1, 1)`,
|
||
`depth evaluates to 0.50000005960464478`、要 0.625((64, 48) 与 (126, 94) 落在 64×48 的 FBO 之外,读到
|
||
`{0,0,128,0}` / 0.996,同样红)。round 3 的底色下同一改动读到的正是它要的蓝 / 0.5——这就是审查指出的空过。
|
||
还原后三臂 `Passed`。
|
||
|
||
**2. 门里一个到不了的合取项(nit)。** round 3 的门写成 `!SplitLane::IsSplitLane() &&
|
||
!PeekSplitRuntime().transportResolved`,并说「标记单独仍然有效」。标记那一项到不了:标记置位而传输未解析时,
|
||
fixture 的 SetUp 已经经 `SplitLane::SkipReasonForSplitOnlyAssertions()` → `SplitRuntimeSkipReason()`
|
||
(「MG_Config::Transport resolved to 'monolith', not to a split transport」)`GTEST_SKIP`,`Ready()` 为假,
|
||
用例在门之前就返回了。在每一个到得了的状态里,门都等于 `!PeekSplitRuntime().transportResolved`。已删掉
|
||
那一项(`SplitLane.h` 的 include 随之去掉),注释改述这一点,§2.10 第 1 条的原文保留为历史并加了指回。
|
||
行为不变:monolith `DirectVulkan.…AFlipped…` 仍 `Skipped`(同一文案),`{Split,Spawn,Tcp}.Full.…AFlipped…`
|
||
仍 `Passed`。
|
||
|
||
**3. §6 第 1、2、3 条改为按符号引用(nit)。** round 2 记的 `WireFramebuffer.inc:932-946` / `:878` /
|
||
`:1095-1125` 在 round 3 于它们上方加了七行之后已经全部错位。现在按 `BlitWireFramebuffers` 的 `blit` lambda
|
||
里的臂与 `MGLOG_E_ONCE` / `RecordTextureCopyError` 的文案引用;第 1 条里 monolith 那一处也改为
|
||
`VulkanRenderer::BlitFramebuffer` 里 `vkCmdResolveImage` 之后的 `vkCmdBlitImage`,不再带 `pipe` 行号。
|
||
|
||
本 round 只动这份笔记与一个测试源文件,不碰 `MG_Backend`,G1 不受影响。门见 §7 末尾的 round 4 一段。
|
||
|
||
---
|
||
|
||
## 3. 片 3:两处 `MagmaP7AllocatorDebtScope`
|
||
|
||
### 3.1 债是真的,但它早就没有对象了
|
||
|
||
隐藏的 blit 程序、它的两个采样器和隐藏的深度 mip 程序都是**前端对象**。在活动传输下,server 后端在
|
||
apply 线程上创建它们、也在 apply 线程上销毁它们,而它们的析构函数会跑 client 死亡助手和那个
|
||
lifetime-id 探针——所以 P5c 给这两处 teardown 一个具名豁免,P5e 裁定 12 把它按债重命名。
|
||
|
||
**退役它的不是一个新豁免,而是对象不存在。** P5f fv 早已给 `InitializeBlitResources` 和
|
||
`InitializeDepthMipmapResources` 加了非 monolith 传输的 early return,所以在 monolith 臂之外
|
||
`m_blitResources` 从不持有任何东西,`= {}` 什么也不销毁。这两个 scope 自那天起就是罩在一条跑不到的
|
||
路径上的标记。
|
||
|
||
### 3.2 证明,不是论证
|
||
|
||
两处 teardown 里放一个临时探针:在非 monolith 传输下任一资源非空就按名结束会话。武装着跑:
|
||
`integration-magma-split` 93、`-spawn` 72、`-tcp` 74、`integration-magma-full-split` 524、
|
||
`-full-spawn` 524、`integration-split` 187、`integration-magma-buffers` 21,**全绿,它一次都没响**。
|
||
|
||
**负对照才让这成为测量**:把探针的传输判据去掉,**每一条 monolith `DirectVulkan.` 条目都在 teardown
|
||
时死了**(8/8 abort,而且用例本身先 PASS 了),split 条目照样绿。
|
||
|
||
`integration-magma-full-tcp` 在探针下的那一条红是 CONTRACT-P7 §2.5 记过名的 StreamLink × Magma
|
||
曝光 texel(`IterationRPProgram203Scenario`),不是探针的死亡——它 Failed,不是 aborted。
|
||
|
||
### 3.3 对着 P5e 裁定 12 的「四笔债」重数
|
||
|
||
裁定 12 点了**四**处 Magma 站点(`VulkanRenderer.cpp` ×3、`ResourceTracker.h` ×1)。其中两处在 P7
|
||
开始前就没了——`git log -S` 把 `ResourceTracker.h` 那处记在 P5f fv(`4f3d2d6b`)、第三处
|
||
`VulkanRenderer.cpp` 记在 P5f fm(`036c3a3d`)——所以 P7 基线 `e8b2c4bd` 上只剩**两**处,就是本片
|
||
删掉的这两处。Magma 的 apply 线程分配器债现在是**零**处。
|
||
|
||
### 3.4 类型留下,并且写明了为什么
|
||
|
||
`MG_Test/Wire/RemoteClientTest` 的 `RemoteGuards.BarrieredLegacyScopesCannotExemptAllocator` 与
|
||
`.BarrieredFrontendRegistryMembersRefuseBothLegacyScopes` 拿它当**负对照**:在 apply 线程上构造它,
|
||
然后断言分配器**照样**拒绝。那是 P5f (fr) 立下的性质,删掉类就删掉了唯一钉住它的用例。
|
||
后端已无任何使用点。
|
||
|
||
---
|
||
|
||
## 4. 片 4:(B′),棘轮的 `p7-magma` 桶
|
||
|
||
### 4.1 做了什么
|
||
|
||
在 **disaggregated 构建**里,monolith 臂也改走烘焙模块:
|
||
|
||
- `InitializeBlitResources` / `InitializeDepthMipmapResources` → `return true`(无事可做);
|
||
- `TryBlitToDefaultFramebufferWithShader` → 把两个 `BlitImageBinding` 转成 `WireImage` 后调
|
||
`BlitWireColorToDefault`(`WireColorBlit.inc`);
|
||
- `GenerateDepthMipmapWithShader` → 逐级调 `GenerateWireDepthMipLevel`(`WireDepthMipmap.inc`),
|
||
收尾一次 `TransitionWireImage` 把图像交回调用方承诺的 `finalLayout`;
|
||
- `GetOrCreateBlitPipeline`、三段 GLSL 文本、八个 `kHidden*` id、`BlitResources` /
|
||
`DepthMipmapResources` 的前端成员:`#if !MOBILEGL_BUILD_DISAGGREGATED`。
|
||
|
||
**为什么是 `#if` 而不是运行时分支**,这正是 §4.2 的全部内容:P5f fv 的 early return 让符号**仍然被
|
||
引用**,棘轮不管那条分支跑不跑。把构造编译掉才让它们掉下来。而**成员也得走**,不只是构造:
|
||
`SharedPtr` 成员的析构本身就是一次对 `~ProgramObject` 的引用。
|
||
|
||
`#else` 分支逐语句原样,G1 钉住的就是它。
|
||
|
||
### 4.2 桶表:前 / 后
|
||
|
||
| bucket | before | after | a6 | 含义 |
|
||
|---|---:|---:|---:|---|
|
||
| `p6-core` | 11 | 11 | 6 | 没有后端对象引用:传输/applier 自己的账 |
|
||
| **`p7-magma`** | **101** | **88** | 101 | 只被 DirectVulkan 引用:P7 的账 |
|
||
| `p3b-p4b-espryt` | 13 | 18 | 14 | 只被 DirectGLES 引用 |
|
||
| `both-backends` | 61 | 56 | 60 | 两个后端都引用 |
|
||
| **合计** | **186** | **173** | 184 | |
|
||
|
||
`p3b-p4b-espryt` 的 +5 不是变坏:那 5 个符号从 `both-backends` **移**了过去,因为 DirectVulkan 不再
|
||
引用它们,只剩 DirectGLES。掉的是 13 个,合计 186 → 173。
|
||
|
||
**掉下来的 13 个**(`--assert-monotone` 逐条列名,随本片 `--write-baseline` 重基线,7 条
|
||
`# P13` 注解原样带过):
|
||
|
||
- `ProgramObject::{AllocateLifetimeId, AttachShader(...), Link(bool), ~ProgramObject}`(4)
|
||
- `SamplerObject::{SetLodRange, SetWrapR, SetWrapS, SetWrapT}`(4)
|
||
- `ShaderObject::{Compile, DropCompileNode, JoinPendingCompile, ReleaseCompileNode, SetShaderSource}`(5)
|
||
|
||
即 §4.2 点名的那三个前端类的全部构造面。
|
||
|
||
### 4.3 剩下的 88 个:逐个引用对象点名,以及为什么它们不是 (B′) 的
|
||
|
||
§4.2 写的「降到 0」**按实测不成立**,而且差距不在 (B′) 做没做完,在于桶里绝大多数符号**根本不是
|
||
隐藏程序引来的**。逐引用对象:
|
||
|
||
| 引用对象 | 数量 | 是什么,为什么还在 |
|
||
|---|---:|---|
|
||
| `Renderer/UniformManager.cpp.o` | 62 | monolith 描述符绑定器对**应用自己的** GL 纹理对象的遍历:`TextureObjectBase` 35、`TextureObjectWithOneMipmap` 20(含其 vtable / typeinfo)、四个 `TextureObject{1D,2D,2DCube,3D}` 各 1、`MGPipeNoteAggregate` 1。split 下 `SetupDraw` 分支到 `SetupWireDraw`,这条路一行都不跑——但那是**运行时**分支(ID-P7-5 明确把它留在优化阶段),所以符号仍被引用。清它要对 `UniformManager` 的 monolith 臂做和 (B′) 同形的 `#if`,是 wave 3 的活,不是本片的 |
|
||
| `Renderer/VkSamplerManager.cpp.o` | 9 | `SamplerObject::Get{BorderColor,BorderColorI,BorderColorUI,CompareMode,MinLod,SamplerCompareFunc,WrapR,WrapS,WrapT}`——同上,monolith 采样器缓存读应用的 `SamplerObject` |
|
||
| `UniformManager.cpp.o` + `VkSamplerManager.cpp.o` | 5 | `SamplerObject::Get{MagFilter,MaxAnisotropy,MaxLod,MinFilter,MipmapMode}`,同一条路的两个读者 |
|
||
| `Renderer/VulkanRenderer.cpp.o` | 3 | `GLImpl::CopyTextureImageToClientOrPBO_State`(monolith 回读打包)、`PipeInputs::HasOpenTransformFeedbackSpan`、`FramebufferAttachmentObject::IsValid` |
|
||
| `Renderer/VkTextureManager.cpp.o` | 3 | `PipeInputs::GetTextureObject`、`MGPipeTextureLegacyArmScope::{ctor,dtor}`——legacy 臂的具名 scope,P3b/P4b 的 |
|
||
| `BackendObject_DirectVulkan.cpp.o` | 1 | `PipeInputs::InvalidateCompileEnv` |
|
||
| `UniformManager.cpp.o` + `VulkanRenderer.cpp.o` | 1 | `BufferObject::EnsureGpuResidentStorage` |
|
||
| `VkClearManager` + `VkRenderPassManager` + `VulkanRenderer` | 1 | `FramebufferAttachmentObject::GetSize` |
|
||
| `VkRenderPassManager` + `VulkanRenderer` | 1 | `FramebufferAttachmentObject::IsComplete` |
|
||
| `Renderer/VkRenderPassManager.cpp.o` | 1 | `RenderbufferObject::IsAllocated` |
|
||
| `DirectVulkan.cpp.o` + `VulkanRenderer.cpp.o` | 1 | `VertexArrayObject::GetIndexBufferBindingSlot` |
|
||
|
||
**没有一个标 `# P13`**,而这是有意的:§4.2 的 `# P13` 是给「不动 pull `.text` 就消不掉」的符号准备
|
||
的,上面没有一个证明了这一点——`UniformManager` / `VkSamplerManager` 的 monolith 臂是**pull 构建
|
||
自己的代码**,对它们做 `#if MOBILEGL_BUILD_DISAGGREGATED` 与本片对 `VulkanRenderer.cpp` 做的是同一件
|
||
事,pull 构建逐字节不动。它们是 **wave 3 的工作量**,不是 P13 的边界问题。把它们提前标成 P13 会把一
|
||
件没人试过的事记成一件试过做不到的事。
|
||
|
||
### 4.4 门
|
||
|
||
`integration-gpu` **1705**(monolith `DirectVulkan.` 条目都在里面)、`integration-magma-split`
|
||
**93**、`-spawn` **72**、`-tcp` **74**、`integration-magma-full-split` **524**、
|
||
`ctest -L unit` **2423**,全绿。
|
||
|
||
`link_ratchet --assert-monotone` 对**重基线后**的文件:173 不变,RC 0。
|
||
|
||
**retrace(本片的关键读数,因为 monolith 臂在 disaggregated 构建里换了实现)**:
|
||
|
||
| case | ssim | mismatchPixels |
|
||
|---|---:|---:|
|
||
| `OpenRA.DirectVulkan`(monolith) | **1.000000** | 0 |
|
||
| `OpenRA.DirectVulkan.SPLIT` | **1.000000** | 0 |
|
||
|
||
整条 DirectVulkan 矩阵:monolith 39/40 绿、SPLIT 38/39 绿,两边红的是**同一条**
|
||
`minecraft-1.21.4-fabric-iris-iterationrp-in-world`(ssim 0.027915)。**已核实是既有的**:在包 B 的
|
||
树(`~/w7/p7-magma-b/build-retrace`,本分支的父提交)上同一条用例同样红。它要 CONTRACT-P7 §2.4 说的
|
||
三个 iterationRP 旋钮,而那三个是 CI 作业导出的、不是 ctest 条目自带的。
|
||
|
||
G1 pull `.text` **`0xa52203`**、`nm --defined-only` 与 `~/w7/p7-before/pull-syms.txt` 逐行相同
|
||
(30570 行,0 差异)——本片改的每一行要么在 `#if MOBILEGL_BUILD_DISAGGREGATED` 里,要么在
|
||
`#if !MOBILEGL_BUILD_DISAGGREGATED` 里而那一侧逐语句未动。
|
||
|
||
### 4.5 欠设备核对
|
||
|
||
monolith 臂在 **Android 的 disaggregated 包**里现在跑的是烘焙 blit。旋转(`ROTATE_90/180/270`)的
|
||
几何只有真机能看:`BlitWireColorImage` 的 `quarterTurn` 归一化与它替换掉的
|
||
`TryBlitToDefaultFramebufferWithShader` 的 `dstNormWidth/dstNormHeight` 是同一个算式,但本机每一个
|
||
表面都是 `IDENTITY`,这条等式没有被执行过。
|
||
|
||
---
|
||
|
||
## 5. 要手机的清单(本包全部的设备债)
|
||
|
||
1. **片 1**:旋转表面上的缩放多重采样 blit(本机只有 identity)。
|
||
2. **片 2**:没有 `VK_KHR_depth_stencil_resolve` 的设备上的 shader 深/模板 resolve——本机只能经
|
||
`MGITEST_MAGMA_FORCE_SHADER_DEPTH_RESOLVE` 到达。Adreno 830 是否带这两个扩展本身也要看一眼:
|
||
带,则这条臂在真机上同样只有旋钮可达;不带,则它是真机的**默认**臂。另看 renderbuffer 与
|
||
texture 的 D24S8 是否映射到同一个 `VkFormat`:不同则 `MsFlip.` 在跨格式 Y decline 上红(§2.6)。
|
||
3. **片 4**:`ROTATE_90/180/270` 下 monolith 臂的烘焙 blit 几何(§4.5)。
|
||
4. 包 B 遗留、本包未碰:非恒等旋转下的 `default-color-blit-shape` scratch 臂,以及
|
||
OpenRA 三次 `pm clear` 冷跑的 1.0 验收。
|
||
|
||
---
|
||
|
||
## 6. 记录债(写给 CONTRACT-P7 §12 的几行)
|
||
|
||
1. **缩放后的第二段没有裁剪**(`WireFramebuffer.inc`,`BlitWireFramebuffers` 的 `blit` lambda 里多重采样
|
||
颜色 resolve 臂的第二段:`vkCmdResolveImage` 进 resolve scratch 之后、`destination.isDefault` 的
|
||
`else` 分支那一次 `vkCmdBlitImage`。本节按符号引、不按行号——round 2 记的行号在 round 3 加行之后
|
||
已经错位一次,审查 round 4)。多重采样颜色 resolve 的第二段
|
||
`vkCmdBlitImage` 把目的矩形原样交给驱动;一个越出目的图像的矩形是
|
||
`VUID-vkCmdBlitImage-dstOffset-00248/00249`,不是一张被裁过的图。**这条与 monolith 臂共有**
|
||
(`VulkanRenderer::BlitFramebuffer` 多重采样颜色臂里 `vkCmdResolveImage` 之后的那次
|
||
`vkCmdBlitImage` 同样不裁),所以它不是分离缺陷,也不该由本包单独改;
|
||
两条臂一起裁是一件独立的活。
|
||
**部分生效(审查 round 2,已关)**:同一个缩放,mask 若是 `COLOR|DEPTH`,round 1 先由这条臂把颜色
|
||
缩放写进目的地,再由深度臂记 `INVALID_OPERATION`——出错的调用留下了一半效果,18.3.1 不允许。
|
||
现在缩放形状在任何 aspect 之前由 `DeclineWireDepthStencilResolveShape` 决定,整个调用报错、
|
||
什么也不写(§2.9 第 3 条,red-once 已做)。round 2 的预检漏掉了默认 draw framebuffer——同一个
|
||
缩放落到**窗口**上时颜色照样先写进 swapchain——round 3 补上(§2.10 第 2 条,red-once 已做)。
|
||
剩下的债只是上面的「不裁」。
|
||
2. **`MagmaWireFatal("multisample-resolve-region")`**(`WireFramebuffer.inc`,同一条多重采样颜色 resolve
|
||
臂在建 resolve scratch 之前的源区域检查)仍然对
|
||
**源矩形越出读缓冲**的 blit 带走会话。GL 对这种形状的承诺是「那些像素的值未定义」,不是一个
|
||
错误——所以正确的收口是 decline 或钳制,不是 Fatal。本包没有改它,因为它不带 `@P7`、也不是
|
||
§3.2 点名的行;记在这里。
|
||
3. **1 → N 的等矩形 decline**(`WireFramebuffer.inc`,`BlitWireFramebuffers` 的 `blit` lambda 里多重采样
|
||
**目的地**那一段,`source.samples == destination.samples` 的 `else`:`MGLOG_E_ONCE("… aspect 0x%x
|
||
cannot go from a %u-sample source to a %u-sample destination …")` 加
|
||
`RecordTextureCopyError(… "glBlitFramebuffer cannot change the sample count of an attachment in
|
||
that direction.")`;它前面同一段里的尺寸 / 格式 decline 是 `"… a blit onto a multisample attachment
|
||
carries no scale, no flip and no format conversion …"`,即第 10 条说的那一处)拒绝的是一个**合法**形状:
|
||
18.3.1 说单采样源写进多重采样目的地是**样本复制**。本包 decline 它,是因为 Vulkan 没有命令能
|
||
表达它,而 monolith 臂对同一形状的「可观测」是一次 VU 违规(`vkCmdBlitImage` 的两侧都必须是
|
||
单采样)——即没有一个正确的对照读数可抄。要真的实现它需要一条以目的地采样数建管线的 draw,
|
||
也就是 resolve 机器反过来再写一遍。
|
||
4. **tcp 车道带不了 server 端测试旋钮**(§2.7)。**七**条 knob 条目——`.ShaderMip1.` `.ShaderMip2.`
|
||
`.DepthMip.` `.DefaultBlitShape1.` `.MsResolve1.` `.MsFlip1.`(round 2 加的)以及 B3 合入时进表的
|
||
`.StaleSerial.`——因此只注册在 split + spawn,并在 `spawn_lane_parity.py` 的
|
||
`MAGMA_SERVER_ENV_KNOB_NO_TCP` 里具名(本分支没有 B3,它的门量到的是六条;落地树七条)。要收回这条,
|
||
`tcp_server_fixture.py` 得接受每用例的 server 环境——一个 supervisor 控制项。
|
||
5. **X 镜像与跨格式 Y 镜像的深/模板 resolve**(§2.8)decline。前者要逐 texel 的 region,后者要
|
||
`BlitDepthAcrossFormats`(与 monolith 共用)长出翻转。两者都不是一个片的体量。这两条 decline
|
||
拒绝的是**合法**的 blit,所以它们的 `INVALID_OPERATION` 是规则 I (a) 的具名拒绝,不是 GL 的答案。
|
||
**部分生效(审查 round 2,已关)**:round 1 在颜色 aspect 已经镜像写完之后才 decline 深度——颜色
|
||
镜像了、深度没动、再报一个 GL 不会报的错。现在**形状** decline 在任何 aspect 之前决定,整个调用什么也
|
||
不写(§2.9 第 3 条;默认 draw framebuffer 那一半是 round 3 关的,§2.10 第 2 条)。两种 decline 各有
|
||
自己的 once 站点。跨格式那条在 renderbuffer 与 texture 的 D24S8 映射到不同 `VkFormat` 的设备上会让
|
||
`MsFlip.` 变红(§2.6)。
|
||
6. **monolith `DirectVulkan` 臂的翻转 / 缩放多重采样深度 blit**(`VulkanRenderer.cpp:9594`、`:9608`,
|
||
落地树行号):翻转被拒(「depth blits with flipped rectangles are not supported yet」,目的地保持
|
||
清屏值、无错误),缩放被**执行**(GL 说是 `INVALID_OPERATION`)。这是一处 **wire 与 monolith 的
|
||
分歧**,且 wire 臂是更正确的一方;`AFlippedMultisampleResolve…` 在 monolith 条目上以具名理由
|
||
`Skipped`。monolith 的修正归 P13 / G1(G1 期间 pull 构建的 `.text` 不许动)。
|
||
7. **Espryt(DirectGLES,monolith 与 split 一样)的翻转 / 缩放多重采样深度 resolve**:翻转什么也不写
|
||
且不报错,缩放不报 `INVALID_OPERATION`。同一用例在 DirectGLES 条目上以具名理由 `Skipped`。
|
||
这是 **P3b / P4b** 的债。
|
||
8. **同尺寸、合法的 MSAA FBO → 默认 framebuffer 深/模板 blit 是会话 Fatal**(审查 round 3 记债,
|
||
未改)。`ResolveWireDepthStencil` 的区域判据(`WireFramebuffer.inc` 的 `destination.isDefault` 子句,
|
||
`Magma:multisample-depth-resolve-region`)对默认 draw framebuffer 一律 Fatal——而「把 MSAA 场景
|
||
resolve 到窗口、mask 里带 `DEPTH`」是标准写法,GL 允许,18.3.1 只要求尺寸相同。round 3 之后形状
|
||
decline 走在它前面(§2.10 第 2 条),所以现在只有**合法**的同尺寸形状还会撞到它:错误的形状 decline,
|
||
正确的形状带走会话。收口应是把默认 framebuffer 的深/模板图像当普通目的地走同一条 resolve 臂。
|
||
9. **scissor 把目的地裁空的 blit 静默返回,即便 GL 对该形状仍会报错**(审查 round 3 记债,未改)。
|
||
`BlitWireFramebuffers` 的 `clipAxis` 在裁空时直接 return,先于任何错误检查;而 18.3.1 的错误检查
|
||
(尺寸不同的多重采样 blit、格式不兼容等)与 scissor 无关——一次被 scissor 裁光的非法 blit 仍欠一个
|
||
`INVALID_OPERATION`。收口是把形状 / 格式的错误检查提到裁剪之前。
|
||
10. **MS → MS 的 blit 逐 aspect 决定**(审查 round 3 记债,未改)。`BlitWireFramebuffers` 多重采样
|
||
目的地那一段的 decline(尺寸、采样数、`source.format != destination.format`)写在逐 aspect 的
|
||
lambda 里,而格式相等是**每个 aspect 各自**的事实:一次 `COLOR|DEPTH` 的 MS→MS 调用可以复制颜色
|
||
(颜色格式相同)、再 decline 深度(深/模板格式不同)——与第 1、5 条同一类部分生效。§2.9 第 3 条 /
|
||
§2.10 第 2 条的预检只覆盖「多重采样源 → 单采样目的地」那条臂,不覆盖这段。
|
||
|
||
---
|
||
|
||
## 7. 审查 round 的门(本树一行;落地树是 integrator 的门)
|
||
|
||
round 1 的这一节把每个读数都记在「`5d896170`」上,而 `5d896170` 不是落地树的祖先(提交是被
|
||
cherry-pick 到落地树上的)。所以这里只记**本树**的读数,并点名量的是哪棵树:
|
||
|
||
- **本树**(合并前):`p7/magma-b2@1bf48cfb`,即 round 3 的两条代码提交之顶(round 2 的三条在它
|
||
下面);本节所在的文档提交只动这份笔记与 `VulkanRenderer.h` 的一条注释。下表在 `1bf48cfb` +
|
||
那条注释的树上量(即最终头的代码内容),并在最终头上重量一遍,读数相同。
|
||
- **落地树:integrator 的门。** 数字由 integrator 在合入后实测并维护,本笔记不引落地树的 SHA。落地树
|
||
上多了本分支没有的注册(例如 `DirectGLES.{Split,Spawn,Tcp}.ForcedDs.*`、`VerifySplit.`、B3 的
|
||
`.StaleSerial.` 条目),所以两棵树的 `integration-{split,spawn,tcp}` / `unit` / parity 读数不可互比。
|
||
|
||
| 门 | 本树 `p7/magma-b2@1bf48cfb` |
|
||
|---|---|
|
||
| `ctest -L unit` | **2423**,全绿 |
|
||
| `integration-split` | **187**,全绿 |
|
||
| `integration-spawn` | **103**,全绿 |
|
||
| `integration-tcp` | **106**,全绿 |
|
||
| `integration-magma-split` | **95**(94 + `MsFlip1.`),全绿 |
|
||
| `integration-magma-spawn` | **74**(73 + `MsFlip1.`),全绿 |
|
||
| `integration-magma-tcp` | **70**(`MsFlip1.` 不上 tcp),全绿 |
|
||
| `integration-magma-full-split` | **525**,全绿 |
|
||
| monolith `DirectVulkan.…AFlipped…` / `DirectGLES.…AFlipped…` | 均 `Skipped`,具名理由(§2.9 第 1 条、§2.10 第 1 条) |
|
||
| `DirectVulkan.{Split,Spawn,Tcp}.Full.…AFlipped…` | 三条 **`Passed`**(round 2 时 `Skipped`);`VerifySplit.` 见 §2.10 第 1 条(一次性 worktree 上 `Passed`,正式读数归 integrator 的门) |
|
||
| `spawn_lane_parity.py build-split` | RC 0;gated 档点名 6 条 `MAGMA_SERVER_ENV_KNOB_NO_TCP` 条目(落地树 7 条,含 B3 的 `.StaleSerial.`),每个 tail 恰好命中一条 |
|
||
| `fatal_census` | 79 / 44 / 0,RC 0 |
|
||
| `link_ratchet --assert-monotone` | 173 不变,RC 0 |
|
||
| G1 pull 构建 | RC 0,`.text` `0xa52203`,`nm --defined-only` 与 `~/w7/p7-before/pull-syms.txt` 0 增 0 减 |
|
||
| `@P7` | 19 行,全是注释 |
|
||
|
||
`scripts/data/link_ratchet_baseline.txt` 的 `base commit` 头注释指 `6af422b3`——173 是在那棵树上量出来的,
|
||
不是在 `4bee1313` 上;本 round 没有动它。
|
||
|
||
**round 4**(本树 `p7/magma-b2`,round 3 之顶再加两条提交:测试一条、笔记 + 测试一条;`MG_Backend` 一字未动,
|
||
G1 不受影响,所以上表的 G1 / ratchet / parity / `unit` 各行本 round 没有重量)。在 round 4 两条提交之顶量得:
|
||
`ninja -C build-split` rc 0;`integration-magma-split` **95** / `integration-magma-spawn` **74** /
|
||
`integration-magma-tcp` **70**,全绿;`DirectVulkan.{Split,Spawn,Tcp}.MsFlip.` 三条 `Passed`(探针指向
|
||
`resolved.fbo` 的一次性证明下三条全红,§2.11 第 1 条);monolith `DirectVulkan.…AFlipped…` /
|
||
`DirectGLES.…AFlipped…` 仍 `Skipped`(同一文案);`DirectVulkan.{Split,Spawn,Tcp}.Full.…AFlipped…` 三条仍
|
||
`Passed`;`fatal_census` 79 / 44 / 0,RC 0。
|