diff --git a/docs/40_任务/STEP-094_通用RenderSegment分段渲染与Style分类诊断_Codex任务_v1.md b/docs/40_任务/STEP-094_通用RenderSegment分段渲染与Style分类诊断_Codex任务_v1.md new file mode 100644 index 000000000..b8a737700 --- /dev/null +++ b/docs/40_任务/STEP-094_通用RenderSegment分段渲染与Style分类诊断_Codex任务_v1.md @@ -0,0 +1,599 @@ +# STEP-094 通用 Render Segment 分段渲染与 Style 分类诊断 — Codex 任务 v1 + +## 0. 任务目标 + +从已冻结的 Particle V12 `Bottom Retained / Continuous / Top Retained` 单 Continuous Range 模型,演进到最终通用模型: + +```text +Style Z-order + ↓ +连续 layerIndex + ↓ +若干连续 Render Segment + ↓ +每个 Segment 的执行策略仅为: +CONTINUOUS 或 RETAINED +``` + +Style 顺序继续是唯一 Z-order 事实来源。Renderer 不理解 LOW / MEDIUM / HIGH,也不理解 AIS、Route、地图、Weather 等业务语义。 + +本 STEP 同时必须建立新的 pull-based Segment Diagnostics,能够取回“当前 Style → Segment → Layer”的真实分类快照,供后续人工判断 Segment 划分是否合理。 + +## 1. 当前冻结基线 + +工作目录:`/Users/tei/dev/MapLibreParticleLab` +目标分支:`particle/main` + +当前已知 V12 冻结基线: +- HEAD:`7eaff6e12360e26591dceb5e011129eeab7ba4c7` +- Commit:`release: finalize unified particle.12` +- Tag:`maplibre-particle/rn/13.4.1-particle.12` +- `HEAD == origin/particle/main` +- 工作区 clean + +开始前必须重新执行 fetch/status/HEAD 检查,以实际仓库为准。禁止 reset/clean,禁止回退、移动、覆盖 V12 Tag。STEP-094 是 V12 之后的新开发,不修改 V12 已发布事实。 + +必须先读取: +- 根目录 `AGENTS.md` +- `ARCHITECTURE.md` +- STEP-092 / STEP-093 任务、Step 记录与完成报告 +- V12 当前 Continuous Range、Retained Cache、Fast Path、Android/iOS/RN bridge 实现 +- 当前 `RendererRuntime.ts`、`types.ts`、`NativeWeatherRuntimeBridge.ts` + +## 2. 最终架构原则 + +1. Style Layer 顺序是唯一 Z-order 真相。 +2. 整个 Style 必须按连续 layerIndex 被完整划分为 1..N 个 Render Segment。 +3. 每个 Segment 只声明 `RETAINED` 或 `CONTINUOUS`。 +4. 允许多个 RETAINED、多个 CONTINUOUS,且可按 Style 顺序任意交错。 +5. 相邻同策略 Segment 不得自动合并。 +6. 每个 RETAINED Segment 独立拥有 cache / revision / invalidation / rebuild / GPU resource。 +7. CONTINUOUS Segment 不创建 retained texture/FBO/compositor。 +8. Renderer 不自动分析 Layer 更新频率,不自动调整 Z-order。 +9. App 通过 Style 顺序 + Segment boundary 表达分类。 +10. 不建立 LOW/MEDIUM/HIGH 第二套业务分类。 +11. 不硬编码 NavSea Layer ID。 +12. 不增加空白 Anchor / Marker Layer。 + +V12 三明治只是本模型的一个特例:`RETAINED → CONTINUOUS → RETAINED`。 + +## 3. 命名约束 + +MapLibre 现有代码已经大量使用 shader/bucket 的 `Segment` / `SegmentVector`。本任务禁止新增裸名称 `Segment` 造成语义冲突。 + +新模型命名必须明确属于 Renderer execution topology,例如: +- `RenderSegmentStrategy` +- `RenderSegmentDefinition` +- `RenderSegmentPlan` +- `ResolvedRenderSegment` +- `RenderSegmentDiagnostics` +- `RetainedSegmentCache` + +具体文件名可按当前代码结构调整,但必须避免与 geometry/shader Segment 混淆。 + +## 4. Segment Plan 公共语义 + +推荐公共模型: + +```text +RenderSegmentDefinition + strategy: RETAINED | CONTINUOUS + startLayerId?: string +``` + +规则: +- definitions 至少 1 个。 +- 第 0 个 Segment 从 Style index 0 开始,`startLayerId` 必须省略/为空。 +- 第 1..N-1 个 Segment 必须提供非空 `startLayerId`。 +- startLayerId 必须引用当前 Style 中已经存在的普通 Layer。 +- Native 根据当前 Style 解析真实 layerIndex。 +- App/RN 不传数字 index。 + +例如: + +```text +[ + { strategy: RETAINED }, + { strategy: CONTINUOUS, startLayerId: "rn-weather-color" }, + { strategy: RETAINED, startLayerId: "land-area" }, + { strategy: RETAINED, startLayerId: "ais-layer" } +] +``` + +解析后: +- Segment 0 = `[0, index(rn-weather-color))` +- Segment 1 = `[index(rn-weather-color), index(land-area))` +- Segment 2 = `[index(land-area), index(ais-layer))` +- Segment 3 = `[index(ais-layer), layerCount)` + +Segment 2/3 虽然都是 RETAINED,也必须保持两个独立 cache,不得合并。 + +这种定义保证整个 Style 完整覆盖;插入普通 Layer 后依据 Style 位置自然进入对应 Segment;最顶端新增 Layer自动属于最后一个 Segment。 + +## 5. Plan 合法性与 resolve + +有效计划必须满足: +- Style ready; +- 所有 boundary Layer 存在; +- boundary index 严格递增; +- 无重复 boundary; +- 每个 resolved Segment 非空; +- 最终覆盖 `[0, layerCount)`; +- 不重叠、不留 gap。 + +hidden / visibility=none 的 boundary Layer 仍参与 topology。Visibility 变化不得改变 Segment membership。 + +以下情况 plan invalid: +- boundary missing; +- boundary 顺序反转或重复; +- Style 未 ready; +- 空 definitions; +- 非法 strategy; +- JSON/schema 非法。 + +invalid 时不得 crash、不得猜 boundary、不得复用 stale cache。必须释放/隔离失效 topology 的 retained resource,安全走 full renderer,并在 diagnostics 给出明确 reason。Style 后续恢复合法时允许自动重新 resolve。 + +必须有 monotonic `configRevision`。Style add/remove/reorder 后重新 resolve;实际 begin/end 变化时推进 `topologyRevision`。Visibility 变化不得推进 topologyRevision。 + +## 6. Renderer 执行模型 + +Resolved Segment 按 Style 顺序执行: + +```text +for segment in resolvedSegments: + RETAINED -> build/reuse cache -> composite + CONTINUOUS -> direct render +``` + +逻辑上按 Segment 顺序组合,但实际实现必须继续满足 MapLibre 原有 RenderPass 语义。 + +必须保持: +- 全 Style 原始 global layerIndex; +- 原始 ordinal; +- `parameters.currentLayer`; +- `depthRangeSize`; +- Opaque reverse traversal; +- Translucent forward traversal。 + +禁止每个 Segment 从 0 重新编号,禁止为了 Segment 模型重新排序 Style Layer。 + +## 7. RETAINED Segment 独立 Cache + +每个 RETAINED Segment 必须拥有独立: +- cache state; +- content revision; +- build/reuse/invalidation count; +- last invalidation reason; +- texture/compositor create count; +- resource release count。 + +GPU resource 必须 lazy 创建。CONTINUOUS Segment 绝不能因为占位而创建 retained texture。 + +Plan/topology 改变后,不能证明安全复用的旧 cache 必须释放并重建;stale segment cache 绝不能错误 composite。本 STEP 不要求复杂 cache migration,correctness-first。 + +## 8. Invalidation 粒度 + +目标是 Segment 级 invalidation。 + +能够明确定位影响 Segment 时,只 invalidate 受影响 RETAINED Segment;其他 RETAINED Segment 保持 valid/reuse。 + +LayerMutation 若明确属于某 Segment,应只使该 Segment dirty。Source/Tile mutation 若能从现有 RenderLayer/Source 关系安全确定影响的多个 Segment,应 invalidate 对应集合。 + +若无法可靠确定影响范围,允许保守 invalidate 全部 RETAINED Segment。本 STEP 不建立复杂通用 dependency graph。 + +camera/transform/viewport/resize/pixel ratio、style reload、image/sprite/glyph、placement/symbol fade/transition、context reset、debug options、unsupported 3D、resource/compositor failure 等无法证明局部安全时可 invalidate 全部 retained。 + +完成报告必须区分“已实现的 segment-local invalidation”和“仍采用全 retained invalidation 的原因”。 + +## 9. Cache ON/OFF + +现有 Cache ON/OFF 总开关继续有效。 + +Cache OFF: +- Segment Plan 仍然 resolve; +- Diagnostics 仍能看到 Style/Segment/Layer 分类; +- RETAINED Segment 不错误复用 retained GPU cache; +- Renderer 安全走非 retained 路径。 + +Cache ON: +- 每个 RETAINED Segment 独立 build/reuse; +- CONTINUOUS Segment 直接绘制。 + +关闭所有 CONTINUOUS Layer 的 visibility 不得删除 Segment topology。 + +## 10. V12 兼容入口 + +不得破坏现有: +- `setRetainedUnderlayEnabled()` +- `setContinuousLayerRange(startLayerId,endLayerId)` +- `getRetainedUnderlayDiagnostics()` + +新内部实现应尽量只有一套 Segment topology。 + +`setContinuousLayerRange(start,end)` 应作为 compatibility adapter,转换成等价 RenderSegmentPlan: +- start 前存在 → RETAINED +- start..end → CONTINUOUS +- end 后存在 → RETAINED + +自然退化成 V12 原有 1/2/3 Range。 + +旧 API 与新 Segment Plan 不得同时形成两套 Renderer topology。最后一次显式 topology 配置必须只有一个 active plan,并从 diagnostics 可见 `configSource`。 + +旧 `getRetainedUnderlayDiagnostics()` 保留兼容摘要;新的多 Segment 事实以新 Diagnostics API 为准。 + +## 11. 新 RN / Native API + +新增稳定公共语义: + +```text +RendererRuntime.setRenderSegmentPlan(reactTag, plan) +RendererRuntime.getRenderSegmentDiagnostics(reactTag) +``` + +建议 TS: + +```text +RenderSegmentStrategy = "RETAINED" | "CONTINUOUS" + +RenderSegmentDefinition = { + strategy: RenderSegmentStrategy + startLayerId?: string +} + +RenderSegmentPlan = { + schemaVersion: 1 + segments: readonly RenderSegmentDefinition[] +} +``` + +RN public API 必须是 typed object。TurboModule ABI 可使用 JSON string 作为 plan/snapshot 内部传输,避免可扩展嵌套数组变成脆弱 parallel arrays。若采用 JSON,必须有 schemaVersion 与严格校验;public TS 不暴露 raw JSON。 + +必须沿当前真实链路扩展: +`RendererRuntime → NativeWeatherRuntimeBridge/TurboModule → Android/iOS package bridge → MapLibre platform API → Core Renderer state`。 + +不得新建第二套独立 RN bridge。 + +## 12. Segment Diagnostics — 强制要求 + +这是 STEP-094 的强制验收项,不是附加日志。 + +新增 pull-based `getRenderSegmentDiagnostics()`,必须能够取回当前真实 Style 的: +1. Style 全 Layer 顺序; +2. 当前 resolved Segment 顺序; +3. 每个 Segment 的 strategy; +4. 每个 Segment 的 begin/end; +5. 每个 Segment 内实际包含的 Layer; +6. 每个 RETAINED Segment 的 cache 状态与统计。 + +Diagnostics 只能按需读取。禁止 per-frame 打印完整 Style/Segment/Layer,禁止每帧构造大 JSON/大字符串。 + +## 13. Diagnostics Snapshot 最低字段 + +顶层至少: + +```text +schemaVersion +enabled +configured +valid +configSource +configRevision +topologyRevision +styleLayerCount +segmentCount +retainedSegmentCount +continuousSegmentCount +coverageComplete +fallback +lastReason +fastPathEligible +fastPathActive +fastPathFallbackReason +fastPathHit +fastPathMiss +fullCpuFrame +``` + +`configSource` 至少区分: +- `explicit-render-segment-plan` +- `continuous-range-compat` +- `unconfigured/legacy`(若仍存在) + +必须提供完整 ordered `styleLayers[]`,用于 plan invalid 时仍可人工分析 Style。 + +## 14. Style Layer Diagnostics + +每个 `styleLayers[]` / Segment 内 `layers[]` 至少返回: + +```text +layerIndex +layerId +layerType +visible +``` + +如当前 Style/Core 可低成本稳定取得,还应返回: +- `sourceId` +- `sourceLayer` + +不适用时可为空/null,禁止伪造。Layer Diagnostics 只描述通用 Style 信息,禁止加入 AIS/Route/Wind 等业务判断。 + +## 15. 每个 Segment Diagnostics + +每个 Segment 至少: + +```text +segmentIndex +strategy +configuredStartLayerId +beginIndex +endExclusive +resolvedStartLayerId +resolvedEndLayerId +layerCount +layers[] +``` + +如果 `strategy=RETAINED`,还必须有: + +```text +cacheState +contentRevision +build +reuse +invalidation +lastInvalidationReason +textureCreate +compositeCreate +resourceRelease +``` + +如果 `strategy=CONTINUOUS`,不得伪装成 disabled retained cache。retained-only 字段应为 null/not-applicable,或由 TS discriminated union 排除。 + +## 16. Diagnostics 一致性 + +当 plan valid: +- `styleLayers.length == styleLayerCount` +- Segment 按 segmentIndex/beginIndex 严格递增 +- 所有 `segment.layers[]` 拼接后必须与 `styleLayers[]` 完全一致 +- 每个 Style Layer 必须且只能属于一个 Segment +- `segment.layerCount == segment.layers.length` +- `coverageComplete=true` + +当 plan invalid: +- 仍尽可能返回当前 ordered styleLayers +- segments 可为空或只返回已安全解析部分,但必须 `valid=false` +- 禁止把猜测结果标成 valid + +## 17. DEBUG 使用目标 + +必须能取回类似: + +```text +Segment 0 RETAINED [0..18) + background + water + coastline + +Segment 1 CONTINUOUS [18..20) + rn-weather-color + rn-weather-particles + +Segment 2 RETAINED [20..27) + land-area + navigation-marks + route + +Segment 3 RETAINED [27..30) + ais + radar + alarm +``` + +此信息只用于人工分析 Style 分类是否合理。Renderer 不根据 Debug 结果自动重新分类。 + +设计文档必须给出至少一个完整 JSON/TS snapshot 示例。 + +## 18. Particle Fast Path + +V12 已有 Particle Fast Path 不得无声退化。 + +至少保证: +- 对“恰好一个 CONTINUOUS Segment + 其余为 RETAINED”的 V12 等价拓扑,且 Continuous 内容满足现有支持条件时,现有 Fast Path 能继续工作。 +- 不存在某个 retained cache 时不得成为 miss 原因。 + +对于多个 CONTINUOUS Segment,若当前 Fast Path 无法安全支持,允许 fail closed: +- `fastPathActive=false` +- 明确 fallback reason +- 正常 full CPU frame +- Segment topology / retained cache / Z-order 仍正确 + +禁止为了 STEP-094 一次性重写整个 RenderGraph 或实现所有 N-Continuous Fast Path 优化。 + +## 19. Style Mutation + +必须验证: +- Segment 内新增/删除/reorder Layer +- boundary 前后插入 Layer +- boundary Layer hidden +- boundary Layer 删除/重新出现 +- boundary reorder 导致 plan invalid +- plan 更新后恢复 + +普通 Layer 插入 Segment 内后应自然成为该 Segment 成员,不要求 App 给每个 Layer 单独注册频率 metadata。 + +相邻 RETAINED Segment 即使策略相同,也必须依靠显式 boundary 保持独立。 + +## 20. GPU 生命周期 + +实际 retained GPU resource 数量应与当前 resolved plan 中 RETAINED Segment 数量一致,允许 lazy 未创建状态,但不得为 CONTINUOUS Segment 分配 retained target。 + +Plan topology 变化后 stale resource 必须正确 release。稳定帧不得重复创建 retained texture/FBO/compositor。OpenGL 与 Metal 行为必须一致。 + +## 21. Native Directed Tests(不加入 Jest) + +本任务明确不加入 Jest。 + +至少覆盖: +1. 单 RETAINED Segment 覆盖全 Style +2. 单 CONTINUOUS Segment 覆盖全 Style +3. V12 等价 R-C-R +4. C-R-R +5. R-R-C +6. R-C-R-C-R 多段交错 +7. 相邻 R-R 不自动 merge +8. hidden boundary 不改变 topology +9. boundary missing / duplicate / 顺序非法 +10. Style 内插入 Layer 后 membership 正确 +11. boundary 删除后 fail safe、恢复后重新 resolve +12. retained resource 数量匹配 RETAINED Segment 数 +13. CONTINUOUS 无 retained resource +14. Cache OFF 时 topology diagnostics 仍完整 +15. V12 `setContinuousLayerRange` 兼容映射 +16. global layerIndex / Opaque / Translucent 语义不变 +17. 多 CONTINUOUS Fast Path 安全 fallback + +Diagnostics tests 额外验证: +- styleLayers 顺序精确 +- segments 顺序精确 +- 每个 Segment 的 layers 成员精确 +- 拼接 segment.layers == styleLayers +- layerIndex 不重编号 +- layerId/layerType/visible 正确 +- sourceId/sourceLayer(若实现)正确 +- invalid plan 仍能取得 ordered styleLayers +- snapshot pull 不产生 per-frame 日志 + +## 22. 平台与 RN 验证 + +Core/C++: +- 执行规定的 Mac 原生精确编译与 Native tests +- OpenGL / Metal +- 编译输出遵循全局 build-output-throttle + +Android: +- 完成源码、JNI/Kotlin/Java/RN bridge 修改 +- Android Gradle 编译由用户手工执行,不由 Codex 运行 +- 报告列明“未执行 Android 编译/实体机”直到用户验证 + +iOS: +- 只面向 iPhone/iPad arm64 真机架构 +- 不要求 Simulator slice +- 可执行当前工程已有的 Mac/iOS arm64 精确编译验证 +- 不伪造实体机运行 PASS + +## 23. 最小 Debug/Validation 入口 + +在当前已有 Particle validation/Test Host 体系中补一个最小 pull 入口: +- Fetch Segment Diagnostics +- 展示或输出一次完整 snapshot +- 能看到 Segment 列表和每个 Segment 的 Layer 列表 + +不得增加持续轮询,不得把大 snapshot 每帧写日志。若现有 UI 已有 diagnostics panel,优先复用。 + +## 24. 性能要求 + +Segment topology/style diagnostic 数据只在 config/style topology 或相关 debug metadata 变化时更新,或在显式 diagnostics pull 时做必要轻量组装。 + +禁止因为 Particle 30/60fps: +- 每帧扫描/复制完整 Style Layer 字符串 +- 每帧 JSON stringify +- 每帧创建 Segment diagnostics 大对象 +- 每帧 Logger 输出 topology + +高频 render path 只消费预解析的轻量 segment ranges/cache state。 + +## 25. 明确不做 + +本 STEP 不做: +- LOW/MEDIUM/HIGH 枚举或自动频率分类 +- Renderer 识别 NavSea 业务 Layer +- 自动调整 Style Z-order +- Anchor/Marker Layer +- 复杂通用业务 dependency graph +- Weather provider / Route ETA / AIS 专项 renderer +- PBF 重生成 +- 通用 RenderGraph 重写 +- 自动合并同策略 Segment +- 多 Continuous 的高级 Fast Path 优化 +- per-frame Segment debug log +- Jest + +如发现必须突破这些边界才能保证 correctness,停止扩大范围并在报告明确 BLOCKED/PARTIAL。 + +## 26. 必做文档 + +新增: +- `docs/30_设计/STEP-094_通用RenderSegment模型与Style分类Diagnostics设计_v1.md` +- `docs/50_Step记录/STEP-094_通用RenderSegment分段渲染与Style分类诊断_v1.md` +- `docs/报告/STEP-094_通用RenderSegment分段渲染与Style分类诊断_Codex完成报告_v1.md` + +追加: +- `粒子开发记录.md` + +同主题已有文件则递增版本,不覆盖历史。所有文档中文。 + +设计文档必须包含最终 Segment 数据模型、config/resolve 生命周期、V12 compatibility mapping、cache ownership、invalidation、Fast Path 边界、Android/iOS/RN API、Diagnostics schema、完整 Style→Segment→Layer snapshot 示例。 + +## 27. 完成报告必须记录 + +- 起始 HEAD / 最终 HEAD +- 修改文件清单 +- RenderSegment config API +- boundary Layer ID → layerIndex 解析 +- N Segment 遍历 +- retained cache ownership/resource lifecycle +- segment-local 与 global invalidation +- V12 compatibility / Fast Path +- Diagnostics schema +- styleLayers / segment.layers 验证 +- RN/Android/iOS bridge +- OpenGL / Metal +- Native test 数量与结果 +- 未执行 Android/实体机项目 +- known limitations +- commit SHA/message +- push result / remote branch +- origin/particle/main Final HEAD +- 最终 `git status --short` + +## 28. Git 规则 + +仅 scoped staging。禁止 `git add -A`、`git add .`、`git reset --hard`、`git clean`,不得删除/覆盖无关 dirty/untracked。 + +结束前必须: +1. `git diff --check` +2. 核对 diff +3. 只 stage 本任务文件 +4. scoped commit +5. push `origin particle/main` +6. fetch/确认远端 + +最终要求: +```text +HEAD == origin/particle/main +git status --short 无本任务残留 +``` + +push 失败不得声称完成。 + +## 29. PASS Gate + +只有以下全部成立才可判 STEP-094 PASS: +- Style Z-order 仍唯一 +- 1..N 连续 Segment 完整覆盖 +- RETAINED/CONTINUOUS 可任意交错 +- 相邻同策略 Segment 不自动合并 +- 每个 RETAINED Segment 独立 cache/revision/invalidation/resource +- V12 Continuous Range 兼容 +- V12 等价 Fast Path 不无声退化 +- 新 Diagnostics 能真实返回 Style→Segment→Layer +- diagnostics pull-based、无 per-frame 大开销 +- Android/iOS/RN API 完整 +- Native directed tests 通过 +- 规定编译验证完成 +- 文档完成 +- scoped commit/push 完成 +- HEAD 与远端一致 + +关键项未完成必须明确 PARTIAL/BLOCKED,禁止伪造 PASS。