# STEP-081 — iOS Metal Renderer 与真机 Smoke 入口 Codex 任务 v1 状态:计划 日期:2026-09-17 ## 1. 任务性质与执行机器 本任务在 `Mac-mini-tei.lan` 的 `/Users/tei/dev/MapLibreParticleLab` 执行,是 Android 粒子系统完成后的第一张 iOS/Metal 实现任务。 当前代码事实: - branch:`particle/main` - 起点 HEAD:`f23f4143b9642de0e8d6661dd567e791494a0a0b` - `origin/particle/main`:同一 commit - 当前 Android/RN 代码版本:`13.4.1-particle.5` - iOS 官方基线:`ios-v6.28.0`,与 Android 共用 core `18545ca10d296704b2cba675b182ff2c8da24588` - iOS 当前 renderer:Metal - `ParticleGpuValidationShader` 目前只有 OpenGL ShaderSource,Metal 尚未实现/注册。 Codex 是本任务的大规模代码实现者;**Codex 禁止执行任何 iOS/Xcode/CMake 编译、链接、安装、Simulator 或真机操作**。Codex 完成后停止,由 RDC 把结果交给 GPT 审查;审查通过后,实际编译和真机验证由 GPT + RDC 完成。 ## 2. 前置必读 开始修改前必须读取并遵守: 1. `AGENTS.md` 2. `PARTICLE_BASELINE.md` 3. `docs/00_项目规范/` 全部当前文件 4. `docs/00_项目总则/README.md` 及其列出的当前有效总则 5. `docs/00_项目总则/当前基线与开发路线_v2.md` 6. `packages/maplibre-particle-rn/CHANGELOG.md` 与 `README.md` 7. 当前 `RasterParticleLayer`、`WeatherColorLayer`、QBIN V4 Projection/Materialization 代码 8. Metal backend、Metal shader group/program、iOS app CMake 与 `MLNMapView` private Core seam 若旧总则中出现“Simulator 验收”或“Codex 负责构建”的描述,以本任务和用户最新规则为准:**iOS 不做 Simulator 测试;Codex 不编译;RDC 编译;运行验收只用真机。** ## 3. 本 Step 目标 实现第一条可被 iOS 真机触发的 Metal 粒子渲染路径: ```text QBIN V4 / canonical field → RasterArraySource V4 renderer projection → WeatherColorLayer + RasterParticleLayer → ParticleGpuValidationShader (Metal) → MapLibre Metal gfx backend → iOS 原生 Test App 真机 Smoke 入口 ``` 本 Step 不接 React Native iOS bridge。 ## 4. 固定架构边界 必须保持 Android 已冻结的核心语义不变: - 不改变 QBIN V4 文件格式、Decoder、FieldProfile/Binding 语义。 - 不改变 `RasterArraySource` 对 T0/T1/MIX、Forecast Clock、boundary reuse 的所有权。 - 不改变 `WeatherColorLayer` 与 `RasterParticleLayer` 分离原则。 - 不新增 iOS 专用 Field 数据模型,不复制一套 Particle Runtime。 - 不把 provider、HTTP、manifest、下载、缓存或 NavSea 业务逻辑放进 Native/iOS。 - 粒子颜色继续独立于 WeatherColor ramp;不得为了 Metal 顺手改变视觉产品语义。 - iOS/Metal 应消费与 Android/OpenGL 相同的 C++ RenderLayer、UBO、field snapshot 和 renderer-facing V4 projection。 后端差异只允许落在 Metal Shader/资源绑定/必要的 backend thin-hook 与 iOS Test App smoke seam。 ## 5. 必做项 A — Metal Particle Shader 新增 `ParticleGpuValidationShader` 的 Metal `ShaderSource`,语义必须与当前 OpenGL 版本逐 pass 对齐,至少覆盖: - State A/B update - Trail fade - Trail particle line draw - Composite / FrozenComposite - WeatherColor pass(当前 `u_pass.x > 4.5`) - T0/T1 `timeMix` - field bounds / respawn bounds - VELOCITY 与 DIRECTION 两种 advection semantics - particleColor / trailColor / speed-color optional path - WeatherColor stops/ramp - invalid alpha / invalid sample 的 fail-closed 行为 - world/map matrix projection Metal 实现必须复用现有 `ParticleGpuValidationUBO`,不得另建 iOS 专用 UBO。必须核对 Metal `alignas(16)`/buffer layout 与当前 `sizeof(ParticleGpuValidationUBO) == 31 * 16` 契约。 必须从当前 shader IDs / texture IDs / attribute IDs 推导 Metal binding,不得凭 OpenGL location 猜测。 建议文件形态遵循现有 Metal shader 规范,例如: ```text include/mbgl/shaders/mtl/particle_gpu_validation.hpp src/mbgl/shaders/mtl/particle_gpu_validation.cpp ``` 具体文件名可按仓库现有命名契约调整,但不得把 MSL 字符串塞进 renderer layer 源文件。 ## 6. 必做项 B — Metal backend 注册与构建图接线 必须完成: - 在 Metal renderer backend include 新 shader。 - 将 `BuiltIn::ParticleGpuValidationShader` 注册进 Metal shader registry。 - 补齐 Metal shader `attributes`、`textures` 与 UBO/buffer binding。 - 如当前 CMake/Bazel/source list 不是自动 glob,补齐最小构建图接线。 - 不修改 OpenGL shader 语义来“迁就”Metal;若共享 ID 定义确有缺口,只做 backend-neutral 最小修正并在报告中单列原因。 必须静态检查当前 `RenderRasterParticleLayer` / `RenderWeatherColorLayer` 使用的 gfx API 是否存在明显 OpenGL-only 假设。能通过现有 gfx 抽象工作的代码保持不动;只有明确阻断 Metal 的点才允许最小修改。 ## 7. 必做项 C — iOS 原生真机 Smoke 入口 在现有 `platform/ios/app` 内增加一个最小、隔离、可明确触发的 Particle/QBIN V4 Smoke 场景,用于后续 RDC 编译安装后在真实 iPhone/iPad 上触发 Metal shader runtime compilation。 要求: - 使用现有 iOS Test App,不新建第二个产品工程。 - 场景应能从 App 内明确进入,名称应能识别为 Particle / QBIN V4 Smoke。 - 使用仓库现有 Wind Golden QBIN T0/T1 作为本地 fixture;不得联网下载。 - fixture 可通过 CMake resource copy 或其他现有 iOS app 资源机制进入 bundle;不得复制出新的数据格式。 - 通过 iOS Objective-C++ / private test seam 取得当前 `mbgl::Map` / Style,并调用现有 C++ Host API;不得新增另一套 runtime。 - 建立 `raster-array` source、`weather-color` layer、`raster-particle` layer,并提交 Wind T0/T1。 - Smoke 默认应同时显示 WeatherColor 与 Particle,便于真机确认 Metal 两种 pass 都被实际触发。 - 至少提供 T0 / midpoint / T1 三个固定时间状态或等价的可操作入口,使后续真机能验证 `mix`。 - 提供 clear/reload 最小入口或可重复进入场景的方式,以便观察资源释放/重建。 Smoke 代码只能存在于测试 App/测试 seam,不得进入公开 iOS SDK API,也不得成为 NavSea 正式接口。 ## 8. 非目标 本 Step 明确不做: - React Native iOS bridge / TurboModule - Expo plugin iOS 接线 - NavSea iOS 接入 - npm/iOS artifact 发布 - Android AAR/RN package 版本升级 - Vulkan 实现 - 新粒子算法、视觉重设计、性能调优 ## 9. 允许修改范围 优先限制在: ```text include/mbgl/shaders/mtl/ src/mbgl/shaders/mtl/ src/mbgl/mtl/renderer_backend.cpp 必要的 CMake/Bazel/source list src/mbgl/renderer/layers/(仅 Metal 阻断的 backend-neutral 最小修正) platform/ios/app/ integration/react-native/MapLibreParticleRNTestHost/assets/qbin-golden/wind/(只读 fixture 来源) docs/30_设计/ docs/50_Step记录/ docs/报告/ 粒子开发记录.md ``` 若必须超出以上 production 范围,先判断是否仍属于明确的 Metal thin-hook;若需要改 QBIN/Core contract、RasterArraySource API 或 Android bridge,立即停止并在报告标为 BLOCKED,不得自行扩大任务。 ## 10. 禁止修改范围 禁止: - `docs/00_项目总则/` - `docs/00_项目规范/` - QBIN V4 格式/Decoder/Profile/Binding contract - Android JNI/Kotlin/RN bridge - Android 版本号与公开 artifact coordinate - `packages/maplibre-particle-rn` 公共 API - upstream remote/tag/history - 与本 Step 无关的已有文件/未跟踪文件 ## 11. Codex 验证规则 — 严禁编译 Codex 本任务只允许静态验证,例如: ```text git diff --check git status --short git grep / rg / find 必要的文本/结构一致性检查 ``` **禁止 Codex 执行任何可能进入 iOS/Native 构建、链接、shader runtime 编译、安装或运行的命令**,包括但不限于: ```text xcodebuild cmake / ninja / make / bazel build clang / clang++ / metal / metallib 的编译调用 pod install / swift build simctl 任何 iOS Simulator 命令 任何真机安装/启动命令 ``` 也不要用 Android/Linux build 代替 iOS 验证。本 Step 的编译状态在 Codex 报告中必须写为 `NOT_RUN_BY_DESIGN`。 不加入 Jest,不执行 Jest。 ## 12. GPT/RDC 后续验收接口 Codex 必须在完成报告中明确列出,供 GPT/RDC 后续逐项执行: 1. iPhoneOS device build 所需的推荐 CMake/Xcode 入口与 target 名称。 2. Smoke 场景在 iOS Test App 中的进入方法。 3. 真机预期出现的关键日志事件,至少覆盖 shader/layer creation、field ready、particle resource create。 4. T0 / midpoint / T1 与 clear/reload 的人工操作步骤。 5. 若 Metal shader runtime compile 失败,应优先检查的源文件/函数/绑定表。 ## 13. 必做输出 Codex 必须实际生成/更新: ```text docs/30_设计/STEP-081_iOS_Metal_Renderer与真机Smoke入口设计_v1.md docs/50_Step记录/STEP-081_iOS_Metal_Renderer与真机Smoke入口_v1.md docs/报告/STEP-081_iOS_Metal_Renderer与真机Smoke入口_Codex完成报告_v1.md 粒子开发记录.md ``` 设计文档必须记录 OpenGL → Metal pass 对照、Metal UBO/attribute/texture binding 表、Metal 注册位置、Smoke 场景数据链和后续 RN iOS bridge 的明确边界。 Step 状态在 Codex 结束时只能根据事实写:代码实现完成但未编译时,写“进行中 / WAITING_RDC_BUILD_REVIEW”或等价明确表述;**不得写 iOS PASS、Metal PASS 或真机 PASS**。 完成报告必须至少包含: - 执行结论:PASS/PARTIAL/BLOCKED/FAIL(仅针对 Codex 代码任务本身) - branch、Start HEAD、End HEAD、工作树状态 - 实际修改/新增文件 - Metal shader/pass/binding 实现摘要 - iOS Smoke 入口说明 - 与任务书差异 - 构建记录:明确 `NOT_RUN_BY_DESIGN — Codex prohibited from building` - 静态检查记录 - 已知风险/未完成项 - 给 GPT/RDC 的编译与真机验收清单 - commit hash、commit message、push result、remote branch、Final HEAD ## 14. Git 收尾 本任务会修改项目文件,因此 Codex 必须: 1. 只提交本任务相关文件,不得夹带既有无关 dirty/untracked。 2. 使用 scoped commit message,例如:`feat: bring up particle renderer on ios metal`。 3. commit 后 push 到 `origin/particle/main`。 4. push 失败不得声称完成。 5. 完成后不得继续下一 Step,不得自行开始 RN iOS bridge。 ## 15. 停止条件 出现以下任一情况必须停止扩大修改并在报告中写明 BLOCKED/PARTIAL: - Metal 实现需要改变 QBIN V4/Core contract 才能继续。 - 需要建立 iOS 独立 Particle Runtime 或复制 Android Runtime 逻辑。 - 必须修改 Android bridge/API 才能让 iOS smoke 工作。 - 发现现有 gfx RenderTarget/Texture/Lines 在 Metal 根本不具备所需能力,且修复将变成大规模 gfx backend 重构。 - 需要升级 Xcode、MapLibre baseline、CMake、SDK 或第三方依赖。 - 无法以现有 iOS Test App/private test seam 触发 Core Host API,且需要新增公开 SDK API。 完成本任务后立即停止,等待 RDC 将 Codex 结果交给 GPT 审查。GPT 审查通过后,才由 RDC 执行 iPhoneOS device build,并只在真实 iPhone/iPad 上做运行验收。