Files
MapLibreParticleLab/docs/20_调查/STEP-095_V13独立严格代码与性能调查_v1.md
tei ad5f92c48e
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
docs: audit V13 source and performance for STEP-095
2026-09-25 20:46:44 +09:00

30 KiB
Raw Blame History

STEP-095 V13 独立严格代码与性能调查 v1

日期:2026-09-25(Asia/Tokyo)。性质:独立静态审查;只写指定中文文档,不修复源码,不运行构建、测试、codegen、安装或设备操作。

1. 执行摘要与结论边界

V13 的通用分段解析、Style 顺序及保守 Fast Path 门控有源码依据,但不能据此批准 GPU 正确性或性能。本轮先检查 V12→V13 diff、真实调用链和生命周期,再阅读旧报告逐项挑战。新增优先问题为:离屏目标切换未重置 CPU stencil 掩码记录;Metal depth/stencil 清除契约未完整下传;LayerGroup 抛错后 retained build 仍可能标成功;V4 PLAY 缺少生产时钟推进调用。前三项的实际像素、故障注入和设备行为仍需验证。

旧 F01/F02/F03/F04/F07 的成本路径成立,但没有本轮 profiler 数据证明热点排序、OOM 或收益。F06 多 Continuous 退出静态 CPU Fast Path、F08 保守全局失效属于显式设计限制。F09 可给出计数跨 topology 错归的具体链,但不证明 stale texture 被复用。F05 的 Host .10/native .13 错配成立,历史 TS2307 不能仅归因于版本号;F10 只证明协调文档滞后。

新增成本还包括 V4 全网格物化、UI 线程解码、普通粒子 Metal 离屏等待及 drawable 重建。未找到足以定 P0 的证据;不宣称不存在其他缺陷。调查内容完成,Git 交付结果见阶段记录的收尾条目。V13 产品运行态不判 PASS:本轮所有构建、测试、设备、性能验证均 NOT RUN。 RDC 仍须独立复核和验证。

2. 冻结基线、环境与范围

项目 核实结果
机器/目录 Mac-mini-tei.lan,Darwin x86_64;/Users/tei/dev/MapLibreParticleLab
分支/起始 HEAD particle/main;05878d662308b9a92c20c433c3cd2943d74ae718
起始状态 工作树 clean;子模块未见偏离记录提交的标记
远端 cached origin 与实际 git ls-remote 都是上述 HEAD;origin 为 https://git.eyaku.jp/tei/MapLibreParticleLab/
冻结源码 ee0b89e711bf01335b3aa71d36def785cd97fec3
V13 功能/旧报告归档 016fd1fff6a33cf795c10d4f5c5413d308383677 / 45c4dca84928a57a2cf0226737c34cabd7fbfbfb
V12 比较点 tag 解引用提交 7eaff6e12360e26591dceb5e011129eeab7ba4c7
V13 tag .13 tag 对象 bccbceddec70f7a2b6362bce653f9c577aa2db1d,解引用为冻结源码,远端一致
manifest sourceCommit ddf20dec9fe9cd05b77274827b6825829500dd5a;至冻结提交为发布元数据收尾,生产源码一致
模型记录 用户在本次同一会话恢复指令中明确指定 gpt-6-astra high,与任务要求一致;这是当前会话的用户指定记录。未获得可独立核验的底层启动参数,不声称已独立验证实际模型/effort

冻结源码至起始 HEAD 仅新增旧审查报告及 STEP-095 任务书;下文源码行号按冻结源码,与本轮起始工作树对应。V12→V13 整体 diff 为 45 文件、2393 行增加/203 行删除(含文档),主要新增 segment/parser/resolver、runtime diagnostics、renderer/orchestrator 调度与平台桥接,并非粒子数值 shader 的整体重写。

已读取 AGENTS、PARTICLE_BASELINE、项目规范、项目总则 README 所列当前有效规则及基线 v2,交叉阅读 STEP-088~094 的任务/设计/阶段/报告相关内容。总则仍含早期 .3 和 Linux 主线描述,本任务以 Mac .13 冻结点为准,不重写历史文档。官方 Core 基线 18545ca10d296704b2cba675b182ff2c8da24588,Android 官方 13.4.1、iOS 官方 6.28.0。

2.1 发布坐标(仅核对仓库记录)

来源:release/maplibre-particle/release-manifest.json 与 release/maplibre-particle/ios/release-manifest.json。

产物 坐标 manifest 大小/SHA-256
RN @navsea/maplibre-particle-rn@13.4.1-particle.13,MLRN 11.3.6 25,966 bytes;3a726db06cb967fe56de77ca4a72feed98cd642a2d1b73fd51b1531d15ef7539
Android OpenGL cc.navsea.maplibre:android-sdk-particle-opengl:13.4.1-particle.13 169,786,873 bytes;ddf1deced00cc963d1d625c73c68c449232602113a1490349e69100473dda82b
iOS Metal 6.28.0-particle.13,MapLibre XCFramework/SPM exactVersion 8,418,198 bytes;8d47d9f6d44479aff51299c213887bd9be204da320da4fd4fff15dd064930556

manifest 的 PUBLISHED_PUBLIC_READBACK_PASS 是 HISTORY。本轮没有下载、重算产物散列、重建或核实设备实际链接版本;文档提交不是新 V13 发布。

2.2 调用链和未覆盖范围

已沿 segment JSON/plan → runtime → orchestrator/renderer → cache → PaintParameters/GL/Metal target,及 canonical/QBIN/profile → Store/Clock/projection → RasterArraySource immutable Impl → WeatherColor/Particle RenderLayer → Field/State/Trail GPU 追踪;检查 Android Java/Kotlin/JNI、iOS ObjC++、RN typed API/JSON Spec、Host package/lock/plugin及 Integration 只读状态。阅读 resolver/cache/diagnostics/field/decoder/reseed 测试源码,不等同执行测试。

未逐行形式化验证全部官方 renderer/driver、Vulkan、业务 provider/HTTP/Route/ETA或所有并发交错;未使用设备、capture、sanitizer、fuzzer。此报告不是全仓无缺陷证明。

3. Finding 总表

D=源码可复核缺陷路径;C=源码确定成本;R=后果需运行验证;E=环境/文档偏差。置信度均指源码链而非事故发生概率。每项详细位置、修复与验收见后文。

编号 严重度/类别/置信度 触发与影响 旧报告关系
N01 P1/D+R/高 相同 tiles 跨 target,CPU stencil 映射复用,后段可能被裁掉 新增
N02 P1/D+R/高 Metal retained depth/stencil clear 未完整转换,模拟器 attachment 缺口 新增
N03 P1/D+R/高 group 绘制抛错被 catch,仍标 cache 成功,可能持续复用残图 新增
N04 P1/D/高 V4 只 PLAY 不继续 set time,生产时钟无推进调用 新增
N05 P2/D/高 JSON NUL/重复 strategy 被接受,严格解析失真 新增
N06 P2/D+R/高 结构合法但数值非法的场先入库,物化失败后可用投影被置空 新增
N07 P2/D/高 同 view 重复 attach,listener 和持有引用递增 新增
C01 P1/C/高 full diagnostics 锁内深复制进入 fast/render F01
C02 P1/C+R/高 Metal retained build 与普通 State/Trail target 等待 F02,新增扩大范围
C03 P1/C/高 内容 dirty 释放同尺寸可复用 GPU allocation F03
C04 P1/C+R/高 多 R 全视口资源无总预算;Store 也缺 fieldKey 总预算 F04,新增场预算
C05 P2/C/高 ordinal 线性前缀遍历,fast update 仍扫全部 items F07,新增扫描
C06 P1/C+R/高 同时间/mix-only 整网格物化;提交链可占用 UI 新增
C07 P2/C/高 tick 重建 drawable/attributes/tweaker,窗口切换复制场 新增
O01 P2/D/高 新 topology 先发布,旧 cache 析构向新 index 计数 F09
E01 P1/E/高 Host RN .10 与 Android 插件 .13 错配 F05
E02 P3/E/高 Integration 仍旧状态,实际接入 UNKNOWN F10,降级

4. 新增正确性和生命周期发现

N01:CPU stencil 记录跨 framebuffer 复用

证据:src/mbgl/renderer/renderer_impl.cpp:798-847,938-945;src/mbgl/renderer/retained_underlay_cache.cpp:304-319;src/mbgl/renderer/paint_parameters.cpp:185-201,365-374;src/mbgl/gl/layer_group_gl.cpp:67-98;src/mbgl/mtl/tile_layer_group.cpp:118-119。

最短链:同一个 PaintParameters → 第一个 R 清 stencil、写 mask 并记录 tileClippingMaskIDs → 第二个 R 新 target/清 stencil → tileIDsCovered 为真而跳过写 mask → draw 仍 Equal 非零 ID。CPU 记录属于前一 target,后一 GL target 实际为零。main buffer 清除后也未清 CPU 记录;updateStencilBufferAvailability 不是映射重置。

触发用例:同 vector source、同 tile 集合的两个 fill 分置相邻 R-R,首次都 build;或 R build 后同 tiles 的 C 绘入主目标。tile 集合变化可触发清记录,所以不是所有画面必坏。V13 任意 R-R 扩大暴露面,V12 多 target 也应回归,不能断言只由 V13 引入。

最小修复:target/pass 切换时明确失效 CPU mask/编号,或按 target generation 隔离,并保证 GPU clear 一致。验收:GL/Metal cache OFF 对照,同 source R-R/R-C-R 的首帧、rebuild、reuse 像素和 stencil capture。缺口源码已确认,实际像素 NEEDS_RUNTIME。

N02:Metal depth/stencil 描述未完整下传

证据:retained_underlay_cache.cpp:304-310 请求 clearDepth=1、clearStencil=0;src/mbgl/mtl/render_pass.cpp:13-38 只转换 clearColor;src/mbgl/mtl/offscreen_texture.cpp:32-83,139-148 绑定附件但该路径未设置 depth/stencil clear/load/store。模拟器不创建 stencilTexture,也未将 combined depth/stencil texture 绑定 stencilAttachment;格式选择见 src/mbgl/mtl/texture2d.cpp:99-104。

触发:Metal retained tile/depth 绘制,尤其首次 target、simulator。源码确认契约缺口,但未测驱动默认内容/validation 行为,不宣称所有真机黑屏。isRenderable 仅验证 color,depth/stencil create 在 bind,早期就绪判断不能证明所有附件就绪。

最小修复:完整翻译 descriptor、正确绑定 combined attachment,并验证所有附件后允许 build;保持官方接入薄。验收:Metal API Validation、真机/模拟器 capture 核对 attachment/load/store/clear,故障注入验证安全 fallback。NEEDS_RUNTIME。

N03:绘制异常未阻止 cache 发布为成功

证据:src/mbgl/renderer/render_orchestrator.hpp:156-178 的 visitor catch 只通知 observer;renderer_impl.cpp:798-824 随后无错误结果判断,finishBuild/markBuildSucceeded。

触发:R 的一个 layerGroup.render 抛错,observer 正常返回,其他 group 继续,残缺图像可变 valid 并在稳定帧 reuse。反例:资源准备阶段已有失败回退(retained_underlay_cache.cpp:240-255、renderer_impl.cpp:662-677),问题不等于所有资源失败都没有 fallback。

最小修复:build 汇总明确成功状态,失败 target 不发布/复用,可恢复错误进入完整渲染或约定安全失败。验收:第二个 group 故障注入,确认 successful build/reuse 不增长、无 stale composite、恢复和资源释放正确。NOT RUN。

N04:V4 PLAY 没有生产时钟推进

证据:src/mbgl/style/sources/raster_array_source.cpp:453-470;src/mbgl/particle/field/field_runtime.cpp:196-220;src/mbgl/renderer/layers/render_particle_validation_layer.cpp:1174-1189,1276-1278。生产树 src/include/platform/packages 中 advanceForecastClock 仅见声明和定义,无调用。Android platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/WeatherRuntime.java:225-242、iOS platform/ios/src/MLNParticleFieldRuntime.mm:147-165 的 wake 只 repaint。

最短链:设一次 requested time → PLAY 改 clock state → repaint/particle cadence → renderer 读取不变的 immutable projection.mix。粒子运动不能证明预报时间在播放。Host 每次显式 set time 可绕过,但不代表 PLAY 本身有效。

最小修复:在既有 map/source 所属线程接入唯一单调时钟,明确速度、pause/resume、后台和销毁语义,不建立第二套时间真相。验收:仅设一次时间,PLAY 的 .5/1/2 倍 mix、PAUSE、跨窗口和恢复;test/particle/field_runtime.test.cpp:272-310 手动 advance 单测不覆盖生产接线。本轮 NOT RUN。

N05:Segment JSON NUL 截断与重复键

证据:src/mbgl/renderer/render_segment_json.hpp:16-49。Parse 用 C 字符串,strategy/startLayerId 用 GetString 未带 GetStringLength;"RETAINED\u0000x" 截成 RETAINED,"boundary\u0000x" 可解析到另一真实 ID。segment 两个重复 strategy 满足 MemberCount<=2,白名单不检唯一性,读取首值。

触发可由 primitive JSON/native 入口构造,TS typed API 不替代校验。普通未知 strategy/schema、missing/reversed 仍会 invalid/fallback。最小修复:长度感知解析/构造,拒绝 NUL/重复键,保持 invalid 清旧 plan 语义。验收:上述 payload、raw NUL 后缀、正常 unicode、未知字段、invalid→valid及两桥接错误归一化。NOT RUN。

N06:数值非法的场在入库后才被拒绝物化

证据:src/mbgl/particle/ingress/qbin_v2_decoder.cpp:41-73 校验结构、CRC、scale/offset但不扫描 Float32 样本;src/mbgl/particle/field/field_profile_validator.cpp:77-166 匹配契约;field_projection_materialization.cpp:38-67,97-135 才检查解码数值;raster_array_source.cpp:422-440,496-522 先 submit,再物化,失败 next 对应投影为空。

触发:已有绑定字段,同时间更高 revision、CRC 正确、valid=1、样本 NaN/Inf 的 QBV2。结构/契约可接受,替换旧帧后物化失败,但 submit 返回 AcceptedInserted/AcceptedReplacedRevision。有限 scale 乘法溢出也应纳入验证。此处不声称 NaN 上传 GPU——物化拒绝正是反例;缺陷是 accepted/可渲染语义及旧状态保留脱节。

最小修复:明确 ingress 数值约束,入库前校验或事务式验证,保留合法无效 cell/通用未绑定 plane 语义。验收:好旧帧→坏高 revision,检查返回值、Store/投影保持、noData/validity、极值及恢复。NOT RUN。

N07:Android attach listener 积累

证据:packages/maplibre-particle-rn/android/src/main/java/org/navsea/maplibre/particle/weather/WeatherRuntimeBridgeModule.kt:30-63。每 attach 新增捕获 concrete map 的 listener;显式 detach 只 dispose runtime,view detach 回调也不移除 listener。

同一个存活 view 重复 attach/detach,listener/引用及回调为 O(k)。未证明 view 回收后永久泄漏或 UAF;每次重新解析 view、没有全局 reactTag registry 是正面约束。最小修复:view/map 单一 listener、attach 幂等、明确 remove 生命周期。验收:同 view 100 次、换 view、卸载/后台恢复,listener/dispose/存活对象回基线。NOT RUN。

5. 性能、资源与观测

C01:完整 diagnostics 深复制进入热路径

证据:renderer_impl.cpp:198-208,500-505 → retained_underlay_runtime_state.hpp:243-254 锁内复制 styleLayers、segments.layers、字符串。成功 fast frame 可两次,不是所有帧固定两次。成本 O(L+S),锁竞争程度待测。修复:一致的轻量热快照与完整外部 pull 分开,不能无同步拆字段。验收:稳定 30/60 FPS 的完整快照次数应随外部 pull,测 alloc/frame、锁等待、CPU;无收益百分比。

C02:Metal 等待不限于 retained rebuild

证据:retained_underlay_cache.cpp:316-319 → src/mbgl/mtl/command_encoder.cpp:29-31 → mtl/offscreen_texture.cpp:86-91 commit/waitUntilCompleted,失效 R 逐段同步;稳定 reuse 没有 retained build wait。

新增链:src/mbgl/renderer/render_target.cpp:71-119 普通 target 也 present;render_particle_validation_layer.cpp:1990-2111 tick 注册 State/Trail 写目标,初始化可能更多。因此 retained 稳定也可能有多个普通粒子 wait,属继承成本。修复前先 capture buffers、wait 栈及依赖,再设计有序异步提交,不能直接删 wait。验收:State A/B 无别名,Trail/composite 顺序与轨迹一致,CPU wait/GPU frame time 成对比较。NEEDS_RUNTIME。

C03:内容失效与 allocation 销毁耦合

证据:retained_underlay_cache.cpp:161-237 revisionChanged 同时 invalidate/release;:240-255,365-374 重建/释放 texture/compositor。触发为内容/相机等 revision 改变,不是稳定帧无条件分配。修复:contentDirty 与尺寸/context/格式的 resourceInvalid 分开,同尺寸有效 context 保留 allocation。验收:mutation、camera、resize、context loss 分开统计 build/create/release/peak;先保证 N01/N02 clear 正确。耗时收益待测。

C04:多段 GPU 与多字段 CPU 无总预算

证据:renderer_impl.cpp:506-524;retained_underlay_cache.cpp:240-255;src/mbgl/gl/offscreen_texture.cpp:18-35、mtl/offscreen_texture.cpp:20-55。每 R 全视口 color/depth/stencil;RGBA8 color 理论下界 R×W×H×4 bytes,另有附件、alignment、主 framebuffer、State/Trail及延迟释放,不能把逻辑 release 当物理显存回收。

新增:src/mbgl/particle/field/field_runtime.cpp:223-230 对新 fieldKey 建 series;include/mbgl/particle/field/field_runtime.hpp:115 每 series 默认容量并非总 key/总 bytes 上限。QBIN 单文件64 MiB/解码32 MiB 上限也不约束累计持有量。

修复:map 预算、分配前溢出安全估算、超限明确 full-render/拒绝策略,不合并相邻 R、不淘汰仍绑定窗口。验收:R×viewport×字段数阶梯、allocation failure/context loss、30分钟以上 peak/回收。OOM/泄漏未证实,NEEDS_RUNTIME。

C05:ordinal 前缀遍历和全层扫描

证据:render_orchestrator.hpp:156-178 的 multimap std::distance 是线性,S 次范围定位可能 O(S×G);render_orchestrator.cpp:1202-1226 fast updateParticleLayers 仍遍历完整 items,非粒子只跳过 update;:973-975 按 retained 稳定性还可能扫 source fading。

修复:topology 改变时缓存 global ordinal/粒子列表,保持 generation 和原始全局深度编号。验收:固定粒子层扩大 L/G/S,测 CPU/调用次数并回归 reorder/delete。实际热点占比待测。

C06:同时间/mix-only 仍全网格物化,UI 成本遗漏

证据:raster_array_source.cpp:453-455,496-522 在 sameProjection 前分别物化 color/particle;field_runtime.cpp:196-200 相同非零时间也返回 true;field_projection_materialization.cpp:69-75,97-211 分配/遍历 validity、T0/T1 scalar/vector。Wind 双绑定可重复同向量物化。mix 更新产生新 Impl/onSourceChanged,render_orchestrator.cpp:361-365 全局 SourceMutation 可进一步失效所有 R。

桥接:Android withMap UI 调度经 platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp:1501-1517 同步到 Source;iOS packages/maplibre-particle-rn/ios/WeatherRuntimeBridge.mm:105-120,235-240 的 withMap 与 platform/ios/src/MLNParticleFieldRuntime.mm:222-252 也同步提交 Core。预读取文件不等于 CRC/解码/物化已经离开 UI。成本随格点/plane 增长,实际卡顿/ANR未测。

修复:相同时间早退,按端点 identity/binding 共享不可变物化、mix 单独更新;若 worker 解码,owner-thread 发布必须带 map/source generation,禁止 worker 直接改 Source。局部失效必须先有完整依赖。验收:同时间、mix-only、跨窗口、双绑定、最大网格的 CPU/alloc/UI阻塞/upload/rebuild计数。NEEDS_RUNTIME。

C07:tick 对象重建及端点复制

证据:render_particle_validation_layer.cpp:826-904 clearDrawables 后新 attributes/builder/tweaker;:1668-1669,1990-2111 更新 target 注册及 State/Trail/composite;:657 createOrUpdate UBO 不证明跨新 drawable 复用;:1494-1499,1538-1563 场端点切换复制数组。

反例:State/Trail textures 和共享顶点不是每 tick 全部重建,field 复制主要在窗口边界,不能称 CPU 每帧模拟全部粒子或无条件上传场。修复:稳定 drawable 保留,仅更新 uniforms/texture,端点共享不可变存储。验收:tick/bootstrap/reseed/resize/端点轮换分别测对象、UBO、upload和峰值。NOT RUN。

O01:旧 cache release 记入新 topology

证据:retained_underlay_runtime_state.hpp:173-240 先发布新 entries;renderer_impl.cpp:500-524 再 clear 旧 cache;retained_underlay_cache.cpp:120-122,365-374 析构按旧 segmentIndex 计数;runtime :256-272 寻找当前 entry。

旧 index 0 的 R 换成新 R,旧 release 可记入新 R;新 index 为 C/越界时 per-segment 计数丢失。不证明 GPU 未释放或旧图复用。另 runtime :198 root fallback 只表示 resolution invalid,不能覆盖 cache OFF/unsupported/resource fallback;消费方不可读成 GPU 当前 retained 成功。

修复:计数带 cache identity/generation,聚合历史与当前段分开,明确两类 fallback。验收:真 cache R-R→C-R、相同 index 换边界、disable/restore析构计数,纯手动 counter 测试不足。NOT RUN。

6. 环境发现和旧 F01~F10 复核

E01 定位:integration/react-native/MapLibreParticleRNTestHost/package.json:12、package-lock.json:12,1765-1766 为 .10,plugins/withParticleNativeAndroid.js:9 注入 .13,当前 package/native 为 .13。默认干净 Host 不能证明 V13 全链。旧 typecheck exit2/TS2307/TS7006 为 HISTORY;缺模块和旧 API 是不同原因,本轮未复跑。修复方向:后续单独对齐 package/lock/native resolved version,干净安装、typecheck/codegen及设备调用;不能把临时工作树链接 PASS 当默认包 PASS。本轮不改依赖。

E02 定位:只读 /Users/tei/dev/navsea-particle-integration HEAD 39ad8415fbdb76c1822460bb09f3a3f35fe141e0,compatibility/MATRIX.md 与 status/ 仍含 Sept18 .5、iOS 等待、RN NOT_STARTED。它与本仓 .13 是不同时点,真实 NavSea 接入 UNKNOWN。降 P3 文档项,建议负责人以接入 commit/包/设备证据更新,不改 Core 协议;本轮不改 Integration。

旧项/原结论 当前意见 修正和依据 补证
F01 P1 深复制 CONFIRMED C01,成功 fast 可两次而非每帧必两次 alloc/锁/CPU NOT RUN
F02 P1 retained wait CONFIRMED C02,限定 build,补普通粒子 wait 收益 NEEDS_RUNTIME
F03 P1 dirty 释放 CONFIRMED C03,稳定 reuse 不重建 内容/resize/context分测
F04 P1 无预算 CONFIRMED C04,无预算不等于已 OOM peak/压力 NEEDS_RUNTIME
F05 P1 Host 不可复现 QUALIFIED E01,错配确定,旧 TS2307非本轮且不可仅归版本 干净安装 NOT RUN
F06 P1 multi-C full CPU QUALIFIED 显式设计限制,建议 P2;不等于关闭 GPU retained reuse 相同Style A/B NOT RUN
F07 P2 ordinal 线性 CONFIRMED C05,优化定位不能改全局编号 S/G基准 NOT RUN
F08 P2 全局失效宽 QUALIFIED 保守设计,未证明 stale;未知依赖不能裁窄 source/tile/glyph依赖
F09 P2 错归风险 CONFIRMED O01具体先换entries后旧析构链;不证明stale texture 真cache生命周期 NOT RUN
F10 P2 文档漂移 QUALIFIED E02降P3;不推定实际接入 负责人跨项目核对

没有为凑数将整个旧项标 DISPROVED;被否定的是“多C关闭所有GPU reuse”“计数错归证明旧纹理复用”“.10必然造成TS2307”“单测证明像素正确”等外推。旧报告未明确作这些断言之处,也不反向指控它作过。

7. 反例、边界和设计限制

  1. render_segment_plan.hpp:32-157 采用完整 ordered IDs(含 hidden),边界存在且递增,全R/全C合法,相邻同策略不合并,V12经同模型映射;首段可省 startLayerId 是契约。普通 invalid 清 resolution、恢复重解析有依据。
  2. reorder 不是“仅added/removed所以遗漏”:src/mbgl/renderer/style_diff.cpp:9-42 序列差异体现移动,render_orchestrator.cpp:318-329 重建 orderedLayers,未报告无可达链的 reorder bug。
  3. renderer.cpp:37-59 在 full createRenderTree 前清 prepared tree,fast gate 检查 style/source 等输入;不能只见缓存引用便断言 UAF。context/destroy 极端交错仍需验证。
  4. renderer_impl.cpp:798-918 保留 opaque reverse/translucent forward 与 global ordinal,compositor premultiplied alpha/depth disabled 有源码依据。但不能推导所有分段像素等价,N01/N02仍为 gate;不凭空宣称所有 alpha 顺序错误。
  5. Cache OFF、不支持内容、资源准备失败已有普通路径;多 C 只退出 CPU fast,R可reuse。3D/debug/legacy/custom gate保守,不建议绕过求性能。
  6. QBIN有文件/plane/cell/decoded上限、CRC/bounds/长度检查,Clock有速度/整数溢出检查;FieldSeries按时间/revision处理重复/旧版本并shared持有窗口。未找到可证实的任意写/越界链;N06是数值发布语义。旧canonical adapter已有有限性检查,不能一概否定。
  7. State A/B、Trail、T0/T1和方向/速度各有路径;render_particle_validation_layer.cpp:1671-1810 resize重建Trail、按zoom-out gesture决定reseed并保留其他状态,不代表orientation/zoom-out设备通过。nearest/linear采样及双端点validity需数值视觉基准,本轮未断言错误插值。
  8. 共享海陆mask尚无验收证据:field_projection_materialization.cpp:77-92 snapshot displayDomain为GLOBAL;render_particle_validation_layer.cpp:278-293,1314-1324 有synthetic coastal mask路径。不能据此证明Wave/Tide/Current共用正式Land/Ocean Mask;陆地覆盖显示不等于mask。列为架构/接入证据缺口,不擅改协议。
  9. 桥接保持map-scoped,typed object经内部JSON,没有引入业务协议;普通invalid plan会关闭旧计划。符号接线不等于ABI/codegen或销毁竞态已测。

8. V12/V13 架构与成本比较

L=层数、G=LayerGroup数、S=段数、R=retained数、W/H=物理视口、P=格点。仅源码模型,不是测量。

维度 V12 V13 判断
topology 固定range,最多两个R 任意独立R/C,相邻R不合并 扩大管理/资源上界,不自动提高FPS
GPU复用 固定retained部分 每R独立 Layer fingerprint局部化,全局依赖仍保守
CPU fast 合格单连续区间 恰好一个C且gate满足 多C full CPU不等于GPU cache关闭
diagnostics 旧统计结构 完整Style和重复段层列表 C01 O(L+S)复制
范围定位 固定数量 S段前缀可能O(S×G) 实际占比待测
retained资源 至多两组 O(R×W×H) 物理峰值与OOM未测
Metal等待 固定targets 随失效R增加 普通State/Trail是继承成本
场/粒子更新 已有物化/drawable 多数继承 C06/C07不全归因V13

STEP-090 fast ON 21.7%/OFF97.0% RenderThread仅历史特定实验,不外推V13。历史一次退出及随后短时未复现,既不证明泄漏也不证明长稳。必须同设备、Style、源数据、视口、刷新率/热状态配对,先像素正确再比CPU/GPU。

9. 测试证据与 RDC 验证矩阵

项目 历史 本轮
STEP-094 GL构建、8 suites/43 tests 报告PASS HISTORY/NOT RUN;纯状态解析不能验证GPU
Field/QBIN/viewport69 tests、package TS 旧审查PASS HISTORY/NOT RUN
Metal-only iPhoneOS编译 STEP-094 PASS HISTORY/NOT RUN;不验证附件/像素
Android APK、RN codegen STEP-094 PASS,codegen用底层入口 HISTORY/NOT RUN
Host工作树替换TS及旧默认失败 两种不同依赖环境 HISTORY/NOT RUN,可同时成立
本轮静态/文档检查 不适用 已执行;Git结果见阶段收尾

以下所有运行项本轮均未执行。

Gate Android GL iOS Metal真机/模拟器 Vulkan/其他 证据要求
R/C/R-R/R-C-R/C-R-R/R-R-C/R-C-R-C-R NOT RUN NOT RUN NOT RUN cache OFF/ON截图、像素差、pass/ordinal
同source stencil、半透明fill/line/symbol NOT RUN NOT RUN NOT RUN 首帧/rebuild/reuse、depth/stencil capture
hidden/reorder/delete/restore/invalid NOT RUN NOT RUN NOT RUN 下一帧无stale、revision与plan
OFF/资源失败/draw失败/context loss NOT RUN NOT RUN NOT RUN 失败不可reuse,资源配对与恢复
PLAY/T0T1/坏数值/乱序/旧revision NOT RUN NOT RUN NOT RUN time/mix、返回码、旧窗口保持策略
pan/zoom-out/pitch/resize/orientation NOT RUN NOT RUN NOT RUN state/trail/reseed及无额外field提交
30/60FPS,单C/多C、mutation NOT RUN NOT RUN NOT RUN CPU/GPU p50/p95/p99、miss/wait/alloc
预算/峰值/30分钟以上长稳 NOT RUN NOT RUN NOT RUN R×视口×字段阶梯、bytes/后台/卸载
attach/detach/双map/销毁中完成 NOT RUN NOT RUN NOT RUN owner thread、generation、listener
干净包版本/ABI/codegen NOT RUN NOT RUN 不适用 resolved包/散列/生成接口/实际调用

RDC先记录HEAD/manifest/tag/构建配置;以下是既有精确命令,本轮未执行。新增缺陷尚未补测试,旧过滤集PASS不能关闭本报告。

cmake --build build-step088-opengl --target mbgl-test-runner -j3
build-step088-opengl/mbgl-test-runner --gtest_filter='RenderSegmentPlan.*:RenderSegmentDiagnostics.*:ContinuousLayerRange.*:RetainedDynamicBoundary.*:RetainedLayerGroupRange.*:RetainedUnderlayCache.*:RetainedUnderlayRevision.*:ParticleFastPath.*'
build-step088-opengl/mbgl-test-runner --gtest_filter='ParticleFieldRuntime.*'
cmake --build build-ios --target ios-sdk-static -- -quiet

Metal命令前确认构建目录MLN_WITH_METAL=ON、MLN_WITH_OPENGL=OFF;缺目录由RDC按规范配置,不复用未知缓存。RN先解决真实resolved .13前提,再按STEP-094/083现行入口typecheck/codegen。失败回传首个真实error、target、上下文和日志路径,成功仅exit/耗时/摘要。

10. 优先级与建议修复批次

只建议,不创建修复任务、不改源码。

批次 范围 Gate/安全约束
A 正确性 N01/N02/N03 target/Metal/失败发布,N04时钟另小提交 最小复现、故障注入、两平台OFF基线、PLAY端到端;不借机全面重构
B 无设备可先回归 N05/N06/N07/O01/E01 纯测试/桥接由RDC执行;版本可复现,不代替A的GPU gate
C CPU安全优化 C01轻快照、C05ordinal/粒子列表、C06相同时间早退/端点复用 同步一致、Style唯一顺序、调用/分配次数证明
D GPU资源/同步 C02/C03/C04/C07 先profile,再预算和allocation/content分离;明确buffer依赖,不能直接删wait
E 较大架构 multi-C fast、source依赖、异步大场、正式共享mask 单独设计,未知依赖继续全局失效,不引入provider/HTTP业务调度

11. Git 与交付

仅四个允许路径:本文、docs/50_Step记录/STEP-095_V13独立严格代码与性能审查_v1.md、docs/报告/STEP-095_V13独立严格代码与性能审查_Codex完成报告_v1.md、根粒子开发记录.md末尾追加。创建前同主题输出不存在,使用v1,不覆盖旧报告。

起始HEAD 05878d662308b9a92c20c433c3cd2943d74ae718。检查路径/引用/git diff --check后仅scoped staged/commit/push origin particle/main。实际SHA/message、push/remote/status及最终收尾提交自引用说明见阶段记录第4节;推送未完成前不写Git PASS。冻结源码至最终文档提交的差异只含既有两份文档及本轮四份文档,不含源码/shader/API/依赖/build/manifest/tag/产物。