首页系统综合问题如何用 GPU硬件层加速优化Android系统的游戏流畅度

如何用 GPU硬件层加速优化Android系统的游戏流畅度

时间2023-04-29 05:25:03发布分享专员分类系统综合问题浏览227

今天小编给各位分享手机系统优化软件的知识,文中也会对其通过如何用 GPU硬件层加速优化Android系统的游戏流畅度和如何使用硬件加速或者GPU,使程序运行加速等多篇文章进行知识讲解,如果文章内容对您有帮助,别忘了关注本站,现在进入正文!

内容导航:

  • 如何用 GPU硬件层加速优化Android系统的游戏流畅度
  • 如何使用硬件加速或者GPU,使程序运行加速
  • 手机设置里 硬件加速渲染 要开哪个
  • 安卓软件对于硬件的优化是如何进行的?
  • 一、如何用 GPU硬件层加速优化Android系统的游戏流畅度

    作为一款VR实时操作游戏App,我们需要根据重力感应系统,实时监控手机的角度,并渲染出相应位置的VR图像,因此在不同 Android 设备之间,由于使用的芯片组和不同架构的GPU,游戏性能会因此受到影响。举例来说:游戏在 Galaxy S20+ 上可能以 60fps 的速度渲染,但它在HUAWEI P50 Pro上的表现可能与前者大相径庭。 由于新版本的手机具有良好的配置,而游戏需要考虑基于底层硬件的运行情况。

    如果玩家遇到帧速率下降或加载时间变慢,他们很快就会对游戏失去兴趣。如果游戏耗尽电池电量或设备过热,我们也会流失处于长途旅行中的游戏玩家。如果提前预渲染不必要的游戏素材,会大大增加游戏的启动时间,导致玩家失去耐心。如果帧率和手机不能适配,在运行时会由于手机自我保护机制造成闪退,带来极差的游戏体验。

    基于此,我们需要对代码进行优化以适配市场上不同手机的不同帧率运行。

    所遇到的挑战

    首先我们使用Streamline 获取在 Android 设备上运行的游戏的配置文件,在运行测试场景时将 CPU 和 GPU性能计数器活动可视化,以准确了解设备处理 CPU 和 GPU 工作负载,从而去定位帧速率下降的主要问题。

    以下的帧率分析图表显示了应用程序如何随时间运行。

    在下面的图中,我们可以看到执行引擎周期与 FPS 下降之间的相关性。显然GPU 正忙于算术运算,并且着色器可能过于复杂。

    为了测试在不同设备中的帧率情况,使用友盟+U-APM测试不同机型上的卡顿状况,发现在onSurfaceCreated函数中进行渲染时出现卡顿, 应证了前文的分析,可以确定GPU是在算数运算过程中发生了卡顿:

    因为不同设备有不同的性能预期,所以需要为每个设备设置自己的性能预算。例如,已知设备中 GPU 的最高频率,并且提供目标帧速率,则可以计算每帧 GPU 成本的绝对限制。

    数学公式: $ 每帧 GPU 成本 = GPU 最高频率 / 目标帧率 $

    CPU到 GPU 的调度存在一定的约束,由于调度上存在限制所以我们无法达到目标帧率。另外,由于 CPU-GPU 接口上的工作负载序列化,渲染过程是异步进行的。CPU 将新的渲染工作放入队列,稍后由 GPU 处理。

    数据资源问题

    CPU控制渲染过程并且实时提供最新的数据,例如每一帧的变换和灯光位置。然而,GPU 处理是异步的。这意味着数据资源会被排队的命令引用,并在命令流中停留一段时间。而程序中的OpenGL ES 需要渲染以反映进行绘制调用时资源的状态,因此在引用它们的 GPU 工作负载完成之前无法修改资源。

    调试过程

    我们曾做出尝试,对引用资源进行代码上的编辑优化,然而当我们尝试修改这部分内容时,会触发该部分的新副本的创建。这将能够一定程度上实现我们的目标,但是会产生大量的 CPU 开销。

    于是我们使用Streamline查明高 CPU 负载的实例。在图形驱动程序内部libGLES_Mali.so路径函数, 视图中看到极高的占用时间。

    由于我们希望在不同手机上适配不同帧率运行,所以需要查明libGLES_Mali.so是否在不同机型的设备上都产生了极高的占用时间,此处采用了友盟+U-APM来检测用户在不同机型上的函数占用比例。

    经友盟+ U-APM自定义异常测试,下列机型会产生高libGLES_Mali.so占用的问题,因此我们需要基于底层硬件的运行情况来解决流畅性问题,同时由于存在问题的机型不止一种,我们需要从内存层面着手,考虑如何调用较少的内存缓存区并及时释放内存。

    解决方案及优化

    基于前文的分析,我们首先尝试从缓冲区入手进行优化。单缓冲区方案• 使用glMapBufferRange和GL_MAP_UNSYNCHRONIZED.然后使用单个缓冲区内的子区域构建旋转。这避免了对多个缓冲区的需求,但是这一方案仍然存在一些问题,我们仍需要处理管理子区域依赖项,这一部分的代码给我们带来了额外的工作量。多缓冲区方案• 我们尝试在系统中创建多个缓冲区,并以循环方式使用缓冲区。通过计算我们得到了适合的缓冲区的数目,在之后的帧中,代码可以去重新使用这些循环缓冲区。由于我们使用了大量的循环缓冲区,那么大量的日志记录和数据库写入是非常有必要的。但是有几个因素会导致此处的性能不佳:1. 产生了额外的内存使用和GC压力2. Android 操作系统实际上是将日志消息写入日志而并非文件,这需要额外的时间。3. 如果只有一次调用,那么这里的性能消耗微乎其微。但是由于使用了循环缓冲区,所以这里需要用到多次调用。我们会在基于c#中的 Mono 分析器中启用内存分配跟踪函数用于定位问题:

    $ adb shell setprop debug.mono.profile log:calls,alloc

    我们可以看到该方法在每次调用时都花费时间:

    Method call summary Total(ms) Self(ms) Calls Method name 782 5 100 MyApp.MainActivity:Log (string,object[]) 775 3 100 Android.Util.Log:Debug (string,string,object[]) 634 10 100 Android.Util.Log:Debug (string,string)

    在这里定位到我们的日志记录花费了大量时间,我们的下一步方向可能需要改进单个调用,或者寻求全新的解决方案。

    log:alloc还让我们看到内存分配;日志调用直接导致了大量的不合理内存分配:

    Allocation summary Bytes Count Average Type name 41784 839 49 System.String 4280 144 29 System.Object[]

    硬件加速

    最后尝试引入硬件加速,获得了一个新的绘图模型来将应用程序渲染到屏幕上。它引入了DisplayList 结构并且记录视图的绘图命令以加快渲染速度。

    同时,可以将 View 渲染到屏幕外缓冲区并随心所欲地修改它而不用担心被引用的问题。此功能主要适用于动画,非常适合解决我们的帧率问题,可以更快地为复杂的视图设置动画。

    如果没有图层,在更改动画属性后,动画视图将使其无效。对于复杂的视图,这种失效会传播到所有的子视图,它们反过来会重绘自己。

    在使用由硬件支持的视图层后,GPU 会为视图创建纹理。因此我们可以在我们的屏幕上为复杂的视图设置动画,并且使动画更加流畅。

    代码示例:

    // Using the Object animator view.setLayerType(View.LAYER_TYPE_HARDWARE, null); ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, 20f); objectAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { view.setLayerType(View.LAYER_TYPE_NONE, null); } }); objectAnimator.start(); // Using the Property animator view.animate().translationX(20f).withLayer().start();

    另外还有几点在使用硬件层中仍需注意:

    (1)在使用之后进行清理:

    硬件层会占用GPU上的空间。在上面的 ObjectAnimator代码中,侦听器会在动画结束时移除图层。在 Property animator 示例中,withLayers() 方法会在开始时自动创建图层并在动画结束时将其删除。

    (2)需要将硬件层更新可视化:

    使用开发人员选项,可以启用“显示硬件层更新”。如果在应用硬件层后更改视图,它将使硬件层无效并将视图重新渲染到该屏幕外缓冲区。

    硬件加速优化

    但是由此带来了一个问题是,在不需要快速渲染的界面,比如滚动栏, 硬件层也会更快地渲染它们。当将 ViewPager 滚动到两侧时,它的页面在整个滚动阶段会以绿色突出显示。

    因此当我滚动 ViewPager 时,我使用 DDMS 运行 TraceView,按名称对方法调用进行排序,搜索“android/view/View.setLayerType”,然后跟踪它的引用:

    ViewPager#enableLayers(): private void enableLayers(boolean enable) { final int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { final int layerType = enable ? ViewCompat.LAYER_TYPE_HARDWARE : ViewCompat.LAYER_TYPE_NONE; ViewCompat.setLayerType(getChildAt(i), layerType, null); } }

    该方法负责为 ViewPager 的孩子启用/禁用硬件层。它从 ViewPaper#setScrollState() 调用一次:

    private void setScrollState(int newState) { if (mScrollState == newState) { return; } mScrollState = newState; if (mPageTransformer != null) { enableLayers(newState != SCROLL_STATE_IDLE); } if (mOnPageChangeListener != null) { mOnPageChangeListener.onPageScrollStateChanged(newState); } }

    正如代码中所示,当滚动状态为 IDLE 时硬件被禁用,否则在 DRAGGING 或 SETTLING 时启用。PageTransformer 旨在“使用动画属性将自定义转换应用于页面视图”(Source)。

    基于我们的需求,只在渲染动画的时候启用硬件层,所以我想覆盖ViewPager 方法,但由于它们是私有的,我们无法修改这个方法。

    所以我采取了另外的解决方案:在 ViewPage#setScrollState() 上,在调用enableLayers() 之后,我们还会调用OnPageChangeListener#onPageScrollStateChanged()。所以我设置了一个监听器,当 ViewPager 的滚动状态不同于 IDLE 时,它将所有 ViewPager 的孩子的图层类型重置为 NONE:

    @Override public void onPageScrollStateChanged(int scrollState) { // A small hack to remove the HW layer that the viewpager add to each page when scrolling. if (scrollState != ViewPager.SCROLL_STATE_IDLE) { final int childCount = <your_viewpager>.getChildCount(); for (int i = 0; i < childCount; i++) <your_viewpager>.getChildAt(i).setLayerType(View.LAYER_TYPE_NONE, null); } }

    这样,在 ViewPager#setScrollState() 为页面设置了一个硬件层之后——我将它们重新设置为 NONE,这将禁用硬件层,因此而导致的帧率区别主要显示在 Nexus上。

    作者:陈可心

    原文链接:http://click.aliyun.com/m/1000306394/

    本文为阿里云原创内容,未经允许不得转载。

    一、如何使用硬件加速或者GPU,使程序运行加速

    DXVA是视频硬件加速的统称,不仅仅是视频数据解码(包括H261,MPEG1,MPEG2,H263,MPEG4), 还有Alpha blending, Picture resampling等。但对于播放时CPU利用率影响最大的,则是视频解码,尤其是HDTV的解码。对于低端系统来说,让GPU来负责硬件解码是不二之选。但使用硬件解码,在整个功能上也受到很多限制,尤其是解压以后的视频数据的后期处理(如deinterlace,锐化,去马赛克). 因此对于追求画质的烧友,宁可放弃硬件解码,当然代价是需要升级整个系统。稍后再谈。

    硬件解码生效的时候,系统是怎么运转的呢?现在我们有两个处理器,CPU和GPU。他们通过PCI/AGP/PCIE总线交换数据。
    1。CPU从文件系统里读出原始数据(DirectSHow的源滤镜),分离出压缩的视频数据(分离器)。放在系统内存中。 GPU 发呆
    2。CPU把压缩视频数据交给GPU, 这时总线上开始忙了,压缩数据从系统内存拷贝到显卡上的显存里。
    3. CPU要求 GPU开始硬件解码,现在 CPU进入发呆期,GPU开始忙。当然CPU会定期查询一下GPU忙的怎么样了。
    4。GPU开始用自己的电路解码视频数据(已经在显存里了),解压后的数据还是放在显存里面。CPU继续发呆。
    5. 视频数据刚解码完成以后还不能立刻拿去显示,因为还需要后期处理,如deinterlace, 3:2pulldown,等等。GPU再用自己的后期处理电路来进行处理。CPU还是发呆
    6。后期处理以后的未压缩数据拿去显示到屏幕上, GPU再开始忙视频的缩放,亮度,gamma等事情。CPU还是闲
    7. GPU终于忙完了,下面的视频数据在哪里?通知CPU,GPU先歇会。 CPU又开始忙了,回到第1步。

    上面可以看到,硬件解码生效的时候,CPU真的可以很闲,但是为了让它生效,有些条件必须满足。最关键的原因是,与CPu->系统内存和GPU->显卡显存比起来,PCI、AGP、PCIE总线是龟速。PCI是133MB/S, AGP8X是2.1GB/S, PCIE16X是4GB/S, 而CPU-系统内存,GPU-显存则快若干倍。有兴趣的可以把不同时代的内存总线和AGP/PCIE总线速度进行一下对比。因为CPU和GPU互连的总线很慢,因此,视频数据(无论是解压前还是解压后)一旦交给GPU,GPU就要负责把它处理完,直到最终显示。
    如果在前面1-5步里有哪一步GPU不能做或你不让它做,视频硬件解码就不生效,CPU要负责。
    当然,你可能会问,也许CPU很慢,说不定在龟速总线上传输数据,GPU分担一部分工作,还是比全部CPU做要快呢? 也许如此,但在Directshow架构里,代表视频数据处理各环节的滤镜(分离器,解码器,后期处理,渲染器)需要协商出一个大家都接受的视频数据存储方式,如果某个滤镜说我只能在系统内存里玩,大家都得要在内存里玩,GPU和显存只好放弃。

    二、手机设置里 硬件加速渲染 要开哪个

    1、首先确定自己没有开启省电模式,然后点击手机上的“设置”选项。
    2、下拉到最底下,点击“关于手机”。
    3、在“关于手机”界面连续点击7下版本号,打开“开发者选项”。

    4、退回到手机设置界面,点击“开发者选项”进入。

    5、在开发者选项中将“强制进行GPU渲染”、“强制启用4x MSAA”、“停用HW叠加层”三项打开。

    强制进行GPU渲染:使用GPU渲染可以增加2D应用的流畅度,同时会增加手机的功耗。
    强制启用4x MSAA:就是抗锯齿,让画面的边缘更加柔滑,会增加功耗和占用部分内存,追求画面极致可开启,若内存不足则关闭。

    三、安卓软件对于硬件的优化是如何进行的?

    首先,通过题主给的例子是无法证明Android上的游戏对硬件优化有问题的。

    i9500的GPU是SGX544MP3;iPhone 5的GPU是SGX543MP3。
    这两者的差别据我所知仅在与对DirectX的支持。
    i9500上GPU的实际运行频率为480MHz(跑分或运行一部分自带应用时会“超频”到533MHz);iPhone 5上则大概在333MHz左右。从这一点上来看GS4确实还是有明显的优势。

    最重要的一点在于,GS4的有着一块分辨率为1920*1080的屏幕,一共有2073600个像素,iPhone 5的分辨率仅为1136*640,像素数目是727040,只比GS4像素数目的1/3多那么一点。

    在理想的极端条件下,同样的3D渲染对GS4的GPU施加的压力三倍于对iPhone 5的压力;在现实中,更高的像素数目对内存带宽比对GPU本身相更为敏感。

    Exynos 5410的内存带宽高达12.8GB/s,确实相当高,但iPhone 5虽然只有1/3于GS的像素数目也有不低的8.5GB/s带宽。

    事实上,即使是iPad 4,配备了明显更为强大的SGX554MP4 GPU,并具备其他移动设备难望其项背的17GB/s内存带宽,在2048*1536=3145728个像素的重压下,以原生分辨率运行大型3D游戏的时候表现也只能说差强人意。

    然后,我就谈谈Android上的游戏对硬件优化到底有什么问题。

    我觉得可能是唯一也是最大的问题,碎片化——所有iOS设备使用的都是PowerVR系列的GPU,但是Android上的GPU,光是常见的就有:PowerVR,Adreno,Mail和GeForce四家,游戏很难全面地优化。

    比如说,去年年底之前Android市场上最强大的GPU是Exynos 4上的Mail 400MP4,不论是Tegra 3还是Adreno 225在性能上都要弱很多。于是乎当时的游戏几乎都只给Exynos 4优化,反正因为性能问题在其他的GPU上跑高画质也不可能流畅。到了年底APQ8064上市,Adreno 320成为了新的王者,但是不少游戏在Adreno 320上的画质却还不如Mail 400。到现在,用Adreno 320的设备越来越多,也有越来越多的游戏为其优化,尴尬的一方变成了i9500上的PowerVR——Android市场上的上一款流行的PowerVR GPU是性能连SGX544MP3的零头都赶不上的SGX540。

    Android 4.3率先支持OpenGL ES 3.0标准可以看做是Google对GPU碎片化所提出的解决方案。OpenGL ES 3.0使得不同系列的GPU都可以使用统一的ETC2贴图格式,降低了分裂的程度。但是Android 4.3离普及还非常遥远,另一方面硬件对OpenGL ES 3.0的支持也比较少,比如说PowerVR 5系列就只支持OpenGL ES 2.0,6系列才能支持3.0。而且就算API统一了,想要“完美”地优化每一款GPU也是不可能的任务,不同的设计会有不同的专长。比如说Adreno系列GPU的Shader性能特别的强,如果一个游戏特别注重运用Shader的话在Adreno系列上的表现会明显比在同档次其他GPU上好。现实是,多数游戏还是优先为iOS设备上的PowerVR设计的,并不会运用那么多的Shader特效。

    关于手机系统优化软件的问题,通过《手机设置里 硬件加速渲染 要开哪个》、《安卓软件对于硬件的优化是如何进行的?》等文章的解答希望已经帮助到您了!如您想了解更多关于手机系统优化软件的相关信息,请到本站进行查找!

    爱资源吧版权声明:以上文中内容来自网络,如有侵权请联系删除,谢谢。

    手机系统优化软件
    6个WPS表格操作技巧,小白也能变身表格小能手 各国旅游出境WiFi和电话卡推荐 - 买电话卡还是租随身WiFi?