Files
MapLibreParticleLab/docs/60_测试/30_02_GPU_PingPong与ContextRecreation最小技术验证报告_v2.md
OpenAI Codex ba488f8702
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
docs: record 30-02 manual validation handoff
2026-08-29 21:27:45 +08:00

6.9 KiB
Raw Permalink Blame History

30-02 GPU Ping-Pong 与 Context Recreation 最小技术验证报告 v2

日期:2026-08-29

当前状态:WAITING_MANUAL_VALIDATION

1. 前置状态与本轮范围

  • 30-01 已由用户完成 Android OpenGL 实机验收并正式记录为 PASS;PASS 回填提交为 b34b0a3e22f91a0101b0bbd02190e3384f6ef2ae。
  • 历史 v1 报告的 BLOCKED 保留不改;它记录的是当时 30-01 正式状态尚未回填,不是 GPU/gfx 失败。
  • 本轮只准备 Android OpenGL 的 30-02 validation-only Stage A;未实现正式粒子、真实 Field、Mask、Vulkan 或 iOS。

2. 静态源码确认

以下是 Codex 可从源码确认的实现事实,不等同于设备运行结论:

  • RenderParticleValidationLayer 建立固定 16x16 的 State A/B 两套独立 RenderTarget,每帧从 read slot 采样并写入另一个 slot。
  • Trail A/B 是两套与当前 viewport 同尺寸的真实 RenderTarget;Trail pass 读取 previous trail,执行 0.965 fade 并加入移动 marker,随后由主 translucent pass 合成。
  • 正常帧只把 State write 与 Trail write 注册到当帧 render-target list;read target 不作为当帧附件,从结构上避免同一 texture 同时采样和写入。
  • 首帧或 Trail resize 后,新的 read target 先以空 group 清屏;注册顺序为 State 初始化/写入、Trail 初始化/写入,主 LayerGroup 随后合成最新 Trail。
  • ping-pong slot 在主 pass 的 Drawable Tweaker 到达时提交;此时当帧离屏 State/Trail pass 已按 RenderOrchestrator 的 render-target 顺序完成编码。
  • 每帧只更新小型 UBO;没有 CPU 回读或复制完整 State/Trail 数据。
  • viewport 改变时只重建 Trail A/B,State A/B 保持固定尺寸和当前状态。
  • layer 不可渲染时移除已注册 target 并重置 slot/frame;layer remove 会移除 target;context lost 会记录旧 generation 被丢弃,新的 RenderLayer/resource set 使用递增 generation。
  • shader 只注册到当前 OpenGL backend;没有修改 Vulkan、Metal 或 iOS shader/backend。
  • 没有修改 RenderTarget、CommandEncoder 或其他通用 gfx API;使用现有 createRenderTarget、render-target 顺序、pass end/present 与 texture sampling 链。

3. DrawableBuilder 生命周期

所有新 Drawable 都严格执行:配置 builder → flush(context) 完成当前 Drawable → clearDrawables() 转移已完成对象 → LayerGroup::addDrawable()。没有恢复 30-01 曾出现的“未 finalize 就 clear”错误,也没有通过空指针跳过 render pass。

4. 验证日志

日志关键字:ParticleValidation30_02。状态变化与第 1 帧/每 60 帧记录:

  • resource generation;
  • State/Trail A/B create、resize、destroy/context-lost;
  • frame、State read/write、Trail read/write;
  • order=State,Trail,Composite;
  • hazard=SAFE / distinct=true / cpuStateCopy=false;
  • viewport、zoom、bearing、pitch;
  • Test App ACTIVE、STATIC、DISABLED 状态。

日志是待用户采集的验证接口;本报告未伪造任何设备日志。

5. 静态检查结果

  • shader manifest JSON 解析:PASS。
  • shader 源生成并确认 OpenGL generated header、BuiltIn、manifest 注册存在:PASS。
  • C++ clang-format --dry-run --Werror:PASS。
  • git diff --check:PASS。
  • shader ID、UBO、attribute、texture、GL ShaderInfo 与 GL backend 注册符号一致性检索:PASS。
  • Android XML:已人工检查结构;环境缺少 xmllint/Ruby XML parser,未宣称解析器 PASS。
  • 编译、Gradle、Android 构建、安装、ADB、设备运行:均未执行,遵守用户“不编译”和指令书限制。

6. 用户手工编译与安装

当前 Makefile 的 x86_64 Test App OpenGL 命令为:

cd /mnt/sda1/MapLibreParticleLab
source /root/.maplibre-particle-env
cd platform/android
RENDERER=opengl BUILDTYPE=Debug JOBS=3 make android-x86-64

预期 APK:

platform/android/MapLibreAndroidTestApp/build/outputs/apk/opengl/debug/MapLibreAndroidTestApp-opengl-debug.apk

如需命令行安装,必须由用户手工执行:

adb -s 192.168.1.146 install -r platform/android/MapLibreAndroidTestApp/build/outputs/apk/opengl/debug/MapLibreAndroidTestApp-opengl-debug.apk

7. 用户手工运行步骤

  1. 打开 Test App,在主菜单顶部确认 APK 版本/Git revision,再进入 Custom Layer → Particle Core Layer Validation。
  2. 过滤日志:adb -s 192.168.1.146 logcat | grep -E 'ParticleValidation30_02|ParticleValidation'。
  3. T1 初始创建:确认 State A/B、Trail A/B create,generation 初值和 frame=1 commit;地图与蓝/黄顺序参照正常。
  4. T2 ACTIVE:保持至少 120 帧;确认 State 与 Trail 均 A/B 交替、frame 增长、轨迹 marker 移动/衰减且地图正常。
  5. T3 STATIC:点击 STATIC 并静置,确认 validation 不再主动推进;随后 pan/zoom/rotate/pitch,确认地图事件可触发 redraw,停止操作后不再持续推进。
  6. T4 resize:旋转屏幕或改变模拟器窗口尺寸;确认 Trail A/B resize old=... new=... StatePreserved=true,State A/B 没有重新 create,地图无异常。
  7. T5 disable/enable:点击 DISABLE,确认 layer/resource destroy 且停止;点击 ENABLE,确认新 generation 建立、slot/frame 从初始状态恢复,无 crash。
  8. T6 context/surface recreation:保持 App 进程存活,先 Home/Recent Apps 切出再返回;若没有出现 context lost discard,启用开发者选项“不保留活动”后离开并返回验证 Activity,或旋转触发 Activity/Surface 重建。仅界面重现不算成功,必须捕获旧 generation 的 context lost discard/destroy 和新 generation create。
  9. T7 recreation 后继续 ACTIVE 至少 120 帧;确认新 generation 的 ping-pong 恢复、Trail 从清空重新积累、无旧 generation 后续 commit、地图正常、无 crash/stale framebuffer。
  10. 保存完整关键日志和可见现象,回传给 Codex 进入阶段 B。

可选手工启动命令:

adb -s 192.168.1.146 shell am start -n org.maplibre.android.testapp/.activity.particle.ParticleCoreLayerValidationActivity

8. 当前证据边界与未验证项

  • 用户手工编译结果:未提供。
  • Android OpenGL 实际运行结果:未提供。
  • State/Trail 实机持续交替:未验证。
  • 当前 OpenGL driver 的 pass 同步/hazard:静态设计成立,尚无实机证据。
  • resize、disable/enable:尚无实机证据。
  • 真实 EGL context/surface recreation、旧资源失效与新 generation 恢复:尚无实机证据。
  • crash、framebuffer corruption、地图回归:尚无实机证据。

因此当前不能判定 PASS,也未发现可据以判定 FAIL 的运行证据;正式状态只能是 WAITING_MANUAL_VALIDATION。

9. 30-03 状态

不允许进入 30-03。必须先由用户完成上述 Android OpenGL 手工验证,并在阶段 B 将 30-02 正式更新为 PASS;若无法确认真实 context recreation,则按指令书判定 BLOCKED。