docs: record particle static freeze retest
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled

This commit is contained in:
OpenAI Codex
2026-08-30 07:33:39 +08:00
parent 364b8f381e
commit 625836fcaf
3 changed files with 192 additions and 0 deletions

View File

@@ -0,0 +1,100 @@
# 30-02 GPU Ping-Pong 与 Context Recreation 最小技术验证报告 v3
日期:2026-08-30
当前状态:`WAITING_MANUAL_VALIDATION`
## 1. 本轮实机发现
用户在 30-02 v2 对应 Android OpenGL APK 上完成 T3 检查并明确报告:
- STATIC 静止时,粒子/Trail 正常停止;
- STATIC 下拖动地图时,MapLibre redraw 会使 State/Trail 继续推进;
- 停止拖动后,State/Trail 再次停止。
因此原实现的 T3 判定为 `FAIL`。这是明确的设备运行事实;本报告不补写用户未提供的 frame 数值或日志数值。
## 2. 原因
原实现只在 `needsRepaint()` 中用 ACTIVE/STATIC 控制验证层是否主动请求下一帧,但 `RenderParticleValidationLayer::update()` 没有按 ACTIVE/STATIC 区分 GPU 工作。
地图 pan/zoom/bearing/pitch 会合法触发 MapLibre redraw;每次 redraw 都会再次执行原 `update()`,继而:
1. 注册 State write RenderTarget;
2. 注册 Trail write RenderTarget;
3. 设置 `pending=true`;
4. composite Tweaker 调用 `commit()`;
5. State/Trail slot 与 `committedFrame` 前进。
所以 `needsRepaint=false` 只能停止 validation 自己制造的连续帧,不能保证在其他合法地图帧中冻结 GPU simulation。
## 3. 最小修复
仅修改:
- `src/mbgl/renderer/layers/render_particle_validation_layer.cpp`
- `src/mbgl/renderer/layers/render_particle_validation_layer.hpp`(说明性注释)
修复内容:
- `update()` 在已有资源上先撤销上一帧注册的 RenderTarget,然后读取当前 evaluated ACTIVE 状态。
- STATIC 分支不注册任何 State/Trail RenderTarget,不创建 State/Trail update Drawable,并清除任何 `pending` swap。
- STATIC 只为主 LayerGroup 建立 `FrozenComposite` Drawable,采样最后一次已经 commit 的 `trailRead` texture。
- `FrozenComposite` Tweaker可以在当前 MapLibre translucent pass 更新 composite UBO/texture 并读取当前 viewport、zoom、bearing、pitch,但在调用 `commit()` 前明确返回。
- STATIC 的 shader frame 值使用当前 `committedFrame`,不预先计算为下一 simulation frame。
- STATIC 下即使 viewport 改变也不重建、清空或推进 Trail;冻结 texture 由主 pass 重新显示。恢复 ACTIVE 后,既有 ACTIVE resize 路径才重建 Trail。
- 如果 layer 从未有过 ACTIVE/已 commit Trail 就直接处于 STATIC,不创建或清屏离屏资源,也不显示未初始化 texture。
- ACTIVE 路径的 State A/B、Trail A/B、pass 顺序、hazard 约束和 slot commit 保持不变。
## 4. 静态控制流确认
以下事实已经从修复后源码确认:
- `AddRenderTargetRequest` 只存在于 STATIC 提前返回之后的 ACTIVE 路径。
- State/Trail `buildQuad()` 只存在于 ACTIVE 路径。
- `resources->pending = true` 只存在于 ACTIVE 路径。
- STATIC 进入时强制 `resources->pending = false`。
- `FrozenComposite` 在 Tweaker 内先返回,不可能落入 `resources->commit()`。
- STATIC composite 绑定 `trailTargets[trailRead]`,read/write slot 参数相同且没有 target attachment。
- MapLibre redraw 没有被阻止;主 LayerGroup composite 仍会在当前地图 render pass 中执行。
## 5. 静态检查
- C++ `clang-format --dry-run --Werror`:PASS。
- `git diff --check`:PASS。
- ACTIVE/STATIC、RenderTarget 注册、pending、commit 与 `committedFrame` 控制流检索:PASS。
- 编译、Android、Gradle、ADB、安装与运行:未执行,遵守用户要求。
静态检查只能证明代码路径,不替代 Android OpenGL 重测。
## 6. T3 重新验证
使用包含修复提交 `364b8f381e27eee36c4895084b2f0578a023fa61` 的新 APK:
1. 进入 `Particle Core Layer Validation`,保持 ACTIVE,确认 State/Trail 正常交替并记下最近一次 `commit frame=N`、State read slot 与 Trail read slot。
2. 点击 STATIC,确认日志出现:`STATIC frozen composite ... frame=N ... offscreenPasses=0 swap=false`。
3. STATIC 静止至少 3 秒,确认粒子/Trail 不推进。
4. STATIC 下连续执行 pan、zoom、bearing、pitch;地图必须正常移动和 redraw,冻结 Trail 可以随主 pass 重新显示。
5. 操作期间确认画面中的 marker/fade 不推进;不得出现新的 State pass、Trail pass、slot swap 或 simulation `commit frame` 增长。
6. 停止操作后仍保持冻结。
7. 点击 ACTIVE,确认 GPU ping-pong 从冻结的 State/Trail slot 继续,而不是在 STATIC 操作期间跳过 frame/index;继续运行到下一次节流日志,确认 frame 恢复增长。
8. 再执行一次 ACTIVE → STATIC → 地图手势 → ACTIVE,排除只在首次切换正确。
用户手工日志命令:
```bash
adb -s 192.168.1.146 logcat | grep -E 'ParticleValidation30_02|ParticleValidation'
```
## 7. 仍需完成的 30-02 验证
本轮只修复 T3。以下仍沿用 v2 的待验证状态:
- 修复后 T3 Android OpenGL 重测;
- T4 resize;
- T5 disable/enable;
- T6/T7 真实 context/surface recreation 与恢复;
- 无 stale resource/framebuffer corruption/crash;
- 最终完整 PASS 证据。
当前最终状态仍为 `WAITING_MANUAL_VALIDATION`,不得写 PASS,也不允许进入 30-03。

View File

@@ -0,0 +1,80 @@
# 30-02 GPU Ping-Pong 与 Context Recreation 验证 Codex 完成报告 v3
日期:2026-08-30
执行结论:`WAITING_MANUAL_VALIDATION`
## 1. 输入与判定
用户提供了明确 Android OpenGL 运行现象:STATIC 静止时停止,STATIC 地图拖动时 State/Trail 随 redraw 继续推进,停止拖动后又停止。原 v2 实现的 T3 因此为 `FAIL`。
本轮授权范围仅是修复 30-02 STATIC freeze;未重新执行其他测试,也未扩大到正式粒子、Mask、Vulkan、iOS 或 30-03。
## 2. Git 基线
- 分支:`particle/main`。
- 本轮开始 HEAD:`ba488f87027b3a53e7eb031e26c263c39a26bdc0`。
- 开始时本地与 `origin/particle/main` 同步,工作区干净。
- 30-01 仍为正式 `PASS`。
- 30-02 v1 BLOCKED、v2 Stage A 文档与全部历史提交均保留。
## 3. 原因分析
`needsRepaint()` 正确地在 STATIC 返回 false,但它只决定 validation layer 是否主动请求 MapLibre 下一帧。地图手势产生的合法 redraw 仍会运行 RenderLayer `update()`。
原 `update()` 无条件建立 State/Trail write pass、注册 RenderTarget、设置 pending;主 composite Tweaker又无条件尝试 commit。因此每个由地图手势产生的帧都会推进 GPU ping-pong。缺陷不在 MapLibre redraw,而在 validation GPU scheduling 没有把 ACTIVE 状态作为执行 State/Trail pass 的硬门槛。
## 4. 修改文件
- `src/mbgl/renderer/layers/render_particle_validation_layer.cpp`
- `src/mbgl/renderer/layers/render_particle_validation_layer.hpp`
- `docs/60_测试/30_02_GPU_PingPong与ContextRecreation最小技术验证报告_v3.md`
- 本完成报告
- `粒子开发记录.md`
没有修改 Test App、shader、通用 gfx、RenderTarget、Renderer 主循环或 style property。
## 5. 修复实现
- 新增 validation-only `FrozenComposite` pass mode。
- STATIC 有历史 Trail 时,主 pass 只采样当前已 commit 的 `trailRead`。
- STATIC 不注册 State/Trail RenderTarget,不运行 State update,不运行 Trail fade/marker update。
- STATIC 清除 pending;FrozenComposite Tweaker 在 `commit()` 前返回,不交换 slot、不增加 `committedFrame`。
- STATIC 仍在正常 MapLibre translucent render pass 内重绘 composite,并取得当前 viewport/zoom/bearing/pitch;没有阻止 pan/zoom/bearing/pitch redraw。
- STATIC resize 不重建 Trail,恢复 ACTIVE 后才由原 ACTIVE resize 路径处理。
- ACTIVE 恢复后沿用冻结时的 State/Trail read slot,继续既有 ping-pong。
## 6. 静态检查与未执行项
- `clang-format --dry-run --Werror`:PASS。
- `git diff --check`:PASS。
- GPU scheduling/commit 控制流检查:PASS。
- Android 编译、Gradle、ADB、安装、运行:未执行。
- C++ 编译:未执行。
严格遵守用户“不运行 Android 编译、Gradle 或 ADB”以及此前“不要编译”的要求。
## 7. 重新验证要求
技术报告 v3 第 6 节给出完整 T3 重测步骤。关键证据是:
- STATIC 日志显示固定 `frame=N`、固定 State/Trail read slot、`offscreenPasses=0 swap=false`;
- STATIC 地图手势正常,但 marker/fade、State/Trail pass、slot 与 simulation frame 不推进;
- ACTIVE 恢复后从 N 继续增长。
其他 T4–T7 项仍按 v2 执行。
## 8. Git 收尾
- STATIC 修复 commit:`364b8f381e27eee36c4895084b2f0578a023fa61`。
- commit message:`fix: freeze particle gpu state in static mode`。
- 修复 commit push:成功。
- 公开远端:`origin`(`ssh://git@192.168.200.230:2222/tei/MapLibreParticleLab.git`)。
- 远端分支:`particle/main`。
- 修复 push 后远端可见 HEAD:`364b8f381e27eee36c4895084b2f0578a023fa61`。
- v3 报告/开发记录收尾 commit 与最终远端 HEAD:按自引用规则在最终回复记录。
- 无未提交的无关修改。
## 9. 当前状态与范围
原 T3 实机结果已如实记为 FAIL;修复后的 T3 尚未由用户重测。因此 30-02 总体状态继续为 `WAITING_MANUAL_VALIDATION`,不得写 PASS,不允许进入 30-03。

View File

@@ -94,3 +94,15 @@
- 不允许进入 30-03;若无法确认真实 context recreation,最终应按指令书标记 `BLOCKED`。
- 技术报告:`docs/60_测试/30_02_GPU_PingPong与ContextRecreation最小技术验证报告_v2.md`。
- Codex 完成报告:`docs/报告/30_02_GPU_PingPong与ContextRecreation验证_Codex完成报告_v2.md`。
## 2026-08-30 — 30-02 T3 STATIC freeze 实机缺陷修复
- 用户 Android OpenGL 手工验证确认:STATIC 静止时 State/Trail 停止,但 STATIC 拖动地图触发 MapLibre redraw 时仍继续推进,停止拖动后再停止;原 T3 正式判定为 FAIL。
- 原因是 `needsRepaint=false` 只停止 validation 主动请求帧,而原 `update()` 在地图手势帧中仍无条件注册 State/Trail RenderTarget、设置 pending,并由 composite Tweaker提交 slot/frame。
- 最小修复在 `RenderParticleValidationLayer` 增加 STATIC frozen-composite 路径:地图主 pass 仍正常 redraw 并显示最后 commit 的 Trail,但不注册离屏 target、不执行 State/Trail update、不 fade/加 marker、不 swap、不增加 simulation frame/index。
- STATIC 下不因 resize 重建/清空 Trail;恢复 ACTIVE 后才继续原 ping-pong 与 resize 生命周期。
- 仅修改 validation RenderLayer `.cpp/.hpp` 和本轮文档;未修改 Test App、shader、通用 gfx、正式粒子、Mask、Vulkan 或 iOS。
- C++ 格式、diff 与 GPU scheduling/commit 静态控制流检查通过;按用户要求未编译,未运行 Android/Gradle/ADB。
- 修复后的 T3 等待用户在 commit `364b8f381e27eee36c4895084b2f0578a023fa61` 上重新手工验证;30-02 总体状态仍为 `WAITING_MANUAL_VALIDATION`,不允许进入 30-03。
- 技术报告:`docs/60_测试/30_02_GPU_PingPong与ContextRecreation最小技术验证报告_v3.md`。
- Codex 完成报告:`docs/报告/30_02_GPU_PingPong与ContextRecreation验证_Codex完成报告_v3.md`。