Files
MapLibreParticleLab/docs/30_设计/STEP-081_iOS_Metal_Renderer与真机Smoke入口设计_v1.md
tei f1c0f92b2b
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
fix: close STEP-081 iOS Metal particle rendering
2026-09-18 07:58:51 +09:00

4.8 KiB
Raw Permalink Blame History

STEP-081 iOS Metal Renderer 与真机 Smoke 入口设计 v1

状态:CLOSED / PASS。已在 Pleiades(iPad mini 5 / iPadOS 26.5.2)完成签名安装、Metal runtime、deterministic fixtures 与 QBIN V4 T0/MID/T1/Clear 真机验收。

目标和边界

Metal 路径消费既有 RasterArraySource V4 renderer projection、WeatherColorLayer 与 RasterParticleLayer。没有 iOS Field model、QBIN decoder 分支或公开 iOS SDK API。Smoke 代码仅在 platform/ios/app/MBXViewController.mm,RN iOS bridge 仍是明确非目标。

OpenGL → Metal pass 对照

u_pass.x OpenGL 既有语义 Metal ParticleGpuValidationShader
< 0.5 State A/B update / seed / respawn 同一 T0/T1 decode、timeMix、VELOCITY/DIRECTION advection 与 fail-closed state write
< 1.5 Trail fade 同一 retention fade;legacy validation marker 保留
1.5–3.5 Composite / FrozenComposite 同一 trail/particle 色彩、mask、speed-color 和 legacy diagnostic 分支
> 3.5 Trail particle line draw State read/write displacement line,respawn alpha 抑制跨屏线
> 4.5 WeatherColor 同一 scalar/vector magnitude、stops/ramp 和 invalid discard
> 5.5 无 Metal-only current-endpoint 1 px quad coverage;只补 raster coverage,不改变 State、速度、时间步或 previous→current 物理长度

MSL 使用 ParticleGpuValidationUBO 的同字段 vec4/float4x4 布局;声明与 C++ 的 alignas(16) 相同,并在 MSL 中静态断言 31 * 16 字节。此 Step 未改动 C++ UBO、QBIN V4 contract 或 OpenGL source。

Metal binding

类别 Metal index Stable ID
vertex attribute short2 a_pos attribute 0 idParticleGpuValidationPosVertexAttribute
UBO buffer drawableReservedUBOCount idParticleGpuValidationUBO
previous texture/sampler 0 idParticleGpuValidationPreviousTexture
mask texture/sampler 1 idParticleGpuValidationMaskTexture
field T0 texture/sampler 2 idParticleGpuValidationFieldTexture
field T1 texture/sampler 3 idParticleGpuValidationNextFieldTexture
state texture/sampler 4 idParticleGpuValidationStateTexture

这些 index 来自 Metal ShaderSource 的 attributes/textures 表以及 existing shader IDs,而非 OpenGL location 推测。注册位于 src/mbgl/mtl/renderer_backend.cpp,CMake source/include list 位于 cmake/metal.cmake。

Smoke 数据链

Test App Runtime Styling 菜单新增 Particle / QBIN V4 Smoke (T0)。点击后可选 T0、midpoint、T1 或 clear/release。它从 app bundle ParticleSmokeFixtures/T0.qbin、T1.qbin 读取现有 RN Wind Golden fixtures;platform/ios/app/CMakeLists.txt 在构建后从唯一 fixture 来源复制,不创建第二种数据格式。

private MLNMapView seam 提供 mbglMap。Smoke 直接创建 RasterArraySource,提交 fixture.wind T0/T1、Wind profile contract、ColorBinding 与 VectorComponents ParticleBinding,再添加 WeatherColorLayer 与 RasterParticleLayer。T0=1789239600000、midpoint=1789241400000、T1=1789243200000,全部通过 source-owned requested forecast time 选择窗口/mix。clear 先移除 layers 后移除 source,允许重复创建。Wind Golden fixture 实际范围为 112.5E..157.5E、0..55.776573N,Test App smoke 会把相机置于约 27.8883N / 135E、zoom 3,保证 FIELD_READY 后画面可观察;这只是 Test App 可视化入口,不改变 Core 数据范围。

Metal 真机收口结论

真机调试确认两个 Metal 特有问题并形成正式修复:

  1. ShaderProgram::getRenderPipelineState() 的缓存复用 key 原先只包含调用方 reuse hash,没有包含 color/depth/stencil attachment pixel format。粒子 State 使用 RGBA32Float、Trail 使用 RGBA8Unorm、主 renderable 常见 BGRA8Unorm,同一 shader 因此可能复用到不兼容的 pipeline。修复后 cache key 显式合并 color/depth/stencil format;物理 iPad 上 Trail RGBA8 写入从全零恢复为有效像素。
  2. deterministic Vortex 实测真实 previous→current 线段平均约 0.065 px、最大约 0.24 px,全部小于 0.5 px。Metal MTLPrimitiveTypeLine 对该亚像素长度没有稳定可见覆盖。正式 previous→current line 保持不变,Metal 额外在真实 currentPosition 绘制 1 px quad coverage;不拉长轨迹、不改变 State、advection、时间步或物理速度。

同时确认 Metal vertex-stage texture/sampler binding、State A/B RGBA32Float、Trail A/B RGBA8、矩阵投影与 Composite 均可工作。

后续边界

STEP-081 已关闭。下一轮如需 iOS RN,必须另行设计桥接;不得把本 App 的 private Core seam 提升为 SDK 或 NavSea API。当前 Metal vertex+fragment 双阶段纹理绑定可在后续独立技术债中收窄为 stage-specific binding,但不得在 STEP-081 收尾中继续重构。