Files
MapLibreParticleLab/docs/报告/40_01_Android粒子最小正式闭环_Codex完成报告_v1.md
OpenAI Codex b0f855eb09
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
docs: record 40-01 closeout push
2026-09-02 09:07:09 +08:00

7.7 KiB
Raw Blame History

40-01 Android 粒子最小正式闭环 Codex 完成报告 v1

1. 执行结论

40-01 已完成 Stage A 实现、连续调试修复和 Stage B Android OpenGL x86_64 手工验收,正式状态为 PASS。

2. Git 基线

  • branch:particle/main
  • start commit:1ec44701146925dec9a87618e3f90bee9a12073f(docs: record 30-03 final push metadata)
  • 工作树:保留三份既有未跟踪任务书,不纳入本任务提交。
  • submodule:已记录,未修改。
  • git rerere.enabled:true。

初始 Stage A 实现提交:0b076c6d52fffb2ee4411cac64f06d43cea260c8(feat: establish android particle field rendering loop)。

本轮修正实现提交:39c7ae22ede51f4b755dc658e2e27b24b26b807e(feat: establish formal raster particle source chain)。

首次 push:成功,origin/particle/main 从 1ec447011 更新为 0b076c6d5。本报告保留 Stage A 初始提交与中间修复的历史事实;Stage B 文档收尾 commit、push 结果与最终远端 HEAD 在交付时记录。

3. 实际修改

  • 新增隔离的 mbgl::particle::OfflineFixtureParticleAdapter 与 backend-neutral ParticleFieldSnapshot,并新增正式 RasterArraySource -> RenderRasterArraySource -> RasterParticleLayer -> RenderRasterParticleLayer。正式 layer 为 Source::Required,不再由 source-less particle-validation 承担 40-01 闭环。
  • 新增确定性 uniform-east、uniform-north、vortex fixture 及生成脚本;metadata 遵循架构文档 v1 contract。
  • RenderRasterParticleLayer 复用已验证的 State A/B、Trail A/B、shared mask、camera transform、world wrap、antimeridian 与 canonical composite;没有新建 Android 侧或第二套 GPU 粒子引擎。历史 ParticleValidationLayer 仍可作 validation tool,但不是正式 source path。
  • Android Test App 将 fixture 打包进 src/main/assets/integration/particle-fixtures/,Style 使用 asset:// URI;Core 只通过 FileSource bytes loader,Linux helper 保留仓库 fixture 读取。
  • NoData cell 不再使整个合法 field 无效。GPU field alpha 保存 validity,State sampling 命中 invalid cell 会确定性 respawn;NaN/Inf 仍 fail closed。
  • 修复 STATIC/context recreation 的资源 bootstrap:field、mask、trail、state 和首帧 composite 均可在 STATIC 中建立,bootstrap 为零 simulation step。
  • Test App 保存 fixture selection,并增加 east/north 最小切换控制。

4. 构建与测试记录

  • Linux OpenGL 受影响对象编译:PASS。
  • C++ 格式、git diff --check、fixture JSON/生成/sha256:PASS。
  • adapter smoke test:PASS,三份普通 fixture 成功 decode/validate;nodata fixture 的单 cell invalid 标记被保留且 field 整体合法。Android asset 与仓库 fixture byte parity:PASS。
  • Stage A 阶段未运行 Gradle、APK 安装、ADB 或 Android 实机验证;Stage B 已由用户完成 Android OpenGL x86_64 手工验收,结果见第 5 节。

4.1 RasterArray 离线下载枚举接入修复

  • Android OpenGL 实际编译发现 OfflineDownload 的“required offline resource count”与“offline resource queue/download”两个穷尽 SourceType switch 漏掉 RasterArray。
  • 当前 RasterArraySource 只以 FileSource::request(Resource::source(...)) 读取 metadata 与 field;40-01 的 URL 是 APK asset://integration/particle-fixtures/...。其 Impl 未定义 tileset、zoom range 或 OfflineDownload 可管理的 URL/resource contract,因此这两个 switch 均增加显式 SourceType::RasterArray no-op,不增加资源计数或下载队列。
  • 未添加 default:;全仓非 vendor 的 SourceType switch 复核后,除本文件两个遗漏外均已处理 RasterArray。
  • Linux/Core 精确编译 offline_download.cpp.o(含 -Werror)、clang-format --dry-run --Werror 与 git diff --check:PASS。commit 和 push 结果在本轮交付中报告;状态继续为 WAITING_MANUAL_VALIDATION,未运行 Gradle 或 ADB。

4.2 RasterArray Source RenderItem 空指针修复

  • Android OpenGL 首次启动日志确认 fixture 已成功从 APK asset 加载、粒子 layer 已 evaluate,随后 Renderer::Impl::render() 在 State A/B 创建前发生 fault addr 0x0 的 SIGSEGV。
  • 根因是 loaded + needsRendering 使 RenderRasterArraySource enabled,但其 createRenderItem() 返回空指针;RenderOrchestrator 将该值放入 source item vector,RenderTree 随后无条件解引用。该全局契约不作容错放宽。
  • 修复在 RasterArray source 内按 ImageSource 生命周期准备并移交合法 no-op RenderItem:无 upload、无 render pass、无 particle draw。正式 GPU particle 绘制仍只属于 RenderRasterParticleLayer。
  • Linux/Core render_source.cpp.o 和含新增 RasterArrayRenderItem 的 source.test.cpp.o 均以 -Werror 精确编译;clang-format --dry-run --Werror、git diff --check 与全部 RenderSource createRenderItem() return audit 均通过。未运行完整 Linux 测试二进制、Android Gradle、ADB 或真机测试,状态仍为 WAITING_MANUAL_VALIDATION。

5. Stage B 最终 Android OpenGL x86_64 验收

用户已手工完成并确认以下全部 PASS:GLOBAL + ACTIVE + UNIFORM EAST;ACTIVE → STATIC → ACTIVE;UNIFORM EAST → UNIFORM NORTH → UNIFORM EAST;STATIC + OCEAN A/B Rotation 自动恢复;ACTIVE Rotation;Pan / Zoom / Bearing / Pitch;World Wrap;Antimeridian 双向跨越;GLOBAL / OCEAN A / OCEAN B;Shared Mask reuse;DISABLE / ENABLE;快速 Fixture 切换;最终重复 Rotation 回归。

同一 RenderThread/resource generation 内,GLOBAL、OCEAN_ONLY_A、OCEAN_ONLY_B 日志均复用相同 maskGeneration 并输出 reuse=true。graphics resource 重建后 generation 与 maskGeneration 可递增,这是新 GPU resource,不构成同一 generation 内重复创建。

6. 40-01 最终调试事实

  • OfflineDownload 两处 exhaustive SourceType switch 补入 RasterArray 的显式 asset-fixture no-op。
  • enabled RasterArray source 空 RenderItem 导致的 RenderThread SIGSEGV 已修复为 source 内合法 no-op RenderItem。
  • 处理过 Android APK / .cxx 旧 native 缓存观察问题。
  • 修复 per-source transient renderability 导致的 ACTIVE/STATIC reset loop,使 simulationFrame 与 A/B ping-pong 跨 frame 持久。
  • 正式 Composite 现在显示 Trail RGB;legacy validation 的 stripe/anchors/world-wrap 诊断显示仍保留。
  • shader 的唯一 source 为 GLSL,generated OpenGL header 经 generator 同步且幂等。
  • opaque RenderTarget clear 下 State 通过 stateSeeded 显式 seed;不再错误依赖 sampled alpha。
  • RasterArray snapshot generation 为跨 source instance 的 runtime revision;renderer 用 generation、fixtureID、dataVersion 三元 identity 阻止 east/north GPU field 误复用。
  • Rotation/Viewport STATIC 自动恢复完成并通过回归。

7. 范围外事项

40-01 的 Android OpenGL x86_64 范围已 PASS。iOS/Metal、Android Vulkan、真实在线数据、生产 coastline/mask、性能和独立 EGL context-loss 设备证据不在本次 PASS 声明范围。

8. 与指令书差异

此前报告错误地写为“无”:当时正式 Source/Layer/RenderLayer 链尚未建立,且 Android runtime fixture 仍错误依赖源码仓库相对路径。本轮已修正为正式 Source-required 链和 APK asset 输入边界;后续修复和 Stage B 实机证据现已使 40-01 正式 PASS。

9. Stage B Git 收尾

  • final Stage B closeout commit:8eaed68c45a99eaed60d2b0534b9f10949af8311
  • commit message:docs: close 40-01 android validation
  • push:成功,origin/particle/main 从 34cc5be26 更新到该 closeout commit。
  • remote branch:origin/particle/main;该次 closeout push 后 HEAD:8eaed68c45a99eaed60d2b0534b9f10949af8311。