Files
MapLibreParticleLab/docs/20_调查/STEP-119_Symbol结果证书与R缓存Build实现依据_v1.md
tei 3d989a00a8
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
feat: admit settled Symbol render results to retained cache
2026-10-11 16:47:21 +09:00

11 KiB
Raw Blame History

STEP-119 Symbol结果证书与R缓存Build实现依据 v1

日期:2026-10-11(JST)。状态:IMPLEMENTED_WAITING_ANDROID;Shared Core已有实质实现,尚无本轮编译、GPU、Android或视觉验收结论。

1. 基线与原证据

仓库 /Users/tei/dev/MapLibreParticleLab,Mac.lan / Darwin24.6.0 / x86_64,particle/main@869930046b11dbeb3b147e3be952a2e847316292。Native版本13.6.1-particle.23。Integration本地只读HEAD=80667d6c343411d03a760425438e3d292f452118;已读取AGENTS、instructions、README、WORKFLOW、TEAM_MODEL和contracts/rfc/adr/status/compatibility,未写跨仓文件。纯Renderer内部优化,不新增公共接口、所有权或错误协议;C-001/C-002和Core-owned timeline/playback保持。

STEP117揭示:Continuous重新计算令placementChanged=true;recent复用设置stale,hasTransitions=true。旧Symbol gate要求changed=false、fade=0、transition=false,两个分支都不能自举。global retainedPlacementStable、retainedStaticStable、retainedSupported、preparedSceneSupported还有独立阻断。

STEP118保留原63基础层manifest,仅测试副本排除tide-spots:62基础层+2天气层,Native64,R[0,62)、C[62,64),missingSourceIds=[],static-placement、Build0/Reuse0。旧设备90.00806697399821秒FastDelta0/FullDelta942、decisionMismatch0,不是本轮结果。

旧APK源码3051196054c7b69815c298040dae61d26499d9f2,SHA=44afcfabe0cf4f1ec93f35899241bd73093aa6db4b5cb82ca2120dd531b8f3e9。旧result.json SHA=d3d20fc35bbd17e9f0ea0dd014ca4af8e0c5c5284d9f0c009bc20981d876ff10;screen.png SHA=c8b57a8432626c9209ca9a614a747728d4256bd09273b28c26a793a75a6d44d4。本轮只读解析/核对,文件未修改。

2. 实际渲染生命周期

  1. 正常Full先createRenderTree:Source/style差分、跨瓦片ID匹配、全场Placement碰撞与commit继续使用原实现,没有按R段拆碰撞或冻结新结果。
  2. RenderTreeImpl::prepare调用Placement::updateLayerBuckets,继续处理text/icon、重复符号、variable anchors、方向、opacity、动态顶点、沿线投影和排序。
  3. Renderer依次上传source/layer/atlas,updateLayers创建或更新Drawable,processChanges实际应用注册/移除队列。
  4. 所有正常Full LayerGroup先runTweakers并upload。SymbolLayerTweaker记录同一份传给GPU的evaluated props、drawable/tile UBO字段;记录frameCount,并确认evaluated/drawable/tile UBO存在和consolidated容量,未执行、出错、缺buffer或错误帧不能补证。
  5. 此后采集每R的原生Symbol绘制输入,与上一成功提交Full的证据精确比较。符合就准入首次Build,不依赖已有缓存。
  6. Build保持原双pass和原始全局ordinal;finishBuild后再检查输入未改变。资源/绘制错误走Fallback;实际主缓冲按原R/C层序composite或live绘制。
  7. present和endFrame成功返回之后再次检查输入、epoch及错误代次,才记录完成Full/Build证书。它证明成功编码和提交,不宣称GPU fence完成或像素等价已经测量。
  8. 后续一次正常Full Reuse成功提交后,才允许Fast。Fast使用相同证书版本、content/topology/config、相机、backend viewport、pixelRatio和crossSourceCollisions,并继续原24项Gate。

普通Full替换旧prepared tree时只销毁引用式RenderItem;证据拥有复制的字节和必要资源引用,跨Full保留。style/context/显式prepared-tree reset仍清证书。symbolCompletedSignature独立保存上一Full的非相机输入,防止glyphURL/fontFaces/placement设置等在旧树销毁后丢失保护。

3. 结果证据包含什么

实际输入 采集与保护
Symbol uniforms 从SymbolLayerTweaker实际提交的CPU参数复制;包含paint颜色/透明度/halo、tile/label/coord矩阵、尺寸/插值、gamma、text/icon/halo标志;忽略SymbolDrawableUBO末尾12字节非shader padding
顶点与实例属性 对实际Drawable绑定的VertexAttributeArray/InstanceAttributeArray记录属性索引、类型、stride、offset、vertexOffset和共享原始字节;包含静态布局、动态位置/角度、opacity、data-driven paint、排序实例;共享属性必须已有GPU背板,索引必须已上传且非dirty
已释放的不可变buffer 只在producer已release且存在GPU backing时用保持存活的对象/背板身份;不能读取的可变输入拒绝。不是把任意空数据当相等
text/icon/索引与排序 原生SymbolBucket对应text/icon/sdfIcon buffer、segment范围、instance/vertex/index长度、sortKey;两条路径均记录实际三角索引字节,release后必须保持不可变索引对象与GPU背板身份;instancing固定quad和segment仍核对
fade 检查每个实际opacity顶点的packed值及当帧fade;必须在放置目标方向达到shader clamp终点,并且真实Placement fade已结束;非有限值、负值、非整数或越界packed值拒绝
atlas/texture/sampler 保持atlas、glyph/icon及实际绑定纹理/原生atlas tweaker身份,核对尺寸/format、上传状态和实际绑定一致。原生tweaker的sampler策略由固定bucket/layout和相同camera/无手势状态决定;glyph/icon像素原地更新由既有全局epoch保护
shader 独立provenance记录只在实际GL/Metal编译源码与原生Symbol源码完全相符、额外宏属于原生uniform白名单时登记;保留shader对象身份。名称相同的未知/替换shader不借用fade契约
LayerGroup/层序 processChanges之后验证Symbol组确实注册,隐藏层无旧注册组,collision额外组或陌生组拒绝;记录全局group总数、原始ordinal、组身份/层索引/数量/enable,以及Drawable实际混合方程/因子/颜色mask、剔除/深度/3D状态。全局depth range与跨段排序因此参与证据
版本与生命周期 精确结果revision、成功Build revision、成功Reuse状态;绑定content/topology/config、camera矩阵、viewport、pixelRatio、crossSourceCollisions;原update signature/SourceRevisionBook/Annotation Gate继续使用

每个结果字节缓冲上限16MiB,超限拒绝证书;没有提高公共容量或假装完整证明。资源引用避免地址ABA;比较对象是字节序列而不是散列。既有segment cache revision组合仍保留,但Fast还直接核对证书状态,不能靠组合散列碰撞取得证书;Full Reuse也要求candidateHasBuild精确版本,缺匹配Build时显式invalidate旧Cache,再走Build。

4. Placement与fade语义

没有修改placementIsRecent、setPlacementStale、原hasTransitions、commit/fadeStartTime、updatePeriod或placement计算频率。原hasTransitions仍用于正常renderer请求刷新。新增内部hasActiveSymbolFade仅表示实际fade;retainedRangeIsStable、retainedSegmentIsStable、retainedPlacementTransitionActive和Fast动态输入改用它。

GL三个原生Symbol vertex shader和Metal symbol.hpp三类shader均使用unpack后的base opacity加/减fadeChange并clamp到[0,1]。>=1在合法packed值上足以达到fade终点,但不能证明顶点、uniform、atlas或层序相同。因此没有单独用>=1放行,而是逐opacity检查+完整结果比较+提交代次。

重算仍令placementChanged=true,诊断继续如实记录;它不再被当成最终GPU输入改变。recent/stale仍请求刷新,不能单独代表正在fade。Fast rebase保留被证书确认的Full fade值,不把它清为0来取得准入。

5. 完整准入与失效

首次Build路径:已完成Full证据 → 下一Full同绑定同输入且已settled → Build编码成功 → present/endFrame及复核 → Build证书。Reuse/Fast路径:同版本缓存 → 正常Full Reuse成功提交 → 原24Gate全部通过 → Fast。preparedSceneSupported与global/perSegment稳定性均使用同一结果证明,不存在只改perSegment条件的旁路。

以下继续fail-closed:missing Source、CustomMVTVector未知revision、tile fading、未loaded style/sprite/image manager、paint/light transition、非粒子repaint、3D/debug/非continuous、不支持C、Annotation pending、相机/viewport/pixelRatio/非相机参数、异步content或pending changes、资源/编译/上传/绘制错误、未知placement-capable类型或shader(Symbol原生typeInfo指针必须匹配,名称相同不足以强制转换)、证据超限/不可读取。

Glyph requested/error/loaded、Tile error/changed、Symbol error新增或保持epoch推进;Image missing/remove/update、Source差分、Context reset、Style clear沿用原保护。捕获到的renderer/registry错误推进错误代次与全局content epoch;逃出上传/编码/present的异常由Renderer外围捕获,清prepared/证书、失效所有旧Cache后原样抛出;证书不能使用失败更新的旧Drawables。Build前和成功提交后都有epoch复核,证据观察期间的变化拒绝完成证书。

现有回调/registry操作运行在renderer调度线程;content revision是原有atomic。此优化不建立后台并发访问Drawable的通道,不改变callback线程合同。真正跨线程竞态仍需RDC平台实测。

6. 反例与保守限制

  • 同placed布尔但variable anchor/角度/opacity不同:实际属性字节变化,revision递增,重新Full取证。
  • controller不fade但尚未上传/陌生shader/atlas未绑定:complete=false,拒绝证书。
  • glyph/icon纹理指针不变但内容更新:content epoch变化,旧Build/ReUse证书失配。
  • Source同名替换、原63层缺tide:SourceRevisionBook/loaded/缺源保护仍拒绝,不能借空RenderItem作零贡献证明。
  • 下方段删除group导致上方R ordinal/depth改变:全局group数量/ordinal证据变化,上方R不得复用旧结果。
  • Build存在但没有成功Full Reuse:canFast=false;失败/未完成的Full不能刷新成功提交证据。
  • Vulkan/WebGPU目前没有本轮原生shader provenance登记,Symbol结果证书保守拒绝;它们的普通Full渲染不变。本轮不宣称跨后端运行通过,也不以GL代替Metal验证。
  • 16MiB上限、非常大的PBF、持续Glyph/Tile更新、不同native实例buffer生命周期均可能继续阻止Build;须保留真实结果修复,不能提高测试阈值制造PASS。

7. 测试与待证事实

新增13项Step119SymbolResults,位于已登记的两个test/renderer文件。覆盖真实Controller lifecycle+SymbolBucket opacity/dynamic buffer、packed clamp反例、variable位置/角度、camera/viewport/pixelRatio、CollisionGroups、真实uniform/wrapped tile编码、未知shader、失败提交、Annotation与24Gate、真实Tile/Glyph/Image/Context/Style回调、Source同名替换/缺失和跨段registry移除。

所有新增测试NOT COMPILED/NOT RUN。部分Build标记和字节payload是状态机fixture,绝不称真实GPU等价;现有CrossTileSymbolLayerIndex和Annotations图像测试必须由RDC一并验证。原PBF跨段collision、实际Glyph/Atlas延迟、Full/Fast图像、真实Build/Reuse/Fast和性能仍全部待独立验收。源码去除逻辑自举死锁,不承诺本机实机目标已实现。