From 92953fe46daee7f622e4105b3f7ab7255d0f166b Mon Sep 17 00:00:00 2001 From: OpenAI Codex Date: Thu, 3 Sep 2026 18:26:46 +0800 Subject: [PATCH] docs: record runtime particle field updates --- .../STEP-045_Runtime_Field动态更新接口_v1.md | 35 ++++++++++++ ...untime_Field动态更新接口_Codex完成报告_v1.md | 54 +++++++++++++++++++ 粒子开发记录.md | 10 ++++ 3 files changed, 99 insertions(+) create mode 100644 docs/50_Step记录/STEP-045_Runtime_Field动态更新接口_v1.md create mode 100644 docs/报告/40-04_Runtime_Field动态更新接口_Codex完成报告_v1.md diff --git a/docs/50_Step记录/STEP-045_Runtime_Field动态更新接口_v1.md b/docs/50_Step记录/STEP-045_Runtime_Field动态更新接口_v1.md new file mode 100644 index 000000000..69eb41f22 --- /dev/null +++ b/docs/50_Step记录/STEP-045_Runtime_Field动态更新接口_v1.md @@ -0,0 +1,35 @@ +# STEP-045 Runtime Field 动态更新接口 + +- 状态:`IMPLEMENTED / WAITING FOR ANDROID VALIDATION` +- 前置:40-03 / STEP-044 已 `CLOSED / PASS`。 +- 范围:唯一正式链路 `RasterArraySource -> RasterParticleLayer -> GPU State/Trail/Composite` 的低频内存 Field 时间窗推进;不接网络或真实天气 Provider。 + +## 实现 + +- `RasterArraySource::updateRuntimeFieldWindow(ParticleFieldSnapshot)` 是正式强类型入口。它验证 Source 已加载、Snapshot 有效、grid/bounds/NoData 等插值契约兼容且 runtime generation 单调递增;成功时只把 Source 的权威窗口从 `T0/T1` 原子推进为 `T1/newT1`,并发出 `onSourceChanged()`。 +- 已有的 `RasterArraySource::Impl::field/nextField` 继续是正式 T0/T1 权威状态。Kotlin 不保存 T0/T1,JNI 不保存窗口或管理 renderer/GPU;Android 仅以 source id 调用薄桥 `advanceRasterArraySourceFieldWindow()`。 +- 为离线 Android 验证,Style 的 `runtime-fields` 在 Source 内预加载 C=`vortex`、D=`nodata`。`advanceRuntimeFieldWindow()` 只从该 Source-owned 队列取候选;候选资源完成顺序不影响 revision,因为 candidate 进入权威 T1 时才取得 process-wide generation。 +- A=`uniform-east`、B=`uniform-north`、C=`vortex`、D=`nodata`。因此两次按钮推进是 A/B→B/C→C/D;不调用 `setStyle()`,不重建 Layer/Source。 +- Renderer 继续使用已有 content identity 与双 Field slot:旧 T1 成为新 T0 时记录 `FIELD_REUSE from=OLD_T1 to=NEW_T0`;只有新 T1 按 `FIELD_UPLOAD reason=NEW_CONTENT` 上传。窗口有重叠时既有逻辑保持 `simulationRebuild=false`、`trailCleared=false`。 +- `raster-particle-time-mix` 未改,仍仅更新 Core paint property/UBO;它不上传 Field、不清 trail、不 reset simulation、不 reload Style。 + +## 失败与重复语义 + +- 当前 T1 内容重复提交:`NOOP`,不发出 Source change、upload 或 reset。 +- 缺失/非法 Snapshot、未加载 Source、不兼容 grid、非单调 generation、候选未完成或耗尽:`FIELD_WINDOW_UPDATE_REJECTED reason=...`,当前有效窗口和 simulation 原样保留。 +- 更新是低频事件;没有每帧 Field copy、hash、Snapshot 创建或 texture upload。 + +## Android 待验收 + +1. 点击 `TIME WINDOW` 建立 A/B,检查 MIX 0/50/100。 +2. 第一次 `ADVANCE`:检查 B→新 T0 reuse、只上传 C、没有 style/layer/source recreate、`simulationRebuild=false`、`trailCleared=false`。 +3. 第二次 `ADVANCE`:同样检查 C→新 T0 reuse、只上传 D。 +4. 在 C/D 再检查 MIX 0/50/100;Field upload/reset/trail clear 计数不应因 MIX 改变。 +5. 第三次 `ADVANCE` 应明确拒绝 `NO_PRELOADED_FIELD`,不中断当前窗口。 + +## 本地验证边界 + +- Linux/OpenGL 精确编译:`raster_array_source.cpp.o`、`style/conversion/source.cpp.o`、`source.test.cpp.o`。 +- 新增 Source 定向测试对象覆盖 A/B→B/C→C/D、重复 Snapshot NOOP、无效 Snapshot fail-closed,并已精确编译;当前 build tree 缺少大量无关测试依赖,未把完整 `mbgl-test` 二进制执行误报为通过。 +- 未运行 Android Gradle、ADB、APK 安装、设备测试或 Jest。 +- 实现提交:`45502a53f4fc486bd24cb0008d1ab0ff221e7e63`(`feat: add runtime particle field updates`);文档收尾另行提交。 diff --git a/docs/报告/40-04_Runtime_Field动态更新接口_Codex完成报告_v1.md b/docs/报告/40-04_Runtime_Field动态更新接口_Codex完成报告_v1.md new file mode 100644 index 000000000..705bfe231 --- /dev/null +++ b/docs/报告/40-04_Runtime_Field动态更新接口_Codex完成报告_v1.md @@ -0,0 +1,54 @@ +# 40-04 Runtime Field 动态更新接口 Codex 完成报告 + +## 状态 + +`40-04:IMPLEMENTED / WAITING FOR ANDROID VALIDATION` + +40-03 的 `CLOSED / PASS` 不变。本轮只交付运行中 Field 窗口推进接口;没有执行 Android 构建或实机验收。 + +## 完成结果 + +1. 正式 Runtime Field API 位于 `RasterArraySource`:`updateRuntimeFieldWindow(particle::ParticleFieldSnapshot newT1)`;验证辅助入口为 `advanceRuntimeFieldWindow()`。 +2. 参数是新的 immutable `ParticleFieldSnapshot`;它包含 fixture/content identity、dataVersion、runtime generation、grid、bounds、NoData、velocity 和 validity。 +3. 权威 T0/T1 是 `RasterArraySource::Impl::field/nextField`。 +4. Android/Kotlin 不持有 T0/T1;仅触发 source id 的 advance action,状态行也不复述具体 T0/T1。 +5. JNI 是薄桥:`MapLibreMap -> NativeMapView -> JNI -> Style::getSource() -> RasterArraySource`,不保存窗口、不做 Field 业务计算、不碰 GPU。 +6. A/B→B/C 时 Source 输出 old T1(B) 为 new T0;renderer 的 SHA-256/content identity 命中旧 T1,复用其 texture。 +7. B/C→C/D 同理,旧 T1(C) 成为 new T0。 +8. 正常推进只上传一个新 Field;旧 T1 的 GPU resource 被复用。 +9. 正常推进不 Layer recreate。 +10. 正常推进不 Style reload。 +11. 重叠窗口不 reset simulation,renderer 日志为 `simulationRebuild=false`。 +12. 重叠窗口不 clear trail,renderer 日志为 `trailCleared=false`。 +13. MIX 保持既有 property-only Core setter/UBO 路径,与 Runtime Field update 解耦。 +14. 重复当前 T1 内容为 `NOOP`;重复队列推进耗尽为明确 `NO_PRELOADED_FIELD` reject,均不产生 upload/reset。 +15. 无效、未加载、不兼容或 non-monotonic Snapshot fail closed,记录 `FIELD_WINDOW_UPDATE_REJECTED reason=...`,不替换当前窗口。 +16. 不存在每 frame Field copy/hash/upload;候选仅在 source asset 加载后缓存,runtime generation 仅在候选真正进入 T1 时分配。 +17. 未修改 full particle draw;仍是 40-03 已验收的 `State N -> draw N -> Trail -> Composite`。 +18. 本地检查:受影响 Linux/OpenGL Core、conversion 与 `source.test.cpp.o` 精确 `-Werror` 编译;新增定向 Source test 对象覆盖窗口两次推进、NOOP、invalid fail-closed。当前 build tree 缺少大量无关测试依赖,完整 `mbgl-test` 会触发全量重建,故未将其二进制执行误报为通过;`clang-format --dry-run --Werror` 与 `git diff --check` 通过。 +19. 等待 Android 手工验证:A/B、B/C、C/D 的 reuse/upload/no-reset/no-clear、C/D MIX、候选耗尽拒绝,以及 Android toolchain 编译。 +20. 实现 commit hash:`45502a53f4fc486bd24cb0008d1ab0ff221e7e63`。 +21. commit message:`feat: add runtime particle field updates`。 +22. push 结果:待文档收尾 commit 后推送至 `origin/particle/main`。 +23. `origin/particle/main` 最终 HEAD:待 push 后在交付记录中确认。 + +## Android 验证入口与日志 + +`TIME WINDOW` 加载 A=`uniform-east` / B=`uniform-north` 并由 Source 预加载 C=`vortex`、D=`nodata`。每次 `ADVANCE` 不调用 `setStyle()`:Core 记录 `FIELD_WINDOW_UPDATE_REQUEST` 和 `FIELD_WINDOW_UPDATE_APPLIED`,renderer 记录 `FIELD_REUSE from=OLD_T1 to=NEW_T0`、新内容的 `FIELD_UPLOAD reason=NEW_CONTENT` 以及 `simulationRebuild=false trailCleared=false`。第三次 advance 应只见 reject,不影响当前 C/D。 + +## Windows 11 手工验证 + +```powershell +cd /mnt/sda1/MapLibreParticleLab/platform/android +./gradlew :MapLibreAndroidTestApp:assembleOpenglDebug -Pandroid.injected.build.abi=x86_64 --console=plain +adb -s 192.168.1.146 install -r .\MapLibreAndroidTestApp\build\intermediates\apk\opengl\debug\MapLibreAndroidTestApp-opengl-debug.apk +adb -s 192.168.1.146 logcat -c +adb -s 192.168.1.146 shell am start -n org.maplibre.android.testapp/.activity.particle.ParticleCoreLayerValidationActivity +adb -s 192.168.1.146 logcat -v time ParticleValidation:I ParticleField:I ParticleGPU:I "*:S" +``` + +依次点击 `TIME WINDOW`、`MIX 0/50/100`、`ADVANCE`、`ADVANCE`,然后在 C/D 再点击 MIX 0/50/100。记录两次 `FIELD_REUSE from=OLD_T1 to=NEW_T0`、每次恰一条新内容 upload、无 Style reload/layer recreate/reset/trail clear;第三次 `ADVANCE` 应为 `NO_PRELOADED_FIELD` 拒绝且 C/D 继续运行。 + +APK 路径:`./MapLibreAndroidTestApp/build/intermediates/apk/opengl/debug/MapLibreAndroidTestApp-opengl-debug.apk`。 + +Android Gradle、ADB、实体机和 Jest 均未由 Codex 执行。 diff --git a/粒子开发记录.md b/粒子开发记录.md index d9e90e243..63e26e27c 100644 --- a/粒子开发记录.md +++ b/粒子开发记录.md @@ -282,3 +282,13 @@ - count change 仅重建 State/full draw resources,未引入 Field upload、Style reload 或 MIX 改变;40-02 的 MIX property-only 与时间窗 Field reuse(`simulationRebuild=false`、`trailCleared=false`)保持。 - 已验证容量 **≥ 1M**,满足当前项目需求,不再扩展 2M/4M/8M 压测。1M 是本验证设备上的已验证容量,不是理论最大值、硬编码产品默认值或所有 Android 设备的统一保证。 - 本收尾只回填文档;Codex 未运行 Android Gradle、ADB、设备测试或 Jest,也未修改功能代码。 + +## 2026-09-03 — 40-04 Runtime Field 动态更新接口(STEP-045) + +- 正式 Runtime Field 更新入口落在 `RasterArraySource`:`updateRuntimeFieldWindow(ParticleFieldSnapshot)` 把 Source 权威窗口由 `T0/T1` 推进为 `T1/newT1`,并通过既有 Source observer 通知正式 RasterParticle renderer;没有 Style reload、Source/Layer recreate 或第二套 Field/GPU 系统。 +- `RasterArraySource::Impl::field/nextField` 继续是唯一正式 T0/T1 权威状态。Android Validation 只通过 `MapLibreMap -> NativeMapView -> JNI -> Style::getSource()` 薄桥请求 advance;Kotlin/JNI 不保存窗口,不操作 renderer 私有资源。 +- 离线验证初始 A/B 为 uniform-east/uniform-north;Source 自己预加载 C=vortex、D=nodata。候选在真正进入 T1 时才获得 process-wide runtime generation,避免异步 asset 完成顺序造成 stale/non-monotonic revision。 +- 既有 renderer content identity/slot ownership 未改:A/B→B/C 和 B/C→C/D 都复用 OLD_T1 作为 NEW_T0,只上传新 T1,保留 simulation 与 Trail(`simulationRebuild=false`、`trailCleared=false`)。MIX 仍是 property-only,不参与 Field update。 +- 重复当前内容明确 NOOP;无效、未加载、不兼容、非单调或无候选更新 fail closed,不污染当前有效窗口。没有每帧 Field copy/hash/upload,也未修改 40-03 full particle draw。 +- Linux/OpenGL 受影响 Core/conversion/source test object 精确编译;定向窗口推进 test object 覆盖已加入,完整 `mbgl-test` 因 build tree 缺失大量无关依赖未执行,未将其误报为通过。格式与 diff 检查结果在完成报告收尾记录。未执行 Android Gradle、ADB、APK、实体机或 Jest;当前状态仅为 `IMPLEMENTED / WAITING FOR ANDROID VALIDATION`。 +- 实现提交:`45502a53f4fc486bd24cb0008d1ab0ff221e7e63`(`feat: add runtime particle field updates`);文档收尾提交另行记录。