docs: record STEP-058 weather cadence

This commit is contained in:
OpenAI Codex
2026-09-07 14:55:38 +08:00
parent b9b3dd2253
commit 8a74a3c24e
4 changed files with 117 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
# STEP-058 Weather-local Target FPS 与 Repaint Gate 设计
## Host contract
`WeatherRuntime.TargetFps` 只提供 `AUTO`、`FPS_30`、`FPS_60`,默认 `AUTO`。`WeatherRuntime.setTargetFps()` 返回 typed `CommandResult`,`getTargetFps()` 返回当前 Host 选择。Host 不接触 RenderLayer、deadline、`needsRepaint()` 或 renderer `requestRender()` 细节;未来 RN 只包裹该 facade 方法。
## Shared cadence authority
天气 cadence 归 `RasterArrayTimelineRuntime` 所有,与 source 的 T0/T1、MIX、playback 共存。它保存 target mode、单一 monotonic last cadence tick、deadline 判定和低频 tick 计数。Particle 与 WeatherColor renderer 都读取同一 timeline authority;没有各自 timer 或 gate。AUTO 始终 due,30/60 使用约 33.33/16.67ms 间隔,且 target 切换重置 cadence deadline,不改变 Timeline/field/window。
`tick()` 仅在 deadline 到达时推进真实 `steady_clock` elapsed;不把 1/30 或 1/60 写入 simulation delta。这样 particle lifecycle、Trail fade、Timeline playback 和速度仍使用真实 wall time。
## Repaint 与 delayed wake-up
`RenderRasterParticleLayer::needsRepaint()` 与 `RenderWeatherColorLayer::needsRepaint()` 共享 source timeline 的 due 判定。Android `WeatherRuntime` 使用已有 `MapLibreMap.triggerRepaint()` 作为最小 delayed wake-up seam,在 READY 且至少一层需要天气持续动画时按目标间隔唤醒;AUTO 不安装天气 wake-up。Runtime disable/clear、两层 hidden 或错误状态会停止 wake-up。未使用 `MapView#setMaximumFps()`,因此 camera/其他 layer 仍可保持地图自身帧率。
地图高频 camera frame 在未到 deadline 时只重用现有粒子/Trail composite,不推进 State、Trail、Timeline 或 field upload;天气到 deadline 后两层再次消费同一 cadence。WeatherColor visibility 不依赖 particle visibility:Particle hidden + WeatherColor PLAY 仍可唤醒;两层 hidden、WeatherColor PAUSE 且 Particle hidden 时不持续唤醒。
## 动态修改与边界
target 切换仅更新 source/timeline cadence,不 reload Style、不重提交 field、不 reset particle State、不 clear Trail、不重建 field texture。clear/disabled 后 timeline 被清空,cadence naturally 无 due frame。Core 保留 canonical U/V、T0/T1/MIX、Runtime Field Window、OLD_T1→NEW_T0 reuse 与 only NEW_T1 upload。
## 测试策略
cadence deadline 通过显式 `steady_clock::time_point`/duration 的 deterministic 测试验证,不使用 sleep:AUTO always due、30/60 deadline 前后、target switch 和 single-authority 行为。Android popup 仅作为 Host 模拟器提供 FPS AUTO/30/60 与 HUD 显示;Android Gradle/设备验收另行执行。

View File

@@ -0,0 +1,33 @@
# STEP-058 Weather-local Target FPS 与 Repaint Gate
状态:`IMPLEMENTED / WAITING_ANDROID_VALIDATION`
Starting HEAD:`6d514e3aae68f579af41b10f85efe0f3b28784b2`,分支 `particle/main`。
## 目标
为天气粒子与 WeatherColor 建立 source-local AUTO/30/60 cadence 和 repaint gate,不限制全局 Map FPS,不进入 React Native package。
## 已完成
- `WeatherRuntime.TargetFps`、`setTargetFps()`、`getTargetFps()` typed Host API,经 `MapLibreMap → NativeMapView → JNI → RasterArraySource` 接线。
- `RasterArrayTimelineRuntime` 持有单一 target/deadline authority;Particle 与 WeatherColor 共用 due 判定,真实 `steady_clock` elapsed 驱动 Timeline、particle lifecycle 与 Trail fade。
- 未到 deadline 的地图高频帧不推进天气 State/Trail/Timeline;Android facade 使用既有 `triggerRepaint()` 低频 delayed wake-up,不调用全局 `setMaximumFps()`。
- REAL WEATHER popup 增加 FPS AUTO/30/60,HUD 显示当前选择;两层 visibility、PLAY/PAUSE、clear/disabled 的持续 wake-up 规则已收敛。
- 增加 deterministic cadence 测试,覆盖 AUTO、30/60 deadline、target 切换与单 authority。
## 保护与禁止范围
canonical field、field bytes、submit result、timestamp、playback、WeatherColor ramp、particle/trail color、OFF unload、hidden cleanup、Runtime Field Window、OLD_T1→NEW_T0 reuse、only NEW_T1 upload、simulation/trail reset 保护均未重写;未新增 RN/provider/route/ETA/Jest,也未使用全局 Map FPS cap。
## 验证
- throttle 下 Linux/OpenGL `mbgl-test-runner` 与 `mbgl-render-test-runner` 增量构建:PASS。
- throttle 下 deterministic cadence 测试 `Source.RasterArrayTimelineCadenceUsesOneSharedDeterministicDeadline`:PASS。
- throttle 下 `Source.RasterArray*` 定向测试:PASS。
- `git diff --check`:PASS。
- 未执行 Android Gradle、APK、ADB、设备/虚拟机测试或 Jest。
## 剩余风险
Android JNI/Java compile 与设备上 30/60 tick、camera 并发、visibility/off wake-up 仍需统一人工验收;天气 camera skipped-frame composite 的具体 GPU 视觉连续性需实机确认。

View File

@@ -0,0 +1,53 @@
# STEP-058 Weather-local Target FPS 与 Repaint Gate — Codex 完成报告
状态:`IMPLEMENTED / WAITING_ANDROID_VALIDATION`
## 实际完成
- `WeatherRuntime` 新增 typed `TargetFps.AUTO/FPS_30/FPS_60`、`setTargetFps()`、`getTargetFps()`。
- 接通 `MapLibreMap → NativeMapView → JNI → RasterArraySource`;Core `RasterArrayTimelineRuntime` 作为 Particle/WeatherColor 共用 cadence authority,保存 target、deadline 与低频 tick 计数。
- `needsRepaint()` 与 timeline due gate 统一;未到 deadline 时不推进 Timeline、State、Trail 或 field upload,camera frame 可重用已有 composite。
- Android facade 仅使用已有 `triggerRepaint()` 做 delayed wake-up,不使用 `MapView#setMaximumFps()` 或 Android 高频 polling。
- REAL WEATHER tuning popup 增加 FPS AUTO/30/60,HUD 显示当前 target;target 切换不 reload Style、resubmit field、reset simulation/Trail 或重建 field texture。
- 增加 deterministic non-sleep cadence 测试与 source 定向覆盖。
## 修改文件
- `include/mbgl/style/sources/raster_array_source.hpp`
- `src/mbgl/style/sources/raster_array_source.cpp`
- `src/mbgl/renderer/layers/render_particle_validation_layer.cpp`
- `src/mbgl/renderer/layers/render_weather_color_layer.cpp`
- `platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp`
- `platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp`
- `platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMap.java`
- `platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java`
- `platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java`
- `platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/WeatherRuntime.java`
- `platform/android/MapLibreAndroid/src/test/java/org/maplibre/android/maps/WeatherRuntimeStateTest.java`
- `platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt`
- `test/style/source.test.cpp`
- `docs/30_设计/STEP-058_WeatherLocalTargetFps与RepaintGate设计_v1.md`
- `docs/50_Step记录/STEP-058_WeatherLocalTargetFps与RepaintGate_v1.md`
- `粒子开发记录.md`
## 验证
- `ninja -C build-linux-opengl mbgl-test-runner mbgl-render-test-runner`(经 build-output-throttle):PASS。
- `mbgl-test-runner --gtest_filter='Source.RasterArrayTimelineCadenceUsesOneSharedDeterministicDeadline'`(经 throttle):PASS。
- `mbgl-test-runner --gtest_filter='Source.RasterArray*'`(经 throttle):PASS。
- `git diff --check`:PASS。
未执行 Android Gradle/APK、ADB、设备/虚拟机测试或 Jest。
## 设计边界与风险
天气 cadence 绑定 Source-owned timeline,未改变 canonical/T0/T1/MIX、Runtime Field Window、OLD_T1→NEW_T0 reuse、only NEW_T1 upload、simulation/trail reset 语义。Android delayed wake-up 与 JNI/Java compile、camera skipped-frame 的实际视觉连续性仍需人工验收;本报告不宣称 Android validated。
## Git
- Starting HEAD:`6d514e3aae68f579af41b10f85efe0f3b28784b2`
- 功能 commit:待提交后记录
- 文档 commit:待提交后记录
- Push:待提交后记录
- Remote branch:`origin/particle/main`
- Final HEAD:待提交后记录

View File

@@ -482,6 +482,12 @@ WeatherColorLayer 的 `ParticleGpuValidationUBO` designated initializer 补齐 `
- REAL WEATHER submit 使用 `FieldSubmitResult`/`accepted()` 与 enum 日志,不再依赖 `getCode()`;REAL WEATHER 的 playback/visual 不再回退到 MapLibreMap 低层入口,旧 fixture/diagnostic 路径继续保留。
- 本轮仅执行 `git diff --check` 与源码静态审计;未执行 Android Gradle、APK、ADB、设备测试或 Jest,状态为 `IMPLEMENTED / READY_ANDROID_COMPILE_CHECK`。
## 2026-09-07 — STEP-058 Weather-local Target FPS 与 Repaint Gate
- 新增 source-owned `RasterArrayTargetFps`(AUTO/30/60)与单一 `RasterArrayTimelineRuntime` cadence authority;Particle/WeatherColor 共用 monotonic deadline,真实 wall-time simulation、Timeline、T0/T1 window reuse 保持不变。
- Android `WeatherRuntime.setTargetFps()` 通过 typed MapLibreMap/JNI source setter 接线;使用已有 `triggerRepaint()` 做目标间隔 delayed wake-up,不使用全局 `MapView#setMaximumFps()`,REAL WEATHER popup 提供 FPS AUTO/30/60 与 HUD。
- 未到 deadline 的 camera frame 不推进天气 State/Trail/Timeline;两层 visibility、PLAY/PAUSE、clear/disabled 组合按 shared cadence 规则处理。Linux/OpenGL 增量构建与 deterministic/source 定向测试通过,Android Gradle/设备/Jest 未执行。
## 2026-09-07 — STEP-057D 审计后小修正
- 独立代码审计发现 REAL WEATHER 下 `WeatherRuntime` timeline 命令被拒绝时,TestApp 原条件表达式会跳过 reject 分支并误记为成功。