docs: close 40-01 android validation
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled

This commit is contained in:
OpenAI Codex
2026-09-02 09:06:39 +08:00
parent 34cc5be261
commit 8eaed68c45
4 changed files with 88 additions and 45 deletions

View File

@@ -2,7 +2,7 @@
## 状态
进行中。40-01 Stage A 的代码和 Linux 静态验证完成;最终 Android 状态固定为 `WAITING_MANUAL_VALIDATION`,尚未进入手工 APK 验收。
完成。40-01 Stage B Android OpenGL x86_64 手工验收已完成,正式状态为 `PASS`。
## 目标与基线
@@ -18,7 +18,7 @@
- [x] Android Test App 从 APK `asset://integration/particle-fixtures/...` 提供正式 source 输入;Linux smoke helper 仍可读取仓库 fixture。
- [x] NoData cell 作为 GPU field texture alpha=0 上传;shader 遇到 invalid sample 确定性回到 seed position,不把 NoData 当速度。
- [x] STATIC recreation 仍走 zero-step State/Trail/bootstrap composite,commit 不增加 `simulationFrame`。
- [ ] Android OpenGL APK 手工编译与 T1-T12:仅 GPT 复审远端代码通过后由用户执行。
- [x] Android OpenGL x86_64 APK 手工验收:GLOBAL/ACTIVE/STATIC、fixture 切换、Rotation、Camera、world wrap、antimeridian、mask、disable/enable 与快速切换均 PASS。
## 允许修改
@@ -30,10 +30,10 @@
## 构建与检查
- Linux OpenGL 受影响 `render_source.cpp.o` 与新增 `source.test.cpp.o` 精确编译:PASS(`-Werror`);`RasterArrayRenderItem` 单测已编译入测试目标,未在本轮执行完整测试二进制。
- `clang-format --dry-run --Werror`、`git diff --check`:PASS;fixture generator 不受本次枚举接入影响,未重跑。
- adapter smoke:`uniform-east`、`uniform-north`、`vortex` 均 valid;`nodata` valid 且有 1 个 invalid cell。
- Linux OpenGL 受影响 Core 与 `source.test.cpp.o` 均在各轮修复后精确编译:PASS(`-Werror`);完整 `mbgl-test` 不属于本任务的精确验证范围。
- `clang-format --dry-run --Werror`、`git diff --check`、shader generator/source-header parity 与生成器幂等检查:PASS。
- adapter smoke:`uniform-east`、`uniform-north`、`vortex` 均 valid;`nodata` valid 且有 1 个 invalid cell。Android APK OpenGL x86_64 手工验收:PASS。
## 当前结果、阻塞与下一步
正式 Source/Layer/RenderLayer 已不依赖 source-less `particle-validation` Layer;历史 validation Layer 只保留为既有验证工具。Android 首次实际启动的 RasterArray source RenderItem 空指针已在 source 内补为合法 no-op RenderItem,保持全局 RenderSource 契约。随后实机日志发现 ACTIVE/STATIC 每帧重置:RenderOrchestrator 的按 source 可渲染性扫描会短暂调用 `markLayerRenderable(false)`,它不是持久 disabled;粒子层原先却在该回调中 `resetSequence()`,每帧清空跨 render 的 frame/slot/seed 状态。已删除该错误 reset 边界,真实重建仍限于 field、viewport、context 与 layer removal;新增状态转换及前 3 帧采样日志。正式 Composite 已改为显示 Trail RGB,legacy validation display 保留原 stripe/anchor/world-wrap 分支;State 以 `stateSeeded`/`u_mask.w` 而非 RenderTarget alpha 进行显式 seed。最新实机确认 east direction 通过,但 source recreation 后 north 仍显示 east:`RasterArraySource` 的 instance-local generation 在新 source 从 1 重启,renderer 又只比较 generation,错误复用 east GPU field。generation 现为 process-wide atomic runtime snapshot revision,renderer 同时比较 generation、fixtureID、dataVersion;fixture switch 保持既有 field texture replace、resetSequence、state re-seed 与 trail clear。Linux 精确编译、定向 source test object、format 与 diff 已通过;Android 实机验收仍由用户执行,40-01 保持 `WAITING_MANUAL_VALIDATION`。
正式 `RasterArraySource -> RasterParticleLayer` 闭环已通过 Android OpenGL x86_64 Stage B。历史调试中先后修复 OfflineDownload 枚举接入、enabled RasterArray source 空 RenderItem SIGSEGV、旧 APK/.cxx native 缓存、ACTIVE/STATIC transient reset、formal Composite 未显示 Trail、shader source/generated header 不一致、opaque RenderTarget clear 下的 State seed、source 重建的 field identity generation collision,以及 STATIC Rotation/Viewport 自动恢复。最终实机已确认:east/north/east 切换方向正确、ACTIVE/STATIC lifecycle 正确、Camera 与 Rotation 正确、GLOBAL/OCEAN A/OCEAN B 与 shared mask reuse 正确。相同 RenderThread/resource generation 内三种 mask consumer 均复用同一 `maskGeneration` 且 `reuse=true`;graphics resource 重建后的 generation 递增属于新 GPU resource,不是同 generation 内重复创建。40-01 正式关闭为 `PASS`。iOS、Vulkan、真实在线数据、生产 coastline/mask 和性能结论不在本 Step 范围。

View File

@@ -2,62 +2,81 @@
## 状态
`WAITING_MANUAL_VALIDATION`。30-01、30-02、30-03 的正式记录均为 `PASS`,30-03 允许进入本任务。本报告只记录 Codex 的 Stage A 事实,不把未执行的 Android 编译或设备视觉验收写为 PASS。
`PASS`。用户已完成 40-01 Stage B Android OpenGL x86_64 手工验收。本文保留 Stage A 静态检查及失败/修复历史,并以 Stage B 验收作为最终结论。
## 基线与范围
- 分支:`particle/main`
- 开始 HEAD:`1ec44701146925dec9a87618e3f90bee9a12073f`
- 平台范围:Android OpenGL;未修改 iOS、Vulkan、NavSea 或在线数据链。
- Test App 继续使用既有 `Particle Core Layer Validation` 入口,但其 Style 现在创建正式 `raster-array` source 和 `raster-particle` layer;Core adapter 不依赖 Kotlin/Android UI 或 Android asset API。
- 本次 PASS 范围:Android OpenGL x86_64 离线 fixture 正式粒子闭环;不扩大为 iOS、Metal、Android Vulkan、真实在线数据或生产 coastline/mask 的 PASS。
## 已实现的 Stage A 链路
## 最终正式链路
```text
APK asset://integration/particle-fixtures/{uniform-east,uniform-north}/
-> RasterArraySource -> RenderRasterArraySource
-> ParticleFieldSnapshot -> GPU field texture
-> RasterParticleLayer (Source::Required) -> RenderRasterParticleLayer
-> State A/B field sampling -> Trail A/B -> canonical world composite / shared coastal mask
-> State A/B -> Trail A/B -> formal Trail composite / shared coastal mask
```
- fixture contract 使用 `metadata.json + field.f32`,校验 schema、id、WIND/GLOBAL、EPSG:4326、bounds、grid registration/order、interleaved UV、little-endian float32、NoData 声明、长度和 SHA-256。Android asset 由 Test App 打包,Core 只接收 FileSource 返回的 metadata/field bytes;Linux helper 才读取仓库 `particle-fixtures/`。
- `uniform-east`、`uniform-north` 和 `vortex` 均为确定性 16x16 fixture;不会在每帧解析或上传。切换 fixture 时递增 `fieldGeneration/gpuFieldGeneration`,清空旧 trail;Camera 操作不触发 field upload。
- shader 的 State pass 实际采样 GPU field texture,Trail pass 从 State write texture 读取粒子位置,未使用 Kotlin/CPU 每帧粒子循环。field texture alpha 表示 cell validity;NoData cell 上传为 alpha=0,State pass 在该 sample 上确定性 respawn 到 seed position,绝不将 `-9999` clamp 成速度。
- STATIC 不再因资源缺失提前返回。新的 context/resource generation 会建立 field、mask、trail 和 state;STATIC 首帧走零步 bootstrap,提交 state/trail slot 但不增加 `simulationFrame`,之后保持 frozen composite。
- Activity Bundle 保存/恢复 active、enabled、mask mode 与 fixture mode;GPU runtime state 不写入 Bundle。
- fixture 使用 `metadata.json + field.f32`,Core 仅接收 FileSource bytes;metadata、binary length 与 SHA-256 经过校验。
- State pass 采样 GPU field,Trail 从 State write texture 读取;不使用 Kotlin/CPU 每帧粒子循环。NoData cell 以 field alpha=0 表示,确定性 respawn,绝不把 `-9999` 当速度。
- STATIC 首帧可以 zero-step bootstrap,之后使用 frozen composite;Activity Bundle 恢复 active、enabled、mask mode 与 fixture mode。
## Codex 可执行检查
## Codex 静态验证
| 检查 | 结果 |
|---|---|
| `ninja -C build-linux-opengl` 受影响 Core 对象 | PASS:正式 `raster_array_source.cpp`、`raster_particle_layer.cpp`、`raster_particle_layer_factory.cpp`、`render_source.cpp`、`RenderRasterParticleLayer` 实现、adapter 与 source conversion |
| Linux OpenGL 受影响 Core 与 `source.test.cpp.o` 精确编译 | PASS(`-Werror`) |
| `clang-format --dry-run --Werror` | PASS |
| `git diff --check` | PASS |
| `python3 tools/generate_particle_fixture_f32.py` 后 metadata JSON 与 SHA-256 | PASS |
| adapter smoke test | PASS:`uniform-east`、`uniform-north`、`vortex` 分别加载为 16x16;`nodata` 为合法 16x16 field 且恰有 1 个 invalid cell |
| APK asset parity | PASS:四份 Android asset 的 metadata 与 field bytes 均与仓库 fixture 完全相同 |
| fixture metadata / SHA-256、adapter smoke、APK asset parity | PASS |
| shader source/header parity 与 generator 二次运行幂等 | PASS |
| RasterArray runtime generation / field identity 定向 C++ 测试对象 | PASS |
首次整库构建尝试被 sandbox 默认 ccache 目录只读中断;以 `CCACHE_DIR=/tmp/maplibre-particle-ccache` 重新执行上述受影响对象检查后通过。这不是代码编译失败。
完整 `mbgl-test` 不是本任务的精确验证范围,未将未执行测试伪造为 PASS。
## 用户手工 Android OpenGL 验收
## Android OpenGL x86_64 手工验收(Stage B)
未执行。已核对当前模块提供 `opengl` flavor,用户应在提交后执行:
用户已确认下列项目全部 `PASS`:
```bash
cd platform/android
./gradlew :MapLibreAndroidTestApp:assembleOpenglDebug
```
| 项目 | 结果 |
|---|---|
| GLOBAL + ACTIVE + UNIFORM EAST | PASS |
| ACTIVE → STATIC → ACTIVE | PASS |
| UNIFORM EAST → UNIFORM NORTH → UNIFORM EAST | PASS |
| STATIC + OCEAN A/B Rotation 自动恢复 | PASS |
| ACTIVE Rotation | PASS |
| Pan / Zoom / Bearing / Pitch | PASS |
| World Wrap | PASS |
| Antimeridian 双向跨越 | PASS |
| GLOBAL / OCEAN A / OCEAN B | PASS |
| Shared Mask reuse | PASS |
| DISABLE / ENABLE | PASS |
| 快速 Fixture 切换 | PASS |
| 最终重复 Rotation 回归 | PASS |
随后按任务书执行 T1-T12,尤其验证 STATIC + OCEAN A/B rotation 无按钮恢复、east/north 方向差异、field/mask generation 在 Camera 操作中稳定,以及 disable/enable、world wrap 和双向 antimeridian。日志筛选关键字:`ParticleField|ParticleGPU|ParticleMask|ParticleRender|ParticleValidation`。
Shared Mask 日志事实:同一 RenderThread / GPU resource generation 内,GLOBAL、OCEAN_ONLY_A、OCEAN_ONLY_B 均复用同一 `maskGeneration`,并记录 `reuse=true`。graphics resource 重建后 `maskGeneration` 可以递增;这是新 GPU resource generation 的重建,不是同 generation 内重复创建。
## 未覆盖与风险
## 40-01 调试与修复历史
- T1-T12 Android 设备验收、截图和 OpenGL shader 实机链接尚未执行。
- 独立 EGL context-loss 设备证据沿用 30-02 的 Accepted Risk;本实现已按 resource generation 重建 CPU field 的 GPU texture。
- iOS、Metal、Android Vulkan、真实数据、生产 coastline/mask、最终粒子数和性能指标均不在本 Stage A 范围。
- Android T1-T12 和实机 OpenGL shader 链接尚未执行;NoData 已有 deterministic fixture/static smoke 覆盖,但没有实机视觉证据。
以下失败过程保留为调试与验证记录,不影响最终 PASS:
## 下一步
- `SourceType::RasterArray` 首次 Android C++ 编译遗漏 OfflineDownload 两个 exhaustive switch;按 APK `asset://` fixture 的 no-op contract 补齐,未用 `default:` 掩盖遗漏。
- enabled `RenderRasterArraySource` 曾返回空 RenderItem,RenderTree 无条件解引用导致首次启动 SIGSEGV;source 内补合法 no-op RenderItem,未弱化 orchestrator contract。
- Android 出现旧 APK / `.cxx` native 缓存造成的观察偏差;以当前源码重新生成 native artifact 后继续验收。
- source-scoped transient `markLayerRenderable(false)` 曾每帧 reset State/Trail;移除错误生命周期边界后 ACTIVE frame/slot 连续推进,STATIC 仅在必要时 zero-step bootstrap。
- formal Composite 曾只让 Trail RGB 影响 alpha、主体仍为 legacy stripe;`FORMAL_PARTICLE` 改为显示 Trail RGB,legacy validation display 保留。
- shader 逻辑曾与 generated OpenGL header 不同步;已回写 GLSL source、由项目 generator 生成 header,并完成 parity/幂等检查。
- opaque RenderTarget clear 使 `previous.a` 不能表达未 seed;改用 `stateSeeded` 经 UBO 显式 State seed,初始 marker 分散于 world。
- Style source recreation 时 instance-local field generation 碰撞,north 复用 east GPU texture;generation 改为 process-wide revision,renderer 同时比较 generation、fixtureID、dataVersion。
- Rotation / Viewport 的 STATIC 自动恢复纳入本任务,已由 STATIC OCEAN A/B 与最终重复 Rotation 回归验证。
等待用户提供 Android OpenGL build 与 T1-T12 实际结果;仅在收到证据后进入任务书定义的 Stage B。
## 范围外事项
40-01 的 Android OpenGL x86_64 范围已 PASS。iOS/Metal、Android Vulkan、真实数据、生产 coastline/mask、性能和独立 EGL context-loss 设备证据不在本次 PASS 声明范围。NoData 有确定性 fixture/static smoke 覆盖,本轮未单独形成 NoData 视觉结论。
## 最终结论
40-01 Android 离线 Fixture 到正式粒子渲染最小闭环正式判定为 `PASS`。

View File

@@ -2,7 +2,7 @@
## 1. 执行结论
Stage A 代码与静态检查完成,任务状态为 `WAITING_MANUAL_VALIDATION`。本报告不声明 40-01 PASS。
40-01 已完成 Stage A 实现、连续调试修复和 Stage B Android OpenGL x86_64 手工验收,正式状态为 `PASS`。
## 2. Git 基线
@@ -16,7 +16,7 @@ Stage A 代码与静态检查完成,任务状态为 `WAITING_MANUAL_VALIDATION
本轮修正实现提交:`39c7ae22ede51f4b755dc658e2e27b24b26b807e`(`feat: establish formal raster particle source chain`)。
首次 push:成功,`origin/particle/main` 从 `1ec447011` 更新为 `0b076c6d5`。本报告的修正元数据将作为独立 docs commit 推送到同一分支;最终远端 HEAD 在交付时报告。
首次 push:成功,`origin/particle/main` 从 `1ec447011` 更新为 `0b076c6d5`。本报告保留 Stage A 初始提交与中间修复的历史事实;Stage B 文档收尾 commit、push 结果与最终远端 HEAD 在交付时记录。
## 3. 实际修改
@@ -33,7 +33,7 @@ Stage A 代码与静态检查完成,任务状态为 `WAITING_MANUAL_VALIDATION
- Linux OpenGL 受影响对象编译:PASS。
- C++ 格式、`git diff --check`、fixture JSON/生成/sha256:PASS。
- adapter smoke test:PASS,三份普通 fixture 成功 decode/validate;`nodata` fixture 的单 cell invalid 标记被保留且 field 整体合法。Android asset 与仓库 fixture byte parity:PASS。
- 未运行 Gradle、APK 安装、ADB 或 Android 实机验证,遵守任务书限制。
- Stage A 阶段未运行 Gradle、APK 安装、ADB 或 Android 实机验证;Stage B 已由用户完成 Android OpenGL x86_64 手工验收,结果见第 5 节。
## 4.1 RasterArray 离线下载枚举接入修复
@@ -49,12 +49,28 @@ Stage A 代码与静态检查完成,任务状态为 `WAITING_MANUAL_VALIDATION
- 修复在 RasterArray source 内按 ImageSource 生命周期准备并移交合法 no-op RenderItem:无 upload、无 render pass、无 particle draw。正式 GPU particle 绘制仍只属于 `RenderRasterParticleLayer`。
- Linux/Core `render_source.cpp.o` 和含新增 `RasterArrayRenderItem` 的 `source.test.cpp.o` 均以 `-Werror` 精确编译;`clang-format --dry-run --Werror`、`git diff --check` 与全部 RenderSource `createRenderItem()` return audit 均通过。未运行完整 Linux 测试二进制、Android Gradle、ADB 或真机测试,状态仍为 `WAITING_MANUAL_VALIDATION`。
## 5. 已知问题与未完成事项
## 5. Stage B 最终 Android OpenGL x86_64 验收
- Android OpenGL 的 T1-T12 仍待用户执行,T1 rotation 无按钮恢复是硬门槛。
- 未实现 iOS/Vulkan/真实在线数据/生产 coastline/性能结论。
- Android OpenGL 实机的 NoData visual/runtime evidence、T1-T12、Vulkan 和 iOS 均未执行。
用户已手工完成并确认以下全部 PASS:GLOBAL + ACTIVE + UNIFORM EAST;ACTIVE → STATIC → ACTIVE;UNIFORM EAST → UNIFORM NORTH → UNIFORM EAST;STATIC + OCEAN A/B Rotation 自动恢复;ACTIVE Rotation;Pan / Zoom / Bearing / Pitch;World Wrap;Antimeridian 双向跨越;GLOBAL / OCEAN A / OCEAN B;Shared Mask reuse;DISABLE / ENABLE;快速 Fixture 切换;最终重复 Rotation 回归。
## 6. 与指令书差异
同一 RenderThread/resource generation 内,GLOBAL、OCEAN_ONLY_A、OCEAN_ONLY_B 日志均复用相同 `maskGeneration` 并输出 `reuse=true`。graphics resource 重建后 generation 与 maskGeneration 可递增,这是新 GPU resource,不构成同一 generation 内重复创建。
此前报告错误地写为“无”:当时正式 Source/Layer/RenderLayer 链尚未建立,且 Android runtime fixture 仍错误依赖源码仓库相对路径。本轮已修正为正式 Source-required 链和 APK asset 输入边界,并新增 STEP-040 记录。Stage A 仍为 `WAITING_MANUAL_VALIDATION`,不声明 PASS。
## 6. 40-01 最终调试事实
- OfflineDownload 两处 exhaustive `SourceType` switch 补入 RasterArray 的显式 asset-fixture no-op。
- enabled RasterArray source 空 RenderItem 导致的 RenderThread SIGSEGV 已修复为 source 内合法 no-op RenderItem。
- 处理过 Android APK / `.cxx` 旧 native 缓存观察问题。
- 修复 per-source transient renderability 导致的 ACTIVE/STATIC reset loop,使 simulationFrame 与 A/B ping-pong 跨 frame 持久。
- 正式 Composite 现在显示 Trail RGB;legacy validation 的 stripe/anchors/world-wrap 诊断显示仍保留。
- shader 的唯一 source 为 GLSL,generated OpenGL header 经 generator 同步且幂等。
- opaque RenderTarget clear 下 State 通过 `stateSeeded` 显式 seed;不再错误依赖 sampled alpha。
- RasterArray snapshot generation 为跨 source instance 的 runtime revision;renderer 用 generation、fixtureID、dataVersion 三元 identity 阻止 east/north GPU field 误复用。
- Rotation/Viewport STATIC 自动恢复完成并通过回归。
## 7. 范围外事项
40-01 的 Android OpenGL x86_64 范围已 PASS。iOS/Metal、Android Vulkan、真实在线数据、生产 coastline/mask、性能和独立 EGL context-loss 设备证据不在本次 PASS 声明范围。
## 8. 与指令书差异
此前报告错误地写为“无”:当时正式 Source/Layer/RenderLayer 链尚未建立,且 Android runtime fixture 仍错误依赖源码仓库相对路径。本轮已修正为正式 Source-required 链和 APK asset 输入边界;后续修复和 Stage B 实机证据现已使 40-01 正式 PASS。

View File

@@ -214,3 +214,11 @@
- renderer 使用 shared `fieldIdentityChanged()` 三元判断:generation、fixtureID、dataVersion 任一改变都会重新上传 field texture 并保留既有 `resetSequence()`、State re-seed、Trail clear 路径;三者相同不重复上传。fixture switch 日志记录 from/to、old/new generation、gpuFieldGeneration、trail clear 与 state seed。
- 新增定向 C++ 测试:两个独立 RasterArraySource 实例加载 east/north 得到不同 generation;同 generation 的 east/north 仍判定 identity changed;同 fixture/generation/dataVersion 不判定变更,dataVersion 改变则判定变更。
- Linux OpenGL 的 RasterArraySource、RenderLayer 与 `source.test.cpp` 精确编译,format/diff 均通过;未运行 Android Gradle/ADB/真机,40-01 继续 `WAITING_MANUAL_VALIDATION`。下一轮只验收 GLOBAL + ACTIVE + uniform-east 后切 uniform-north 的方向变化。
## 2026-09-02 — 40-01 Stage B Android OpenGL 最终关闭
- 用户完成 Android OpenGL x86_64 手工验收,40-01 正式状态更新为 `PASS`。
- GLOBAL + ACTIVE + UNIFORM EAST、ACTIVE→STATIC→ACTIVE、UNIFORM EAST→UNIFORM NORTH→UNIFORM EAST、STATIC OCEAN A/B Rotation 自动恢复、ACTIVE Rotation、Pan/Zoom/Bearing/Pitch、World Wrap、双向 Antimeridian、GLOBAL/OCEAN A/OCEAN B、Shared Mask reuse、DISABLE/ENABLE、快速 fixture 切换与最终重复 Rotation 回归全部 PASS。
- 同一 RenderThread/resource generation 内 GLOBAL/OCEAN_ONLY_A/OCEAN_ONLY_B 复用同一 `maskGeneration`,日志为 `reuse=true`;graphics resource 重建后的 generation/maskGeneration 递增属于新 GPU resource,不属于同 generation 内重复创建。
- 40-01 历史调试链完整保留:OfflineDownload exhaustive switch、RasterArray no-op RenderItem SIGSEGV、Android APK/.cxx 旧 native 缓存、lifecycle reset loop、formal Composite Trail 显示、shader source/generated header 同步、opaque clear State seed、field identity generation collision、Rotation/Viewport STATIC restore 均已解决并由最终手工回归覆盖。
- 本次仅回填 Stage B 文档,不重新运行 Android Gradle、ADB 或实体机;iOS/Metal、Vulkan、真实数据、生产 mask、性能和独立 EGL context-loss 设备证据仍为范围外,不被 40-01 Android OpenGL PASS 隐含覆盖。