1.移动平台的特点

和PC平台相比,移动平台的GPU架构有很大不同。由于处理资源等条件的限制,移动设备上的GPU架构专注于尽可能使用更小的带宽和功能,也由此带来了许多和PC平台完全不同的现象。
例如,为了尽可能移除那些隐藏的表面,介绍overdraw(即一个像素被绘制多次),PowerVR芯片(通常用于ios设备和某些Android设备)使用了基于瓦片的延迟渲染(Tiled-based Deffered Rendering,TBDR)架构,把所有的渲染图像装入一个个瓦片(tile)中,再由硬件找到可见的片元,而只有这些可见片元才会执行片元着色器。另一些基于瓦片的GPU架构,如Adreno(高通的芯片)和Mali(ARM的芯片)则会使用Early-Z或相似的技术进行一个低精度的深度检测,来剔除那些不需要渲染的片元。还有一些GPU,如Tegra(英伟达的芯片),则使用了传统的架构设计,因此在这些设备上,overdraw更可能造成性能的瓶颈。
由于这些芯片架构造成的不同,一些游戏往往需要针对不同的芯片发布不同的版本,以便对每个芯片进行更有针对性的优化。尤其是在安卓平台上,不同设备使用的硬件,如图形芯片、屏幕分辨率等,大相径庭,这对图形优化提出了更高的挑战。相比于Android平台,ios平台的硬件条件则相对统一。

2.影响性能的因素

首先,在学习如何优化之前,我们得了解影响游戏性能的因素有哪些,才能对症下药。对于一个游戏来说,它主要使用两种计算资源:CPU和GPU。它们会相互合作,来让我们的游戏可以在预期的帧率和分辨率下工作。其中,CPU主要负责保证帧率,GPU主要负责分辨率相关的一些处理。
据此,我们可以把造成游戏性能的瓶颈的主要原因分成以下几个方面。
(1)CPU:
●过多的draw call
●复杂的脚本或物理模拟
(2)GPU:
●顶点处理
◈过多的顶点
◈过多的逐顶点计算
●片元处理
◈过多的片元(即有可能是由于分辨率造成的,也有可能是由于overdraw造成的)
◈过多的逐片元计算
(3)带宽:
●使用了尺寸很大且未压缩的纹理
●分辨率过高的帧缓存
对于CPU来说,限制它的主要是每一帧中的draw call数目。简单来说,就是CPU在每次通知GPU进行渲染之前,都需要提前准备好顶点数据(如位置、法线、颜色、纹理坐标等),然后调用一些列API把它们放到GPU可以访问到的指定位置,最后调用一个绘制命令,来告诉GPU“嘿,我把东西准备完了,你赶紧出来干活吧(渲染)。”而调用绘制命令的时候,就会产生一个draw call。过多的draw call会造成GPU的性能瓶颈,这是因为每次调用draw call时,CPU往往都需要改变很多渲染状态的设置,而这些操作是非常耗时的。如果一帧中draw call的数目过多的话,就会导致CPU把大部分时间都花费在提交draw call的工作上面了。当然,其他原因也可能造成CPU瓶颈,例如物理、布料模拟、蒙皮、例子模拟等,这些都是计算量很大的操作。但我们主要讨论的是Shader方面的技术,因此这些我们不做讨论。
而对于GPU来说,它负责整个渲染流水线。它从处理CPU传递过来的模型数据开始,进行顶点着色器、片元着色器等一系列工作,最后输出屏幕上的每个像素。因此,GPU的性能瓶颈和需要处理的顶点数目、屏幕分辨率、显存等因素有关。而相关的优化策略可以减少处理的数据规模(包括顶点数目和片元数目)、减少运算复杂度等方面入手。
在了解上面的基本内容后,本章后续涉及的优化技术有:
(1)CPU优化
●使用批处理技术减少draw call数目
(2)GPU优化
●减少需要处理的顶点数目
◈优化几何体
◈使用模型的LOD(Level of Detail)技术。
◈使用遮挡剔除(Occluision Culling)技术。
●减少需要处理的片元数目
◈控制绘制顺序
◈警惕透明物体
◈减少实时光照
●减少计算复杂度
◈使用Shader的LOD(Level of Detail)技术。
◈代码方面的优化
(3)节省内存带宽
●减小纹理大小
●利用分辨率缩放
在开始优化之前,我们首先需要知道是哪个步骤造成了性能瓶颈。而这可以利用Unity提供的一些渲染分析工具来实现。