# MapLibreParticleLab 粒子连续渲染静态底图缓存与动画快路径优化规划 v1 ## 1. 目标 STEP-086 已确认:Particle / WeatherColor 的 needsRepaint 会通过全局 repaint 让完整 MapLibre scene 连续出帧。React 不会每帧重新提交 PBF,但 Native Renderer 会重复进入 source/layer orchestration,并重新提交静态 PBF/fill/line/symbol draw。 本规划目标: - 地图真实变化时仍走 Full Frame。 - Camera、Style、Tile 稳定且只有 WeatherColor/Particle 动画时,复用 Static Underlay。 - NavSea / React 不参与 Renderer cache 管理。 - 不改变 NavSea ↔ Particle C-001 公共边界。 ## 2. 当前关键代码 必须以当前 origin/particle/main 实际代码为准,重点包括: - src/mbgl/renderer/layers/render_particle_validation_layer.cpp - src/mbgl/renderer/layers/render_weather_color_layer.cpp - src/mbgl/renderer/render_orchestrator.cpp/.hpp - src/mbgl/renderer/renderer.cpp - src/mbgl/renderer/renderer_impl.cpp/.hpp - src/mbgl/map/map_impl.cpp - include/mbgl/renderer/render_target.hpp - src/mbgl/renderer/render_target.cpp - src/mbgl/renderer/layers/render_heatmap_layer.cpp - src/mbgl/renderer/layers/render_hillshade_layer.cpp ## 3. 核心结构 不增加永久 public static/dynamic layer flag。采用 Renderer 内部 retained dynamic boundary: - WeatherColor 是 boundary candidate。 - RasterParticle 是 boundary candidate。 - 同时存在时取最小 layerIndex。 - boundary 之前连续 LayerGroup 前缀作为 Static Underlay。 - boundary 及之后继续实时绘制。 - 没有 boundary 时完全保持原 Renderer。 Layer 顺序、parameters.currentLayer、depthRangeSize、opaque/translucent 原始 ordinal 必须保持,不允许对子集从 0 重新编号而改变透明/depth 语义。 ## 4. Static Underlay Cache 建议 Renderer-owned helper: - src/mbgl/renderer/retained_underlay_cache.hpp - src/mbgl/renderer/retained_underlay_cache.cpp 职责: - offscreen renderable / texture - viewport size - boundary - valid/invalid - invalidation reason - build/reuse/fallback 计数 - compositor resources 不改变 Heatmap/Hillshade RenderTarget 现有行为;复用现有 gfx::OffscreenTexture / RenderTarget / Drawable / shader abstraction。 ## 5. Texture Composite 使用独立语义的 RetainedUnderlayCompositeShader: - viewport/fullscreen quad - sample cached RGBA texture - 正确 premultiplied alpha - 不做 map transform / color ramp / Particle 业务 不要长期复用 LocationIndicatorTexturedShader。 ## 6. STEP-088 先只消除静态地图重复 GPU draw,仍保留: - Map::Impl::onUpdate - UpdateParameters - createRenderTree - source update / TilePyramid update - source/layer prepare - updateLayers - LayerGroup tweaker/upload Render 阶段: 1. cache invalid:boundary 前 LayerGroups render 到 offscreen。 2. cache valid:跳过 boundary 前静态 draw。 3. main framebuffer clear。 4. composite cached underlay。 5. boundary 及之后 WeatherColor/Particle/动态 overlay 正常绘制。 6. present。 ## 7. STEP-089 在 STEP-088 实机通过后再做 production invalidation: - Camera center/zoom/bearing/pitch - viewport/pixelRatio - style/layer add/remove/reorder/change - source/tile/bucket/drawable 变化 - sprite/image/glyph - symbol placement/fade - context/surface recreation - 3D/terrain/custom/debug fallback - OpenGL/Metal 一致生命周期 ## 8. STEP-090 条件步骤 只有 STEP-089 后真实 NavSea profile 仍证明主要 CPU 落在: - Map::Impl::onUpdate - createRenderTree - Vector/PBF source update - TilePyramid update - source/layer prepare 才进入 Animation-only fast path。 如果 STEP-089 已满足性能目标,不执行 STEP-090。 ## 9. STEP-088 安全边界 PoC reuse 至少要求: - 2D - Camera fingerprint 连续一致 - viewport 不变 - style loaded - boundary 不变 - context/resource 正常 以下至少 fallback full render: - has3D - Debug Overdraw - cache texture/compositor 创建失败 - viewport resize - boundary change - context 不可用 - legacy RenderItem ordering 无法证明安全 - 其他不能证明 cache 正确的状态 原则:不确定就 full render,不用 stale cache 换性能。 ## 10. 观测 复用 include/mbgl/particle/renderer_debug_counters.hpp,建议增加: - FullRendererFrame - RetainedUnderlayBuild - RetainedUnderlayReuse - RetainedUnderlayFallback - RetainedUnderlayInvalidation - RetainedUnderlayStaticGroupDraw - RetainedDynamicGroupDraw 固定 Camera + Particle 约 30 FPS 时,理想: - RetainedUnderlayBuild ≈ 1 - RetainedUnderlayReuse 持续增长 - ParticleSimulationAdvance 持续增长 - StaticGroupDraw 建 cache 后不随 Particle FPS 增长 - DynamicGroupDraw 持续增长 ## 11. 不允许 - React RAF 驱动 - Host renderFastFrame/cacheMapNow/invalidateBasemap API - NavSea 手工管理 renderer cache - 修改 C-001 - 永久 public static/dynamic flag - 改变 Style layer ordering - STEP-088 就跳过 source/update/prepare - Android/iOS 不同 renderer semantics - stale cache ## 12. 执行顺序 1. STEP-088:PoC + observability 2. 用户 Android/NavSea 真机验证 3. STEP-089:production invalidation/fallback 4. 用户再次 profile 5. 只有 CPU orchestration 仍是瓶颈时才 STEP-090