Files
MapLibreParticleLab/docs/报告/STEP-102_RenderSegment无Placement段局部复用_Codex完成报告_v1.md

130 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# STEP-102 RenderSegment 无 Placement 段局部复用 Codex 完成报告 v1
## 1. 执行结论
**代码完成,等待独立构建与运行验证;STEP-102 尚非 PASS。** 已按任务书实现 full CPU placement-free Retained Segment 局部复用、逐段 fallback reason 和实际 main-buffer 执行诊断。C++ 与 Android 测试均只交付源码,未运行。没有编译、设备或视觉结果,不能据此宣称无 stale、Z-order 错乱或 crash。
## 2. Git 基线与工作树
- 工作区:`/Users/tei/dev/MapLibreParticleLab-step102`
- 当前机器:macOS 15.7.7 / Darwin x86_64;未连接或操作设备。
- 分支:`step102-placement-free-retained-locality`
- start HEAD:`6df21dac38f072c5ad35b8dfc7ec5217509602bc`
- end HEAD:仍为 `6df21dac38f072c5ad35b8dfc7ec5217509602bc`;本阶段未 commit、push、merge。
- 子模块:`git submodule status` 均以 `-` 开头,本 worktree 未初始化;未更改。
- 工作树:仅下列任务文件有本阶段差异;任务开始时已经未跟踪的 v2/v3 审查说明及 STEP-102 任务书未修改、未暂存。
- V19/V20 release worktree、`particle/main`、tag 与发布坐标未修改;无新 artifact。
## 3. 实际修改与新增文件
生产代码:
1. `include/mbgl/renderer/render_segment.hpp`:结构查询、placement gate、全局 live reason 辅助函数及 diagnostics 字段。
2. `src/mbgl/renderer/render_orchestrator.hpp`、`src/mbgl/renderer/render_orchestrator.cpp`:对 full CPU 提供结构查询和 placement transition 查询;旧动态查询保持原样。
3. `src/mbgl/renderer/renderer_impl.cpp`:逐段 gate/fallback、全局 live reason、实际执行记录。
4. `src/mbgl/renderer/retained_underlay_runtime_state.hpp`、`src/mbgl/renderer/render_segment_json.hpp`:只读快照与 JSON 字段。
5. `packages/maplibre-particle-rn/src/types.ts`:现有 diagnostics 返回类型 additive 扩展。
测试/Validation:
6. `test/renderer/retained_underlay_cache.test.cpp`:新增 `RenderSegmentPlacementFree.*` C++ 测试源码。
7. `platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt`:STEP-102 场景菜单、Intent 入口、轮询及审计日志。
8. 新增 `platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/Step102PlacementFixture.kt`:离线 R-C-R symbol/placement-free 两组 fixture。
文档:新增 `docs/50_Step记录/STEP-102_RenderSegment无Placement段局部复用_v1.md`、本报告;追加 `粒子开发记录.md`。
## 4. 实现与任务书逐项对照
- **结构能力**:扫描同一 style-layer 元数据中的 `layerType == "symbol"`;越界 range 返回 placement-capable 以 fail-closed。`retainedRangeUsesPlacement()` 的 `needsPlacement()` 动态语义未变。custom/custom-drawable 仍由原 unsupported gate 处理。
- **逐段 gate**:placement-free 返回通过;placement-bearing 要求 `!placementChanged && symbolFadeChange == 0 && !placementTransitionActive`。`symbolFadeChange==0` 只是沿用保守 gate 的条件,不命名为严格 stable。transition disabled 且 fade=1 仍不能让含 symbol 段复用。
- **逐段 fallback**:优先明确 source、global resource、placement、layer transition、legacy/unsupported 等本段理由。`static-placement` 只会由本段 gate 失败产生;不再拷贝 aggregate placement/transition 理由给邻段。
- **full CPU main-buffer**:全局 live 条件只删掉 aggregate `!retainedPlacementStable`,其他既有 3D、debug、非 Continuous MapMode、sprite、global resources、light transition 条件保留。原 `visitRenderSegmentExecution()` 和 Style 顺序不变。camera/viewport/pixelRatio、topology、content/global revision、resource/compositor failure 的原有失效路径未放宽。
- **兼容/安全边界**:aggregate `retainedStaticUsesPlacement`、`retainedPlacementStable`、prepared-tree/Fast Path eligibility 与 revision 观察继续原用;含 symbol 的 retained 仍 fail-closed;C-001、RN method surface、`setRenderSegmentPlan()` 输入未变。
与 v3 审查设计无架构差异。逐段 gate 额外显式查询当前 placement transition,属于对 placement-bearing 的更保守判定;原 `retainedSegmentIsStable()` 内仍保留既有 transition 检查。测试和 Android 场景均不修改 Placement 核心算法。
## 5. diagnostics 字段与真实执行语义
每段新增 `placementCapable`、`placementGatePassed`、`actualExecution`。前者来自 style-layer 结构,第二项表示本帧 full CPU placement cache gate;Continuous 段的 gate 为非阻塞值。`actualExecution` 在 main-buffer 全局 live 分支或 mixed executor 的 composite 回调实际发生后记录。即使 `cache.finalDecision=reuse`,全局门槛触发时仍记录 `actualExecution=live`。
全局新增 `placementChanged`、`symbolFadeChange`、`placementTransitionActive`、`crossSourceCollisions`、`mainBufferExecutionMode`、`globalLiveFallbackReason`。`mixed` 表示进入 Style 顺序的 mixed executor,可以包含某些 Retained live;`global-live` 表示整帧 live 分支。尚未渲染时 `mainBufferExecutionMode/actualExecution=not-rendered`。查询只拷贝已记录快照,不推进 revision;Android/iOS Shared Core 使用同一 JSON writer,RN TS 只补类型。
## 6. 测试源码覆盖矩阵
| 合同场景 | 新增/现有测试源码 | 尚待运行证明 |
| --- | --- | --- |
| A:R0 free、C live、R1 symbol live;Style 顺序 | `RenderSegmentPlacementFree.MixedExecutionKeepsFreeRangesInStyleOrder` | Android T1 真实 GPU composite/live 与视觉 Z-order |
| B:symbol 当前 placementData 为空仍 capable | `StructuralCapabilityAndConservativeGate` 直接输入 symbol style 结构,不依赖 placementData | Android 空 bucket/placementData 条件仍需设备审计 |
| C:两个 free Retained 复用 | `MixedExecutionKeepsFreeRangesInStyleOrder` 中 R0/R2;Android T2 | 60 秒 build/reuse/invalidation 窗口 |
| D:source-local unloaded/fading/mutation | 既有 `RenderSegmentLocality.ReadinessAndFadeFollowOnlyDependencies` 与本轮两 free cache 断言;Android T1 动态 symbol source | 设备 R0 计数不误增 |
| E:bearing 保守 gate | `StructuralCapabilityAndConservativeGate` changed/fade=1/transition 活跃组合 | transition disabled 场景的 GPU 行为 |
| F:真实全局门槛 | `RealGlobalGatesStillForceGlobalLive`;既有 revision/cache tests | style/context/image/glyph/light 等设备失效 |
| G:拓扑与 key | `TopologyAndCameraChangesCannotReuseOldRetainedKey`;既有 `OldCacheReleaseCannotChargeReplacementAtSameIndex` | 真正 GPU resource 释放及无 stale texture |
| H:reuse 但 global-live | `DiagnosticsRecordActualMainBufferAndDoNotMutateOnRead` | 设备日志中 cache/actual 分离 |
测试源码只验证可隔离的策略、cache 决策、diagnostics 和 mixed traversal;无法单凭这些单元测试替代真实 renderer/GPU 场景。
## 7. Android Validation 场景
Test App 的 STEP-093 菜单新增 `STEP-102 PLACEMENT LOCALITY`,也可用 Intent `step102_scenario` 启动:
- `T1_FREE_SYMBOL`:R0 background/fill(无 symbol)→ C0 持续粒子 → R1 symbol;每 500ms 更新 R1 GeoJSON point,让 placement/source 活跃。
- `T2_TWO_FREE`:相同 R0/C0,R1 改为 fill;两个 Retained 均结构上 placement-free。
每个 `STEP102_SAMPLE` 记录固定 camera、placement 四个全局字段、main-buffer mode/reason、每段 capability/gate/actual、cache decision、build/reuse/invalidation/fallback。tick 8/130 打窗口标记。日志字段用于验收,不在 App 中自行宣告 PASS。
## 8. 实际检查与 NOT RUN
- 已执行:`git status --short`、`git diff`/`rg` 只读审计;`git diff --check` **PASS**。三个新增未跟踪文件另以 `git diff --no-index --check /dev/null <文件>` 检查,无空白错误;该命令因有差异正常退出 1。
- **NOT RUN**:CMake/Ninja/Bazel configure/build/link、C++ GTest、Android Native TestRunner、Android Gradle、APK/AAR、codegen、Jest、ADB、设备/截图/logcat、iOS/Metal、NavSea、发布、commit、push。
- 无 APK/AAR、大小、SHA-256、运行日志或最终性能结果。没有编译失败或测试失败的事实;缺少编译/运行证据。
## 9. 后续精确验证命令与硬门槛
先由 RDC 在本工作区运行 host 定向测试;若当前 Mac `libuv` 环境仍阻塞,应记录首个真实 configure 错误,而非改动依赖:
```bash
cmake --preset macos-metal
cmake --build build-macos-metal --target mbgl-test-runner --parallel 3
build-macos-metal/mbgl-test-runner --gtest_filter='RenderSegmentPlacementFree.*:RenderSegmentLocality.*:RenderSegmentDiagnostics.*'
```
**Android Validation APK 只由用户手工构建**,使用项目固定入口:
```bash
cd /Users/tei/dev/MapLibreParticleLab-step102
./tools/particle_android_validation/build_validation_apk.sh
```
构建成功后由 RDC/用户核对 APK ZIP、ABI、`libmaplibre.so`、SHA-256、branch/commit/dirty 状态,再在选定设备上独立运行。下列 `<SERIAL>` 需替换为实际 `adb devices` 返回的 serial;每场景单独清日志、force-stop、启动并留存完整 logcat:
```bash
adb -s <SERIAL> install -r artifacts/maplibre-particle/android-validation/MapLibreAndroidTestApp-validation-opengl-debug-x86_64.apk
adb -s <SERIAL> logcat -c
adb -s <SERIAL> shell am force-stop org.maplibre.android.testapp
adb -s <SERIAL> shell am start -n org.maplibre.android.testapp/.activity.particle.ParticleCoreLayerValidationActivity --es step102_scenario T1_FREE_SYMBOL
adb -s <SERIAL> logcat -v threadtime -d > /tmp/step102-t1-logcat.txt
rg 'STEP102_(SCENARIO_START|STYLE_READY|SAMPLE|WINDOW_MARKER)|Fatal signal|ANR' /tmp/step102-t1-logcat.txt
```
对 `T2_TWO_FREE` 重复 `logcat -c`、force-stop、启动、保存到 `/tmp/step102-t2-logcat.txt`。每组至少等待 tick 130(约 65 秒)后取最终日志。T1 硬门槛:固定 camera、`mainBufferExecutionMode=mixed` 的稳定窗口中 R0 `placementCapable=false`、`actualExecution=composite`、buildDelta=0、invalidationDelta=0、reuseDelta>0;R1 `placementCapable=true`,placement gate 失败期间 `actualExecution=live`,C0 live,Style Z-order 正确,无 stale/crash/ANR。T2 两个 Retained 均无 symbol,build 一次后持续 reuse/composite。若窗口内出现真实 global mutation,应结合 `globalLiveFallbackReason` 与 lastMutation 重新选择稳定窗口,不把合法 global invalidation 算作误伤。
还需独立做 STEP-100 source locality 与 STEP-101 teardown 回归,以及 global light/style/context/camera、topology 变动资源释放验证。iOS/Metal 只可在相同源码提交的 Mac/iOS 验收后声明通过。本阶段均未执行。
## 10. 风险、未完成事项与交接
- Android symbol glyph asset 与 placement 活跃窗口尚未由构建/设备核实;T1 若未出现 placement gate 失败,不构成主场景验收。
- 现有 C++ topology 测试验证 key/revision 无旧 cache reuse,不能证明真实 GPU 资源已释放;需设备/后端证据。
- `placementChanged` 与 `symbolFadeChange` 在 Fast Path 帧来自既有 prepared render tree;本 Step 没有改变 Fast Path 判定或语义。主验收只使用 `fullCpuFrame` 增长的 full CPU 窗口。
- 构建或运行失败应保留现场、回传首个真实错误及必要上下文;不得放宽测试或安全门槛。没有触及任务书要求 BLOCKED 的架构扩张条件。
本阶段未创建 Git commit,故无 implementation commit SHA;也未执行 merge、push 或远端 HEAD 回读。后续独立验收决定 scoped commit/merge 与发行流程。
## 11. V21 发行风险豁免记录(2026-10-08)
- 用户明确要求:V21 必须包含 STEP-102;本次发行不以正式 GTest、Android T1/T2 实机回归、iOS/Metal 运行态验收为前置条件,改由代码审查后执行完整发布流水线。
- 源码审查基线:`0ce551ad3791a21dbd8507e6cf8c607c270b6eee`。已检查结构性 symbol/Placement 分类、逐段 gate、真实全局 live 门槛、main-buffer 顺序、诊断数据和 Android Validation 场景;`git diff --check` 通过,未发现明确阻断发布的源码问题。
- 已有构建证据仅限 STEP-102 Metal Core 编译成功(Bazel 642/642),以及临时 helper smoke 10/10。正式 C++ GTest 受 `libuv` 依赖缺失阻塞,Android 与 iOS 运行态验收没有执行。
- **验收豁免不等于测试 PASS**:STEP-102 不标记 `CLOSED / PASS`,而按“源码审查后接受未验收风险发行 V21”记录。不能声称已经证明运行态无陈旧纹理、Z-order 错乱或崩溃。
- V21 Pipeline 的 prepare、build、publish、finalize 仍必须全部执行并以真实返回值、artifact 校验和公开回读为准;构建或发行阶段失败不可豁免。