指令计数判断着色器性能不可靠/UE5/Unity测量着色器性能准确方法【Ben图形/21-21】...
着色器性能Game艺视界原创 15038 0
实名

通过了实名认证的内容创造者

发布于 2022-3-21 22:02:15

您需要 登录 才可以下载或查看,没有账号?注册

x
b64e78dc188da7f93a16111abbb1eb9.png

本期内容
今天我们将讨论如何测量着色器的性能,测量性能是一个复杂的话题, 所以这将是本周由两部分组成的第一部分, 我将向您展示一个简单的性能测量方法,然后解释为什么它可能会产生误导 ,然后下周我将向您展示测量性能的最有效方法。

14c27c6a05d0868484e44dc7a75e09d5.png


因此您正在制作一个像这样的复杂着色器,并且您想知道是你正在做的事情会运行得足够快或者如果它会减慢你的游戏速度,你怎么知道着色器是否太复杂或者你有一个非常复杂的着色器,并且你试图简化它你怎么知道您更改正在发挥作用,您需要做的是测量显卡渲染着色器所需的时间。判断着色器速度的方法是查看指令计数,因此在“unreal”中,我们可以查看着色器编辑器底部的统计面板,它显示基本过程着色器323指令

如果我简化了我的着色器例如:我有这个在这里进行雨量计算,如果我简化这一点跳过这块,看看这里的线基色是什么这里的粗糙度在这里,断开镜面反射然后在此处正常连接我的着色器 将重新编译,您可以看到现在我有167条指令,因此您可以看到如果我删除来自着色器的东西我的指令数下降了。所以我可以使用它作为相对度量来判断着色器是比另一个着色器快还是慢,如果我进行这样的优化并且它减少指令计数,这意味着我的着色器将运行更快


有时可以减少这个指令计数,实际上会使着色器运行变慢,我要解释为什么指令计数是非常不准确的着色器性能度量,但首先我们需要备份和理解一些基本原则。比如什么是指令所以首先你在虚幻的材质编辑器或unity的着色器图中制作你的着色器,或您使用的是一个漂亮的用户友好的基于节点的界面,它基本上是可视化编程,但是您真正要做的是编写代码图中的每个节点代表一行或多行着色器代码,游戏引擎从每个节点中获取代码。您的图形并将其放在一起以使用 hlsl 或 glsl 等语言创建基于文本的着色器

如果我们转到工具菜单并选择着色器代码。您可以在这里看到由虚幻和虚幻生成的代码示例hlsl 代码,你可以看到你创建的着色器图生成的代码,这很酷。你知道吗?当你制作着色器图形时你正在编写所有这些代码,那么这些代码是在图形硬件上运行的吗?

不,在游戏引擎写出所有这些着色器代码之后,这个过程实际上还有几个步骤然后代码被发送到图形api如 directx 或 opengl或 metal 取决于在您的平台上图形API将此高级代码转换为汇编语言,汇编语言是一个原始指令或数学命令的列表,我们要求硬件执行这些命令中的每一个比如说,获取内存寄存器中的数据并对其执行特定的数学运算。这就是在编译着色器时术语指令的来源我们得到一个很大的GPU指令,这个列表中的指令数是我们得到指令数的地方,通过查看指令数来测量着色器速度的一个问题可以在这个步骤中找到,如果着色器中有一个循环它应该执行一组任务,您的指令列表将显示它可以执行的所有循环的最大可能指令数。它可以执行的所有循环的说明。因此该列表包含列出循环可以运行的最大次数的指令,当着色器运行它只需要执行一次或两次循环,但指令列表中的所有指令仍将重复循环可以运行的最大次数。因此在这种情况下指令计数明显高于应有的水平并且不是准确的测量




在此过程中还有一个步骤图形API将此指令列表发送到图形驱动程序,驱动程序再次将此指令列表直接转换为针对您的特定显卡优化的命令。因此汇编语言指令上一步中的所有图形硬件都是通用的。但在这一步中我们将制作为您定制的命令特定的图形硬件,在这一步中我们将看到为什么指令计数对性能的估计很差的更多原因,因为我们现在对将着色器图形转换为图形所需的步骤有了更好的理解硬件可以执行

让我们更具体地看一下在这些步骤中发生了什么,在这些步骤中我们将 hlsl 代码转换为硬件特定的命令。以说明我将在这里切换到使用称为着色器游乐场的工具。在着色器游乐场中我将在描述中放一个指向该网站的链接
https://shader-playground.timjones.io/
这是一个工具允许我们在左侧和右侧的 hlsl 代码中编写着色器。它将向我们展示编译器做了什么 使用我们的 hlsl 代码,这是一个非常棒的工具

从现在开始在我的频道上,这就是我们将要编写着色器的方式,我们不会再使用基于节点的漂亮界面unreal或unity我们将在着色器游乐场中用代码编写所有着色器,开个玩笑我只是想看看你是否醒着不,我只是想用这个工具来说明几点关于着色器指令的要点。所以我们从一个超级基本的着色器开始。它所做的只是获取输入颜色并返回该颜色本身,在中间它表明我们正在使用Directx 编译器 microsoft fxc 我们也可以使用dxc只是为了好玩
让我们改变这个着色器看看会发生什么,当然我们在这里有我们的说明。我们在这里看到的主要是将一种颜色移动到另一个地方,这是输入颜色它是说把它移到输出寄存器这就是这个着色器正在做的所有事情,你可以看到它正在执行两条指令所以这很简单
你可能只是为了好玩,让我们改变这个着色器而不是只返回输入,只是输入颜色让我们返回输入颜色的符号,看看会发生什么我们只需要等待几分钟让它编译,然后它就会给我们正确的结果,所以现在它已经编译好了你可以看到我们这里有一个新指令叫做sine cos 它是执行那个正弦波。这个指令实际上是执行正弦和余弦但我们只需要符号。所以它只使用那部分但无论如何我只是想告诉你改变我们的着色器在这里,当着色器被编译时会创建新指令但这个工具真正酷的是它允许我们看到,将从汇编语言中为 amd 的 radeon 卡生成的特定指令。

所以我们不仅可以看到汇编语言在这里,但我们实际上可以看到专门为 radeon 卡生成的命令所以让我们将其更改为radeon gpu 分析器。现在我们在右侧看到的说明是特定于我在中间选择的 amd 图形硬件
甚至比如果我在此处设置此下拉列表 为 isa 故障更好我们将获得一条新信息看看这个我们在右侧有此列称为周期,执行这些指令中的每一个需要多少个硬件周期。

所以你可以看到这里是一个乘法指令这需要四个周期。
这是一个符号指令它需要16 个周期

所以现在我们可以看到这个循环信息我想告诉你两件非常重要的事情,首先看看这里有多少个符号指令一二三四所以它做了四次这个符号为什么那么好,如果我们在这里看看我们的着色器。所以实际上有四个值红绿蓝和 alpha

当我们执行正弦时我们必须这样做在所有四个通道上,您可以看到我们有 16 个循环用于红色 16 个循环用于绿色16 个循环用于蓝色,以及每个 alpha 有16个循环 ,所以这在我们的汇编中仅显示为单个指令的东西中加起来多达 64 个循环

如果我 在这里切换回 microsoft fxc

那里你只需要一个正弦余弦指令来执行一个 实际上需要64周期的操作
所以这是一个非常重要的点如果我有一个着色器对浮点数进行所有操作。而另一个着色器是只对浮点数进行所有操作,它们可能具有相同的指令数但浮点数 4 版本实际上比浮点数版本在 gpu 上渲染的时间长四倍,因此指令数量存在很大差异它的显示与实际需要多长时间才能正常 渲染
让我们再看一件事,我将在这里再次切换回radeon gpu 分析器和这个元素可能是最重要的,所以在这里要特别注意,注意符号指令花费 16 个周期乘法指令只花费4个周期。这两条指令在汇编语言中只显示为一条指令

但在生成的命令中,对于 radeon 正弦波的成本实际上是它的4倍。所以我们我们从这学到了什么,我们了解到并非所有指令都是相同的。让我们看看另一个指令,我只是为了简化它并摆脱它所有额外的东西,我要把我们的颜色改为只浮动而不是浮动4,你现在会看到我们只有一个乘法和一个符号而不是像我们以前那样的四个

如果我们做双曲正切会发生什么等待编译,看看会发生什么,好了我们这里有更多的指令,如果我把它设置为isa细分现在我们有一个乘两个指数,加上减去一个倒数,再加上一个乘它实际上总共有64个循环

让我们看看fx告诉我们的是什么,所以你记住我们最简单的着色器只是两条指令。但是如果我们输入颜色进行棕褐色处理,它现在表示大约为8指令,所以我们已经去了2个,我们已经从两个增加到了8个所以我们的切线我们的双曲正切运算它说需要6个

但是如果我们再次切换到我们的radeon gpu 分析器,我们将所有周期加起来实际上是 64 个周期。所以发生的事情是这花费了你认为的两倍半时间,如果你 “只是查看指令数与周期数的关系。所以我们从中学到了什么,并非所有指令都是相同的其中一些指令比其他指令慢得多
所以为了帮助我们看到这一点,我继续输入了不同的着色器函数。常见的着色器函数在这里 并写下它花费了多少个周期,我在这里制作了这个方便的图表所以我有所有这些不同的着色器函数。调用天花板夹 ddx ddy 距离 fmod 所以我在这里有所有这些功能然后在右侧,我将计算每个周期所需的周期加起来您可以看到这些变化很大,绝对指令需要0周期着色器实际上能够免费执行该周期。但其中一些是其他的就像反正弦和反正切看看超过 64 条指令来执行 tan 2函数,所以你可以看到并不是所有的指令都是平等的
文档地址:
https://docs.google.com/spreadsheets/d/1gIlwVwO9DoQKb-7rpXhvzXcxdZSwPHs_hYHnouQtTYA/edit#gid=0

让我们总结一下我们已经学到了三个重要的原则关于汇编语言指令计数
第一个是这个不太常见,但如果我们的着色器中有循环并且我们不一定需要执行每个循环那么它仍然很重要。指令计数仍将报告每个可能循环中的所有指令,因此我们最终得到的循环中指令数量可能是实际执行次数的许多倍

第二个原则是指令计数不考虑数据因此如果我们在浮点数 4 上执行指令。那么执行该操作的周期数是浮点数的四倍并且指令计数根本不反映这一点,因此我们的着色器实际上可以作为比实际指示的指令计数贵四倍


然后最终所有指令都不是创建相等的,其中一些指令只有四个周期。我想再次强调这些周期 计数特定于 radeon 硬件。它们可能不同在nvidia 硬件上的 Apple 设备上的移动设备上,但并非所有的要点都是,并非所有的指令都是相同的,因此有些它们可能只有四个周期其中一些 可能超过64个周期

因此您知道一条指令与另一条指令之间的差异高达16倍,因此如果您想使用指令计数我希望我已经向您展示了这个值是真的不可靠。即使它可能会告诉你当你增加或减少着色器的复杂性时 。你知道事情会发生变化这告诉你的是相对毫无价值的信息,有了这个充满希望的结局,我想我们应该称这个视频很好,我希望我已经说服了你们

好的,所以你需要做什么来衡量你的性能?我要创建另一个视频,我将在其中详细介绍如何准确所以我希望你们都回来观看那个视频。


本期内容
今天我们将讨论衡量着色器性能的最有效方法
上周我们讨论了着色器计数,我给出了三个主要原因,为什么使用指令计数不是判断你的着色器性能的准确方法所以上周的视频是关于不该做什么的
本周我将向你展示判断你的着色器性能的最有效方法,所以你正在制作一个复杂的着色器你想知道你在做什么会运行得足够快,或者如果它会减慢你的游戏速度, 你如何判断你的着色器是否太复杂。或者你有一个非常复杂的着色器你试图简化它,你如何判断你的更改是否对你需要做的事产生了影响,你需要做的是测量图形卡渲染着色器所需的时间,所以为了进行此测量,我们将遵循三个步骤。

我们将构建一个非常简单的场景,其次我们将在上运行该场景目标硬件,第三我们将使用一个工具来测量渲染场景所需的时间
所以首先让我们从在虚幻中构建一个非常简单的场景开始,我有一个空关卡里面绝对没有任何东西,接下来我想做的就是在我的关卡中添加一个平面,我想确保它在位置 0 0 0 所以我只是要在这里输入全零,然后在我的视口中我可以按F键,我已经将它移到 0 0 0位置

所以现在它在原点,接下来我需要做的是向我的场景添加灯光,所以我只需点击创建灯光定向,因为它是一个定向光, 它在场景中的位置并不重要。我要按E,我要旋转我的灯这样它才能真正照亮我的场景

然后我需要做的最后一件事就是我需要在我的场景中添加一个相机,所以我要点击创建然后我将点击所有类,然后我会选择相机所以现在我的场景中添加了一个相机

现在我需要做的下一件事就是找到我想要的材料,想要测量性能并将其应用到平面上,所以我 将在我的内容抽屉中找到我的材料文件夹。我知道我想要测量性能的材料被称为 m wood Oak 所以我只需单击并将其拖到场景中并将其放在我的平面上。现在您可以看到我的相机视图正在看着那个下雨的木质材料 ,现在我准备好了 测量这种所以我创建了一个非常简单的场景。其中只有一个相机、一个定向光和一个平面。

你可以反复使用这个场景以及测量各种材料的性能和当你想测量一个新的时,你所要做的就是在平面上应用一种新的材料, 所以一旦你创建了这个场景,你就不需要再次设置它,你可以继续使用这个非常简单的样本场景来衡量你的表现,所以我们需要做的下一件事是我们需要在我们的目标硬件上运行这个场景 ,为了做到这一点,我们需要构建一个包在虚幻 5 中构建包有点复杂我就不在这里介绍这些步骤,因为超出了本教程范围。
但是为了让包正确构建您还需要做一些额外的事情除此之外,我们将来到编辑菜单,我将选择编辑项目设置,

然后我要选择地图和模式,你需要确保你创建的地图在编辑器启动地图下还有一个游戏默认地图。我要去到这里来做另存为材料速度测试2,并点击保存现在我要确保在此处选择该级别在编辑器启动地图和游戏

现在我将在平台按钮下出现在这里 ,您可以看到有很多不同的平台我可能会进行构建但在这种情况下我只是要 在 Windows 上进行构建只是为了让事情变得简单,这样你就可以看到我现在有Windows那么无论你开发项目的平台是什么,这都是最好的因为如果你在特定的平台上衡量你的表现,因为我在为android设备开发游戏,如果我要衡量在 windows pc 上测量我的材料的性能, 而不是 windows pc 结果与 android 结果几乎没有共同点所以我需要确保我正在我的目标硬件上构建和运行我的项目,以便为了从着色器时间测量中获得正确的结果 。

所以我将在 Windows 下来到这里我将为我的二进制配置(00:07:31开始)

为什么我选择运行它在编辑器之外?
原因是当您的项目在编辑器中运行时编辑器启用了各种附加功能,允许您以交互方式编辑场景当您构建场景时,它会全部删除那些额外的东西你剩下的只是你的项目,它可以尽可能快地运行如果你在编辑器中运行你的项目,它会非常慢,而且你实际上不会得到一个精确的测量

现在我们将切换到unity我将向您展示如何做同样的事情因此在unity 中,我们将再次选择文件新场景我将选择空场景,并单击创建我们想要一个空场景因为我们想要一个没有干扰的地方,并且没有其他对我们的 gpu 或我们的计算机征税的地方。我们只是要添加一个平面一个相机和一个灯并保持我们的场景尽可能简单

添加我们的相机,显示平面,给我们平面添加材料。我将使用我创建的一个现有的,这个称为材料性能测试,所以我只需点击并将其拖放到我的平面上,你可以看到我有一点凹凸贴图,这是我们在之前的视频中创建的着色器图


我们需要做的是在文件下选择构建设置,我们需要确保我们的目标平台再次设置为 windows 支持非常广泛的不同平台,从游戏机到安卓手机再到各种 ios 设备的事情, 但我们只是要保持简单

现在就在windows上运行它以便立即构建我的场景。我的场景名为“无标题”,因此我需要执行文件另存为,然后放入场景文件夹现在在我的构建设置窗口中,我可以点击添加打开的场景

取消除了我想要包含的这个场景之外的,所有内容然后点击构建。并且我将选择我的unity文件夹将其放入,您可以将它放在您想要的任何计算机位置

我将关闭编辑器就这样没有在后台运行,然后我们将在这里运行我们的构建一个exe文件

你可以看到我们现在得到了一个很好的全屏版本的游戏,关于这个的帧率我注意到我的帧率是 60并且它实际上被锁定到 60 我不想要那个因为它限制了实际性能是每秒 60 帧而不是我能够测量实际的帧速率是多少它把人为限制在每秒 60 帧,所以我们需要解决这个问题

所以我会跳回编辑器,过来在编辑项目设置下我将选择质量,你可以看到有一个叫做vsync count 的设置,它被设置为每个 v 空白,这意味着它会将帧速率限制为刷新率监视器,我要选择不同步 ,现在不再受限于帧速率而是继续创建和渲染这些帧

你做的另一件事是你将你的默认质量设置为低当你运行你的游戏时,你希望它看起来尽可能好但在这种情况下我们只是想测量特定着色器或材质的渲染速度场景正在做的所有其他事情,例如渲染环境光遮挡和雾和体积效果所有其他事情等等将这些设置调低, 我们将尽可能多地消除其他效果来关闭我现在不会讲的额外效果。再次打包

现在我已经关闭了vsync,我应该得到一个更真实或更具有代表性的帧这是实际渲染的速度,所以使用这种方法我可以正确测量我的材质渲染的速度。

现在我还有另一种方法想告诉你这是最准确的方法,而且它使用一个名为和 pix 的软件是由微软开发的一些软件它实际上捕获发送到您的 gpu 的命令。并分析它们并以精确的速度测量类似的东西直到单个纳秒,所以让我们来看看接下来是 pix 软件 ,您可以做的是从里面图片启动您的应用程序。然后捕获发送到您的显卡的所有内容, 并非常精确地测量现在需要多长时间这在虚幻和只要你在打开开发选项的情况下测量。我之前知道我说过你应该关闭这些东西,但是你想将构建设置为开发人员构建,以便它具有内置的调试命令和说明。
选择⬆我们刚刚创建的学习着色器项目,然后单机启动⬇


当它正在运行时您可以在左上角看到这里还有其他几个附加选项
它说我的帧时间 是 10 毫秒,当您在此处显示此文本时意味着您的应用程序正在选择中运行

所以如果我帮助点击 alt 选项卡并再次切换回 pix 现在我可以点击这个 gpu 捕获按钮,它只需要一分钟就可以捕获它需要的一切,你知道那里有什么有几件事我忘了提及。您需要进行设置您需要进行设置才能正确运行选择(00:21:46开始介绍)  

总结一下我们今天学到的知识,以便正确准确地测量着色器或材质渲染您所需的时间
创建一个非常简单的场景,只有一个平面一个相机和一盏灯。然后你构建这个场景并在引擎外部运行它,然后你可以使用帧速率计数器或使用一些非常好的软件来测量渲染时间名为 pix的 playstation 平台上有一个名为 razer 的软件或者您可以在 xbox 上运行 pix我确信在 ios 和 mac 平台以及 android 上都有等效的,选项用于精确测量渲染所需的时间但是这是最准确的方法 ,无论如何您都可以像在材料中所做的非常小的更改一样进行测量。因此上周我们讨论了指令计数是如何不准确的率本周我向您展示了测量材料性能的准确方法



本帖被以下画板推荐:

微信公众号:Game艺视界
使用道具 <
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表