diff --git a/docs/30_设计/STEP-058_WeatherLocalTargetFps与RepaintGate设计_v1.md b/docs/30_设计/STEP-058_WeatherLocalTargetFps与RepaintGate设计_v1.md new file mode 100644 index 000000000..ef1655811 --- /dev/null +++ b/docs/30_设计/STEP-058_WeatherLocalTargetFps与RepaintGate设计_v1.md @@ -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/设备验收另行执行。 diff --git a/docs/50_Step记录/STEP-058_WeatherLocalTargetFps与RepaintGate_v1.md b/docs/50_Step记录/STEP-058_WeatherLocalTargetFps与RepaintGate_v1.md new file mode 100644 index 000000000..5e3e7ac6e --- /dev/null +++ b/docs/50_Step记录/STEP-058_WeatherLocalTargetFps与RepaintGate_v1.md @@ -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 视觉连续性需实机确认。 diff --git a/docs/报告/STEP-058_WeatherLocalTargetFps与RepaintGate_Codex完成报告_v1.md b/docs/报告/STEP-058_WeatherLocalTargetFps与RepaintGate_Codex完成报告_v1.md new file mode 100644 index 000000000..c8ab4abfb --- /dev/null +++ b/docs/报告/STEP-058_WeatherLocalTargetFps与RepaintGate_Codex完成报告_v1.md @@ -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:待提交后记录 diff --git a/粒子开发记录.md b/粒子开发记录.md index 80a5f48da..b97246121 100644 --- a/粒子开发记录.md +++ b/粒子开发记录.md @@ -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 分支并误记为成功。