diff --git a/docs/50_Step记录/STEP-088_静态底图缓存PoC与Renderer观测_v1.md b/docs/50_Step记录/STEP-088_静态底图缓存PoC与Renderer观测_v1.md new file mode 100644 index 000000000..08ec1e5fa --- /dev/null +++ b/docs/50_Step记录/STEP-088_静态底图缓存PoC与Renderer观测_v1.md @@ -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 的唯一当前验收阻塞。 diff --git a/docs/报告/STEP-088_静态底图缓存PoC与Renderer观测_Codex完成报告_v1.md b/docs/报告/STEP-088_静态底图缓存PoC与Renderer观测_Codex完成报告_v1.md new file mode 100644 index 000000000..80c4d095b --- /dev/null +++ b/docs/报告/STEP-088_静态底图缓存PoC与Renderer观测_Codex完成报告_v1.md @@ -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 核验中。 diff --git a/粒子开发记录.md b/粒子开发记录.md index 0d4e285be..519850448 100644 --- a/粒子开发记录.md +++ b/粒子开发记录.md @@ -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。