Unity性能优化 - CPU

优化CPU主要是从优化Draw Call入手

  • 什么是Drawcall? 

  Drawcall是CPU向GPU发送绘制命令的接口调用。理论上每一个不同材质的物件需要渲染在屏幕上时,CPU都会调用图形API ( openGL or Diract3D ) 的Draw接口触发显卡进行绘制。

  • 为什么优化Drawcall?

  Drawcall对硬件和驱动而言,要求大量设置状态(使用哪些顶点、哪些shader等)和状态转换。而Drawcall最大的消耗在于:如果每次drawcall只提交少量的数据将导致CPU瓶颈,CPU无法将GPU填满。Drawcall对GPU的耗费在于硬件一直等待CPU提交数据,而无法得到有效利用。GPU大量的时间耗费在不断切换状态和正确性检测上。 GPU在Draw Call之间,为了防止前后Draw的依赖关系造成绘制错误或者资源竞用,一般会在Draw Call后Flush整个流水线,小粒度的Draw Call对GPU流水线来说是个很大的浪费。(这个问题在D3D老版本存在,在新版D3D11中得到改善。)实际上unity官方指出,Drawcall数量的降低并非重点,重点是减少批次的数量,Drawcall优化实际上是对批次数量的优化。 

可以通过以下几个方法优化

1)批处理

分为动态合并和静态合并两种。

静态批处理就是点击Inspector面板的static中的Batching Static,就可以了,优点是可以把多个对象合并成一个大的对象,将多次绘制命令合并为一次,减少的drawCall,缺点是实现了静态批处理的物体不能移动缩放旋转,还会造成内存的损耗。注意不要将重复的物品进行静态批处理,比如1000棵相同的树,这样会将树的Mesh复制1000次,造成极大的内存损耗,且静态批处理的顶点数限制为65000,对于超出的模型需要另外处理

动态批处理不需要手动设置,只需要在unity设置面板中启用就可以,但是限制比较多,引用Unity官方的一段介绍

 1) . 动态批次是逐顶点处理的,因此仅对少于900个顶点的mesh有效。如果shader使用了顶点位置,法线和UV那么仅支持低于300顶点的mesh,而如果shader使用了顶点位置,法线、UV0、UV1和切向量,则之多仅支持180顶点。

  2) . 缩放问题

  缩放对于批次是有影响的,这里涉及到一个统一缩放和非统一缩放的概念。统一缩放即为三轴同比例缩放,比如(1,1,1),(2,2,2)(5,5,5)... 非统一缩放即为三轴不同比例缩放,如(1,2,1)(2,1,1)(1,2,3)等等。

  3) . 使用了不同的材质,即便实质上是相同的(比如两个一模一样的材质),也不会进行批次。

  4) . 拥有lightmap的物件含有额外的材质属性,比如lightmap偏移和缩放系数等,所以拥有lightmap的物件不能批次。

  5) . 多通道的shader会妨碍批处理操作,接受实时阴影的物件无法批次。

动只有当动态批处理产生的CPU开销小于DrawCall的开销,动态批处理才具有优化性能的效果。而在如今的电子设备上,动态批处理产生的CPU开销反而有可能大于DrawCall的开销,影响性能。因此你需要profile你的应用以确定是否需要动态批处理

2)合并图集

图集是将很多零碎的2D小图整合成一张大图,方便unity渲染合批,降低渲染消耗,还能降低内存,应用几个打包图集的原则

1. 尽量紧凑,没有太多空白。比如一个图集512x512刚好塞满,现在额外加一张小图进去,就被迫变成512x1024,浪费的空间就很多了,而且在有的平台,该图集会被强制变成1024*1024,内存消耗从1M变成4M。
2. Draw Call尽量少,同一个界面的小图尽量在一个图集里。
3. 内存管理方便,加载性能好,打开一个界面时只加载必要的图集,关闭时可以方便地释放图集。
4. AssetBundle打包\热更粒度合理,不能出现“热更一个新界面,大量图集都需要热更”的情况。
5. 维护方便,当界面变化时,调整方便,包括生成图集、调整引用、新图集尺寸变化的影响、新图集AssetBundle变化的影响等等。
6. 图集间隙尽量少,主要靠图集工具,常见的比如更紧凑的多边形Mesh替代Rect Mesh、旋转、切割等等。【TP比Unity的 Spirte Packer算法更好,这里我们不讨论】

3)GPU instancing

1,GPU Instancing 没有动态合批那样对网格数量的限制,也没有静态网格那样需要这么大的内存,它很好的弥补了这两者的缺陷
2,与动态和静态合批不同的是,GPU Instancing 并不通过对网格的合并操作来减少Drawcall,GPU Instancing 的处理过程是只提交一个模型网格让GPU绘制很多个地方,这些不同地方绘制的网格可以对缩放大小,旋转角度和坐标有不一样的操作,材质球虽然相同但材质球属性可以各自有各自的区别,比如渲染大量相同的石头和草,如果不能满足动态合批的条件,就可以选择GPU instacing

猜你喜欢

转载自blog.csdn.net/HelloCSDN666/article/details/124694266