19 KiB
STEP-094 通用 Render Segment 分段渲染与 Style 分类诊断 — Codex 任务 v1
0. 任务目标
从已冻结的 Particle V12 Bottom Retained / Continuous / Top Retained 单 Continuous Range 模型,演进到最终通用模型:
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. 最终架构原则
- Style Layer 顺序是唯一 Z-order 真相。
- 整个 Style 必须按连续 layerIndex 被完整划分为 1..N 个 Render Segment。
- 每个 Segment 只声明
RETAINED或CONTINUOUS。 - 允许多个 RETAINED、多个 CONTINUOUS,且可按 Style 顺序任意交错。
- 相邻同策略 Segment 不得自动合并。
- 每个 RETAINED Segment 独立拥有 cache / revision / invalidation / rebuild / GPU resource。
- CONTINUOUS Segment 不创建 retained texture/FBO/compositor。
- Renderer 不自动分析 Layer 更新频率,不自动调整 Z-order。
- App 通过 Style 顺序 + Segment boundary 表达分类。
- 不建立 LOW/MEDIUM/HIGH 第二套业务分类。
- 不硬编码 NavSea Layer ID。
- 不增加空白 Anchor / Marker Layer。
V12 三明治只是本模型的一个特例:RETAINED → CONTINUOUS → RETAINED。
3. 命名约束
MapLibre 现有代码已经大量使用 shader/bucket 的 Segment / SegmentVector。本任务禁止新增裸名称 Segment 造成语义冲突。
新模型命名必须明确属于 Renderer execution topology,例如:
RenderSegmentStrategyRenderSegmentDefinitionRenderSegmentPlanResolvedRenderSegmentRenderSegmentDiagnosticsRetainedSegmentCache
具体文件名可按当前代码结构调整,但必须避免与 geometry/shader Segment 混淆。
4. Segment Plan 公共语义
推荐公共模型:
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。
例如:
[
{ 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 顺序执行:
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
新增稳定公共语义:
RendererRuntime.setRenderSegmentPlan(reactTag, plan)
RendererRuntime.getRenderSegmentDiagnostics(reactTag)
建议 TS:
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 的:
- Style 全 Layer 顺序;
- 当前 resolved Segment 顺序;
- 每个 Segment 的 strategy;
- 每个 Segment 的 begin/end;
- 每个 Segment 内实际包含的 Layer;
- 每个 RETAINED Segment 的 cache 状态与统计。
Diagnostics 只能按需读取。禁止 per-frame 打印完整 Style/Segment/Layer,禁止每帧构造大 JSON/大字符串。
13. Diagnostics Snapshot 最低字段
顶层至少:
schemaVersion
enabled
configured
valid
configSource
configRevision
topologyRevision
styleLayerCount
segmentCount
retainedSegmentCount
continuousSegmentCount
coverageComplete
fallback
lastReason
fastPathEligible
fastPathActive
fastPathFallbackReason
fastPathHit
fastPathMiss
fullCpuFrame
configSource 至少区分:
explicit-render-segment-plancontinuous-range-compatunconfigured/legacy(若仍存在)
必须提供完整 ordered styleLayers[],用于 plan invalid 时仍可人工分析 Style。
14. Style Layer Diagnostics
每个 styleLayers[] / Segment 内 layers[] 至少返回:
layerIndex
layerId
layerType
visible
如当前 Style/Core 可低成本稳定取得,还应返回:
sourceIdsourceLayer
不适用时可为空/null,禁止伪造。Layer Diagnostics 只描述通用 Style 信息,禁止加入 AIS/Route/Wind 等业务判断。
15. 每个 Segment Diagnostics
每个 Segment 至少:
segmentIndex
strategy
configuredStartLayerId
beginIndex
endExclusive
resolvedStartLayerId
resolvedEndLayerId
layerCount
layers[]
如果 strategy=RETAINED,还必须有:
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.lengthcoverageComplete=true
当 plan invalid:
- 仍尽可能返回当前 ordered styleLayers
- segments 可为空或只返回已安全解析部分,但必须
valid=false - 禁止把猜测结果标成 valid
17. DEBUG 使用目标
必须能取回类似:
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。
至少覆盖:
- 单 RETAINED Segment 覆盖全 Style
- 单 CONTINUOUS Segment 覆盖全 Style
- V12 等价 R-C-R
- C-R-R
- R-R-C
- R-C-R-C-R 多段交错
- 相邻 R-R 不自动 merge
- hidden boundary 不改变 topology
- boundary missing / duplicate / 顺序非法
- Style 内插入 Layer 后 membership 正确
- boundary 删除后 fail safe、恢复后重新 resolve
- retained resource 数量匹配 RETAINED Segment 数
- CONTINUOUS 无 retained resource
- Cache OFF 时 topology diagnostics 仍完整
- V12
setContinuousLayerRange兼容映射 - global layerIndex / Opaque / Translucent 语义不变
- 多 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.mddocs/50_Step记录/STEP-094_通用RenderSegment分段渲染与Style分类诊断_v1.mddocs/报告/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。
结束前必须:
git diff --check- 核对 diff
- 只 stage 本任务文件
- scoped commit
- push
origin particle/main - fetch/确认远端
最终要求:
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。