# STEP-085 V4 Renderer 性能修复设计 v1 状态:`IMPLEMENTED / WAITING_FOR_RDC_NATIVE_BUILD` ## 目标与根因 V4 的 `RasterArraySource` 通过独立的 field-keyed window 产出已经 materialize 的 T0/T1/MIX。旧 renderer 将 V4 误当作“没有 timeline”,从而产生两项错误:WeatherColor 的 `needsRepaint()` 永远为 true;Particle 也永远请求下一帧,并在 `prepare()` 将包含大 vector/scalar/valid 数组的 snapshot 按值复制。 本设计保持 V3 timeline、V4 Runtime Field Window、QBIN 和所有 RN/Host 公共接口不变,只在 Source 内部和共用 renderer seam 修复 cadence/lifetime。 ## 共用 cadence 语义 新增 Source-owned `RasterArrayRendererCadence`。它只负责 visual simulation 的 deadline,不携带 field、不会变更 T0/T1/MIX,也不会调用 ForecastClock。 | targetFps | Core cadence | platform wake | | --- | --- | --- | | AUTO | 每个 MapLibre animation frame 可消费一次 | 沿用平台 animation-frame 语义 | | 30 | 约 33.3ms 才允许一次 simulation | Android Handler / iOS NSTimer 约 34ms 请求一次 repaint | | 60 | 约 16.7ms 才允许一次 simulation | Android Handler / iOS NSTimer 约 17ms 请求一次 repaint | `RenderRasterParticleLayer::needsRepaint()` 仅对 active、visible、field-ready 的 V4 Particle 在 deadline 到期时返回 true。因 camera 而来的额外 frame 仍可 composite 当前 trail,但 `consumeIfDue()` 未成功时不建 State/Trail pass、不推进 ping-pong、不衰减 trail。Forecast PAUSE 不影响该 visual cadence。 Android/iOS runtime timer 仅是已有 facade 的“下一帧 wake”薄层;deadline 与是否推进由共用 C++ Source cadence 判定。hidden、clear、disable 和 dispose 都停止 V4 Particle wake。 ## WeatherColor idle 与 drawable V4 WeatherColor 在 PAUSE、field/window/stops/opacity/transform 不变时 `needsRepaint()==false`。它不再以 `sourceTimeline == nullptr` 作为“永远动画”的代理。 稳定状态下 WeatherColor drawable 复用既有 LayerGroup drawable。T0/T1 texture、mix、opacity、color stops 与 value source 由 Resources/Tweaker 在 render 时更新 UBO;仅 wrap 集合变化才 `clearDrawables()` 后重建。该方案保留 gfx abstraction,未引入 OpenGL/Metal 直接调用。 ## V4 snapshot lifetime materialize 仍发生在 Source 的 binding/window 真正变化时,但 `Materialized*Projection` 与 renderer `sourceField/sourceNextField` 全部改为 `shared_ptr`。Source Impl 的不可变副本持有 projection,RenderLayer 只复制 shared handle;稳定 window 的 `prepare()` 不再深复制 scalar/vector/valid arrays。旧 V3 optional snapshot 路径仍在 Source 变化时构造独立 handle,未改变其 API。 ## Debug/Validation observability `include/mbgl/particle/renderer_debug_counters.hpp` 在非 release 建立低成本 relaxed atomic 累计器,release 编译为 no-op。覆盖:两 layer 的 needsRepaint/update、particle simulation advance、WeatherColor/Particle drawable rebuild、field texture upload、GPU resource create/release-reset、trail create/resize、V4 projection materialize 与 field-window revision。它不逐帧写普通日志,也不暴露给 NavSea。 ## ForecastClock 审查 全仓确认 `RasterArraySource::advanceForecastClock(elapsedMs)` 只有定义,当前 Android WeatherRuntime、iOS `MLNParticleFieldRuntime` 与 RN bridge 均没有 production caller。故 V4 PLAY 自动推进尚无 owner;本 Step 不将 cadence timer 偷接成第二个 forecast clock。Host 显式 `setEncodedForecastTime` 继续触发 window refresh;自动 forecast playback 应单独设计 owner 后处理。 ## 生命周期边界 本 Step 不改变 `detach()`、dispose、Host clear/destroy contract,也不对 retained allocation/Native Heap 归因。计数器和减少 repaint/copy/rebuild 仅为后续 RDC 采样提供证据。