Metal 概述:从「它凭什么」到「我离不开它」

Metal 是苹果在 2014 年 WWDC 上扔出的重磅炸弹。当时我跟很多同行一样,第一反应是——苹果又要搞封闭生态了?后来真正上手做过几个项目,我才明白:它不是为了封闭而封闭,而是为了把 GPU 的能力榨干到最后一滴。

说白了,Metal 是一个低开销、直通硬件的图形与计算 API。它只活在苹果生态里:iOS、macOS、tvOS,还有后来的 iPadOS。跟 OpenGL 这种「写一次跑所有平台」的梦想不同,Metal 从一开始就放弃了跨平台,换来的是极致的性能。

这一章我们先聊三件事:Metal 是怎么来的,苹果的图形生态到底长什么样,以及——为什么要放弃 OpenGL 跳进 Metal 的坑。

Metal 的历史:从 iOS 8 到 Apple Silicon

2014 年 Metal 刚出的时候只支持 iOS,而且只能用 A7 及之后的芯片。我当时在做一个移动端图像处理 App,被 OpenGL ES 的驱动开销折磨得不行。Metal 的到来让我眼前一亮,但说实话,第一版文档写得真不咋样,坑不少。

2015 年 Metal 登录 macOS,你可以用同一套代码写 iPhone 和 Mac 的渲染了。2017 年 Metal 2 发布,加入了外部内存、分层渲染、GPU 驱动的剔除等高级特性。到了 2020 年,苹果推出 Apple Silicon,Metal 成了整个平台的原生语言——因为 M1 的 GPU 架构从底层就是为 Metal 优化的。

所以,现在你不学 Metal,就等于放弃了苹果硬件上 80% 的 GPU 潜力。

关键时间节点

  • 2014 — Metal 1.0 在 iOS 8 上发布,仅支持 A7 芯片
  • 2015 — 扩展到 macOS(El Capitan),统一了 iOS/Mac 的 GPU 编程模型
  • 2017 — Metal 2 引入外部内存、分层渲染、GPU 调试工具
  • 2019 — Metal 3 推出,聚焦于 Apple Silicon 的协作优化
  • 2020+ — Metal 成为 M 系列芯片的原生 API,OpenGL 正式被苹果标记为「已弃用」

苹果图形生态:不只是 Metal

很多人以为苹果的图形生态就只有一个 Metal,其实不然。Metal 是底层的「砖」,上面还搭了各种高层次的「房间」。你想想看:一个游戏引擎或者一个视频处理 App,不可能从头到尾都直接写 Metal 代码吧?

我把整个生态按层级画了一张图,看完你就明白了。

苹果图形生态结构图 应用层 游戏引擎(Unity/Unreal)、ARKit、Core Image、视频编辑器 高层框架 SceneKit · SpriteKit · Metal Performance Shaders Metal API MTLDevice · MTLCommandQueue · 着色器管线 驱动 & 硬件层 GPU 驱动(Apple GPU / 第三方) · 显存管理 · 硬件命令处理器 ⚠️ OpenGL ES 在 iOS 12 后已被标记为弃用 💡 Metal 同时支持图形渲染和通用计算

看到没?Metal 处在中间层,上下都有东西。上面是 SceneKit、SpriteKit 这种你拿过来就能用的框架,下面是 GPU 驱动。我刚开始学的时候想直接跳过上层框架写 Metal,结果被缓冲区管理搞到自闭。后来学乖了——先用 Metal Performance Shaders 做图像卷积,性能直接拉满,代码量砍掉三分之二。

Metal vs OpenGL:一个天上,一个地下

为什么苹果要扔掉 OpenGL?我猜你心里已经有答案了:性能与开销。

OpenGL 的设计哲学是「状态机」。你设置一堆 glEnable、glBindBuffer、glUniform,然后画。这些调用每一个都要经过驱动层的验证、状态比较、缓存失效。CPU 端的开销惊人。而 Metal 把大部分验证工作提到创建管线时完成,运行时只下发最精简的指令。

我做过一个实验:同样渲染一帧装满小球的场景,OpenGL ES 的 CPU 耗时是 Metal 的 3-4 倍。金属后端不只是名字猛,它是真的猛。

个人经验:我有一个项目需要在 iPhone 上实时处理 4K 视频帧(颜色校正 + 模糊)。一开始用 OpenGL ES 的 GLSL 着色器,帧率只有 18fps。改成 Metal 后,不到 30fps?不,是直接稳定 60fps。而且代码量还更少——因为 Metal 的缓冲管理和多线程提交太方便了。

来看一张清晰的对比表格:

对比维度 OpenGL / OpenGL ES Metal
驱动开销 运行时状态验证 → 高 CPU 消耗 预编译管线 → 运行时零验证
多线程支持 单线程上下文,需要自己加锁 原生多线程命令缓冲,无锁提交
GPU 计算 需要扩展(如 GL_COMPUTE_SHADER),限制多 计算着色器是一等公民,与图形管线共享资源
内存管理 手动管理,容易泄漏 资源追踪 + 自动回收,可跨队列共享
着色器语言 GLSL(平台不统一) MSL(Metal Shading Language),基于 C++14
调试工具 Xcode 支持有限 Xcode GPU Frame Debugger 提供帧级管线查看
平台支持 跨平台(但苹果已弃用) 仅苹果生态,原生集成

注意:如果你维护的老项目还在用 OpenGL,苹果从 macOS 10.14(Mojave)起就已经标记它为废弃 API。也许你的 App 现在还能跑,但未来某个系统版本可能就彻底不能用了。我经历过一次被迫迁移的阵痛——后悔没早两年动刀。

最后聊一个大家容易忽略的点:Metal 的计算能力。它不只是用来画三角形的。你用 Metal 做矩阵乘法、神经网络推理、音频频谱分析,都能直接调用 GPU 的并行计算单元。而且因为计算和图形共用同一套内存模型,你可以把计算结果直接映射到纹理,省掉一次拷贝。

怎么说呢?Metal 就是苹果对 GPU 的「完全控制权」。你愿意花时间学这套 API,它就会给你回报——更快的应用、更低的功耗、更流畅的用户体验。