Files
MapLibreParticleLab/docs/20_调查/STEP-048_下一阶段规划调查报告_v1.md
OpenAI Codex f095447678
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
docs: investigate next particle runtime stage
2026-09-04 10:39:15 +08:00

7.6 KiB
Raw Permalink Blame History

STEP-048 下一阶段规划调查报告

基线与方法

  • 分支:particle/main;本地和 origin/particle/main HEAD 均为 46dceb5cb6110c94393b7413465f843844dd6502。
  • 使用 Gitea API api/v1/repos/tei/MapLibreParticleLab/branches/particle%2Fmain 确认,不依赖网页缓存。
  • 工作区只有用户既有 untracked 任务书、日志和 STEP-046-e48fa087-review.diff;本调查不触碰它们。

当前实际结构

Core Runtime

  • src/mbgl/style/sources/raster_array_source.cpp 的 RasterArrayTimelineRuntime 持有 entries、cursor (t0/mix)、speed、state、gap/invalid、monotonic clock;play/pause/setSpeed/seek/step/recover 是低频 Core 命令。
  • 同文件的 RasterArraySource::updateRuntimeFieldWindow() 是已可作为正式输入窗口 API 的最小接入点:检查 validity/compatibility/content identity/generation,推进 T0/T1 并通知 source changed。advanceRuntimeFieldWindow()、repeatRuntimeFieldWindow() 和 controlRuntimeTimeline() 是 validation convenience/control 面。
  • tryInitializeTimeline() 目前将 initial/next/runtime fixture 解码为 6 个 Source-owned snapshot,Validation cache capacity=8;这是有界 validation preload,并非生产 forecast cache。
  • src/mbgl/renderer/layers/render_particle_validation_layer.cpp 的 RenderRasterParticleLayer 读取 RenderRasterArraySource::impl().field/nextField 或 shared timeline;Field identity 决定 GPU upload/reuse,window overlap 保留旧 T1 作为新 T0。其 ParticleGpuValidationTweaker::execute() State pass 负责连续 tick/UBO mix;无需 Android per-frame JNI。

RasterParticleLayer 与 Renderer

  • include/mbgl/style/layers/raster_particle_layer.hpp / src/mbgl/style/layers/raster_particle_layer_impl.hpp 定义正式 layer 和强类型 active、mask、timeMix、count、streak/trail/color properties。
  • GPU state/trail/field texture 生命周期在 render_particle_validation_layer.cpp 的 ParticleGpuResources;visual property 更新只更新 resources/UBO,不要求 Source reload。
  • Renderer 已是正式 raster-particle 路径,但同一实现文件仍含 validation coast mask、legacy validation display 和 fixture diagnostics。这些属于验证快捷路径,不应让 provider/network 进入 renderer。

数据输入边界

  • src/mbgl/particle/field/offline_fixture_particle_adapter.hpp/.cpp 的 ParticleFieldSnapshot 是 backend-neutral immutable value;包含网格、EPSG:4326 bounds、canonical U=east/V=north、NoData、dataVersion、generation、SHA-256、velocity/valid。
  • OfflineFixtureParticleAdapter::load(bytes) 已是纯 C++ bytes loader,但它强制 fixture-v1 schema 和 knownFixture()(east/north/vortex/nodata)。RasterArraySource::loadDescription() 从 FileSource 请求 metadata/field bytes,再调用它。
  • Android ParticleCoreLayerValidationActivity.kt::validationStyle() 拼 asset://integration/particle-fixtures/... 与 runtime fixture descriptors;Kotlin 是 Validation Host,不持有 T0/T1/tick/clock,但确实构造 synthetic fixture source。

Android/JNI 与 WeatherColorLayer

  • Android 的 Timeline 控制经 MapLibreMap → NativeMapView → native_map_view.cpp::controlRasterArraySourceTimeline() 低频进入 Source;没有 per-frame JNI。TIME/VIS/COUNT/MAP/MORE 都是 Test App 验证面,不应进入正式业务链路。
  • 当前仓库没有 WeatherColorLayer 实现类或 renderer 文件;它只出现在架构规范,故与当前 RasterParticleLayer 没有运行时 source/field/timeline 耦合。下一阶段不应实现或合并它。

Validation-only 技术债

状态栏自动 MIX、WAITING/INVALID 可观测性不够明显,已验证为 NON-BLOCKING。它适合未来有 Android 综合 APK 时顺带改善,不能单独触发一次 Android build,也不是 Timeline/Renderer failure。

候选阶段

候选 目标与价值 风险/冻结边界 Android 综合验收
A:Provider-neutral C++ Data Adapter 将 fixture-only decode contract 抽为通用 immutable snapshot adapter,保留 offline fixture adapter 为一个实现;使 Weather Service 未来可向 Source 提交数据而不进入 renderer。 中等;必须维持 snapshot identity、NoData、U/V、T0/T1/reuse/fail-closed。 高,适合一次验证 raw/in-memory T0/T1、A/B→B/C、invalid。
B:生产 Renderer 清理 从 renderer 中拆 validation coast/diagnostics。 高,容易触碰已验证 particle path,当前没有真实 data input 的收益低。 中等,不推荐现在做。
C:Validation UI 可观测性 状态行显示真实 playback state。 低但仅工具收益,不能单独编译。 仅作为 A 的附带项。
D:WeatherColorLayer 增加量化颜色层。 新模块且缺正式输入 contract,会提前耦合两层。 不推荐现在做。

推荐:STEP-048「Provider-neutral C++ Field Data Adapter 与 Runtime 输入契约」

英文短名:Field Data Adapter Contract。

目标

  1. 定义 provider-neutral C++ metadata+bytes → immutable ParticleFieldSnapshot adapter contract,解除 knownFixture() 对正式输入的限制。
  2. 保持 OfflineFixtureParticleAdapter 为 fixture-v1 validation implementation,不让 Android/asset API 跨入 Core adapter。
  3. 为 Source 增加面向已解码 snapshot/时间片描述的明确生产入口,复用现有 updateRuntimeFieldWindow() 的 T0/T1 identity、reuse、NOOP、fail-closed 语义。
  4. 为 invalid/incompatible/provider decode failure 给出明确 error,不污染当前窗口。
  5. 将 Validation UI observability 作为同一 APK 的小附带项,而非单独阶段。

不做什么

不接真实 HTTP/GRIB/provider/vendor;不改 Timeline clock、Particle Renderer/shader、GPU simulation、WeatherColorLayer、iOS/Metal/Vulkan、React Native、容量或独立 UI 重构。

最小修改面(预期)

  • Core:新增 src/mbgl/particle/field/ 下 provider-neutral adapter/interface 与定向 C++ tests;保留 ParticleFieldSnapshot ownership(adapter 创建 immutable value,Source 接管/复制一次)。
  • Source:raster_array_source.hpp/.cpp 仅增加显式 production submit/decode boundary;复用现有 runtime window API。
  • Renderer:不需要修改,除非为读取已经存在的 snapshot identity 做极小编译适配。
  • Android:Test App 仅增加一次可发现的 in-memory/provider-neutral validation scenario 与状态展示;JNI 只发低频 submit 命令,绝无 per-frame API。
  • 文档:STEP/报告/测试矩阵。

接口方向与生命周期

adapter 输入为 provider-neutral descriptor(logical timestamp、field type/domain/grid/vector/NoData/integrity)与 bytes;输出 immutable snapshot 或 structured decode error。Adapter 不拥有 GPU、Style、Renderer 或网络。Source 是当前 T0/T1/timeline authority;Renderer 只消费 snapshot/GPU textures。decode invalid、time interpolation incompatible、generation/content identity conflict 均 fail-closed,继续最后有效 window。

一次 Android 综合验收

Codex 完成完整批次后,用户在 Linux 一次构建,Windows 一次 copy/install,再在设备 192.168.1.146 用 adb -s 192.168.1.146 ... 验收:初始 provider-neutral A/B;A/B→B/C→C/D reuse/only-new-T1;duplicate NOOP;invalid/incompatible fail-closed/recover;PLAY/PAUSE/MIX/VIS/MAP 回归。命令设计为 Windows PowerShell/CMD,不依赖 Linux grep/sed/awk/tee。

结论

推荐直接编写 STEP-048 实现任务书。需要一个小型 C++ adapter contract(新模块/文件,非新 renderer 架构);不需要新的 Renderer、Timeline 或 WeatherColorLayer 架构。