docs: record STEP-088 retained underlay poc
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled

This commit is contained in:
tei
2026-09-21 22:57:53 +09:00
parent 8b9ab30322
commit c58d370e71
3 changed files with 284 additions and 0 deletions

View File

@@ -0,0 +1,122 @@
# STEP-088 静态底图缓存 PoC 与 Renderer 观测 v1
## 状态
进行中
`IMPLEMENTED / WAITING FOR ANDROID VALIDATION`
## 目标
在固定 Camera、Style/Tile 稳定、2D 且存在 WeatherColor/RasterParticle 动态层时,把动态边界之前的连续普通 LayerGroup 前缀缓存为 retained underlay。Particle Tick 仍进入现有 MapLibre update/createRenderTree/prepare/upload 主链,但绘制阶段复用静态底图纹理,只实时绘制动态边界及其上方内容。
## 基线
- 分支:`particle/main`
- 起始 HEAD:`f47469d2ab77cdb959ecfe4081dc571fa1ab78f9`
- 实现提交:`8b9ab303228c307612c47f7f3379ad06206ea14e`
- 当前版本坐标:`13.4.1-particle.10`
## 必做项
- [x] Renderer-internal dynamic boundary。
- [x] LayerGroup before/from、forward/reverse 与 original ordinal。
- [x] Renderer-owned underlay cache 与 OpenGL/Metal compositor。
- [x] full-render fallback 与 legacy ordering 保护。
- [x] 7 个 Renderer debug counters。
- [x] Native 定向测试代码与 CMake 注册。
- [x] Mac OpenGL/Metal 编译及 4/4 定向测试由 RDC 完成。
- [ ] Android/NavSea 实机视觉、counters 与性能验证。
## 允许与禁止范围
允许修改 Renderer/Core/gfx backend/shader/CMake/Native test 和本 Step 文档;必要的 `test/gl/gl_functions.test.cpp` macOS 平台条件小修纳入本次。禁止 Android/NavSea/React 业务修改、Host API、C-001、STEP-089、STEP-090、production 全量 invalidation 与 animation-only fast path。
## 当前问题
STEP-086 已确认 Particle/WeatherColor 的 `needsRepaint()` 会唤醒完整 MapLibre frame。固定 Camera 下仍重复执行 source/layer orchestration、prepare、LayerGroup opaque/translucent draw 与 present;复杂 NavSea Style 因而持续重复提交大量静态 fill/line/symbol/PBF draw。
## 实现结构
- `RenderLayer` 新增仅 Renderer 内部使用的 `startsRetainedDynamicRange()`;WeatherColor 与 RasterParticle 返回 true,不增加 Host/public API。
- `RenderOrchestrator` 保存最小动态 boundary,并提供 before/from、forward/reverse 的 LayerGroup 分段 visitor;callback 保留完整序列 original ordinal。
- Renderer-owned `RetainedUnderlayCache` 持有 RGBA offscreen texture、depth/stencil renderable、compositor LayerGroup、key、valid 状态和 build/reuse/fallback/invalidation 数据。
- 新增独立 `RetainedUnderlayCompositeShader`,OpenGL/Metal 均为 fullscreen textured quad,只采样 premultiplied RGBA,不做 map transform、color ramp 或 Particle 业务。
- OpenGL OffscreenTexture 补齐可选 depth/stencil attachment;通用 gfx Context 的四参数 offscreen 接口由 OpenGL、Metal、Vulkan、WebGPU 后端显式覆盖。
- legacy `RenderLayer::render()` 当前仅 LocationIndicator 需要保护;若它位于 boundary 以下则 full-render fallback。
## Boundary
- WeatherColor 与 RasterParticle 都是 candidate。
- 两者同时存在时取实际 ordered layer 序列中的最小 index。
- only Particle 时使用 Particle index。
- 无 candidate 时 retained path disabled,完整原 Renderer 路径不变。
- 不依赖 React layer ID/name,不由 Host/NavSea 传入。
## Underlay Cache Flow
1. 保留 `Renderer::render → createRenderTree`、source update/prepare、layer prepare、`updateLayers/processChanges`、LayerGroup tweaker/upload。
2. 先按原顺序处理 independent RenderTargets。
3. cache invalid 时,把 boundary 前 LayerGroups 以原始 ordinal/depth 映射分别执行 opaque reverse 与 translucent forward,绘制到透明 clear 的 offscreen。
4. main framebuffer 仍按原 `backgroundColor/depth/stencil` 语义 clear;background optimized-as-color 路径未改。
5. composite cached underlay,再按完整序列 original ordinal 绘制 boundary 及之后的 opaque/translucent groups。
6. legacy items、debug overlay、postRender 与 present 保持原位置。
7. fixed key 且安全条件连续成立时复用;viewport、camera matrix 或 boundary 改变时重新 build。
## Fallback
以下状态不复用缓存:无 boundary、静态前缀为空、style 尚未 loaded、3D、任意 debug options、静态层 transition/repaint、placement/fade、boundary 以下 legacy ordering、offscreen/compositor 创建失败。不能建立安全资源时计数并回到完整绘制路径。
## Renderer 观测
在既有 debug-only counters 中新增:
- `FullRendererFrame`
- `RetainedUnderlayBuild`
- `RetainedUnderlayReuse`
- `RetainedUnderlayFallback`
- `RetainedUnderlayInvalidation`
- `RetainedUnderlayStaticGroupDraw`
- `RetainedDynamicGroupDraw`
`NDEBUG` 下仍为 no-op;未增加 Host API,也未增加逐帧日志。
## 构建与测试
以下由 RDC / 普通 Terminal 在当前 STEP-088 实现上完成:
- `cmake --build build-step088-opengl --target mbgl-test-runner -j3`:成功。
- STEP-088 定向测试:4/4 成功,覆盖 boundary、LayerGroup range/original ordinal、build/reuse/resize/boundary invalidation、3D/resource failure fallback。
- `cmake --build build-ios --config Debug --target mbgl-core -j3`:iOS/Metal device arm64 `BUILD SUCCEEDED`。
- `git diff --check`:成功。
- RDC 为 Mac OpenGL test-runner 链接补充 `test/gl/gl_functions.test.cpp` Apple 平台条件:macOS 不引用仅 iPhone/Simulator 提供的 `glInvalidateFramebuffer` / `glInvalidateSubFramebuffer`。
Codex 收尾阶段按新规则未再启动任何 build/test。Android Gradle、AAR/APK、ADB、Android 设备、NavSea 实机与 Jest 均未执行。
## PoC 限制
- 本 Step 只消除稳定场景下静态前缀的重复 GPU draw;没有跳过 Map update、createRenderTree、source/TilePyramid update、prepare、tweaker 或 upload。
- production 级 style/layer/source/tile/bucket/drawable、sprite/image/glyph、context/surface 等完整 invalidation 属于 STEP-089;本 PoC 只允许在固定 Camera、Style/Tile 稳定条件下判断 reuse。
- 未做 animation-only CPU fast path;STEP-090 未执行。
- 未做通用任意 static/dynamic RenderGraph,也未修改 NavSea、React 或 C-001。
## 用户 Android/NavSea 手工验证项
1. 固定 Camera、复杂真实 Style、Particle 约 30 FPS,确认视觉与原路径一致。
2. 观察 `RetainedUnderlayBuild ≈ 1`、`RetainedUnderlayReuse` 和 `ParticleSimulationAdvance` 持续增长。
3. 确认建 cache 后 `RetainedUnderlayStaticGroupDraw` 不随 Particle FPS 增长,`RetainedDynamicGroupDraw` 持续增长。
4. 分别验证 only Particle、WeatherColor + Particle 的两种 layer 顺序。
5. pan/zoom/resize 后确认 invalidation/rebuild,不能出现 stale underlay。
6. 验证 3D、debug 与 boundary 以下 legacy ordering 会安全回到 full render。
7. 对比 Particle OFF/ON 的 draw calls、RenderThread CPU、main/JS CPU 与画面叠放顺序。
## 当前结果与下一步
STEP-088 实现与 Mac OpenGL/Metal、Native 定向测试已完成;Android/NavSea 运行态证据尚缺。因此当前不满足进入 STEP-089 的验收条件,不得进入 STEP-089/090。下一步仅由用户/RDC 完成上述 Android/NavSea 手工验证并回传事实。
## 必做输出与阻塞
- Step 记录:本文。
- Codex 完成报告:`docs/报告/STEP-088_静态底图缓存PoC与Renderer观测_Codex完成报告_v1.md`。
- 开发记录:已追加 `粒子开发记录.md`。
- 阻塞:Android/NavSea 实机验证尚未执行;这是关闭 STEP-088 和进入 STEP-089 的唯一当前验收阻塞。

View File

@@ -0,0 +1,155 @@
# STEP-088 静态底图缓存 PoC 与 Renderer 观测 Codex 完成报告 v1
## 1. 执行结论
- 状态:`IMPLEMENTED / WAITING FOR ANDROID VALIDATION`
- 结论:Retained Static Underlay PoC、OpenGL/Metal compositor、Renderer counters 与 Native 定向测试代码已实现;RDC 已完成 Mac OpenGL/Metal 编译和 4/4 定向测试。Android/NavSea 尚未验证,因此不关闭 Step,也不进入 STEP-089/090。
## 2. Git 基线
- 机器:Mac mini,Darwin x86_64
- 仓库:`/Users/tei/dev/MapLibreParticleLab`
- 分支:`particle/main`
- 起始 HEAD:`f47469d2ab77cdb959ecfe4081dc571fa1ab78f9`
- STEP-088 实现 Final HEAD:`8b9ab303228c307612c47f7f3379ad06206ea14e`
- 实现提交信息:`feat: add retained underlay render cache poc`
- 当前版本坐标:`13.4.1-particle.10`
- 实现 push:成功,`f47469d2a..8b9ab3032 particle/main -> particle/main`
- 远端分支:`origin/particle/main`
- 既有 dirty/untracked:保留且未暂存,包括 `AGENTS.md`、两个 modified submodule、`platform/ios/app/MBXAppDelegate.m` 与用户既有任务文档。
## 3. 开工前只读确认
已按当前代码确认:
- RasterParticle 与 WeatherColor 的 `needsRepaint()` 经 `RenderOrchestrator::hasTransitions()` 驱动完整 MapLibre frame。
- `Renderer::render()` 每帧仍调用 `createRenderTree()`,随后进入 `Renderer::Impl::render()`。
- `updateLayers/processChanges`、LayerGroup tweaker/upload、`visitRenderTargets` 均位于 draw 分段之前,STEP-088 未跳过。
- main clear、opaque reverse、translucent forward、legacy items、debug、postRender、present 的原始顺序已核对。
- `RenderTarget` / `OffscreenTexture` 以及 Heatmap/Hillshade 的 offscreen + texture composite 模式已作为实现样板,未修改 Heatmap/Hillshade 自身语义。
- background layer optimized-as-color 继续通过 main framebuffer `backgroundColor` clear;underlay offscreen 使用透明 clear。
## 4. 实际实现
### Boundary
- `src/mbgl/renderer/render_layer.hpp`:增加 Renderer-internal boundary 与 legacy-rendering virtual hooks。
- `render_weather_color_layer.hpp`、`render_raster_particle_layer.hpp`:声明为 boundary candidate。
- `render_location_indicator_layer.hpp`:标识 legacy rendering,供 boundary 以下 ordering fallback。
- `render_orchestrator.cpp`:在实际 ordered layers 上取最小 candidate index。
### LayerGroup 分段
- `render_orchestrator.hpp`:增加 before/from、forward/reverse 四种 visitor,callback 获得完整 LayerGroup 序列 original ordinal。
- `renderer_impl.cpp`:`currentLayer = totalGroups - 1 - originalOrdinal`,`depthRangeSize` 仍按完整 group 数计算,避免子集从 0 编号改变 depth/transparency。
### Cache 与 Renderer Flow
- 新增 `retained_underlay_cache.hpp/.cpp`:管理 key、valid、RGBA offscreen、compositor group、build/reuse/fallback counts 与 last invalidation reason。
- key 包含 viewport、boundary 与 projection/camera matrix。
- retained path 只改真正 draw 阶段;createRenderTree、source/layer update/prepare、tweaker/upload 全部保留。
- cache build 顺序为 independent targets → static opaque/translucent to offscreen → main clear → cached composite → dynamic opaque/translucent → legacy/debug/postRender/present。
### Compositor 与 Backend
- 新增 `RetainedUnderlayCompositeShader` 的 OpenGL GLSL/generated header 与 Metal shader source/metadata。
- shader manifest、BuiltIn enum、shader info/defines、GL/Metal backend registration 与 CMake source lists 已接线。
- gfx Context 增加四参数 offscreen virtual;OpenGL 补齐 depth/stencil renderbuffer attachment,Metal/Vulkan/WebGPU 明确 override 已有实现。
### Debug Counters
在 `include/mbgl/particle/renderer_debug_counters.hpp` 新增:
- `FullRendererFrame`
- `RetainedUnderlayBuild`
- `RetainedUnderlayReuse`
- `RetainedUnderlayFallback`
- `RetainedUnderlayInvalidation`
- `RetainedUnderlayStaticGroupDraw`
- `RetainedDynamicGroupDraw`
Release/NDEBUG 仍 no-op,不增加 Host API,不逐帧刷日志。
## 5. 修改文件
实现提交共 39 个文件:
- 构建:`CMakeLists.txt`、`cmake/opengl.cmake`、`cmake/metal.cmake`、`test/CMakeLists.txt`。
- Context/Offscreen:`include/mbgl/gfx/context.hpp`、`include/mbgl/{mtl,vulkan,webgpu}/context.hpp`、`src/mbgl/gl/context.cpp/.hpp`、`src/mbgl/gl/offscreen_texture.cpp/.hpp`。
- Renderer:`src/mbgl/renderer/render_layer.hpp`、`render_orchestrator.cpp/.hpp`、`renderer_impl.cpp/.hpp`、三个相关 RenderLayer headers、新增 `retained_underlay_cache.cpp/.hpp`。
- Shader:`shaders/manifest.json`、两个新增 GLSL、GL/Metal generated/handwritten headers、Metal source、shader source/manifest/defines/info 与 GL/Metal backend registration。
- 观测:`include/mbgl/particle/renderer_debug_counters.hpp`。
- 测试:新增 `test/renderer/retained_underlay_cache.test.cpp`;RDC 小修 `test/gl/gl_functions.test.cpp` 的 Apple/macOS 符号条件。
## 6. Fallback 与安全边界
- 无 boundary:原 Renderer。
- static prefix 为空、style 未 loaded、has3D、debug options:full render。
- static prefix 存在 transition/repaint、symbol placement/fade 或 source fading tile:full render。
- boundary 以下存在 legacy renderer item:full render。
- viewport、camera fingerprint、boundary 改变:cache invalid 后 build。
- offscreen texture/compositor 创建或 renderable 检查失败:计数并 full-render fallback。
STEP-088 的成立前提是固定 Camera 且 Style/Tile 稳定。production 级 style/tile/drawable/context invalidation 明确留给 STEP-089,未在本次越界实现。
## 7. 新增文件
- `include/mbgl/shaders/gl/retained_underlay_composite.hpp`
- `include/mbgl/shaders/mtl/retained_underlay_composite.hpp`
- `shaders/retained_underlay_composite.vertex.glsl`
- `shaders/retained_underlay_composite.fragment.glsl`
- `src/mbgl/renderer/retained_underlay_cache.hpp`
- `src/mbgl/renderer/retained_underlay_cache.cpp`
- `src/mbgl/shaders/mtl/retained_underlay_composite.cpp`
- `test/renderer/retained_underlay_cache.test.cpp`
## 8. 与任务书差异
- 功能范围无扩大:未进入 STEP-089/090。
- 按新 `AGENTS.md`,长时间 Mac 编译/测试由 RDC 执行,Codex 只负责实现、静态审计、文档与 Git 收尾。
- RDC 为完成 Mac OpenGL test-runner 链接,增加了任务范围内必要的 `test/gl/gl_functions.test.cpp` Apple/macOS 平台条件小修。
- 没有提交用户对 `AGENTS.md` 的全局流程修改,也没有提交既有无关 dirty/untracked。
## 9. RDC 构建与测试记录
- OpenGL:`cmake --build build-step088-opengl --target mbgl-test-runner -j3`,结果成功。
- 定向测试:4/4 成功:
- `RetainedDynamicBoundary.SelectsFirstCandidate`
- `RetainedLayerGroupRange.PreservesForwardReverseOriginalOrdinals`
- `RetainedUnderlayCache.BuildReuseAndInvalidation`
- `RetainedUnderlayCache.UnsupportedAndResourceFailureFallBackSafely`
- iOS/Metal device arm64:`cmake --build build-ios --config Debug --target mbgl-core -j3`,结果 `BUILD SUCCEEDED`。
- `git diff --check`:成功。
- RDC 小修说明:Darwin 的 gl functions 实现仅在 iPhone/Simulator 定义 `glInvalidateFramebuffer` / `glInvalidateSubFramebuffer`;macOS test-runner 不应无条件引用,故增加 Apple target 条件。该修复仅影响测试平台链接,不改变 Renderer 业务语义。
按最新 `AGENTS.md` 分工,以上长时间编译/测试由 RDC / 普通 Terminal 执行并回传;Codex 最终收尾没有再次启动 build/test。
## 10. Android 未执行与无法验证
以下均未执行:Android Gradle、AAR/APK、ADB、Android 真机/模拟器、NavSea 实机、Jest。因此无法验证复杂 NavSea Style 下的实际视觉、缓存 counters、draw-call 降幅、RenderThread/main/JS CPU 收益以及所有交互 invalidation。
## 11. PoC 限制、已知问题与未完成事项
- 未实现 STEP-089 的 production 全量 invalidation。
- 未实现 STEP-090 的 Map/update/createRenderTree/source/prepare CPU fast path。
- 未修改 NavSea、React、Host API 或 C-001。
- Android/NavSea 手工验证待用户执行;结果回传前不得把本 Step 标记为关闭。
## 12. 生成产物
本 Step 不生成 AAR/APK/XCFramework/npm artifact;没有发布物、ABI、大小或 SHA-256。Mac 输出仅用于编译/测试验证,不作为发行 artifact。
## 13. 是否满足进入 STEP-089 条件与下一步建议
当前不满足。进入 STEP-089 的前置条件是用户/RDC 在 Android/NavSea 复杂真实 Style 上确认:画面与 ordering 正确、fixed Camera 下 build 约一次且 reuse/Particle advance 持续、static group draw 不随 Particle FPS 增长、camera/resize/fallback 不出现 stale cache。STEP-088 未取得这些证据前不得进入 STEP-089;STEP-090 同样未执行。
下一步只建议执行 STEP-088 Android/NavSea 手工验证,不创建或执行新的 Step。
## 14. Git 收尾
- Final implementation commit hash:`8b9ab303228c307612c47f7f3379ad06206ea14e`
- Commit message:`feat: add retained underlay render cache poc`
- Push result:成功
- Remote branch:`origin/particle/main`
- STEP-088 implementation Final HEAD:`8b9ab303228c307612c47f7f3379ad06206ea14e`
- 本报告与 Step/开发记录由后续独立 docs closeout commit 承载;该提交的精确 hash 因 Git commit 不能自引用,记录在最终响应和远端 HEAD 核验中。

View File

@@ -876,3 +876,10 @@ Android V3-08 单次综合验收已完成并关闭。Native `13.4.1-particle.2`
- Pleiades iPad mini 5 真机在 Test Host signed Release 上完成 `RUN V4 FINAL CONTROL REGRESSION` 单按钮序列:`prepare#1 → PLAY → 约500ms → PAUSE → clear selected → prepare#2 → clear all → detach → attach → prepare#3 → refresh`;用户明确确认“FINAL CONTROL REGRESSION PASS”。
- 最后一次 prepare/refresh 后 Metal V4 Wind 粒子恢复并保持可见;此前用户已确认“粒子恢复了”。single MapLibre SPM、signed Release `BUILD SUCCEEDED`、安装启动与 Metal artifact(`24943196` bytes,SHA-256 `ae88975fc20f4d9961b95079638d0e9c0d8e61d4394d5c0a8ffcc48d173a827f`)验证事实不变。
- STEP-083 正式 `CLOSED / PASS`。App.tsx 回归按钮保留且逻辑不变;未修改 RN public API/native/Core/renderer/release manifest,未提交。下一步进入 NavSea iOS 首批大集成,不再拆分微小 build/install Step。
### 2026-09-21 STEP-088 静态底图缓存 PoC 与 Renderer 观测
- Renderer 内部新增 WeatherColor/RasterParticle retained dynamic boundary、保留 original ordinal 的 LayerGroup 分段访问,以及 Renderer-owned RGBA static-underlay cache;fixed Camera、Style/Tile 稳定的 2D 场景可在首次 build 后跳过 boundary 前静态 GPU draw,仍保留完整 createRenderTree/source/layer prepare/tweaker/upload 主链。
- 新增独立 OpenGL/Metal `RetainedUnderlayCompositeShader`、OpenGL depth/stencil offscreen 支持与 7 个 debug counters;不增加 Host/NavSea API,不修改 C-001,不进入 STEP-089/090。
- RDC 完成 Mac OpenGL test-runner、STEP-088 定向 4/4、iOS/Metal device arm64 `mbgl-core` 与 `git diff --check`;并小修 macOS 不提供 iPhone-only framebuffer invalidate 符号的 test 条件。Android Gradle/AAR/APK/ADB/设备/NavSea/Jest 未执行。
- 实现提交 `8b9ab303228c307612c47f7f3379ad06206ea14e`(`feat: add retained underlay render cache poc`)已 push 到 `origin/particle/main`。当前状态 `IMPLEMENTED / WAITING FOR ANDROID VALIDATION`;Android/NavSea 视觉、counters 与性能证据完成前不进入 STEP-089。