diff --git a/docs/40_任务/30_02_GPU_PingPong与ContextRecreation验证指令书_v1.md b/docs/40_任务/30_02_GPU_PingPong与ContextRecreation验证指令书_v1.md new file mode 100644 index 000000000..8faf120e3 --- /dev/null +++ b/docs/40_任务/30_02_GPU_PingPong与ContextRecreation验证指令书_v1.md @@ -0,0 +1,1184 @@ +# MapLibreParticleLab 30_最小技术验证-02_GPU Ping-Pong 与 Context Recreation 验证指令书 v1 + +## 1. 任务基本信息 + +- 项目:`MapLibreParticleLab` +- 大阶段:`30_最小技术验证` +- 子任务:`30-02 GPU Ping-Pong 与 Context Recreation 验证` +- 当前主线:`particle/main` +- 前置阶段: + - `10_架构调查` 已完成 + - `20_架构设计` 已完成 + - `30-01 Core RenderLayer 接入验证` 必须已经正式 `PASS` +- 前置正式架构文档: + - `docs/10_架构/20_粒子系统总体架构设计_v1.md` +- 任务性质:最小运行时技术验证 +- 本任务不是正式粒子功能实现 +- 本任务允许增加最少量、明确标记为 `VALIDATION ONLY` 的 GPU 验证代码 +- 不允许顺手重构 MapLibre +- 不允许扩大到真实 Particle Field、真实风/浪/潮/海流数据、Land/Ocean Mask、Vulkan 或 iOS + +本任务不加入 Jest。 + +--- + +## 2. 前置门槛 + +`30-02` 只能建立在 `30-01` 已经正式 `PASS` 的基础上。 + +Codex 开始前必须读取当前仓库中的: + +- `docs/60_测试/30_01_CoreRenderLayer接入最小技术验证报告_*.md` +- `docs/报告/30_01_CoreRenderLayer接入验证_Codex完成报告_*.md` +- `粒子开发记录.md` + +并确认当前有效版本明确记录: + +`30-01 = PASS` + +如果当前仓库仍然是: + +- `WAITING_MANUAL_VALIDATION` +- `FAIL` +- `BLOCKED` +- 或无法找到正式 PASS 记录 + +则: + +1. 不得开始 30-02 GPU 代码; +2. 不得自行把 30-01 改成 PASS; +3. 只生成阻塞说明; +4. 明确报告“30-02 前置条件未满足”; +5. 不提交任何 30-02 生产/验证代码。 + +用户当前已经明确要求进入 30-02,但最终仍以仓库中当前正式验证记录为执行门槛。 + +--- + +## 3. 本任务为什么是 30-02 + +总体架构与 30-01 已经把最小技术验证顺序定义为: + +1. Core RenderLayer / Style order / 同帧 Transform / repaint +2. GPU State A/B + Trail A/B ping-pong 与 context recreation +3. Camera / world wrap / Land-Ocean Mask +4. iOS Core Layer 薄接入 + +因此本任务只验证第 2 项。 + +本任务必须回答: + +> 已经通过 30-01 验证的独立 Core Particle RenderLayer,能否在 MapLibre 当前 gfx / RenderTarget / CommandEncoder 生命周期内稳定管理 GPU State A/B 和 Trail A/B,完成无读写冲突的 ping-pong,并在 viewport resize、Layer disable/enable、Surface/GPU context recreation 后正确释放和重建资源。 + +本任务不得提前处理第 3、4 项。 + +--- + +## 4. 必须先读取 + +Codex 开始前必须完整读取: + +1. 根目录 `AGENTS.md` +2. `PARTICLE_BASELINE.md` +3. `docs/00_项目总则/` 下当前全部有效文档 +4. `docs/00_项目规范/` 下当前全部有效文档 +5. `docs/20_调查/10_架构调查报告_v1.md` +6. `docs/10_架构/20_粒子系统总体架构设计_v1.md` +7. `docs/报告/10_架构调查_Codex完成报告_*.md` +8. `docs/报告/20_架构设计_Codex完成报告_*.md` +9. `docs/60_测试/30_01_CoreRenderLayer接入最小技术验证报告_*.md` +10. `docs/报告/30_01_CoreRenderLayer接入验证_Codex完成报告_*.md` +11. `粒子开发记录.md` +12. 30-01 当前实际验证代码 +13. 与下列 gfx / GPU 资源链直接相关的当前源码: + - `gfx::Context` + - `Texture2D` + - `DynamicTexture` + - `RenderTarget` + - `CommandEncoder` + - render pass / upload pass + - texture sampling / attachment 相关实现 + - framebuffer / render target backend 实现 + - Android OpenGL backend + - EGL / surface / renderer context 生命周期 + - resize / surface recreation 相关链 + - 现有使用 offscreen RenderTarget 的 MapLibre 内部示例 + - 现有 texture ping-pong、双缓冲或多 pass 示例,如仓库存在 + +不得根据通用 OpenGL 知识直接猜当前 MapLibre gfx 行为。 + +必须以当前 `particle/main` 实际代码为准。 + +--- + +## 5. 开始前 Git 检查 + +先执行只读检查并记录: + +- 当前分支 +- 当前 HEAD +- `git status` +- 当前公开远端 +- `particle/main` 是否与远端同步 +- 30-01 最终 PASS 对应 commit +- 是否存在与本任务无关的本地修改 + +如果存在无关修改: + +- 不得删除 +- 不得覆盖 +- 不得一起提交 +- 在完成报告中记录 +- 本任务只 stage 本任务相关文件 + +如果当前不是 `particle/main`: + +- 不得擅自覆盖用户工作 +- 先记录实际状态 +- 不得为了完成任务强制 reset + +--- + +## 6. 验证目标 + +本任务只回答下面五个问题。 + +### V1. GPU State A/B 能否通过当前 gfx 资源体系建立并稳定 ping-pong + +必须创建一组最小验证资源: + +- `State A` +- `State B` + +要求: + +- 两个资源在逻辑上独立 +- 当前帧只读其中一个,只写另一个 +- 帧结束后交换角色 +- 下一帧反向读取/写入 +- 不允许同一 pass 内把同一 texture 同时作为读取源和写入目标 +- 不允许依赖 CPU 每帧搬运完整 state +- 不允许依赖平台侧独立 GL 线程逻辑 + +本任务不冻结正式粒子状态 texture 的最终格式。 + +应优先选择当前 Android OpenGL + MapLibre gfx 已明确支持、便于验证的最小格式。 + +报告中必须明确: + +- 选择了什么 gfx texture / renderable resource +- 为什么适合本次验证 +- 哪些属性只是验证选择,不属于正式生产 contract + +--- + +### V2. Trail A/B RenderTarget 能否稳定 ping-pong + +必须创建: + +- `Trail A` +- `Trail B` + +基本要求: + +- Trail 使用真实 offscreen `RenderTarget` +- 当前帧读取 previous trail +- 写入 next trail +- 完成后交换 A/B +- 最后把当前有效 trail 合成到 MapLibre 正常主 render pass +- 不覆盖地图正常 framebuffer 生命周期 +- 不建立 MapView 外部 Overlay + +本任务中的 Trail 只是验证图形。 + +允许使用: + +- 简单移动点 +- 简单线段 +- 简单 alpha 衰减 +- 固定颜色图形 +- 可重复确定性 pattern + +禁止把本任务包装成正式风粒子视觉效果。 + +Trail 必须能够直观看出: + +- 前一帧结果被下一帧正确采样 +- A/B 正在交替 +- 不存在明显 feedback corruption +- resize 后重新建立正确尺寸的 target + +--- + +### V3. 多 Pass 同步 / hazard 是否能在现有 gfx 抽象内正确完成 + +必须确认实际执行顺序至少包含: + +```text +State Read +→ State Write +→ State swap +→ Trail Read +→ Trail Write +→ Trail swap +→ Composite to main render target +``` + +实际顺序可根据当前 gfx API 调整,但必须满足无读写冲突。 + +重点调查并验证: + +- render pass 结束后下一 pass 采样刚写入资源是否成立 +- 当前 gfx 是否自动处理必要状态切换 +- Android OpenGL backend 是否依赖 pass ordering / framebuffer unbind / texture state +- 是否存在显式 barrier API +- 如果 OpenGL 路径不需要显式 barrier,必须如实记录,不得为了“看起来完整”自行增加无意义 barrier +- 如果其他 backend 未来需要不同同步策略,应通过 gfx/backend 边界承载,不得把 GL/Vulkan/Metal 特例散到公共粒子逻辑 + +本任务要验证的是: + +> 当前 MapLibre gfx 抽象是否足够表达安全的 GPU ping-pong。 + +不是要求强行创造一套新的通用同步框架。 + +--- + +### V4. resize / disable / enable 后资源生命周期是否正确 + +必须验证: + +#### viewport resize + +- Trail A/B 按新 viewport 尺寸重新创建 +- 旧 Trail 资源被安全释放 +- State A/B 如果与 viewport 无关,不得无意义重建 +- resize 后第一帧状态明确 +- 不采样已释放 target +- 不出现黑屏、花屏或地图崩溃 + +#### Layer disable + +- 停止新增 GPU 更新 +- 不继续无意义 repaint +- GPU 资源如何保留或释放必须明确 +- 行为应与总体架构生命周期一致 + +#### Layer re-enable + +- 如果资源仍有效,允许复用 +- 如果已失效,必须重新创建 +- ping-pong index / generation 必须恢复到明确状态 +- 不允许使用旧 generation 的资源句柄 + +--- + +### V5. Surface / GPU Context Recreation 后能否正确恢复 + +这是 30-02 的关键门槛。 + +必须调查当前 Android OpenGL 实际: + +- EGL context 生命周期 +- SurfaceView / TextureView surface 生命周期 +- renderer backend activate/deactivate +- gfx context / resource 生命周期 +- Activity background / foreground +- Activity recreate +- surface destroy / recreate + +验证目标: + +1. 能观察到一次真实的 surface/context/resource generation 变化; +2. 旧 State A/B、Trail A/B 不再被使用; +3. 新 GPU context/resource generation 中重新创建验证资源; +4. ping-pong 从明确初始状态恢复; +5. Trail 可以清空重新开始,不要求保留 context loss 前历史; +6. 地图本体继续正常工作; +7. 不 crash; +8. 不访问 stale texture / render target; +9. 不要求宿主重新创建第二套粒子 engine。 + +如果用户的普通后台/前台操作没有触发真实 GPU context recreation: + +- 不得把“Activity 回来了”当成 context recreation 已验证; +- 必须通过日志或资源 generation 证明; +- Codex 应基于当前 Test App / renderer 生命周期给出最小可重复触发方法; +- 如果当前设备/虚拟机环境无法可靠触发,则该项标记 `BLOCKED` 或 `UNVERIFIED`,不得伪造 PASS。 + +--- + +## 7. 验证代码必须保持最小 + +本任务不是正式 GPU Particle Simulation。 + +验证代码只需要证明: + +- gfx texture / renderable resource 可以建立 +- State A/B 可以轮换 +- Trail A/B 可以轮换 +- pass 顺序正确 +- resize 正确 +- context recreation 正确 + +原则: + +> 能用一个极小 deterministic validation state 证明,就不要提前实现真实粒子状态。 + +推荐但不强制: + +- State texture:极小固定尺寸,例如 4×4、8×8 或 16×16 +- State 内容:确定性递增值、位置标记或颜色编码 +- Trail target:按 viewport 尺寸 +- Trail 图形:简单移动 marker / alpha fade / pattern + +最终尺寸和格式必须以当前 gfx 实际能力为准。 + +禁止因为方便直接引入第三方 GPU 库。 + +--- + +## 8. State A/B 验证要求 + +至少记录逻辑: + +```text +frame 1: read=A, write=B +frame 2: read=B, write=A +frame 3: read=A, write=B +... +``` + +必须验证: + +- A/B logical role 每帧交替 +- swap 只在对应 pass 成功完成后发生 +- pass 失败时不能错误推进 index +- disable 后停止推进 +- resource recreate 后 generation 增加并重置 index +- 不跨 generation 复用逻辑引用 + +推荐内部验证元数据: + +- `resourceGeneration` +- `frameIndex` +- `stateReadSlot` +- `stateWriteSlot` +- `trailReadSlot` +- `trailWriteSlot` +- `viewportWidth` +- `viewportHeight` + +这些字段只用于验证,不代表正式公共 API。 + +--- + +## 9. Trail A/B 验证要求 + +Trail A/B 必须真正经过 offscreen RenderTarget。 + +至少验证: + +1. previous trail 被采样 +2. 执行简单 fade / copy / pattern pass +3. 当前验证图元写入 next trail +4. next trail 成为新的 current trail +5. current trail 合成到地图 +6. 下一帧角色交换 + +不得: + +- 直接在主 framebuffer 上画完后声称有 Trail ping-pong +- 只创建两个 texture 但不实际作为 RenderTarget +- 用 CPU image buffer 模拟 GPU trail + +resize 后: + +- old size target 必须退出 +- new size target 必须建立 +- 第一帧允许 clear +- 不要求保留 resize 前 trail 历史 + +--- + +## 10. gfx / backend 边界 + +公共验证逻辑必须优先使用当前 MapLibre gfx API。 + +禁止把下列调用散到 Core 粒子逻辑: + +- raw `glBindFramebuffer` +- raw `glFramebufferTexture*` +- raw `glMemoryBarrier` +- raw Vulkan image barrier +- raw Metal encoder 生命周期 + +如果当前 MapLibre gfx 缺少本验证不可绕过的能力: + +1. 先确认仓库中确实不存在可复用抽象; +2. 只增加最小、粒子无关或 backend 合理归属的 gfx 扩展; +3. 不为未来猜测设计大型抽象; +4. 报告为什么必须新增; +5. 明确 Android OpenGL 与未来 Vulkan/Metal 的边界; +6. 如果必须大量侵入 gfx 通用架构,立即停止并标记架构阻塞。 + +--- + +## 11. Shader 范围 + +本任务允许最少验证 shader,但必须明确标记: + +`VALIDATION ONLY` + +允许: + +- copy +- simple increment +- fade +- constant color +- moving marker +- simple composite + +禁止: + +- 正式 velocity sampling +- 正式 advection +- respawn +- random seed 系统 +- 正式 particle age +- 正式 field bounds +- 正式 wind/current shader +- Land/Ocean Mask +- 正式颜色映射 +- 正式产品参数 + +验证 shader 文件名也应明确体现 validation 属性。 + +--- + +## 12. Context / Resource Generation 记录 + +为了避免把普通 lifecycle 误认为 context recreation,验证必须建立逻辑 generation。 + +例如: + +```text +ParticleGpuValidation: +contextGeneration=1 +resourceGeneration=1 +create StateA +create StateB +create TrailA +create TrailB +``` + +发生真实 context/surface resource invalidation 后: + +```text +contextGeneration=2 +resourceGeneration=2 +create StateA +create StateB +create TrailA +create TrailB +``` + +不要求暴露底层 GL texture id。 + +如果当前 backend 能安全识别 context identity,可记录安全的调试信息。 + +如果不能: + +- 使用 renderer/backend lifecycle 事件 + resource generation 组合证明 +- 不得为了日志强行暴露 backend 私有句柄 + +--- + +## 13. 日志要求 + +日志必须足够判断 PASS/FAIL,但不能每帧爆量输出。 + +至少包含: + +- validation layer create +- GPU validation resources create +- resource generation +- state A/B create +- trail A/B create +- first ping-pong frame +- 每 N 帧一次: + - frameIndex + - state read/write slot + - trail read/write slot + - generation +- resize detected +- trail targets recreate +- disable +- enable +- surface/context invalidation +- resources destroy +- resources recreate +- first frame after recreation +- validation layer destroy + +建议每 60 帧或状态变化时输出一次。 + +禁止每帧完整输出 matrix、texture 描述或大量 GPU 状态。 + +--- + +## 14. Android 第一验证平台 + +本任务第一运行平台固定为: + +**Android OpenGL** + +不在本任务同时验证: + +- Android Vulkan +- iOS OpenGL +- iOS Metal + +原因: + +30-02 的目标是验证 Core gfx ping-pong 与资源生命周期这个架构门槛,不是一次完成所有 backend。 + +如果 Android OpenGL 证明当前 Core/gfx 路线本身无法成立,应先停止回到架构层,不得继续复制到其他平台。 + +--- + +## 15. Android 编译规则:必须由用户手工执行 + +Codex 禁止运行 Android 编译。 + +禁止: + +- `./gradlew assemble...` +- `./gradlew install...` +- Android Studio build automation +- 等价 Gradle Android build +- 自动安装 APK + +Codex可以: + +- 修改验证代码 +- 做静态源码检查 +- 检查 CMake / Gradle 配置 +- 给出用户手工编译命令 +- 分析用户提供的编译错误 +- 在本任务范围内修正代码 + +用户当前 Android OpenGL 构建基线已经采用仅 OpenGL 的目标。 + +Codex 必须根据当前实际 Gradle task 给出准确命令,不得凭旧命令猜测。 + +--- + +## 16. ADB / 设备操作规则 + +Android 安装、启动和实体/虚拟设备验证由用户手工执行。 + +Codex 不得默认: + +- `adb install` +- `adb shell am start` +- 清 App 数据 +- 自动抓 logcat +- 自动重启设备 + +如需给出 ADB 命令,当前 MapLibreParticleLab / AutoNav Android 虚拟机地址固定为: + +`192.168.1.146` + +所有命令必须显式使用: + +`adb -s 192.168.1.146 ...` + +不得省略 `-s`。 + +不得使用旧地址 `192.168.200.145`。 + +--- + +## 17. Test App 验证入口 + +优先复用 30-01 已建立并跑通的 Particle Core Layer Validation 入口。 + +不得为了 30-02 再建立一套完全平行的 Test App。 + +可以在现有验证 Activity / 页面中增加独立 GPU validation 模式或按钮,但必须: + +- 保持 30-01 原有验证能力不被破坏 +- 明确区分 30-01 和 30-02 +- 不让旧测试默认变成正式粒子 demo +- 不引入产品 UI + +建议提供最少控制: + +- `ACTIVE` +- `STATIC` +- `DISABLE` +- `ENABLE` +- `CLEAR/RESET`(如果确有必要) +- 显示当前 generation / frame / ping-pong slots + +具体形式以现有 Test App 结构为准。 + +--- + +## 18. 用户手工验证步骤 + +Codex 阶段 A 完成后,必须给出准确、可直接执行的手工步骤。 + +至少覆盖: + +### T1. 初始创建 + +观察: + +- State A/B 创建 +- Trail A/B 创建 +- generation 初值 +- 首帧成功 + +### T2. ACTIVE ping-pong + +保持至少数十帧。 + +确认: + +- State A/B 持续交替 +- Trail A/B 持续交替 +- frame counter 增长 +- 地图本身正常 + +### T3. STATIC + +确认: + +- ping-pong 停止推进 +- 不继续由 validation layer 触发无意义帧 +- 地图手势仍可触发正常 redraw + +### T4. resize + +执行当前设备环境下真实可行的 resize,例如: + +- 旋转屏幕 +- 改变 Activity / window 尺寸 +- 或当前 Test App 已有明确 resize 方法 + +确认: + +- Trail A/B 被重建为新尺寸 +- State A/B 不发生无必要重建 +- 地图正常 +- 无 stale target + +### T5. disable / enable + +确认: + +- disable 后停止 +- enable 后恢复 +- generation/index 状态合理 +- 无 crash + +### T6. context / surface recreation + +Codex 必须根据当前 Android OpenGL backend 实际生命周期,给出能最大概率触发真实 recreation 的步骤。 + +可能包括但不限于: + +- Activity recreate +- Surface destroy/recreate +- 后台/前台 +- 离开并重新进入验证 Activity + +但最终判定必须看日志是否真正发生资源/context generation 变化。 + +仅“界面重新出现”不算通过。 + +### T7. recreation 后继续运行 + +确认: + +- old resources destroy/invalid +- new resources create +- generation 增加 +- ping-pong 重新正常工作 +- Trail 从清空状态重新积累 +- 地图无异常 + +--- + +## 19. 两阶段执行方式 + +本任务继续采用 30-01 的两阶段方式。 + +### 阶段 A:验证代码准备 + +Codex: + +1. 检查 30-01 PASS 前置条件 +2. 读取当前 gfx / Android OpenGL 生命周期 +3. 设计最小验证实现 +4. 写验证代码 +5. 做静态检查 +6. 生成暂定技术验证报告 +7. 生成 Codex 完成报告 +8. 追加开发记录 +9. 给出用户手工编译/运行步骤 +10. commit +11. push 到公开 `particle/main` + +此时结论只能是: + +`WAITING_MANUAL_VALIDATION` + +不得写 PASS。 + +--- + +### 阶段 B:用户返回编译/运行结果后 + +Codex: + +1. 读取用户提供的编译输出、日志和现象 +2. 只修复 30-02 范围内的问题 +3. 如果发现架构/gfx 路线本身失败,停止 +4. 不通过扩大范围强行修成另一套架构 +5. 更新技术验证报告 +6. 更新 Codex 完成报告 +7. 追加开发记录 +8. commit +9. push 到公开 `particle/main` + +最终只能是: + +- `PASS` +- `FAIL` +- `BLOCKED` + +--- + +## 20. PASS 标准 + +只有同时满足以下条件,30-02 才能 PASS: + +- [ ] 30-01 当前正式状态为 PASS +- [ ] State A/B 两套独立 GPU resource 成功建立 +- [ ] State A/B 按帧安全交替 +- [ ] 不发生同资源同时读写 hazard +- [ ] Trail A/B 两套真实 RenderTarget 成功建立 +- [ ] Trail previous → next 的 GPU pass 实际运行 +- [ ] Trail A/B 按帧交替 +- [ ] Trail 能合成回 MapLibre 正常主 render pass +- [ ] 多 pass 顺序在当前 gfx 中稳定 +- [ ] 当前 Android OpenGL 同步语义已被真实确认 +- [ ] 不依赖 CPU 每帧复制完整状态 +- [ ] 不依赖 MapView 外部 Overlay +- [ ] 不建立平台独立动画循环 +- [ ] resize 后 Trail target 正确重建 +- [ ] disable 后停止无意义 GPU 更新 +- [ ] enable 后可恢复 +- [ ] 实际观察到资源/context generation 变化 +- [ ] context/surface recreation 后旧资源不再使用 +- [ ] recreation 后新资源重新建立 +- [ ] recreation 后 ping-pong 恢复 +- [ ] recreation 后 Trail 可重新开始 +- [ ] MapLibre 地图渲染不被破坏 +- [ ] 无 crash +- [ ] 无明显 stale resource / framebuffer corruption +- [ ] 未扩大到正式粒子算法、真实 Field、Mask、Vulkan、iOS +- [ ] 未引入新第三方依赖 + +任何关键门槛缺少实际运行证据,不得标记 PASS。 + +--- + +## 21. FAIL / BLOCKED 与停止条件 + +出现以下情况时停止继续向后实现。 + +### F1. gfx 无法表达安全 ping-pong + +如果必须绕开当前 gfx,在 Core 粒子逻辑中大量直接写 raw OpenGL 才能完成: + +- 停止 +- 标记架构问题 +- 不继续 30-03 + +### F2. RenderTarget 无法作为下一 pass 的稳定采样源 + +如果当前架构下无法安全完成: + +`write → pass end → sample` + +且无法通过很小的 gfx 合理扩展解决: + +- 停止 +- 报告真实限制 + +### F3. Context recreation 后存在 stale resource + +如果旧 texture / render target 在新 context/resource generation 中仍被使用: + +- 30-02 FAIL +- 不得忽略 crash 或图形损坏 + +### F4. 必须把 GPU 生命周期放到 Android 平台层形成第二套 engine + +如果 Core/gfx 无法共用,必须在 Android 独立维护完整 particle GPU engine: + +- 停止 +- 回到架构设计 + +### F5. 为了验证需要大规模修改 Renderer / Map 主循环 + +如果本验证迫使明显侵入: + +- Renderer 总体架构 +- Map 主循环 +- 通用 Layer 系统 +- 大量 gfx backend + +则停止,不得以“先能跑”为理由继续扩张。 + +### B1. 无法触发真实 context recreation + +如果代码本身运行正常,但当前测试环境无法可靠触发或确认真实 GPU context recreation: + +最终状态应为: + +`BLOCKED` + +不得写 PASS。 + +--- + +## 22. 禁止事项 + +本任务禁止: + +- 正式 Particle Field +- 正式 U/V Grid +- fixture decode 正式实现 +- velocity texture 正式 contract +- 正式粒子 position / age / seed +- 正式 advection +- 正式 respawn +- 正式 random 系统 +- 正式风粒子效果 +- Wave/Tide/Current 正式实现 +- Land/Ocean Mask +- world wrap 专项实现 +- antimeridian 专项实现 +- 真实天气/海洋服务 +- Android Vulkan +- iOS OpenGL +- iOS Metal +- RN/JS bridge +- 新产品 API +- 新第三方依赖 +- MapLibre 版本升级 +- Android SDK / NDK / Gradle 升级 +- 与本任务无关的旧代码清理 +- Jest + +--- + +## 23. 允许修改范围 + +优先只修改: + +- 30-01 已建立的 Particle validation 相关 Core Layer / RenderLayer +- 新增的 `ParticleGpuValidation*` 验证资源/辅助类 +- validation-only shader +- Android Test App 当前粒子验证入口 +- 必要且最小的 gfx 接口扩展 +- 本任务文档 +- `粒子开发记录.md` + +不得机械创建完整正式 particle production 目录树。 + +如果需要改动通用 gfx 文件: + +- 必须逐项列出 +- 解释为什么现有 API 不足 +- 保持修改最小 +- 不得夹带重构 + +--- + +## 24. 建议验证命名 + +优先使用: + +- `ParticleGpuValidationResources` +- `ParticleGpuValidationPass` +- `ParticlePingPongValidation` +- `ParticleTrailValidation` +- `ParticleGpuValidationShader` + +或与当前仓库命名风格一致的等价名称。 + +所有临时代码应明确: + +`VALIDATION ONLY` + +不得把未冻结代码命名为最终 `ParticleSimulation` / `ParticleTrailRenderer` 并假装已经生产化。 + +--- + +## 25. 技术验证报告 + +生成: + +`docs/60_测试/30_02_GPU_PingPong与ContextRecreation最小技术验证报告_v1.md` + +如果同主题已有文件: + +- 不覆盖 +- 递增版本号 + +报告必须严格区分: + +1. 静态源码确认 +2. Codex 可确认的实现事实 +3. 用户手工编译结果 +4. 用户实际运行结果 +5. 日志证据 +6. 推论 +7. 未验证项 + +阶段 A 时必须写: + +`WAITING_MANUAL_VALIDATION` + +--- + +## 26. Codex 完成报告 + +生成: + +`docs/报告/30_02_GPU_PingPong与ContextRecreation验证_Codex完成报告_v1.md` + +如果同主题已有报告: + +- 递增版本号 +- 不覆盖旧报告 + +报告至少逐项说明: + +1. 30-01 前置状态 +2. 当前 Git 基线 +3. 前置文档读取 +4. 实际修改文件 +5. State A/B 实现位置 +6. Trail A/B 实现位置 +7. RenderTarget 创建链 +8. ping-pong swap 逻辑 +9. pass 顺序 +10. 同步 / hazard 处理 +11. Android OpenGL backend 事实 +12. resize 生命周期 +13. disable/enable 生命周期 +14. context/surface lifecycle +15. resource generation 机制 +16. Test App 验证入口 +17. 用户手工编译命令 +18. 用户手工运行步骤 +19. 当前验证状态 +20. 是否修改通用 gfx +21. 是否修改生产代码 +22. 是否引入依赖 +23. 是否扩大范围 +24. 未验证项 +25. PASS / FAIL / BLOCKED 依据 +26. 是否允许进入 30-03 +27. Git commit +28. push 结果 +29. 最终远端 HEAD + +--- + +## 27. 开发记录 + +追加: + +`粒子开发记录.md` + +必须记录: + +- 30-02 开始 +- 30-01 前置状态 +- State A/B 验证结论 +- Trail A/B 验证结论 +- gfx 同步结论 +- resize 结论 +- context recreation 结论 +- 最终状态 +- 是否允许进入 30-03 +- 相关报告路径 + +不得重写已有历史。 + +--- + +## 28. 不主动创建 Step + +本任务不主动创建或修改: + +`docs/50_Step记录/` + +只有用户明确要求时才创建 Step。 + +--- + +## 29. Git 收尾规则 + +本任务只要产生代码或文档修改,就必须 commit 并 push。 + +目标: + +- 本地主线:`particle/main` +- 公开远端对应分支:`particle/main` + +### 29.1 提交范围 + +只允许提交: + +- 本任务验证代码 +- 本任务 shader +- 本任务 Test App 调整 +- 本任务技术验证报告 +- 本任务 Codex 完成报告 +- 本任务对 `粒子开发记录.md` 的追加 + +不得提交与本任务无关的本地修改。 + +--- + +### 29.2 阶段 A 提交 + +验证代码准备完成后: + +1. 检查 `git diff` +2. 明确本任务文件列表 +3. stage 本任务文件 +4. commit +5. push 到公开 `particle/main` +6. 确认远端可见 + +推荐 commit message: + +`test: add particle gpu ping-pong validation` + +阶段 A 报告状态必须仍为: + +`WAITING_MANUAL_VALIDATION` + +--- + +### 29.3 阶段 B 提交 + +用户手工验证结果回填后: + +1. 更新技术验证报告 +2. 更新 Codex 完成报告 +3. 更新开发记录 +4. 如需修复,只修复 30-02 范围 +5. commit +6. push 到公开 `particle/main` +7. 确认远端可见 + +推荐 commit message: + +`test: finalize particle gpu ping-pong validation` + +--- + +### 29.4 Push 失败 + +如果 push 失败: + +- 不得声称完整完成 +- 不得声称公开远端已经更新 +- 完成报告必须写明: + - push 失败 + - 失败原因 + - 本地 commit hash + - commit message + - 目标远端 + - 目标分支 + - 当前本地 HEAD + +--- + +## 30. Git 信息记录 + +Codex 完成报告必须记录: + +- 任务开始 HEAD +- 30-01 PASS commit +- 本次主要变更 commit hash +- commit message +- push 是否成功 +- 公开远端 +- 远端分支 +- push 后远端可见状态 +- 最终远端 HEAD +- 是否存在未提交的无关本地改动 + +为避免报告自引用 commit hash: + +- 完成报告中的“主要变更 commit hash”记录包含验证代码和主要文档的实质性提交; +- 如果还有仅用于回填报告元数据的收尾 commit,Codex 最终回复中额外报告最终远端 HEAD; +- 不得无限 amend 只为让报告包含自己的 commit hash。 + +--- + +## 31. 30-03 进入条件 + +只有 30-02 最终状态为: + +`PASS` + +才允许进入下一项最小技术验证。 + +下一项预计为: + +> Camera / world wrap / Land-Ocean Mask 最小技术验证。 + +如果 30-02 为: + +- `FAIL` +- `BLOCKED` + +则不得提前开始 30-03。 + +必须先处理 GPU/gfx/context 生命周期阻塞。 + +--- + +## 32. 本任务完成定义 + +30-02 真正完成不是“创建了四个 texture”。 + +必须满足: + +> 在 Android OpenGL 的真实 MapLibre RenderLayer / gfx 渲染链中,已经通过用户实际运行证据确认:State A/B 与 Trail A/B 可以使用 MapLibre 当前 GPU resource / RenderTarget 体系安全 ping-pong;多 pass 顺序和同步语义成立;viewport resize 后资源正确重建;Layer disable/enable 生命周期正确;真实 surface/context/resource recreation 后旧资源不会被继续使用,新 generation 可以安全重建并恢复 ping-pong,同时不破坏地图正常渲染。 + +没有用户实际运行证据时,只能标记: + +`WAITING_MANUAL_VALIDATION` + +真实 context recreation 无法验证时: + +`BLOCKED` + +关键架构门槛失败时: + +`FAIL` + +不得为了阶段推进把未验证结果写成 PASS。 diff --git a/docs/60_测试/30_02_GPU_PingPong与ContextRecreation最小技术验证报告_v1.md b/docs/60_测试/30_02_GPU_PingPong与ContextRecreation最小技术验证报告_v1.md new file mode 100644 index 000000000..7a25c038e --- /dev/null +++ b/docs/60_测试/30_02_GPU_PingPong与ContextRecreation最小技术验证报告_v1.md @@ -0,0 +1,71 @@ +# 30-02 GPU Ping-Pong 与 Context Recreation 最小技术验证报告 v1 + +日期:2026-08-29 + +当前状态:`BLOCKED` + +## 1. 阻塞结论 + +30-02 未进入 GPU 验证代码准备阶段。 + +`docs/40_任务/30_02_GPU_PingPong与ContextRecreation验证指令书_v1.md` 第 2 节规定:只有当前仓库存在 `30-01 = PASS` 的正式记录时,才允许开始 State A/B、Trail A/B、RenderTarget、Shader 或 context recreation 验证代码。 + +当前有效前置记录均为: + +- `docs/60_测试/30_01_CoreRenderLayer接入最小技术验证报告_v2.md`:`WAITING_MANUAL_VALIDATION`; +- `docs/报告/30_01_CoreRenderLayer接入验证_Codex完成报告_v2.md`:`WAITING_MANUAL_VALIDATION`; +- `粒子开发记录.md`:修复后的 Android OpenGL 编译和实机运行仍待用户。 + +仓库中不存在 30-01 正式 PASS 记录,也不存在 30-01 PASS commit。因此 30-02 前置条件未满足。 + +## 2. 本轮实际执行 + +- 完整读取 30-02 指令书并执行前置门槛检查; +- 读取当前 30-01 技术报告、Codex 完成报告和开发记录; +- 检查分支、HEAD、工作区、远端同步与 submodule; +- 生成本阻塞报告和对应 Codex 完成报告; +- 追加开发记录。 + +## 3. 未开始的验证项 + +以下项目因前置门槛阻塞,均未实现、未运行、无结论: + +- State A/B GPU resource; +- State A/B ping-pong; +- Trail A/B offscreen RenderTarget; +- previous trail → next trail pass; +- Trail composite; +- 多 pass 同步与 hazard; +- viewport resize 资源重建; +- disable/enable GPU 生命周期; +- context/resource generation; +- Android EGL/surface context recreation 运行验证。 + +不得把“未开始”解释为 PASS 或 FAIL。 + +## 4. 代码与构建 + +- 30-02 Core/gfx/renderer/shader/Test App 代码修改:无。 +- 通用 gfx 修改:无。 +- 生产代码修改:无。 +- 新依赖:无。 +- 编译:未执行。 +- Android/Gradle/ADB:未执行。 +- APK/AAR 或其他产物:无。 + +## 5. 解除阻塞条件 + +用户必须先在最新 `particle/main` 上完成 30-01 修复后的 Android OpenGL 手工编译和实机验证,并回传足够证据,使 30-01 正式报告更新为 PASS。至少需要确认: + +- validation Drawable/Tweaker 真正进入 translucent render pass; +- 同帧 viewport、zoom、bearing、pitch、projection 证据有效; +- pan、zoom、rotate、pitch、resize 正常; +- ACTIVE 持续 repaint; +- STATIC 停止验证层额外 repaint; +- 地图正常且无 RenderThread crash。 + +只有 30-01 报告与开发记录正式更新为 PASS 并提交后,才能重新执行 30-02。 + +## 6. 30-03 状态 + +不允许进入 30-03。30-02 当前为 `BLOCKED`,且其自身尚未开始。 diff --git a/docs/报告/30_02_GPU_PingPong与ContextRecreation验证_Codex完成报告_v1.md b/docs/报告/30_02_GPU_PingPong与ContextRecreation验证_Codex完成报告_v1.md new file mode 100644 index 000000000..6a5e11f94 --- /dev/null +++ b/docs/报告/30_02_GPU_PingPong与ContextRecreation验证_Codex完成报告_v1.md @@ -0,0 +1,95 @@ +# 30-02 GPU Ping-Pong 与 Context Recreation 验证 Codex 完成报告 v1 + +日期:2026-08-29 + +执行结论:`BLOCKED` + +## 1. 30-01 前置状态 + +当前仓库不存在 `30-01 = PASS` 的正式记录: + +- 最新 30-01 技术验证报告 v2:`WAITING_MANUAL_VALIDATION`; +- 最新 30-01 Codex 完成报告 v2:`WAITING_MANUAL_VALIDATION`; +- 开发记录仍要求用户完成修复后的 Android OpenGL 手工编译和实机验证。 + +30-01 PASS commit:不存在。 + +因此触发 30-02 指令书第 2 节停止条件:不得开始 GPU 代码,只生成阻塞说明。 + +## 2. Git 基线 + +- 分支:`particle/main`。 +- 任务开始 HEAD:`a1bcea9bbcbac18b884e647a92775f568d96d0df`。 +- 开始时本地与 `origin/particle/main`:`0 0`,同步。 +- 开始时无已跟踪修改。 +- 开始时存在用户提供的未跟踪 30-02 指令书。 +- submodule:已查询,无本任务修改。 +- origin:`ssh://git@192.168.200.230:2222/tei/MapLibreParticleLab.git`。 +- 目标分支:`particle/main`。 +- 本次 commit hash:因本报告与阻塞文档同一提交,在最终回复记录。 +- commit message:`docs: record blocked gpu validation prerequisite`。 +- push 结果与最终远端 HEAD:提交后在最终回复记录。 + +## 3. 前置文档读取 + +已读取 `AGENTS.md`、`PARTICLE_BASELINE.md`、`docs/00_项目总则/`、`docs/00_项目规范/`、当前 STEP-000、30-02 指令书、架构调查/设计、前置完成报告、全部当前 30-01 技术/完成报告和 `粒子开发记录.md`。 + +## 4. 实际修改文件 + +- 纳入用户提供的 `docs/40_任务/30_02_GPU_PingPong与ContextRecreation验证指令书_v1.md`; +- 新增 `docs/60_测试/30_02_GPU_PingPong与ContextRecreation最小技术验证报告_v1.md`; +- 新增本 Codex 完成报告; +- 追加 `粒子开发记录.md`。 + +未创建或修改 Step,符合 30-02 指令书第 28 节。 + +## 5. State A/B + +未实现、未验证。阻塞发生在允许开始 GPU 代码之前。 + +## 6. Trail A/B 与 RenderTarget + +未实现、未验证。没有创建 texture、RenderTarget、validation shader 或 composite pass。 + +## 7. Ping-pong、pass 顺序与 hazard + +未实现、未验证。没有形成 State/Trail swap,也没有得出 Android OpenGL 同步语义结论。 + +## 8. resize、disable/enable 与 generation + +未实现、未验证。没有增加 resource generation 或生命周期代码。 + +## 9. context/surface lifecycle + +未进入源码实现或设备验证阶段;没有声称普通 Activity lifecycle 等同于真实 context recreation。 + +## 10. Test App 与用户命令 + +30-02 Test App 入口未创建。当前唯一动作是先完成 30-01 手工验证;本轮不提供 30-02 编译/运行步骤,以免用户误以为 30-02 已具备可运行代码。 + +## 11. 构建、测试与产物 + +- 编译:未执行。 +- 测试:只执行文档/Git 静态检查。 +- Android/Gradle/ADB:未执行。 +- APK/AAR:无。 +- 用户此前要求 Codex 不编译,本轮同时遵守该要求。 + +## 12. 修改边界 + +- 通用 gfx:未修改。 +- 生产代码:未修改。 +- shader:未新增。 +- 依赖/SDK/NDK/Gradle/MapLibre baseline:未修改。 +- GPU ping-pong、Mask、Vulkan、iOS:未实现。 +- 架构范围:未扩大。 + +## 13. BLOCKED 依据与未验证项 + +阻塞依据是 30-02 指令书第 2 节的硬前置门槛,而不是 GPU/gfx 技术失败。State、Trail、同步、resize、disable/enable、context recreation 等全部仍为未验证。 + +解除阻塞需要先用最新 30-01 修复提交完成 Android OpenGL 实机验证,并把 30-01 正式更新为 PASS。 + +## 14. 是否允许进入 30-03 + +否。30-02 当前为 `BLOCKED`,不得进入 30-03。 diff --git a/粒子开发记录.md b/粒子开发记录.md index 55b03c8ad..7ea7ac768 100644 --- a/粒子开发记录.md +++ b/粒子开发记录.md @@ -62,3 +62,13 @@ - 版本条用于人工验证时区分旧 APK 与当前源码构建,避免只凭安装时间或文件名判断。 - `git diff --check` 与 Android XML 标准库解析通过;按用户要求未执行任何编译。 - 等待用户手工构建、安装后确认设备端显示。 + +## 2026-08-29 — 30-02 GPU Ping-Pong 与 Context Recreation(前置阻塞) + +- 开始执行 `docs/40_任务/30_02_GPU_PingPong与ContextRecreation验证指令书_v1.md` 并首先检查硬前置门槛。 +- 30-01 最新技术报告与完成报告均仍为 `WAITING_MANUAL_VALIDATION`,不存在正式 PASS 记录或 PASS commit。 +- 按 30-02 指令书第 2 节停止:未创建 State A/B、Trail A/B、RenderTarget、Shader、ping-pong、generation 或 context recreation 验证代码。 +- State A/B、Trail A/B、gfx 同步、resize、disable/enable 和 context recreation 均未验证,无 PASS/FAIL 技术结论。 +- 当前 30-02 状态为 `BLOCKED`;不允许进入 30-03。 +- 阻塞报告:`docs/60_测试/30_02_GPU_PingPong与ContextRecreation最小技术验证报告_v1.md`。 +- Codex 完成报告:`docs/报告/30_02_GPU_PingPong与ContextRecreation验证_Codex完成报告_v1.md`。