大多数浏览器和
Developer App 均支持流媒体播放。
-
Metal 着色器调试和剖析
Metal 提供了强大的工具,用于分析着色器行为并优化性能。深入了解如何使用 Xcode 内新增的形状查看功能来对顶点阶段问题进行故障诊断。使用着色器调试程序来逐步调试顶点、片段以及逐行计算着色器执行情况。详细了解如何分析 GPU 负载,并查看针对 A11 仿生的着色器分析程序增强功能。
资源
- Analyzing resource dependencies
- Debugging the shaders within a draw command or compute dispatch
- Optimizing GPU performance
- 演示幻灯片 (PDF)
相关视频
WWDC20
WWDC18
-
下载
大家好 欢迎你们
今天我非常激动 来到这里 让我们开始吧
着色器是图形的重要部分 它们能帮助你 开发好看的游戏和 App 考虑到大规模并行 执行环境 使用着色器非常不容易 在开发过程中 很多事可能会出错 即便你 纠正了错误 它们还必须运行得很快
我叫 Alp 今天我将 向你们展示强大的工具 和工作流来帮助你们对 Metal 着色器 进行调试和性能分析 让我们首先来谈一下 Metal
Metal 不仅是 帧和语言 我们有 Metal kits 和 Metal Performance shaders 并且我们有强大的工具使你的 开发过程高效 简单
完全融入工具的 Metal 系统跟踪 可以让你看到 CPU 和 GPU 是如何并行工作的 以及 App 的程序运行时间
这是第一款能 对 App 进行性能分析并看到 你的瓶颈所在的强大工具 但我今天的主题是 Metal 帧调试器
它能让你 通过游戏的一帧或计算机上传 来捕捉 Metal 的工作 单步调试过程
检查状态和资源
它提供强大的性能分析特征 让你看到 GPU 计数器和管线数据 它完全集成入 Xcode 为你提供了 对 Metal 工作量进行调试和性能分析的地方 今年 我们为 Metal 帧调试器增加了一些内容 有了依存查看器 现在你可以看到 编码器之间是如何共同工作的 以及它们如何通过资源利用 互相连接 这是一款强大的工具 引导你的工作量 让你明白 如何共同工作来 制作那一帧 明天上午十点 我们有 Metal 游戏性能优化讨论 其中一部分将谈到 依存查看器
但是今天我将围绕几何查看器 着色器调试器和增强版阴影性能分析器 我将展示在日常阴影元素中 对你们有帮助的工作量 那么让我们从 几何查看器开始
顶点阶段 是图形管线中的第一阶段 如果这一步出问题 它会弄乱你的整个图像 所以需要 在调试着色器前 排除一些顶点问题 在顶点阶段中 需要检查一些东西 主要是顶点输入 指数和顶点输出
去年的 Xcode 9 我们介绍了输入属性视图 所有数据都结合在 其中的桌面视图格式上 但是想要真正不与 3D 关联 来调试这样的视觉数据还是 很困难的 所以这就是为什么今年 我们结合了所有这些数据 并且创造了一个你们可以 看见并检查它的地方 现在我想向你们介绍 几何查看器
几何查看器是一个新工具 可以以 3D 形式看到 转换后顶点数据 这样你实际上就可以 知道顶点输出 同时它为你提供 数据输入指数和输出 这样你可以实际上 把它关联回 3D
你能在每次绘图调用使用它 就像附件和绑定资源一样 因此你就有 一个地方来查看所有的 顶点问题
现在让我们来看看三个 常见的顶点问题 让我们看看如何用 几何查看器解决它们 那么这是第一个问题 我将要绘图调用 画一棵树 正如你所看到的 三角形的一些顶点 到了屏幕外面 导致这个三角形歪了 只要用几何查看器 你可以点击看上去 有问题的三角形 并且只要用下面的查看器 你能看到这些顶点 所有的输入和输出数据
而在第二种情况中 我调用相同的绘图 但这次这棵树 完全没有了 只要用几何查看器 和自由运动的相机 你能看到这棵树 完全被画在 Frustum 外面
所以这就能解释为什么它不在 屏幕上 那么用几何查看器 检测这样的情况就 非常简单 并且对于最后一种情况
有时甚至不可能 在 3D 中形成 可见的三角形 这些情况都难以调试 你可能有退化的三角形 因为你让 许多顶点 进入了相同位置 或者在顶点输出位置 可能有无穷大和 NaN 这对 GPU 来说 是未定义行为
好在对于几何查看器 能探测这些情况 并给你提供一个问题按钮 只要点击按钮 你就可以看到问题清单 在这种情况下 它找到了几个退化的三角形
点击其中一个三角形 你能直接看到数据
只要看看这些数据 我就看出我的两个顶点 正在到达原点 所以它是一个退化的三角形
那么正如你在这所有示例中看到的 几何查看器 是一个能够快速检查所有 几何相关问题的 强大工具 如果问题出在输入上 那么你必须回过头去 检查你的模型 但如果问题出在输出上 那么你必须调试 顶点着色器 这就将引入下一个话题
调试着色器 使用新的着色器调试器
着色器很难调试
它们有复杂的数学代码 和大量的矢量运算 并且它们高度平行 你正在写的着色器代码 每隔每帧 就会执行百万次 这是 Unity 《死者之书》样片 中的一个场景 这周早些时候我们在 Keynote 和国情咨文中见过 在这个场景的每一帧中 一千万个顶点位置 在所有不同通道 呈现出六千万个三角形 每一帧
所以当你的着色器出现了问题 你将很难发现 问题出在哪儿 哪个着色器有问题 哪部分着色器编码有问题 所以为了帮你调试着色器 现在我非常高兴地 向你们介绍全新的 着色器调试器
着色器调试器是一个能调试所有 Metal 着色器的新工具 为你在成千上万个线程中 提供丰富可视化效果 并且它能展示来自 GPU 而不是模拟器的实时数据 它提供了你自由的设置方式 这样你能轻松地跟随 自己的操作 根本无需断点
它完全集成到 Metal 帧调试器 这样 你拥有了调试着色器 所需的一切 现在我将把舞台交给 我的同事 Xavier 由他为你们 操作展示着色器性能分析器 Xavier
谢谢 Alp 大家下午好 今天的演示 我想制造 一个看起来很酷的水模拟 但是正如你们所见 出现了一些几何问题 我是 Xavier 非常高兴能向你展示如何 使用全新的着色器调试器 和几何查看器 来确定和解决几何问题 那么我们将 从我们的朋友捕捉开始 你们可以轻松 通过点击调试栏中的 向上切割按钮来做到 现在我们已经捕捉到了帧 可以开始调试我们的问题了 由于碰到了几何问题 我们将用到 全新的几何查看器
几何查看器能让你 导航和检查 绘图调用的几何
水面应该是平滑的 但是我们可以看到 有一个陡峭的悬崖 让我们挑一个 看起来有问题的三角形 比如这一个 现在让我们选中底部 这个破损的顶点 你可以在这里使用这个表格 轻松地做到这一点 那么现在我们找到了 破损的顶点 让我们 找到输入位置 可以看到所有 输入位置对于这个三角形的 所有顶点来说 都很相似 事实上 白色的 坐标完全一致 所以这看起来是正确的 也被检测到了 鉴于输入正确 但我们可以看到这儿 在 3D 视图中 输出是错误的 那么问题一定就是 顶点着色器 那么让我们用全新的着色器调试器 来调试和解决这个问题 只要点击调试按钮 就在右下方的角落里 这样一来 我们现在在着色器调试器中了 非常简单
你在着色器调试器中 注意到的第一件事是 除了源代码之外 你还能看到所有行中 被修改过的变量 如果想要关于变量的 更多细节 你只要打开细节视图 点击这个细节视图按钮 就在这儿
细节视图将会用源代码语言 向你展示变量的 所有值 不仅如此 还包括你正在调试的 三角形的所有顶点 变量的值 在调试导航窗口中 你能看到 历史记录 他可以显示 着色器从头到尾 做过什么 正如你所见 我们可以非常简单地 使用方向键 单步调试代码
你们可能已经注意到了 当我用导航仪导航时 它在源代码中的位置 被高亮了 这个操作是双向的 你可以选中一行你的 源代码 它在调试导航仪中 的位置将被选中 在任何时候 你只要打开变量视图 这儿在底部 就能看到所有 范围内存在的变量 那么我们已经更加了解 着色器调试器了 让我们来调试我们的问题
水是由产生的 位移矢量计算的 其稍后会添加到我们的 最终位置 让我们通过打开这个 细节视图 来进一步了解 这个位移矢量
在这个细节视图里我们可以看到 正在调试的 顶点的正确坐标 是一个很大的负数 与其他正确顶点 中的正数相比 那么接下来的问题就是我们 如何计算这个位移矢量 所以 让我们用调试导航仪 运行函数 看看到底正在发生什么
看这里 甚至不用读代码 我们已经可以 发现有地方出错了 有一个变量的值 不是数字 并且这 很可能破坏进一步 的数学运算 让我们来检查一下这一切 为什么会发生 如果我们在这个调试器中检查 会发现我们正在 对这个负数进行操作 这就是导致 NaN 的原因 所以我们已经找到了原因 我们可以很快解决这个问题 通过对调这两行 这样 我们就不会对负数 进行操作了 现在 我们已经调整了着色器 让我们试一下这些改变 点击这儿 重载变化按钮 在调试栏中 重载着色器将使用 新着色器运行代码 这样你就能 立刻检验结果
现在我们可以看到 水平面光滑了
但是让我们实际检验一遍 只要点击 调试栏中的继续按钮 然后我们能看到 我们的水模拟完全正确
在这个演示中 我们已经看到如何拿一帧 如何用全新的 几何查看器寻找损坏的顶点 如何用全新的 着色器调试器调试和修复 顶点着色器 谢谢 我将把舞台交还给 Alp 很酷 对吧 谢谢 Xavier
现在你已经看过着色器调试器 的作用 让我们进一步 看看如何使用 这个工具解决调试需求 首先 我们来谈谈如何 进入着色器调试器 这儿我已经捕捉了一帧 并且在进行最后一次调用 然后你将选中绘图调用或 发送调用 调试栏上的调试着色器按钮 将被启用 你能轻松进入着色器调试器
点击按钮将会出现一个视图 你可以选择你 感兴趣的线程
选择线程意味着 不同的事情 这取决于 你正在调试的着色器 的类型
对于片元着色器 你将用像素检视器 选中你想要调试的像素 对于顶点着色器 你将用我们刚刚看到的 几何查看器来选中 你想要调试的顶点 对于计算能力 你将用控制键来选择 你感兴趣的线程 然后只要点击调试按钮 就大功告成了 你在着色器调试器中了
当你在里面时 你可以很轻松地 检查任何你感兴趣的变量
你只需找到 变量所在的那一行源代码 那就是你需要做的一切 你不需要任何断点 你不需要单步执行代码 那一行中 修改的变量的值 将在工具栏中显示
正如大家在演示中看到的那样 我们高亮了 NaN 和无穷大 因此很容易找到 一般性错误
你可以用工具栏中的 按钮来启用 细节视图 并得到变量的完整详细细节 这非常有用 特别是如果你想视察 复杂的结构并且想要 潜入不同的组件
或者你可以将鼠标停在任何 源代码里的变量上 你立刻就能看到 变量在当时的值 如果你正在从纹理中采样 就像我们这个例子 并且想快速检测 该纹理是否正确 那么这将尤其有用 就像在 CPU 调试器中 你能够看到 变量视图 向你显示范围内所有变量 因此检视变量 是调试着色器的 核心部分 但是那仅是 故事的一半 你还想知道 你的代码的 执行顺序是什么 着色器调试器也使之 变得相当简单 当你进入着色器调试器后 在调试导航仪中 你会看到着色器 为你选中的线程 执行的所有 源代码行
你可以选中想要的任意一行 并直接导航到该行
这也提供了独特的 执行经验让你 能够仅用光标键 遍历代码 函数在导航器中是 成组的 因此你只需 扩展并运行它们 这也使反向调试 成为了可能 这是 调节着色器的一种 非常有用的方式 只要找到有错误值的变量 然后反向运行 看看哪里 出了错以及出错的原因 你还可以使用过滤 过滤是集中的好办法 你可以过滤任何 着色器代码中 你感兴趣的东西 过滤器将与函数调用 变量 资源 相匹配 你的着色器代码可能会跨越 许多不同文件 但如果你使用过滤器 它只会执行与着色器相匹配的内容 因此这是一个集中的好方法 到目前为止我们所看到的 都针对调试单一线程 但如果是其他线程呢
着色器调试器也让你 能够基于你选中的初始线程来 访问其他线程
这意味着对于顶点着色器 你将获得选中顶点的基元 对于片元着色器 你将获得直接 角度区域以及选定的像素
对于计算能力 你将获得 选中的计算线程的所有线程组 这样你能够获取 与线程组内存有关的所有变量 现在我们来看看获取 其他线程将如何帮助你调试 片元着色器 那么当你的代码执行 上百万不同的像素时 在单个像素中查看单个变量 可能无法帮助你 解决所有情况 我举个例子 我正在计算梯度 而且我看不见单一梯度值 但是我不知道 这个梯度值对我的像素 到底好不好 只要点击一下 打开细节视图 我就能在茫茫像素中 看到我的像素 的梯度值 现在我知道这个梯度不对 因为我能 清楚地看到它不平滑 正如你看到的 细节视图能 帮助你了解着色器 并为它分辨好或不好的值 你能快速进入任何 其他像素 立即查看 那个像素的变量值 你还可以用这个视图 切换线程 切换线程非常适合 比较 这样你就能 清楚地看到好的和不好的像素 你能在它们之间快速跳转 并且查看后台像素的活动
一旦切换线程 我们就更新了执行历史和 变量视图 这样你能充分调试 新选中的线程
这会变得更好
细节视图还能让你 了解散度
无论何时你开启细节视图 右手侧的蒙版 就会始终显示 其他线程执行的相同 代码情况
在这个例子中 是有条件的 只要看看蒙版 我就知道 在这里面大约执行了 一半线程 如果是有条件的话 以对角线形状执行
现在为了展示如何 用细节视图解决片元着色器 中的问题 我将邀请 Xavier 重回舞台 Xavier
谢谢 Alp 在第一个演示中解决了 几何问题后 我加入了高亮作为过程和效果 但是结果却并不尽如人意 因此采取帧捕捉 来调试这个问题
在这儿的视图 我们可以看到 高亮实际上 是在底部产生暗色区域的地方 所以让我们用着色器调试器 来调试和解决这个问题
通过不按 我打开了 像素检视器 这能让你选中你想要调试的像素 因此 这儿我们将选中 一个像素 比如说这个 然后启动着色器调试器 你需要点击这里的调试按钮 在底部右侧的角落里
现在我们就在调试 帧和着色器了
可以看到 高亮从三种不同的 步骤中生成 让我们用细节视图 来迅速了解正在发生什么 我们首先从比较近的 第一个开始看 可以看到这儿 我们正在 从原始色彩中取样 这看上去没问题 接着往下看 这儿我们正在一个方向中 累加高亮 让我们打开 细节视图来看看结果 从细节视图中可以看到 在底部 已经有了暗色区域 就在这儿 那么问题 一定出在我们 累加高亮的过程中 你可以看到 细节视图 是一款了解你着色器的 强大工具 甚至不需要看代码
让我们用调试导航仪 看看第一个像素 到底发生了什么 看这儿 这个函数主要是一个 迭代几次的循环 从 brightnessMap 中累加样本 循环仅在着色器调试器中 被高亮了 这意味着 你可以用着色器调试器 导用迭代 然后和源代码一起获取 在每次迭代中的变量值 如果我们关注这儿 会看到 当我导向 不同迭代时 值会变化
但是真正强大的是 将这与细节视图结合起来 那么这儿 我们将 打开细节视图来看看最终的 色彩 这也是我们 累加高亮的地方
现在让我们用调试导航仪 进行迭代 正如我们看到的 当我迭代时 我们开始为最后的色彩 累加高亮 但是当我继续 向循环末尾迭代时 我们 实际上可以看到 出现了一个图案 那么让我们来看看为什么 会发生这种情况
正如在调试器中 我们实际上可以看到 权重是负的 这就是为什么 在最终呈现时 色彩是分散的 而不是积累在一起的
现在我们已经找到了 问题所在 让我迅速解决它
现在让我们检验结果 只要签入 重载变化按钮 在调试栏中 我们可以看到 现在已经没有其他载体了 但是 让我们在实际操作中看一下 只要点击继续按钮
好了 现在我们的高亮 看上去不错 这只是使用着色器调试器 和它强大的细节视图 来调试 着色器的一个例子 谢谢大家 把舞台交还给 Alp
谢谢 Xavier
现在我们已经看到了 着色器调试器的一切 我们来总结一下 到目前为止谈了什么 着色器调试器是专门 针对调试 Metal 着色器 设计的 考虑到 GPU 的高并行本质 大家也都看到 它对修补非数字和无穷大 的高亮的漏洞 非常有用 很容易发现 一般性错误 并且能让你 更好地了解着色器 有了细节视图 你甚至不需要读代码 了解你的着色器正在做什么
同时它还为着色器开发 提供了绝佳的环境 只要进入着色器调试器 并开始编辑 读取 即可快速迭代你的结果 着色器调试器支持搭载 iOS macOS 和 tvOS 的最新硬件
接下来该欣赏 Xcode 10 了
现在我们已经看到了 如何使用几何查看器和 着色器调试器来调试 着色器问题 现在让我们将目光转向 如何让着色器 运行得更快
因此优化 GPU 的使用 很重要 因为你想让 App 运行得更快 消耗更少的电量 并且有更好的 用户体验 但在开始优化前 必须知道优化内容是什么 如果你有 GPU 限制 典型的 Metal 工作量有许多 不同通道 知道专注哪条通道 是非常重要的 好消息是我们有强大的 内置在 Metal 帧调试器中的 性能分析工具 来帮助你解决问题 GPU 计数器可以给你的 App 带来极佳的表现 可以看到 时间 编码或绘图调用 并且提供不同的计数器 显示瓶颈
从这儿 一旦你知道了 扩展型通道 你就能 继续得到管线数据 你会为你的着色器 进行很好的编译 为你提供 指令类型 使用着色器性能分析器 能让你看到绘图调用 和每个管线状态
的定时 那么今天我将重点谈谈 着色器性能分析器 并且我将展示 能帮助你们优化着色器的 工作流程 一旦你在 Metal 帧调试器中 即将被性能导航器读取 你将看到根据执行时间分类的 所有管线状态 这是一个能够看到我们正在优化的 所有扩展型管线的地方
这儿用这些管线状态 你还能看到 绘图调用 这样就能 直接导向其中一个 看看它正在画什么 如果你是 iOS 或 tvOS 系统 只要前往着色器源 就能看到每行 执行成本 它非常好地展示了 在着色器中 你在哪儿花费的时间最多 按行计算
一旦你进入到着色器源代码中 就可以开始 编辑你的代码并重载 看看计时器是否 有任何时间差异
或者你可以仅仅进入着色器 调试器
如果你想优化 一个算法或者刚刚 通过一个控制流 并且当我知道你究竟能不能优化 那么这是一个极好的工作流 因此着色器性能分析器能 极大地帮助你优化着色器 但现在我们将它在 A11 做得 更优秀 现在所有的二进制芯片 A11 被完全设计为 GPU 现在我们有硬件支持 让你能够更深入 了解你的着色器
正在做什么 现在有了 A11 你就能通过 图表 看到每行 被执行的成本分析 那么着色器包含不同的 执行单元 如果你重度使用 它们中的一个 很可能 会因此碰上瓶颈
算术逻辑单元和内存 分析能让你看到 在不同执行单元 花费的时间
为了确保精确指令在 A11 中更高效 我们做了很多工作 使用健康 溢出 很可能极大增加你的 GPU 预算 你能看到的 另外一个类型是同步 这个类型 很重要 因为你希望着色器 核心忙于运转 而不是 等待同步 在你的着色器代码中 如果正在从纹理 缓冲区中读取数据 或者正在用原子或栅栏 你可能需要暂停 等待同步
我们还能让你看到 内联函数的成本 从着色器中调用 这样你能直接 导向成本最高的 函数 并且开始
优化它
欢迎来到 Apple 设计的 A11 仿生芯片 我们能提供比以往更好的 性能分析数据 今年我们将介绍 即使在内联函数中 也引入了每行定时信息 和指令类型 我是 Max 我将 帮助你获得最优的着色器
性能
所以我再次捕捉了同样的 水模拟 但这次 是在我的 iPhone 上
让我们来通过性能 看看帧的变化 现在我们看到按时间排序的帧使用的 一列管线 我们可以很容易看到 噪声管线 正在消耗大量时间
发现了这一点 我们看到 几乎所有时间都被用在 片元着色器上 但是今年我们更进一步 我们能看到在 着色器调用的 里面的每个函数花费的时间 只要点击这儿前往 源代码文件 就能直接 跳转到正确的那一行 这就是我们检查的第一步
那么现在在右手侧 看到的就是 我们在这个函数 内部花的时间百分比 进一步就能看到 我们在每一行 花费的时间比例
注意 着色器性能分析器 适用与优化后的代码 因此编程器可以对指令 重新排序 并且某些行 可能没有定时信息 接下来就到定时信息了 我们有指令类型 让我们来看一看 大家能看到算术逻辑单元 在做数学运算时 花费了时间 我们正在从内存 纹理中读取 但是引起我关注的是 在同步中 花费的时间 尤其是在这儿等待内存的时间 这意味着我们的 GPU 不能 很快地读取数据 并且不能 通过在其他线程中 执行算术逻辑单元工作 来隐藏这个延迟
那么让我们来弄清楚原因 只要根据性能数字 我们来到了这一行 在这儿 我们花了超过一半的 在着色器内时间 再次看看 指令类型 我们能看到同步 花费了很长时间 但是为什么
这儿我们使用了 靠偏移量从色彩纹理中 读取的色彩值
这个偏移量是从这里的 噪声纹理中读取的 那么我们读取了一个相依纹理 直到获得纹理读取后的 数据 GPU 才能处理 那么我们对此可以做些什么呢 好吧 不从噪声纹理中读取 我们反而可以在 GPU 中 直接计算噪声值 我来演示一下 现在更新我的着色器 着色器现在被送到 我们编写的设备中了 然后整帧将重新运行 并重新进行性能分析 因为只要改变 一个着色器或一个线程就有可能 影响你整个 GPU 时序
一旦完成 我们来看一下
我们看到 现在在着色器中 只花了 3 毫秒 而原先需要 20 多毫秒 但我们再看看指令类型 这儿能看到我们几乎 完全消除了同步时间 并且保持 GPU 高速运转
总而言之 当你在着色器中发现了瓶颈 每行定时信息会 明确告诉你 问题所在 指令类型帮助你 发现原因 这就是我要介绍的部分 将舞台交还给我的同事 Alp 谢谢 Max 结束之前 我想谈谈最后一件事 让你更轻松地使用 这些新的强大工具
希望你们已经离线 编写完了着色器 这样就不用为在线编写 而花费运行时间了 如果你们正在离线编写 着色器 现在我们有一个 全新的编译程序选项可以将 着色器源码保存到建立的 Metal 源中 这样无论何地 你们都能通过 这些工具 处理着色器源码 如果你们正在用 Xcode Project 编写着色器 你们能直接转到 Build Settings 并且启用这一选项 或者你们正在用命令行编写 那么就可以直接让 Metal 编译器 运行 MO 选项
但请记住只有在调试生成时 才启用它 这样你就不会误把着色器源码 和你的 App 一起推送出去 好了
让我们来总结一下今天的内容 我们首先说了几何查看器 它能让你 查看所有与顶点 相关的问题 并且调试 画面问题 请记住 首先要检查几何查看器 确保在调试着色器前 你的几何图形 没有问题 然后我们提到了着色器调试器 这是一款能调试所有 Metal 着色器的强大工具 可以很好地修补漏洞 让你了解和开发 着色器 通过着色器性能分析工具 你甚至可以更进一步 看到 GPU 正在用 A11 仿生芯片 做什么 如果想要了解更多信息 请查看链接
明天上午十点 我们将谈谈 Metal 游戏 性能优化方面 届时 我们将谈论在游戏中 发现的常见 性能问题和可供大家使用的 检测和修补问题的工具 谢谢大家 [ 掌声 ]
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。