fix: use float particle state targets
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled

This commit is contained in:
OpenAI Codex
2026-09-05 09:08:14 +08:00
parent 37c9aa31da
commit f0f0623e06
9 changed files with 175 additions and 12 deletions

View File

@@ -0,0 +1,30 @@
# STEP-055 Android 真实 WeatherV2 风场综合可视化 v2
状态:**IMPLEMENTED / WAITING_ANDROID_VALIDATION**
Starting HEAD:`37c9aa31da1d2b3495c8802e6fd2f6b999562b06`
## 本轮问题与根因
Android 已确认真实 WeatherV2 Field、Host submission、WeatherColorLayer、Timeline State A/B 调度、非零 U/V 与非零 m/s→Web Mercator 位移均存在,但 Timeline Pause 下粒子仍肉眼静止。
根因是 Particle State A/B 与 Trail A/B 共用 `createValidationTarget()` 的 `UnsignedByte` target。State RG 保存的是 Web Mercator world position;RGBA8 的一个量化步长约为 `1/255=0.00392 world`,远大于日志中每个真实 Weather simulation step 的 `0.000003–0.000008 world`,写回后不能累积有效位移。
## 修复
- State A/B target 改为 `TextureChannelDataType::Float`,包括初次创建、context/resource recreation 和 particleCount 变更的 replacement targets。
- Trail A/B 保持 `TextureChannelDataType::UnsignedByte`,继续是 viewport-sized 颜色/透明度 target;没有升级 WeatherColorLayer 或任意无关 full-screen target。
- `RenderTarget` 新增 `isRenderable()`,在 Particle target 创建时立即驱动现有 `OffscreenTexture → GL texture → framebuffer` 创建/检查。Android OpenGL 已有映射链为 `Float → RGBA32F + GL_FLOAT → glFramebufferTexture2D → checkFramebuffer()`;无需新增 backend 抽象。
- Float State FBO 不能创建时不回退到 UByte:`ParticleStateTarget: event=CREATE_FAILED ... dataType=Float` 后停止该 State resource 创建;count change 同样明确返回 `STATE_RESOURCE_CREATE_FAILED dataType=Float`。
- 每个成功 target 输出 `CREATE_SUCCESS`,Trail pair 就绪时另输出一次 `ParticleStateTarget: stateAType=Float stateBType=Float trailAType=UnsignedByte trailBType=UnsignedByte`。
- Shader 注释校正为 State RG 保存 `Web Mercator world position`,不是 field-normalized position。
## 冻结边界
未修改 canonical Field、STEP-054 assets、Host Submission Contract、Timeline、Playback、Runtime Field Window、WeatherColorLayer、U/V=m/s 或 `visualSpeedScale=6000`。继续保持 Timeline Pause 只冻结 forecast 时间、Particle simulation 在当前 Field 中运行;Window reuse、NEW_T1-only、MIX property-only、normal boundary `simulationRebuild=false` / `trailCleared=false` 不变。
## 验证与待验收
已执行 shader 生成、Linux OpenGL 受影响 Core 精确编译、相关测试源精确编译和 `git diff --check`;未执行 Android Gradle/APK/ADB/App/设备或 Jest。
下一轮人工验收的第一优先项是:进入 REAL WEATHER、保持 Timeline Pause,确认 Float State 类型日志后粒子中心位置连续运动。若仍完全不动,停止调节 6000,改以单独任务调查 GPU State readback / State Update→Draw 链。

View File

@@ -0,0 +1,35 @@
# STEP-055 Android 真实 WeatherV2 风场综合可视化人工验收 v3
状态:等待用户手工 Android 验收。Codex 不执行 Android Gradle、APK、ADB、App 启动或设备测试。
## Windows 11 构建与日志
在 Windows 11 项目目录手工执行:
```powershell
./gradlew :MapLibreAndroidTestApp:assembleOpenGLDebug --console=plain
adb -s 192.168.1.146 install -r <APK_PATH>
adb -s 192.168.1.146 logcat -c
adb -s 192.168.1.146 logcat | findstr /I "ParticleStateTarget ParticleMotion REAL_WEATHER ParticleTimeline FIELD_REUSE FIELD_UPLOAD simulationRebuild trailCleared"
```
## 第一优先:State 精度
1. 进入 `Particle Core Layer Validation → REAL WEATHER`,确认 GSI、真实色场、HUD 默认 `P 2048 · W 0.75 · L 0.0040 · O 0.75 · T 0.55 · F 0.88`。
2. **不要点击 PLAY,或在 `TIME → PAUSE` 后观察。** Particle position 必须在固定真实风场中连续、明显移动;Timeline cursor/MIX 冻结不应暂停 simulation。
3. 日志必须有:
```text
ParticleStateTarget: stateAType=Float stateBType=Float trailAType=UnsignedByte trailBType=UnsignedByte
ParticleStateTarget: event=CREATE_SUCCESS kind=STATE dataType=Float
ParticleMotion: ... sampleU=... sampleV=... dt=... visualSpeedScale=6000 estimatedStateDeltaWorld=...
```
4. 若有 `CREATE_FAILED kind=STATE dataType=Float`,记录完整错误;Particle State 应 fail-closed,不得静默以 UByte 继续。
5. 若 Float 日志正确但粒子仍完全不动,**停止调节 visualSpeedScale=6000**,保存日志并进入后续 GPU State texel readback / State Update→Draw 定向任务。
## 继续综合验收
在第一优先项通过后,沿用 v2 的 REAL WEATHER tuning/RESET、PLAY T0→T3、两次 Window Boundary、Duplicate/Invalid、Pan/Zoom/Rotate/Activity Rotation 检查。正常边界仍应为 OLD_T1→NEW_T0 reuse、only NEW_T1 upload、`simulationRebuild=false`、`trailCleared=false`。
本轮没有 Weather Service、React Native、Jest 或 canonical 数据变化。

View File

@@ -0,0 +1,39 @@
# STEP-055 真实 WeatherV2 风场 Particle State 纹理精度修复 Codex 完成报告 v3
## 基线、范围与根因
- Starting HEAD:`37c9aa31da1d2b3495c8802e6fd2f6b999562b06`
- 分支:`particle/main`
- 状态:**IMPLEMENTED / WAITING_ANDROID_VALIDATION**
真实 Weather State shader 已计算非零 m/s→Web Mercator 位移且 State A/B ping-pong 持续,但 State RG world coordinate 写回被共用的 RGBA8/UnsignedByte target 量化。`1/255≈0.00392 world` 大于 Android 已观测的 `0.000003–0.000008 world` 单步位移,故每步无法积累,是“simulation 在跑但粒子静止”的确定性根因。
## 修改
- `render_particle_validation_layer.cpp`:State A/B 初始创建与 particleCount replacement 均为 `TextureChannelDataType::Float`;Trail A/B 仍为 `UnsignedByte`。创建函数显式接收 data type/kind,并在 FBO 创建失败时 log error、拒绝 target,无 UByte fallback。
- `render_target.hpp/.cpp`:新增最小 `RenderTarget::isRenderable()` forwarding,使 target 创建即可验证当前后端实际 FBO。
- `particle_gpu_validation.fragment.glsl`:只修正 RG 为 Web Mercator world position 的注释;未改 m/s conversion 或 `visualSpeedScale=6000`。
- 生成的 OpenGL shader header 同步更新。
Android OpenGL 既有实现已经支持 Float:`gl::Context::createRenderTarget → RenderTarget → gl::OffscreenTexture → Texture2D(RGBA, Float) → GL_RGBA32F/GL_FLOAT → glFramebufferTexture2D → checkFramebuffer()`。因此未修改 Android/OpenGL backend;若设备 FBO 不完整,现有 `isRenderable()` 返回失败,Particle target 记录具体 Float failure 并 fail-closed。
运行时日志包括每个成功 `CREATE_SUCCESS`,以及 State/Trail pair summary:`stateAType=Float stateBType=Float trailAType=UnsignedByte trailBType=UnsignedByte`。这基于已实际完成 backend FBO validation,而非仅打印请求值。
## 架构保护
未修改 canonical Field、U/V 语义、STEP-054 assets、Host submission、Timeline、Runtime Field Window、WeatherColorLayer 或 6000 visual speed scale。没有新增 GPU readback、网络、Provider、React Native、Jest 或 Android UI 变化。
## 验证
- `node shaders/generate_shader_code.mjs`:PASS;generated OpenGL header 与 fragment source 同步。
- Linux OpenGL CMake 精确编译:`render_target.cpp`、`render_particle_validation_layer.cpp`、`gl/offscreen_texture.cpp`、`gl/texture2d.cpp`:PASS。
- 现有非 Jest `test/style/style_layer.test.cpp`:以相同 OpenGL CMake 参数精确编译 PASS;本轮没有适合脱离实际 GL context 的 Float FBO 单元 runner,因此 FBO runtime 完整性保留 Android 实机检查。
- `git diff --check`:PASS(最终提交前将再次执行)。
- Android Gradle/APK/ADB/App/设备:未执行。
- Jest:未执行,未修改。
人工验收说明:[v3](../60_测试/STEP-055_Android真实WeatherV2风场综合可视化_人工验收指令_v3.md)。第一门槛是 Timeline Pause 下 Float State 粒子连续运动;若仍不动,不调 6000,转入后续 GPU State 读回诊断。
## Git
本报告将在功能提交及 push 后记录实际 commit、push result 与 Final HEAD。用户既有未跟踪文件未触碰、未 stage。