问候,亲爱的爱好者和专业人士,图形程序员!让我们开始有关移动渲染优化的系列文章的第二部分。在这一部分中,我们将考虑移动设备上的玩家提供的主要GPU系列。首先,请考虑可以对移动GPU进行分类的许多标准。统一或专用着色器内核
在早期的移动视频卡时代,在散布复杂效果之前,有一种观点认为,对于片段着色器,支持降低精度的计算就足够了。实际上,在典型的显示模式下,每个颜色通道使用8位甚至更少的位。这种观点导致了专用着色器核心的使用。对于顶点,我们使用针对矩阵转换而优化的内核,其精度提高了FP24 / FP32(highp)。对于像素,以较低的精度FP16(mediump)更有效地工作的核心。有了这个高他们不被支持。乍一看,这种专业化使我们能够在芯片上实现更合理的晶体管分布。但是,实际上,这会导致在开发复杂效果以及使用高分辨率纹理时遇到困难。此外,核心专业化可能导致顶点/片段瓶颈。该术语是指由于顶点和像素核心上的不对称负载而使某些核心处于“空闲”状态的情况。 因此,现代体系结构使用统一的内核。这样的内核可以根据负载承担顶点,像素和其他计算任务。向量(SIMD)或标量指令集
本着节省以上描述的晶体管(专注于内核)的精神,设计了一组着色器指令。三维图形的最典型转换使用4个分量矢量进行操作。因此,早期的GPU专门用于此类操作数。如果着色器代码包含优化程序无法打包为矢量操作的异构标量操作,则不会使用某些计算能力。这种现象可以说明如下:有一个着色器可以实现常见的乘加运算:将2个操作数相乘,然后将第三个相加。在条件向量架构(向量ISA =向量指令集架构)上进行编译时,我们得到一条向量指令vMADD,该指令运行1个时钟。在条件标量体系结构上,我们得到4个标量指令,由于改进了流水线,它们也可以在1个时钟周期内执行。现在考虑一个复杂的着色器,它执行2个操作,但对2个组件操作数进行操作。在矢量架构的情况下,我们已经获得2条指令,需要2个时钟周期才能执行。但是,没有对.zw组件采取任何措施,并且处理能力处于空闲状态。在标量架构的情况下,这些相同的操作可以打包为以相同的1个时钟周期运行的4个标量sMADD。因此,在标量架构上,由于管线的改进,可以实现更高的计算密度。但是,如下所示,向量ISA仍然是相关的。因此,将矢量化技术应用于着色器代码很有意义。它们使您可以在使用矢量ISA的视频卡上提高性能。同时,这通常不会损害更现代标量的性能ISA。基于以上特征,我们将考虑当今常见的移动GPU系列。让我们从最普通的家庭开始。许多人知道我们正在谈论英国ARM公司的Mali图形卡。ARM没有直接参与芯片生产,而是提供了知识产权。与其他移动视频卡一样,Mali是片上系统(SoC)的一部分,即 与CPU,GPU和总线的共享内存配合使用。 马里·特加德
2008年,马里·乌特加德(Mali Utgard)建筑的第一批代表诞生,直至今天。这些视频卡根据Mali-4方案xx MP n命名,其中xx是型号,n是片段核的数量。在Mali Utgard着色器核心专长中,所有模型都只有一个顶点。Mali Utgard架构的其他功能:- OpenGL ES 2.0
- 在碎片化的内核中缺乏对highp的支持
- 向量指令集(向量化计算很有意义)
尽管有OpenGL ES规范,Mali Utgard视频卡驱动程序仍可以成功编译使用highp精度的片段着色器(例如,精度默认情况下是使用precision highp float设置的)。但是实际使用的是mediump的准确性。因此,建议对此类视频卡上的移动游戏的所有着色器进行额外测试。根据Unity收集的数据,到2019年底,马里·乌特加德(Mali Utgard)为约10%的玩家开发了设备。并且,如果您在market.yandex.ru上设置了适当的过滤器,则可以看到在2019年发布了超过10部带有这种架构视频卡的新手机。如果您准备抛弃这个受众,那么只需在AndroidManifest.xml中设置对OpenGL ES 3.0支持的要求就足够了:<uses-feature android:glEsVersion="0x00030000" android:required="true"⁄>
除了Mali Utgard之外,如果不支持OpenGL ES 3.0,目前还没有广泛的移动GPU。特别值得注意的是在Mali Utgard上使用了高分辨率纹理。中等精度的尾数只有十位不足以实现高质量纹理化,而一侧的纹理分辨率超过1024。但是,尽管在Mali Utgard片段核中仅支持中级精度,但在直接使用变化时,仍可以获得fp24纹理坐标精度。
varying highp vec2 v_texc;
void main()
{
v_texc = …;
}
...
varying highp vec2 v_texc;
void main()
{
gl_FragColor = texture2D(u_sampler, v_texc);
}
作为某些体系结构的一项奖励,此方法使您可以在运行片段着色器之前预取纹理内容,以最大程度地减少等待纹理采样结果时的停顿。马里·米德加德
在马里Utgard已经取代了马里尘世架构。这种架构有好几代,名称分别为Mali-6xx,Mali-7xx和Mali-8xx。尽管有8岁的年龄,但马里·米德加德(Mali Midgard)可以被称为现代建筑,为大多数新功能提供支持:- 统一着色器内核
- OpenGL ES 3.2(计算和几何着色器,镶嵌...)
但是,Mali Midgard保留了向量ISA。考虑到Mali Midgard的广泛使用(约占我们受众的25%),计算的矢量化就变得很合适。Mali Midgard的另一个功能是前向像素消除技术。每个像素在片段核心的单独流中计算。如果在执行流期间得知结果像素将被另一个图元的不透明像素阻止,则该流将过早终止并将释放的资源用于其他计算。马里双霜
在Midgard旁边,Bifrost体系结构因其向标量ISA的过渡而引人注目。与以前的体系结构相比,最大内核数增加了(从16个增加到32个),并且支持与CPU的改进接口,从而可以一致地访问共享内存:尽管有缓存,但对CPU / GPU内存内容的更改立即变得彼此“可见”,使您可以简化同步。来自非官方
已经进行了许多尝试来对Mali视频卡进行反向工程以创建Linux的开源驱动程序。致力于此工作的专职人员的工作使我们可以了解Mali视频卡的未记录功能。因此,在PanFrost项目中,有一个Mali Midgard / Bifrost的反汇编程序,您可以通过该反汇编程序了解一组着色器说明(该主题尚无公开的官方信息)。阿德雷诺
第二个最常见的移动GPU系列是Adreno。此视频卡安装在美国公司Qualcomm的Snapdragon品牌的SoC上。Snapdragon已安装在三星,索尼等公司的高端智能手机中,
目前的Adreno视频卡是3xx-6xx系列系列。所有这些系列均具有以下功能:- 统一着色器内核
- 伪TBR(位于传统专用GPU内存中的大图块大小)
- 在即时模式下根据场景的性质自动切换(FlexRender)
- 标量指令集
从Adreno 4xx开始,将出现对OpenGL ES 3.1的支持,以及Adreno 5xx-Vulkan和OpenGL ES 3.2的支持。基于Adreno磁贴的渲染
Adreno显卡具有一个称为GMEM的“传统” GPU 。从128kb到1536kb的音量适用。与其他移动GPU开发人员的体系结构相比,这允许您使用更大的切片大小。在Adreno上,图块的大小是动态的,并且取决于所使用的颜色格式,深度缓冲区和模板。在即时模式下工作时,渲染会在系统内存中进行,其中有一个GL ES扩展名,可用于指定首选模式:QCOM_binning_control。但是,高通公司的最新建议建议完全依赖GPU驱动程序,GPU驱动程序本身确定了应用程序生成的命令缓冲区的最优选模式。 在TBR模式下工作时 Adreno进行2次顶点传递:- Binning pass-按bin分配图元(bins,tile的同义词)
- 全顶点传递仅渲染那些落入当前Bin中的图元
在分箱过程中, Adreno仅计算顶点位置。不计算其他属性,优化器删除不必要的代码。在官方文档(9.2优化顶点处理)中,建议将存储位置所需的顶点信息与其余数据分开存储。这使得缓存顶点数据更加有效。Freedreno
与ARM和Imagination Technologies不同,高通不愿透露其GPU内部结构的详细信息。但是,由于反向工程师Rob Clark的努力,可以从Freedreno项目(Linux的开源Adreno驱动程序)中学到很多东西。罗伯·克拉克(Freerobeno)Imagination Technologies的PowerVR
Imagination Technologies是一家英国的无工厂公司,以为Apple产品开发GPU闻名。在苹果公司内部开发的iPhone 8 / X出现之前,该公司一直担任这一职务。尽管关于这些芯片优化的建议没有改变,以及Imagination对苹果的专利主张表明,Apple仍在继续开发PowerVR架构,这是Imagination的原始开发成果。2020年初,Apple 通过Imagination Technologies 恢复了许可惯例。除了具有iOS / iPadOS的设备,PowerVR视频卡还安装在大量的Android智能手机和平板电脑中。考虑在用户中仍然可以找到的PowerVR图形卡系列。PowerVR SGX
首批PowerVR SGX显卡于2009年问世。此体系结构有几代:Series5,Series5XT和Series5XE。Apple一直在iPAD 4 / iPhone 5 / iPOD Touch 5之前使用这些GPU。可以引用以下SGX功能:- 统一着色器内核
- OpenGL ES 2.0
- 矢量指令集
- 支持着色器中的10位lowp精度
- 依赖纹理读取的性能低下
让我们更详细地讨论其中的一些。 低精度
PowerVR SGX是仅有的具有低端硬件支持的最新移动GPU 。较新的PowerVR模型以及其他供应商的所有现代GPU实际上都使用了中级精度。在PowerVR SXG上使用lowp可使您获得更高的计算密度(每个周期更多的操作)。同时,不同于其他精度,针对lowp的拖尾操作(向量分量的排列)不是免费的。此功能以及lowp提供的狭窄值范围([-2,2])限制了它的范围。同时,设定不当的低电压导致SGX系列上出现伪影的现象不会在所有其他使用中等精度的图形卡上看到。因此,您应该考虑拒绝在着色器中使用lowp。相关纹理读取
如您所知,由于需要等待内存读取结果,因此纹理采样操作最慢。对于移动SoC,我们正在谈论与CPU共享的系统内存。为了减少对慢速内存的访问次数,使用了纹理缓存。为了避免在使用纹理进行栅格化时出现停机,应该预先缓存使用过的区域。如果片段着色器使用从顶点着色器传递来的纹理坐标而不进行更改,则可以在执行片段着色器之前确定缓存所需的纹理部分。如果片段着色器更改了纹理坐标或使用其他纹理的数据来计算它,则并非总是可能的。结果,片段着色器的执行可能会变慢。在这种情况下,PowerVR SGX图形卡特别麻烦。此外,即使使用纹理坐标分量的排列(旋转)也会导致依赖纹理读取。这是一个不读取依赖纹理的着色器程序示例。顶点程序attribute highp vec2 a_texc;
varying highp vec2 v_texc;
void main()
{
gl_Position = …
v_texc = a_texc;
}
片段程序precision mediump float;
uniform sampler u_sampler;
varying highp vec2 v_texc;
void main()
{
gl_FragColor = texture2D( u_sampler, v_texc );
}
在这种情况下:片段程序precision mediump float;
uniform sampler u_sampler;
varying highp vec2 v_texc;
void main()
{
gl_FragColor = texture2D( u_sampler, v_texc.yx );
}
PowerVR流氓
PowerVR视频卡采用Rogue架构进行了进一步开发,该架构有几代:从Series6到Series9。所有PowerVR Rogue具有以下功能:- 统一着色器内核
- 标量指令架构
- 支持OpenGL ES 3.0+(最高3.2,以及用于新标尺的Vulkan API)
PowerVR TBDR
像所有常见的移动GPU一样,PowerVR使用图块管道。但是与竞争对手不同的是,Imagination进一步发展并实现了图元的延迟栅格化,这使得无论渲染顺序如何,都可以跳过不可见像素的阴影。这种方法称为“ 基于图块的延迟渲染”,而消除不可见像素的过程称为“ 隐藏表面去除(HSR)”。隐藏的表面去除建议将不透明的几何图形绘制为透明,而不要使用Z Prepass,对于大多数情况下的PowerVR视频卡,这将导致不必要的工作。但是,考虑到混合,将彼此重叠的几个连续的透明像素完全着色以获得正确的颜色。如果最后一个透明像素后跟一个不透明像素,则可以将其丢弃。 开放性想象技术
与其他GPU开发人员相比,PowerVR的创建者提供了更多的开放访问文档。详细介绍了图形管线的体系结构,以及有关Rogue体系结构的一组指令。有一个方便的工具PVRShaderEditor,它使您可以立即接收着色器上的配置信息,以及Rogue的反汇编清单。尽管PowerVR视频卡在基于Android的设备环境中存在的局限性有限,但为iOS的出色图形编程研究它们的体系结构还是有意义的。即时模式移动GPU
我们研究了最常见的移动视频卡家族。所有这些家族都使用了图块渲染架构。但是,有些移动视频卡使用传统的即时模式方法。这里是其中的一些:- NVIDIA(Tegra SoC)
- 除最近的Gen 11外,所有Intel系列
- Vivante GCxxxx(+ Arcturus GC8000)
以立即模式运行的移动视频卡的一个功能是昂贵的FBO清洁操作。回想一下,在图块体系结构上,全屏清理可加快渲染速度,从而允许驱动程序不将旧内容的“加载”操作添加到图块内存中。在移动即时模式GPU上,全屏清洁是一项耗时的操作,除其他功能外,该类GPU可以“计算”。如果添加清理不会加快速度,但是会减慢渲染速度,那么很可能我们正在使用即时模式GPU。好吧,当然,我们不要忘记提及在即时模式GPU上,更改目标是“有条件的免费”过程。玩家之间不同系列的移动GPU的分布
以下是2019年底从玩家处收集的移动GPU的统计信息:下面我们打开“其他”部分基于这些数据,我们从GPU的主要功能方面对其进行了研究。向量ALU(算术逻辑单元)已过时,并被标量ALU取代。如今,大多数带有矢量指令集的移动GPU是Mali Midgard,其性能可以认为是中等的。因为通常,矢量化不会减慢标量ALU的执行;值得将矢量化视为优化移动设备着色器的实际技术。 不赞成使用专用着色器内核,并用统一的内核替换。骨架网格物体上的顶点瓶颈不再令人恐惧。专用内核仅在Mali-4xx(Utgard)系列上使用。回想一下,这些GPU仅支持OpenGL ES 2.0。我们的听众大约有3.5%。最后,绝大多数移动GPU使用图块方法。即时模式已被边缘化,并迅速被淘汰,因为使用它的视频卡。即时模式GPU在我们的播放器中的份额约为0.7%。有用的链接:感谢您的关注!在该系列的下一篇文章中,我们将考虑优化Mobile着色器的技术。