众所周知,Shader中代码的效率对整个游戏或者应用的性能起着至关重要的作用。如果在较为复杂的场景中使用了不够高效的Shader代码,会严重影响帧率。今天这篇文章将由Unity官方技术支持工程师张鑫用一个简单的实验来证明,如何通过改变变量类型来优化游戏或应用的性能。
测试截图:
074634m77gpggqg8dgt7os.jpg
测试信息:

• 测试对象:一个自建的简单场景,包含一个平面Plane,一个球体Sphere和一个长方体Cube。主摄像机围绕并朝向整个场景以恒定的角速度移动旋转。
• 测试Shader:Guertin Motion Blur,详情请查看相关论文:http://graphics.cs.williams.edu/papers/MotionBlurHPG14/
• 曝光模式:恒定曝光时间
• 曝光时间:1/30 ms
• 采样数目:每个像素10次采样
• 最大模糊半径:5%
• 测试平台:iPhone 6S
• 测试API:Metal

首先,我们使用最初版本的Shader,所有Shader的操作方法中,变量均采用32位浮点数(float)类型进行计算。比如其中某个被调用的函数:

[C#] 纯文本查看 复制代码 // Cylinder shaped interpolation float Cylinder(float T, float l_V) { return 1.0 - smoothstep(0.95 * l_V, 1.05 * l_V, T); }
最终的测试结果如下(平均每一帧耗时,单位毫秒):
• 测试样品1:20.10ms
• 测试样品2:20.74ms
• 测试样品3:20.60ms
• 测试样品平均值:20.48ms

最后一次测试的XCode的Profile截图如下:

064951ltuwkojua1jojtja.png

然后,我们对最初版本的Shader做一些简单的修改以进行优化。这里将所有32位浮点数(float)更改成16位浮点数(half)。同样,上面的函数被修改成:

[C#] 纯文本查看 复制代码 // Cylinder shaped interpolation half Cylinder(half T, half l_V) { return 1.0 - smoothstep(0.95 * l_V, 1.05 * l_V, T); }

下面是修改后的测试结果(平均每一帧耗时,单位毫秒):
• 测试样品1:16.58ms
• 测试样品2:15.72ms
• 测试样品3:16.32ms
• 测试杨萍平均值:16.21ms

最后一次测试XCode的Profile截图如下:

064951yn65xe5njzjmmeuq.png
通过以上对比测试,在我们的例子中,通过更改Shader中操作过程中的参数类型,可以得到20%以上的性能提升。

因此,我们可以得出以下结论:在渲染系统中,通过更改操作数的类型,可以有效提高代码运行效率。显然。这些提升,对于硬件并非十分强大的移动平台,将会带来不容忽视的性能优化。

这是因为,在大多移动平台上,GPU有对half操作数的优化支持,能够在足够精度的计算中,得到较为满意的效率提升。但是,half也不能随意乱用,我们一定要尽量减少不必要的类型转换,因为类型转换会耗费更多的GPU运行周期。例如:

[C#] 纯文本查看 复制代码fixed4 uniform; half4 result = pow (l, 2.2) + uniform; // BAD: fixed -> half conversion struct Input { float4 color : TEXCOORD0; }; half frag (Input IN) : COLOR { return IN.color; // BAD: float -> half conversion } half4 tex = tex2d (textureRGBA8bit, uv); // OK: conversion for free

综上所述,在移动平台的游戏开发过程中,我们应时刻警惕类型对性能的影响。根据自己的需要,运用足够精度的操作数类型,并减少不必要的类型转换。这样,我们的代码将会更高效,游戏也会更流畅。


转载请注明来源:Unity官方中文社区 (forum.china.unity3d.com)。请勿私自更改任何版权说明信息。



Shader, Unity, 性能锐亚教育

锐亚教育 锐亚科技 unity unity教程