手机版网站原理,营销方法有哪些,陕西省高速建设集团公司网站,用网址进入的游戏Shader optimization
Fill Rate和 Memory Bandwidth开销最大的地方就是Fragment Shader。开销多大取决于Fragment Shader的复杂程度#xff1a;多少纹理需要采样#xff0c;多少数学计算函数需要使用等等。GPU的并行特性意味着在线程中如果任何地方存在瓶颈#xff0c;都会…Shader optimization
Fill Rate和 Memory Bandwidth开销最大的地方就是Fragment Shader。开销多大取决于Fragment Shader的复杂程度多少纹理需要采样多少数学计算函数需要使用等等。GPU的并行特性意味着在线程中如果任何地方存在瓶颈都会导致有大量fragments的渲染出现问题。
Shader编程和优化是游戏开发中比较困难的一部分因为它很抽象想要写出高质量的Shader代码要比写普通的CPU的游戏逻辑代码差别很大。有时候还要需要些走后门的歪路子小技巧比如提前计算数据把数据存入纹理贴图中。
很多开发者喜欢用可视化的工具编写Shader比如Shader Forge或者Amplify Shader Editor但是它们生成的代码有可能不是最高效的。无论我们用不用可视化工具编写Shader都应该来使用一些能够优化Shader的技巧。
1.Consider using Shaders intended for mobile platforms
Unity的内置Shader中有Mobile的版本这些版本的Shader效率更高PC主机游戏平台也可以使用这些版本的Shader来减少开销但是要评估使用这些Shader导致的渲染效果下降是否可以接受。
2.Use small data types
数据类型越小GPU计算更快。特别是移动平台上。所以我们第一个方法就是将float32位替换成更小的类型比如half16位甚至fixed12位越小的位数也就需要更少的计算量。
Color 数值是优化对象之一通常减少一些精度效果上并没有非常明显的感知但是也要权衡是否真的可以接受渲染上效果的下降。
要注意的是这个优化方法会根据GPU的架构甚至品牌都会有影响优化的效果也会不尽相同我们可能得需要进行不少测试来验证优化效果。
3.Avoid changing precision while swizzling
Swizzling 是shader中从一个现有的vector通过我们想要的数据创建一个新的vector。一些例子比如 用xyzw和rgba都可以无论是个vector还是color这种写法都使得Shader代码更容易理解。
在shader中进行精度的转换是开销很大的操作在swizzling时进行数据精度的转换开销就更大了所以我们要杜绝在在swizzling时进行数据精度的转换如果有这种需求还不如一开始就使用告精度的数据。
4.Use GPU-optimized helper functions
Shader 编译器通常会有效的优化数学运算但是CG和Unity提供的库函数相比自己写的代码大多数情况下还是效率高的多。当我们写自定义的shader时候可以找找库里有没有已经有提供的比如CG库提供了absstep等Unity库提供了 WorldSpaceViewDir()来计算摄像机朝向Luminance()将Color转成grayScale等。
CG库函数http://http.developer.nvidia.com/CgTutorial/cg_tutorial_appendix_e.html
Unity库函数 http://docs.unity3d.com/Manual/SL-BuiltinIncludes.html.
5.Disable unnecessary features
去掉不必要的属性可以节省性能比如我们使用的Shader有没有必要需要transparency, Z-writing, alpha-testing或者alpha blending去掉这些设置或者属性带来的渲染效果的下降是否可以接受如果可以的话这是一个降低Fill Rate开销的好办法。
6.Remove unnecessary input data
删除掉Shader中没用到的输入数据因为它们会需要从内存中读取消耗性能。
7.Expose only necessary variables
把Shader中的变量在material中暴露出来是有开销的因为GPU没办法将这些变量认为是constant的编译器没法按常量编译它们这些数据必须每次都从CPU传入到GPU中。当然把变量暴露出来调整效果调试的时候会比较麻烦所以这条优化可以是在项目的后期再处理。
8.Reduce mathematical complexity
复杂的数学运算会导致渲染的瓶颈因此我们要尽量避免。一种方法是提前计算好把结果存入一张textrue中之后在运行时可以将这个texture传入Shader中然后采样获得结果从而代替复杂的运算。
对于sin()和cos()这些函数我们duck不必这么做因为它们已经被GPU高度优化过但是其他类似 pow(), exp(), log()和我们自己写的函数就是可以优化简化的对象。
这种技术会有额外的内存开销去存储texture也会增加Memory Bandwidth的开销但是Shader没采用这种技术前本来也需要textrue的话如果textrue的alpha通道并没有使用的话我们就可以把结果存入alpha通道中这种做法就非常nice并不会有额外的开销唯一需要的就是程序和美术要配合起来程序提供所需存的结果给美术生成texture。
9.Reduce texture sampling
Memory Bandwidth开销最大的就是texture采样。Texture使用的越少texture越小性能越好。Texture越多cache命中率就会越低Texture越大memory Bandwidth就会消耗的越多。
10.Avoid conditional statements
现代的CPU中对于条件判断语句CPU会尝试进行预测判断最有可能运行的分支提前用空闲的核心计算。等程序真正运行到的时候如果发现决定错误了就舍弃之前的运算而选择另外的分支。这种技术提高了CPU的运行速度因为提前运算或者舍弃结果都要比等待决定哪个才是正确的分支要快而且绝大多数的时候CPU的预测是正确的。
但是在GPU上因为处理是并行的对于条件判断语句必须得决定多少核心运行这个分支多少核心运行其他分支直到所有分支都运行完。比如一个if-else判断GPU需要告诉一部分核心处理true的这条分支路径然后再去要求其他核心处理false的路径除非所有核心处理同样的path否则必须每次都要处理两个path。因此我们应该尽量避免在shader中使用条件判断和多分支当然也取决于必要程度。对于像素级别的计算相比于多分支的开销可能我们倒不如接受一些不必要的计算。
11.Reduce data dependencies
编译器会尽可能的优化我们的Shader代码让GPU处理起来更舒爽。下边这个例子是对优化非常不友好的一段代码 上边的代码数据依赖非常严重每一行的计算都依赖于上一行代码计算的结果这种写法导致编译器没办法优化这段代码因为他们没法在指令级别并行处理。下边的代码则解决了这个问题 这一次编译器识别出这段代码可以在指令级线程并行处理这可以大大提高执行速度。
12.Surface Shaders
Unity的Surface Shaders是一种简化的Fragment Shadersunity引擎会自动将Surface Shaders代码转换但是也就让我们少了很多优化的机会。Surface Shaders能做的事Fragment Shaders一定可以但是Fragment Shader能做的Surface Shaders不一定可以。个人认为是尽量不要用Surface Shaders。
13.Use Shader-based LOD
我们可以强制Unity在渲染远距离的物体时使用更简单的Shaders这样可以有效降低Fill Rate的开销特别是对于我们的目标是要支持多平台或者非常广的硬件范围。LOD keyword可以在Shader中使用来设置当前支持的Shader如果当前的shader和LOD level并不匹配则会降低至其他备用Shader一直到有匹配的Shader我们在运行时可以通过maximumLOD属性来动态更改shader的LOD值。
这个特性和之前介绍过的mesh的LOD技术很相似 可以查看Shader-based LOD 的文档获取更多信息。https://docs.unity3d.com/Manual/SL-ShaderLOD.html