Files
MapLibreParticleLab/docs/报告/40_01_Android粒子Simulation生命周期修复_Codex完成报告_v1.md
OpenAI Codex 300f70f1d4
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
docs: record lifecycle push result
2026-09-01 19:59:09 +08:00

5.2 KiB
Raw Permalink Blame History

40-01 Android 粒子 ACTIVE / STATIC Simulation 生命周期修复 Codex 完成报告 v1

1. 结论

已修复 Android 40-01 的跨 render simulation 生命周期错误。40-01 状态保持 WAITING_MANUAL_VALIDATION;本报告不声明 Android 实机验收 PASS。

2. 实际根因与调用链

  • 日志 ParticleValidation30_02: disabled reset generation=... 的唯一打印方是 src/mbgl/renderer/layers/render_particle_validation_layer.cpp 中 RenderRasterParticleLayer::markLayerRenderable()。
  • RenderOrchestrator::createRenderTree() 按 source 依次计算 layer 可渲染性。Test App style 同时有 raster-array fixture source 与其他 source;处理不匹配 source 时会临时向粒子 layer 传入 willRender=false,处理匹配的 RasterArray source 后同一 render tree 又传回 true。
  • 原 override 把这个 source-scoped 的临时 false 误认为持久 disabled:移除 target、清空注册并执行 ParticleGpuResources::resetSequence()。因此 committedFrame(simulationFrame)每个 render 都从 1 重新开始,State A/B 与 Trail A/B read slot 每帧都回到 A,seed 状态也被清除;STATIC 因而每帧重新 bootstrap。

3. 修复内容

  • 仅修改 src/mbgl/renderer/layers/render_particle_validation_layer.cpp。
  • markLayerRenderable() 现在只调用基类实现;不在按 source 的 transient false 中重置粒子资源。没有修改通用 RenderOrchestrator,保持“最终 enabled RenderLayer 才 update”的既有契约。
  • ParticleGpuResources 仍由 RenderRasterParticleLayer::gpuResources 共享持有,故 committedFrame、State/Trail read slot、seed 标记、targets 与 resourceGeneration 均跨 render() 持久存在。
  • resetSequence() 补充清除未提交 bootstrap 标记与 static freeze sampled-log 标记,确保真实 reset 后的状态完整一致。
  • 新增一次性 ACTIVE/STATIC transition 日志(generation、fixture、simulationFrame、State/Trail read slot);schedule/pass/commit 改为记录前 3 帧和每 60 帧,便于确认 1→2→3 与 A→B→A,同时避免正常运行的 reset 日志洪水。

4. 修改后生命周期

  • ACTIVE:新资源、fixture/field generation 切换、context loss 后资源重建等真实事件可重置;其余连续 render 保留状态并执行 State → Trail → Composite,commit 后 frame 与 A/B slot 正常推进。
  • STATIC:仅当 State/Trail 尚未 seed(首次创建或真实资源事件)时执行一次 zero-step bootstrap;已经有 committed state 时只生成 FrozenComposite,不注册 State/Trail target、不 commit、不增加 frame。
  • ACTIVE→STATIC:保留已有 simulation,进入 frozen composite;如资源尚未 seed,则进行一次必要 bootstrap。
  • STATIC→ACTIVE:沿用既有保存的 frame 和 ping-pong slot 继续 simulation,不再每帧回到 frame 1。

真实失效条件未扩大:fixture/field generation 改变会调用既有 resetSequence();viewport 改变会按既有逻辑重建 Trail A/B;context loss 丢弃 resource 并生成新 generation;layer removal 清理已注册 targets。没有改变 State/Trail ping-pong 结构、fixture contract、resourceGeneration contract、public API、shader、mask、camera/world-wrap/antimeridian 或 GPU pass 顺序;30-02 的 hazard=SAFE 约束仍由原有 distinct read/write targets 与 State,Trail,Composite 排程维护。

5. 代码级自检

  • ACTIVE 连续 render 不再从 markLayerRenderable(false) 调用 disabled reset。
  • simulationFrame/State A-B/Trail A-B 在 ParticleGpuResources 中,并由 layer 的 gpuResources 跨 render 持有。
  • ACTIVE 日志采样可显示 simulationFrame=1,2,3。
  • State 与 Trail 的读写 slot 在每次 commit 以 1-read 交替。
  • STATIC bootstrap 受 !stateSeeded || !trailSeeded 限制,seed 后使用 FrozenComposite。
  • STATIC→ACTIVE 不执行 transient disabled reset,保留现有 frame/slot。
  • field generation、viewport、context、layer removal 的现有资源处理仍保留。
  • State,Trail,Composite 的既有 pass 排程与 hazard=SAFE 检查未变。

6. 构建与交付

  • Linux OpenGL 精确编译:ninja -C build-linux-opengl CMakeFiles/mbgl-core.dir/src/mbgl/renderer/layers/render_particle_validation_layer.cpp.o,PASS。
  • clang-format、git diff --check:PASS。
  • Android OpenGL Debug APK:cd platform/android && ./gradlew :MapLibreAndroidTestApp:assembleOpenglDebug -Pmaplibre.abis=x86_64 --console=plain,PASS(BUILD SUCCESSFUL)。APK 为约 696 MB,归档内 native ABI 仅为 x86_64。
  • 最终代码修复 commit:c222b9a3d26dfb548b2528b3088c7c6799832dc9(fix: preserve particle simulation lifecycle)。
  • push:成功;remote branch:origin/particle/main。完成报告与 Step/开发记录作为同一任务的后续文档提交一并推送。

7. 用户手工验收

请使用本轮生成的 platform/android/MapLibreAndroidTestApp/build/outputs/apk/opengl/debug/MapLibreAndroidTestApp-opengl-debug.apk 安装到 x86_64 测试设备,只验收:GLOBAL + ACTIVE 持续 10–15 秒可见运动;ACTIVE→STATIC 冻结;STATIC→ACTIVE 后再次持续运动。不要将本报告视作已完成 ADB/真机验收。