ARM Mobile Studio性能优化(三)
ARM Mobile Studio性能优化(一)https://unity.cn/projects/arm-mobile-studioxing-neng-you-hua-yi ARM Mobile Studio性能优化(二)https://unity.cn/projects/arm-mobile-studioxing-neng-you-hua-er最近前前后后研究手机GPU一个多月了,发现了很多有
·
ARM Mobile Studio性能优化(一)https://unity.cn/projects/arm-mobile-studioxing-neng-you-hua-yi ARM Mobile Studio性能优化(二)https://unity.cn/projects/arm-mobile-studioxing-neng-you-hua-er
最近前前后后研究手机GPU一个多月了,发现了很多有用的信息,本篇文章记录下研究的结果。网络上有很多人写过类似的文章,其实很多人都和我一样只是非芯片开发的上层普通开发者,底层的知识很匮乏,我还是觉得一定要看一手GPU官方技术文档,因为大家都是对这些技术文档进行的二次理解,当然除了一些做芯片的大佬写的文章了。(大佬可以跳过这篇文章)
另外,不要企图把GPU想的“太笨”,我们做项目都会努力反复优化,我相信GPU厂商也是如此,我们这些普通码农都能想到的优化点,做GPU的科学家们当然更能想到。即使他们想不到别忘了还有Unity作为软件层他也一定能想到。还有就是GPU各大厂商写的技术文档尤其在很多细节的地方写的都是很隐晦的,其中分享的最多的就是ARM的mali,最抠门的要数苹果了,对!你没听错苹果也是有GPU技术文档的,不过就那么几页而已。最后我会把所有厂商公开出来的资料贴在文章的最后。我无法保证我写的就一定100%正确,不过所有内容全部源于官方文档,以及我的一些主观猜测和真机实战测试。
GPU的四大阵营
ARM的mali架构,比如华为、联发科(麒麟系列、天玑系列)就是买了mali的公版架构,然后在进行二次开发制造自己的芯片,ARM的文档写的是最全的,值得大家好好看看。
高通Adreno系列,早期买了AMD的移动芯片进行开发。高通并不像ARM一样卖架构而是直接卖芯片,技术文档就写的很抠门,稍微比苹果大方一丢丢。大家看的就是2015年高通公布的《Adreno OpenGL ES开发人员指南》已经是5年前的文档了,一直都不给我们更新!哎~~ 但是高通的GPU芯片绝对是市场的NO1! 今年9月安卓手机性能排行榜前十名依然被高通865和865+占据着。比如小米 oppo vivo这种就直接买高通或者联发科的芯片。
Power VR 系列,只能说比高通好那么一丢丢,文档也是常年不更新,因为早期的苹果芯片使用的就是Power VR架构,但是后来苹果就自己做GPU了,也就是二次开发延续的这架构。
苹果系列,文档就只写了4页,抠门中的战斗抠门,从A11系列开始苹果就用自己开发芯片,延续了Power VR的TBDR渲染技术。
HSR(全称Hidden Surface Removal) 到这一步很多人就认为TBDR比TBR有优势,因为延迟渲染技术可以使用HSR,它可以在光栅化后剔除掉被遮挡的面,从而减少片元的着色压力。延迟技术可以不用对不透明物体的渲染进行排序,GPU里会判断出遮挡关系,从而剔除被遮挡的面。

Early-Z 在TBR渲染技术中因为没有延迟它只能跟之前渲染的物体进行判断,所以就需要软件在渲染前进行排序。3D摄像机会旋转的,要想实现性能最大化是无法给不透明物体设置一个固定的渲染层级,就得每一帧强制对不透明物体进行排序。因为最终传给GPU的渲染顺序是从前往后,那么当着色新的片元时就可以判断出来是否被遮挡,如果被挡住就不再进行着色,就是Early-Z了,它本身和HSR并不冲突。
Unity的优化 大家别忘了,在和芯片交互的过程中还有Unity,我们能想到的优化办法Unity自然也能想到。所以Unity在渲染时会先判断芯片是否支持HSR,如果芯片不支持HSR那么它就需要对不透明物体进行排序保证从前往后的顺序送入GPU,这样就可以进行Early-z了。你猜我怎么知道的? 这一切都是我真机测出来的:)
HSR阵营 而且我还发现一个更恐怖的东西,HSR这项技术并非只有苹果和PowerVR在用,在mali阵营用有个FPK的技术,大概原理是当发现新着色的片元会挡住之前着色的片元时会强制停止前一个片元着色的线程,实现和HSR不一样但是企图做的事情是一样的。在高通阵营中高通845以后的芯片就支持类似HSR的技术,在Unity的API中就提供了判断机器是否支持HSR的功能 SystemInfo.hasHiddenSurfaceRemovalOnGPU 高通845以后的机器这个就是True了。就像我文章开篇所说不要企图把GPU想的“太笨”,就好比我们做手游,你能想到的优化我也能想到一样,而且每年手机芯片也在更新,看一些好几年公布的技术文档显然是有点落后了。
Alpha Test 在网上搜索很多人都会说Alpha Test可能会使用clip discard方法这样GPU就无法进行Early-z了类似的言论。结论是没错的,但是我想说的美术就想要这效果,比如地上的草啊,树啊什么的,我又不可能把alpha test 改成不透明的怎么办呢? 比如地面有大面积的草,由于即使前面之前有遮挡也无法节省掉片元所以效率肯定会非常低,这时候我们可以用prepass的技术,不输出颜色只负责把每个草的深度记下来,这样就会让Early-z生效优化性能。
在 URP中开启prepass可以参考我的这篇文章 https://www.xuanyusong.com/archives/4759
Alpha Blend 正常情况下Alpha Blend是不写深度的,物体必须是从后向前的顺序绘制。有时物体如果自身有遮挡依然可以使用prepass的技术,这样Early-z依然可能生效。无论透明还是不透明,只要有深度靠前的挡住深度靠后且不是alpha test 时Early-z就会生效
Alpha Test VS Alpha Blend 说Alpha Test比Alpha Blend慢只有Power VR文档上写过,大概意思是如果图片一开始能确定深度的话,所有图元都可以并行执行,但是如果中间有一个是Alpha Test,就意味着它的片元必须执行完才能确定深度,所以后面的图元就要等着它。它推荐使用Alpha Blend代替Alpha Test,同时也提到Alpha Blend即使替换也要减少OverDraw的情况。
我在自己的极限单元测试中确实测出Alpha Test比Alpha Blend慢的情况,但这并不意味着Alpha Blend就能代替Alpha Test,有些效果只能Alpha Test,所以项目中一定要用好prepass这门技术。
接着我说说我的测试方法吧,首先创建一个片在场景中设置好它们的遮挡关系,如果被挡住的图元被HSR或者Early-Z掉那么它的片元着色就不会执行。

但是由于普通的片元着色器很简单,很难在手机上看出是否执行,所以我们需要一个复杂的着色器,这样在Profiler中查看GPU时间就可以判断是否真的被 HSR或者Early-Z掉。
我们先准备一个复杂的shader着色器,我特意使用了噪声函数加多次循环。因为必须要保证每个tile的像素每帧都要变化,因为GPU为了节省带宽最后会判断这个tile的颜色是否真的发生改变才会给显存里写。

而且现在的gpu驱动编译shader也是非常聪明的,明显的复杂写法都可以有效的被内联,我也是费了半天在写了一个不被苹果优化掉的复杂shader,囧~~
在我的测试中发现无论是哪种组合,只要被不透明的物体挡住,那么被挡住物体的片元着色器就一定不会执行,所以说现在的GPU是非常聪明的,总的思路就是减少alpha blend和alpha test。

然后就是测试TBR和TBDR的区别,不透明的物体我们强制让它从后向前绘制,如下图所示,根据原理这在TBDR下RenderQueue1999的片元是不会着色的,但是在TBR下RenderQueue1999 和 2000的片元都会执行,因为Early-Z被打断了。

但是实际测试的结果在TBR下RenderQueue1999物体的片元是不会执行的,这就是我前面的结论Unity在渲染时会先判断芯片是否支持HSR,如果芯片不支持HSR那么它就需要对不透明物体进行排序保证从前往后的顺序送入GPU,这样就可以进行Early-z了。
对于Alpha Blend要想得到Early-z的优化那就是写深度并且调整渲染层级,调整渲染层级后就无法和后面的物体有效混合了,毕竟Blend就是要和后面的物体颜色混合,如果先绘制了前面的物体那就无法和后面物体混合了,但是这样是可以Early-z的。
如下图所示,半透明物体必须从后向前画,我们可以强制修改最前面的RenderQueue让它从前往后绘制,并且写入深度。这样RenderQueue3000的片元着色器是不执行的。但是透明关系就会错误。

至于为什么RenderQueue不透明要从2000开始,AlphaTest从2450 ,半透明3000开始是有原因的。如下图所示,正常情况下AlphaTest是2450不透明物体绘制完毕后在绘制,那么Alpha test的片元会被Early-z 掉,但是我们强制修改AlphaTest的RQ设置到1999,强制AlphaTest先绘制,这会导致Early-z失效。两个物体的片元着色器都会执行。虽然后面的AlphaTest是完全被不透明挡住的。而且TBDR也救不了这种情况,所以说一定要严格按照不透明-》Alpha Test-》半透明的顺序来绘制物体。

接着最近还研究了一下着色器分支预测,如果你在网络上搜索很多人都会说shader里最好不要写if else GPU会将两个分支的代码全部执行,并且在最后丢弃掉没用的另一部分。这是上一代GPU的,新一代GPU其实一定有一定“分支预测”的能力,并不会傻傻的执行两遍。
比如我们写的这样一句代码

编译阶段就可以编译成这样,也就是shader里的[flatten]操作,这样就避免了分支功能。

一两行代码可能没什么性能问题,如果if else 里有各有1000行代码呢?全都被[flatten]以后这就毫无性能可言了,所以现在的gpu都提供了[branch]的功能,原理就是在多个线程束中执行相同的shader,如果这些shader的分支都执行的是同一个的话,那就只会执行一个分支的操作。但是分支会打断GPU并行处理还会有一点消耗。但如果这点消耗大于全部flatten的话那么性能就会提升,还有如果线程束中所执行的shader的分支如果不完全一样的话,那么GPU就会强制flatten操作。
接着我们来做个测试,分别在shader中使用flatten 和branch的操作强制设置分支。



明显branch的性能要高很多。
Shader中我们最常见的操作就是用lerp来代替if else,Lerp的核心思想就是

还是上面这个例子,如果使用lerp的话其实就是flatten的方式来执行它,性能是更慢的不如直接if else。

flatten 和branch我并没有在实际项目中大规模测试过,欢迎各位小伙伴测试。
最后我将我学习的这段时间的资源帖来上,如果发现URL打不开的,就是unity 这个网站的bug。
AMR 阵营 首先要感觉ARM台湾的 (Owen Wu)大佬,就是因为看了它的视频我才知道了ARM工具已经这么先进了,最主要的还是中文值得小伙伴们都看看
[2019 TGDF] Mali GPU 架構以及 Mobile Studio 介紹 (Owen Wu) https://youtu.be/Tds9w2hCujI [Unite Seoul 2019] Owen Wu - Mali GPU 아키텍처와 Mobile Studio https://youtu.be/hQSiDQidyGk [2020 TGDF] 給美術人員的行動平台實務典範 (Owen Wu) https://youtu.be/lnY2mCtZL6U
然后就是ARM官方Mobile Studio的介绍。一共5个视频,教大家如何使用 How to Optimize Game Performance for Android on Arm https://youtu.be/ddN_hoRI8WA
ARM写的针对Unity的性能优化文档 https://developer.arm.com/solutions/graphics-and-gaming/gaming-engine/unity/arm-guide-for-unity-developers
图形开发指南 https://developer.arm.com/solutions/graphics-and-gaming/developer-guides/learn-the-basics
ARM Open GLES 开发指南 https://developer.arm.com/solutions/graphics-and-gaming/apis/opengl-es
Mali 每个型号的区别 https://developer.arm.com/ip-products/graphics-and-multimedia/mali-gpus
Power阵营 7篇视频教程一定要好好看看 Introduction to Mobile Graphics (Part 1/7) https://www.youtube.com/watch?v=TcsFt-s0csA Introduction to Mobile Graphics Architecture (Part 2/7) https://www.youtube.com/watch?v=dqQR4oyG_jg Basic of the PowerVR Framework (Part 3/7) https://www.youtube.com/watch?v=HuBvEPHPdTk OpenGL ES 2.0 (Part 4/7) https://www.youtube.com/watch?v=a1S21DitU34 Debugging with PVRTrace (Part 5/7) https://www.youtube.com/watch?v=1Mt-Sc9aW1U Introduction to PowerVR Graphics Tools and SDK (Part 6/7) https://www.youtube.com/watch?v=S6t5smKS0K4 PowerVR Graphics Tools: Latest Developments and Future Plans (Part 7/7) https://www.youtube.com/watch?v=tOdaU0u9c3U
TBDR介绍 https://docs.imgtec.com/Architecture_Guides/PowerVR_Architecture/topics/powervr_architecture_tile_based_deferred_rendering__tbdr.html
HSR介绍 https://docs.imgtec.com/Architecture_Guides/PowerVR_Architecture/topics/powervr_architecture_hidden_surface_removal_efficiency.html
Power VR的优化 https://docs.imgtec.com/Architecture_Guides/PowerVR_Architecture/topics/rules/c_GoldenRules_the_golden_rules.html
https://docs.imgtec.com/Architecture_Guides/PowerVR_Architecture/topics/rules/c_GoldenRules_the_golden_rules.html
高通阵营 一共8篇硬件和渲染教程视频必看 https://developer.qualcomm.com/software/adreno-gpu-sdk/tutorial-videos
Adreno OpenGL ES Developer Guide 2015年 以后就在没有更新过 https://developer.qualcomm.com/software/adreno-gpu-sdk/tools
苹果阵营 抠门中的战斗抠门,一共4篇描述A11的文章,现在已经A14了。。 https://developer.apple.com/documentation/metal/gpu_features/understanding_gpu_family_4/about_raster_order_groups
在吐个槽 unity connect 不好用啊,我编辑的时候 URL命名是

预览的时候就给我把下划线干掉了,使用URL标签也无果。哎~~~

更多推荐
所有评论(0)