# 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 命令为: ```bash cd /mnt/sda1/MapLibreParticleLab source /root/.maplibre-particle-env cd platform/android RENDERER=opengl BUILDTYPE=Debug JOBS=3 make android-x86-64 ``` 预期 APK: ```text platform/android/MapLibreAndroidTestApp/build/outputs/apk/opengl/debug/MapLibreAndroidTestApp-opengl-debug.apk ``` 如需命令行安装,必须由用户手工执行: ```bash 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。 可选手工启动命令: ```bash 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`。