OpenGL OOM的解决方案

一、 问题描述

GLSurfaceView运行期间抛出OOM崩溃:

07-22 11:47:19.919 24862 25042 W Adreno-GSL: <sharedmem_gpuobj_alloc:2713>: sharedmem_gpumem_alloc: mmap failed errno 12 Out of memory
07-22 11:47:19.920 24862 25042 E Adreno-GSL: <gsl_memory_alloc_pure:2297>: GSL MEM ERROR: kgsl_sharedmem_alloc ioctl failed.
07-22 11:47:19.921 24862 25042 E OpenGLRenderer: GL error:  Out of memory!
07-22 11:47:19.921 24862 25042 F OpenGLRenderer: GL errors! frameworks/base/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp:138



二、 问题原因

这个问题在Google上一搜一大堆,没有明确的解释native层如何引起崩溃,先大致回顾以下绘制流程:

开启硬件加速后,会创建Render Thread,当Vsync信号来到时,执行Choreographer中的traversal这个callback,即UI线程绘制操作,绘制操作会被记录到DisplayList中,同步到Render线程,并渲染出最终的buffer,交给SurfaceFlinger去合成,最终展示在显示屏上。

而该OOM问题对应的SkiaOpenGLPipeline,位于上述Render线程的渲染过程中,再往下分析我也不知道了,本文不对其深入分析,因为无论native因什么导致OOM,归根结底还是OOM问题,我们关心的是如何去解决它。


三、 解决方案

1. 限制使用硬件加速

Android提供了四种级别的硬件加速控制方式:

  • Application:在Manifest文件中的Application Tag中配置属性:
<application android:hardwareAccelerated="true" ...>
  • Activity:在Manifest文件中的Activity Tag中配置属性:
<activity android:hardwareAccelerated="true" ...>
  • Window:运行时对窗口设置flag使其使用硬件加速:
window.setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED)
  • View:运行时对单个View设置层级类型使其停用硬件加速:
view.setLayerType(View.LAYER_TYPE_SOFTWARE, null)

开启硬件加速,是为了充分利用GPU提升渲染性能,但是并非所有场景都需要使用硬件加速,除了通常的Video、WebView、Canvas等场景,其他常规页面不涉及高频刷新的,应该尽量缩小硬件加速的使用范围,将GPU资源更多地分配给真正需要的场景。


2. 避免过度绘制

我们知道,无论一个显示区域有多少图层、多少视图组件,最终通过SurfaceFlinger进行合成后都是一个2D平面图,而那些被遮挡的视图或图层,就成了无效绘制,因为一开始对其的计算将被它上方覆盖,不仅在遍历View树时造成额外开销,也在合成buffer时成了累赘。

避免过度绘制既要减少图层,即布局的嵌套层次,也要减少视图数量,以提升单帧的合成效率。


3. 谨慎使用Alpha

以Activity为例,栈上方的页面如果不是完全不透明的,那么栈下方的Activity可以继续绘制,这就意味着同时渲染两个页面的内容,开销直接翻倍。同样的,单个视图如果是半透明的,也会造成该额外开销。

因此尽量避免半透明大视图,如果实在要使用,那就设置该视图的层级属性为硬件层。


4. 确保有足够的内存

前面所说都是从源头出发,避免OpenGL的过大负担,这一条则是从问题本身角度进行优化,内存不足,那么就想办法让内存尽可能满足。

优化内存主要从以下几个维度考虑:

  • 避免ML。
  • 控制大内存的申请,以Bitmap为例,裁剪大小、降低分辨率、调整编码格式等都可以在创建时减小内存占用,如果是应用内的资源,压缩图片或者使用矢量图代替,也是一种不错的方式。
  • 在内存峰值时及时回收内存。

四、 参考文献

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值