Highlight
Xcode 12 在 Metal Debugger 和 Instruments 中加入 Summary、Insights、Shader Timeline 与 Performance Limiter 轨道,让开发者能从一次 frame capture 找到带宽浪费、冗余 pass 和 shader 执行热点。
核心内容
复杂的 Metal app 很少只在一个地方出问题。一个 frame 可能包含几十个 render command encoder、上千次 draw call、多个中间 texture。画面能正常显示,GPU 仍然可能在多余的 store action、重复的 depth pass 或 shader 热点上浪费时间。
以前排查这类问题,开发者要先知道 Apple GPU 的架构,再从 command buffer、encoder、counter、texture 分配里找线索。新手常见的困境是:已经知道 app GPU-bound,却不知道第一步该看内存、带宽、shader,还是 render pass 依赖。
这场 session 把 Xcode 12 的 Metal 工具链串成一条更清晰的路线。Metal Debugger 负责单帧分析:先 capture frame,再用 Summary 和 Insights 找入口。Metal System Trace 负责一段时间的运行状态:用时间线观察 stutter、dropped frames、memory leaks 和 thermal state。
Apple 用 Larian Studios 的《Divinity: Original Sin 2》iPad 版本做示例。这个 frame 有 4 个 command buffer、53 个 render command encoder、接近 1000 次 draw call,渲染时间约 26ms。Xcode 的 Insights 指出两个可操作问题:一个 depth/stencil 资源被 Store 后没有再使用,另一个 depth pre-pass 在 Apple GPU 上可以移除。
详细内容
Summary View:先从单帧总览开始
(01:22)Metal Debugger 的入口是 frame capture。开发者先在 Xcode scheme 里启用 GPU Frame Capture,运行 Metal app,在想分析的画面点击 debug bar 里的相机按钮。
Xcode 12 新增的 Summary View 把 encoder 概览、性能数字、内存使用集中到同一页。页面里的 Insights 会提示影响 memory usage、bandwidth、performance 或 Metal API usage 的问题。每条 Insight 都带有问题描述、修复提示和相关文档链接。
关键点:
- frame capture 让开发者拿到可重复检查的单帧快照。
- Summary View 把 Overview、Performance、Memory 和 Insights 放到同一处,减少在多个面板之间盲找的时间。
- Insights 的价值在于跳转能力:从一个问题直接进入 Dependency Viewer、Memory Viewer 或其他对应工具。
Dependency Viewer:用依赖线判断带宽浪费
(02:23)Dependency Viewer 可以从 Summary View 的 Show Dependencies 进入,也可以从 navigator 里的 command buffer 或 encoder 进入。它给出所有 GPU pass 的鸟瞰图,适合检查 load/store action 和带宽问题。
(10:37)在示例项目里,Insights 提示某个 encoder 正在存储一个后续没有使用的资源。演讲者跳到 Dependency Viewer 后,看到 depth texture 和 stencil texture 都被设置为 Store,但没有任何线从这些 texture 连到后续 render command encoder。Xcode 因此建议把 store action 改成 Don't Care,这样能节省接近 11MB memory bandwidth。
关键点:
Store会在 render pass 结束后把 attachment 结果写回,成本是内存带宽。- 没有 outgoing dependency 说明这一帧后面没有 encoder 读取这些 depth/stencil 结果。
Don't Care适合后续不再使用的 attachment;这里的判断来自 Dependency Viewer 的资源依赖关系。
Shader Profiler 与 Shader Debugger:把 shader 问题落到源码行
(03:34)对于 shader 性能问题,Xcode 提供 Shader Profiler。开发者切到 “View Frame by Pipeline State”,选择 render pipeline 后,可以在 Apple GPU 上看到 shader source code 的逐行性能分解。Profiler 里还支持直接编辑 shader source,并观察性能变化。
(04:04)对于 shader 结果错误,Xcode 提供 Shader Debugger。入口是 debug bar 里的 debug button。开发者可以选择 pixel 调试 fragment shader,选择 geometry 调试 vertex shader,选择 threads 调试 compute shader。
Shader Debugger 会展示多个线程里的变量状态,还能查看整个 shader 执行期间的值。传统 CPU debugger 容易遇到“单步走过头”的问题;这里不需要反复 step over 或 step into,因为一次调试视图里已经保留了执行过程中的变量值。演讲者给出的例子是直接查看循环第 28 次迭代的状态。
关键点:
- Shader Profiler 面向性能,把热点定位到 shader 源码行。
- Shader Debugger 面向正确性,把 pixel、geometry 或 compute threads 的变量状态展开。
- 直接编辑 shader source 的能力让调试阶段能快速验证假设。
Memory Viewer:检查资源属性和使用状态
(05:24)Memory Viewer 是 Metal Debugger 里检查内存使用的入口。现代 rendering pipeline 给开发者更多显式内存控制权,代价是资源数量和生命周期也更难管理。
Memory Viewer 会列出 app 里的资源和属性,并支持按 volatility、resource type、access、是否被使用来过滤。这个视图适合回答两个问题:哪些资源占用了内存,哪些资源在当前 frame 里没有实际用途。
关键点:
- 资源 breakdown 帮助开发者按类型和访问方式查看内存占用。
- “used or not” 过滤适合清理没有参与当前 frame 的资源。
- Memory Viewer 与 Summary View 的 Memory 区域连在一起,用于从概览跳到资源级检查。
Metal System Trace:把卡顿放回时间线
(06:27)Metal Debugger 看单帧,Metal System Trace 看一段时间。它是 Instruments 里的 template,适合定位 stutter、dropped frames、memory leaks 这类时间相关问题。Game template 还提供了一组适合游戏分析的 track。
(06:50)Encoder Timeline 在 GPU track 下展示 command buffer 的时间线,并按 frame 着色。开发者可以检查 encoder 之间是否有重叠,GPU 是否出现 idle bubble,还可以把 GPU 状态和其他系统 track 关联起来。演讲者举的例子是 thermal state:如果 encoder 变慢时设备已经处在 critical state,app 可能需要减少工作量让设备降温。
(07:25)Shader Timeline 是 Xcode 12 的新轨道,需要在 Metal Application recording options 中启用。它显示 command encoder 执行期间被采样到的 shader,并在底部表格显示采样次数和近似 GPU time。
(07:58)Performance Limiter tracks 也在 Metal Application recording options 中启用,位置是 GPU Counter Set。它展示 limiter values 随时间变化的情况。演讲者还指出,2020 年 GPU Counters 也可用于 non-Apple GPUs。
(08:32)Memory Allocations track 会显示 buffer 和 texture 的分配、释放时机。它适合排查 memory leaks,也适合降低整体 memory footprint。
关键点:
- Encoder Timeline 适合看 GPU 是否连续工作,或者是否出现 idle bubble。
- Shader Timeline 适合解释某个 encoder 为什么耗时,因为它显示采样到的 shader 和近似 GPU time。
- Performance Limiter tracks 把 limiter values 放到时间线上,便于和 frame、thermal state 等信号对齐。
- Memory Allocations track 关注资源生命周期,补足单帧 Memory Viewer 看不到的时间维度。
用 Insights 找到两个真实问题
(09:45)在《Divinity: Original Sin 2》的示例里,Summary View 显示这个 frame 有 4 个 command buffer、53 个 render command encoder、接近 1000 次 draw call,渲染时间约 26ms,并处理接近 450 万个 vertices。
(10:37)第一个问题来自 Bandwidth Insights。某个 depth/stencil attachment 被 Store,但 Dependency Viewer 没有显示后续使用。把 store action 改成 Don't Care 后,可以节省接近 11MB memory bandwidth。
(11:49)第二个问题来自 Performance category。Xcode 提示某个 render command encoder 可能是不必要的 depth pass。这个 encoder 花了 1.71ms GPU time,处理约 100 万个 vertices,thumbnail 显示它把整个场景画进 depth/stencil texture。后续另一个 encoder 又绘制了整个场景。
演讲者判断这很像传统 depth pre-pass。对 non-Apple GPUs,这种技术常用于减少 overdraw。Apple GPU 的 Tile Based Deferred Rendering 架构会自动做 hidden surface removal,所以这个 pass 可以移除,节省 1.71ms GPU time。
关键点:
- Xcode 没有只给出“frame 慢”的结论,而是把问题落到具体 encoder、resource 和 store action。
- Dependency Viewer 用资源依赖验证 store action 是否必要。
- Thumbnail popover 帮助确认 depth pass 是否在重复绘制整个场景。
- Apple GPU 的 hidden surface removal 是移除 depth pre-pass 的依据。
核心启发
-
做一个 frame capture 健康检查面板
- 做什么:给团队内部建立固定流程,每次大版本前抓取关键场景的一帧,记录 command buffer 数量、encoder 数量、draw call 数量、frame time 和 Insights。
- 为什么值得做:session 示例里,Summary View 一眼暴露了 26ms frame、53 个 render encoder 和接近 1000 次 draw call。
- 怎么开始:从 Xcode 的 GPU Frame Capture 开始,把 Summary View 的 Overview、Performance、Memory 和 Insights 作为检查项。
-
做一个 bandwidth 回归清单
- 做什么:专门检查 depth、stencil、color attachment 的 store action,找出 Store 后没有后续使用的资源。
- 为什么值得做:示例里只改一个 depth/stencil store action,就能节省接近 11MB memory bandwidth。
- 怎么开始:在 Dependency Viewer 里从 Insights 跳转到对应 encoder,确认资源是否有 outgoing dependency,再把无用 Store 改成
Don't Care。
-
做一个 Apple GPU 专用渲染路径审计
- 做什么:审查从其他 GPU 架构继承来的 depth pre-pass、overdraw 规避 pass 和中间 texture 写回策略。
- 为什么值得做:Apple GPU 的 hidden surface removal 让某些传统 depth pre-pass 失去价值,示例中移除一个 pass 可节省 1.71ms GPU time。
- 怎么开始:用 Performance Insights 找到高成本 depth pass,再用 thumbnail popover 和 Dependency Viewer 判断是否重复绘制整场景。
-
做一个卡顿调查模板
- 做什么:当玩家反馈 stutter 或 dropped frames 时,用 Instruments 的 Metal System Trace 捕捉一段过程,而不是只看单帧。
- 为什么值得做:Metal System Trace 可以把 Encoder Timeline、thermal state、Shader Timeline、Performance Limiter 和 Memory Allocations 放在同一条时间线上。
- 怎么开始:用 Game template 录制复现场景,先看 GPU track 有没有 idle bubble,再打开 Shader Timeline 和 Performance Limiter tracks。
-
做一个 shader 热点修复循环
- 做什么:把 shader 性能问题拆成“哪条源码行慢”和“哪个变量状态错”两个问题处理。
- 为什么值得做:Shader Profiler 给出逐行性能分解,Shader Debugger 可以查看多个线程、整个执行过程的变量值。
- 怎么开始:在 frame capture 里切到 View Frame by Pipeline State,选择 render pipeline;性能问题进 Shader Profiler,结果错误进 Shader Debugger。
关联 Session
- Harness Apple GPUs with Metal — 先理解 Apple GPU 的 Tile Based Deferred Rendering 架构,再判断哪些传统渲染优化需要调整。
- Optimize Metal apps and games with GPU counters — 深入学习 GPU Counter 和 Performance Limiter,把 Instruments 里的 limiter 信号转成优化动作。
- Build GPU binaries with Metal — 继续处理 shader pipeline 和 Pipeline State Object 加载时间,补足运行期调试之外的构建期优化。
- Debug GPU-side errors in Metal — 配合 Xcode 12 的 GPU-side error reporting,定位 API validation 难以覆盖的 GPU 端错误。
- Bring your Metal app to Apple silicon Macs — 把本 session 的 Apple GPU 工具链经验迁移到 Apple silicon Mac。
评论
GitHub Issues · utterances