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

13 KiB
Raw Blame History

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:

  1. test/renderer/retained_underlay_cache.test.cpp:新增 RenderSegmentPlacementFree.* C++ 测试源码。
  2. platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/particle/ParticleCoreLayerValidationActivity.kt:STEP-102 场景菜单、Intent 入口、轮询及审计日志。
  3. 新增 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 错误,而非改动依赖:

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 只由用户手工构建,使用项目固定入口:

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:

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 校验和公开回读为准;构建或发行阶段失败不可豁免。