1. 经常使用优化工具

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvTXlBcnJvdw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" style="border: none; max-width: 100%;" />

2. 经常使用优化方案

OpenGL ES优化的主要工作是在图形管道中找到影响性能的bottleneck,其bottleneck一般表如今下面几方面:

• 在应用程序代码中。如冲突检測
     • GPU与主内存间的传输数据
     • 在VP(Vertex Processor)中的顶点处理
     • 在FP(Fragment Processor)中的片断处理

可通过DS-5 Streamline来定位性能瓶颈(Locate bottleneck)。为了获取更好的性能。可从下面详细功能着手优化:

2.1 纹理(Texture)

高分辨率的纹理占用大量的内存。它是Mali GPU上的主要负荷,可从下面几方面进行优化:
     • 除非必要,尽量不要使用大纹理
     • 总是打开纹理映射(mipmapping)。有时可能降低了渲染质量
     • 假设可能,排序三角形,当按render的次序render时,使其有相互覆盖的三角形放在一起
     • 压缩纹理。可降低内存占用、传输带宽。Mali-400 MP GPU支持ETC纹理压缩(每一个像素占4bits,且不支持alpha通道),GPU硬件可解压ETC纹理,缺点是将降低图像质量

2.2 抗锯齿(Anti-aliasing)

• GPU支持4x Full Scene Anti-Aliasing (FSAA),其性能损失微不足道;当创建context和rendering surface时,可通过选择EGL配置(EGL_SAMPLES=4)来激活4x FSAA
     • Mali GPU还支持16x FSAA,其性能将下降到4x FSAA的1/4

2.3 绘图模式(Draw Mode)

对于大的网格,一个顶点被包括在多个三角形中,这种顶点被处理的次数依赖调用的绘图函数:

• glDrawElements:每一个顶点仅被处理一次,效率更高。

• glDrawArrays:每一个顶点数据在每一个使用它的三角形中被传输和处理一次

按使用的次序存储顶点数据。能够改善顶点Cache效果。而且降低了从RAM到顶点Cache传输的数据量。

2.4 顶点缓冲对象(Vertex Buffer Objects)

• 使用顶点数组(Vertex Array)存储的顶点数据位于client内存(即主内存)。当调用glDrawArrays或glDrawElements时,将把这些顶点数据从client内存copy到图形内存。

• Vertex Buffer Objects同意OpenGL ES2.0应用在高性能的图形内存中分配且Cahce顶点数据,然后从此内存中进行渲染。这样就避免了每当Draw一个原语时重发数据。

• Vertex Buffer Objects分类:
     1) 数组缓冲对象(array buffer objects):由GL_ARRAY_BUFFER标识。用于存储顶点数据(Vertex Data)
     2) 元素数组缓冲对象(element array buffer objects):由GL_ELEMENT_ARRAY_BUFFER标识。用于存原语索引(indices of primitive)

2.5 数据精度(Data Precision)

在可能的情况下。尽量使用低精度的数据,避免使用浮点和其他32位数据类型:
     • 定义顶点位置使用GL_SHORT
     • 定义Surface Normal使用GL_BYTE
     • 定义颜色使用GL_UNSIGNED_BYTE

2.6 处理的数据量(Volume of Data Processed)

要从下面几方面降低Mali GPU处理的数据量:
     • 仅仅画当前帧看得见的原语:可在应用中通过clipping或frustum clulling来实现
     • 使用ETC压缩纹理
     • 依据深度排序几何体:依照从前到后的顺序排序几何体,依据深度排序draw调用。

2.7 渲染目标(Render Targets)

下面因素与渲染目标有关:
     • 依照因素(cause-and-effect)顺序渲染全部的纹理
       1)在纹理被使用之前render to textures
       2)最后渲染后台缓冲区
     • 一次仅仅绘制到一个渲染目标:确保绘制下一个目标之前,已经完毕当前目标的全部调用
     • 不要在一帧中改动纹理:当调用API之前。设置好全部当前帧须要的纹理

2.8 处理管道(Processing Pipeline)

下面因素与图形处理管道有关:

• 使用eglSwapBuffers:
       假设应用显示动画,确保通过调用eglSwapBuffers来结束一帧。应用接着产生下一帧。这样以确保在计算下一帧时。当前帧仍可稳定显示。

• 避免使用glReadPixels:
       即使读取非常少像素,对性能影响也比較大,由于它暂停了处理管理

• 限制glDrawElements中顶点个数:
       在调用glDrawElements之后,在曾经的操作(如:顶点着色、变换、光照)完毕之后才開始创建多边形列表。为了使之并行。确保单次glDrawElements调用中包括的顶点数不要超过当前帧中全部顶点数的1/5。这在马上调用glDrawArrays之前或之后特别重要。

2.9 着色器程序(Shader Programs)

• 首先运行Shader编译:在应用程序启动时。且在開始向驱动发送顶点或纹理数据之前,完毕Shading语言编译器全部相关的调用
     • 使用自己定义着色器程序:把大的Shader程序採裁剪成每一个Surface所须要的,而不使用大而全的Shader程序。小而精的Shader程序通常运行得更快
     • 考虑程序大小:能够使用Offline Shader Compiler检測程序大小。

一个GPU指令能够包括一系列ESSL操作
     • 循环和条件分支:不要手动展开循环。相反。把数据放到数组中,然后在可能的地方使用for循环。当然,也能够使用if语句。
     • 避免使用过多的varyings:在shader编程时,在Fragment Shader程序中,尽量节约使用varings;由于在VP与内存或FP与内存间传递varings时须要消耗内存带宽
     • 避免使用过多的矩阵乘法:4x4的矩阵与4x1的向量相乘,须要运行16次乘法和12次加法,是非常昂贵的。假设须要一个向量与多个矩阵相乘,则向量依次与每一个矩阵相乘,而不要先把全部的矩阵相乘,然后再与向量相乘
     • 评估程序的代价:经常使用的代价级别例如以下表所看到的,使用Offline Shader Compiler能够更精确地获取程序的代价。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvTXlBcnJvdw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" style="border: none; max-width: 100%;" />

2.10 着色器运算(Shader Arithmetic)

• 顶点处理器基于32位浮点值工作:Vertex Shader使用浮点表示整数。

为了避免32位值,设置Vertex Shader程序的输出varing的精度为mediump或lowp。
     • Fragment Shader使用16位浮点值工作:其构成为:sign;5位指数,以抵消15。10位尾数。用一个隐含的最显著1位

2.11 其他

• 使用点精灵:
        而不是三角形或四边形来表示颗粒实体

• 使用适当尺寸的三角形: 
       避免使用长而细的三角形。FP(Fragment Processor 或Pixel Processor)总是处理4个邻近Fragment的组。因此处理1个像素宽度的Strip比处理2个像素宽度的Strip耗用很多其他的时间。

• 优化状态变化:
       避免状态来回变化,能够把同样状态的调用组织在一起,以降低状态变化

• 清除整个Framebuffer:
       总是调用glClear清除整个Framebuffer。假设可能,在清除framebuffer时,清除全部的buffer,如:color、depth, and stencil buffers。

void glClear(GLbitfield mask);
       參数说明:
       GLbitfield:能够使用 | 运算符组合不同的缓冲标志位,表明须要清除的缓冲,比如glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)表示要清除颜色缓冲以及深度缓冲,能够使用下面标志位:
       1)GL_COLOR_BUFFER_BIT:    当前可写的颜色缓冲
       2)GL_DEPTH_BUFFER_BIT:    深度缓冲
       3)GL_ACCUM_BUFFER_BIT:   累积缓冲
  4)GL_STENCIL_BUFFER_BIT: 模板缓冲

• 最小化draw调用:
       当调用glDrawArrays或glDrawElements时,GPU驱动须要收集全部当前OpenGL ES状态、纹理和顶点属性数据。然后驱动处理这些数据并产生可在GPU硬件上运行的命令,以运行真正的draw调用。

此操作能够耗费大量的时间,所以假设运行多次调用。它将成为rendering的性能瓶颈。假设多个对象具有同样的rendering參数。但使用不同的纹理,则能够把纹理合并到一个大的纹理中。并调整其相应的纹理坐标就可以。

• 避免使用glFlush和glFinish:
       除非你无法避开,否则不要调用glFlush或glFinish,而使用eglSwapBuffers来触发一帧的结束。

(注:glFlush仅仅是把命令发送给Server,但并不等待运行完毕。

假设须要等到Server运行完毕时才返回。则须要调用glFinish,但它严重影响性能。)

3. 发现和消除bottleneck

基本方法:

1) 使用专业工具(如DS-5 Streamline)

2) 在值得怀疑的图形管理阶段。添加或降低负荷,然后观察性能变化情况

发现和消除bottleneck可參考下面方案:

问题点 解决方式
Application code Reduce the amount of processing that is unrelated to OpenGL ES calls, such as input processing, game logic, collision detection, and audio processing.
Driver overhead Group geometry with similar state together and eliminate unnecessary state changes.
Vertex attribute transfer Use smaller data types for the values. Also, use a more economical triangle scheme, and in general use glDrawElements rather than glDrawArrays.
Vertex shader processing, or Transform
and Lighting in OpenGL ES 1.1
Try the following options:
1) Use glDrawElements rather than glDrawArrays.
2) For OpenGL ES 1.1, reduce the number of lights.
2) Minimize the transformations of texture coordinates. You can avoid these transformations by setting the transformation matrix using OpenGL ES 1.1 function glLoadIdentity.
3) For OpenGL ES 2.0, simplify the vertex shader program.
Polygon list building  Use fewer graphics primitives. Also, avoid drawing significant amounts of the total geometry in any single call to glDrawElements.
Varying data transfer In OpenGL ES 1.1, use fewer texture coordinates. In OpenGL ES 2.0, use fewer varyings, and specify lower precision on varying variables out of the vertex shader.
Fragment shader processing, texture, color sum, and fog in OpenGL ES 1.1 Lower the resolution of the render target or reduce the size of the viewport.
For OpenGL ES 1.1, use fewer texture stages.
For OpenGL ES 2.0, simplify the fragment shader program.
Texture bandwidth Try the following options:
1)use fewer texture stages
2)lower the size of the textures, by using a smaller data format for each pixel, lower resolution, or texture compression
3)use a simpler texture filtering mode
4)collapse texture coordinates so that they always read from the same position in the texture.

Transfer to display framebuffer

Try the following options:
1) use a mode with lower pixel precision
2) lower the resolution of the render target.

4. ESSL限定值

OpenGL ES Shading Language规范定义了各种着色器资源(shader resources)大小的最小值。在Mali GPU实现中,当中一些值大于规范中定义的最小值。经常使用的例如以下表所看到的:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvTXlBcnJvdw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" style="border: none; max-width: 100%;" />

Mali GPU OpenGL ES 应用性能优化--基本方法的更多相关文章

  1. Mali GPU OpenGL ES 应用性能优化--測试+定位+优化流程

    1. 使用DS-5 Streamline定位瓶颈 DS-5 Streamline要求GPU驱动启用性能測试,在Mali GPU驱动中激活性能測试对性能影响微不足道. 1.1 DS-5 Streamli ...

  2. ES的性能优化

    ES的性能优化 es在数据量很大的情况下(数十亿级别)如何提高查询效率? 在es里,不要期待着随手调一个参数,就可以万能的应对所有的性能慢的场景.也许有的场景是你换个参数,或者调整一下语法,就可以搞定 ...

  3. WEB前端性能优化常见方法

    1.https://segmentfault.com/a/1190000008829958 (WEB前端性能优化常见方法) 2..https://blog.csdn.net/mahoking/arti ...

  4. OpenCL入门:(三:GPU内存结构和性能优化)

    如果我们需要优化kernel程序,我们必须知道一些GPU的底层知识,本文简单介绍一下GPU内存相关和线程调度知识,并且用一个小示例演示如何简单根据内存结构优化. 一.GPU总线寻址和合并内存访问 假设 ...

  5. ES profile 性能优化用——返回各个shard的耗时

    Profile API 都说要致富先修路,要调优当然需要先监控啦,elasticsearch在很多层面都提供了stats方便你来监控调优,但是还不够,其实很多情况下查询速度慢很大一部分原因是糟糕的查询 ...

  6. 50个PHP程序性能优化的方法

    1. 用单引号代替双引号来包含字符串,这样做会更快一些.因为 PHP 会在双引号包围的 字符串中搜寻变量,单引号则不会,注意:只有 echo 能这么做,它是一种可以把多个字符 串当作参数的" ...

  7. MySQL数据性能优化-修改方法与步骤

    原文:http://bbs.landingbj.com/t-0-240421-1.html 数据库优化应该是每个设计到数据库操作应用必须涉及到的操作. 经常调试修改数据库性能主要有三个方面 1.MyS ...

  8. 50个php程序性能优化的方法,赶紧收藏吧!

    1. 用单引号代替双引号来包含字符串,这样做会更快一些.因为 PHP 会在双引号包围的 字符串中搜寻变量,单引号则不会,注意:只有 echo 能这么做,它是一种可以把多个字符 串当作参数的“函数”(译 ...

  9. 基于live555实现的RTSPServer对底层进行性能优化的方法

    在博客<EasyIPCamera高性能摄像机RTSP服务器RTSPServer解决方案>我介绍了基于live555实现的一套RTSPServer功能组件,当时开发者经过几个月的调试,已经将 ...

随机推荐

  1. vue脚手架引入swiper

    方法一: 下载swiper: npm install swiper --save-dev swiper4.0使用入口:http://www.swiper.com.cn/usage/index.html ...

  2. must have same number of columns as the referenced primary key

    在使用Hibernate实现多对多的测试过程中遇到了这个问题 解决的方法: 将黄色字段的内容添加进去 <set name="customerSet" table=" ...

  3. 2. 区分散列的 undef 值, 和手动赋值 0 不一样。1. 使用exists函数,散列中有这个键(必须是keys %hash 有这结果),则返回真值,

    2. 123 my %vertical_alignment;    124 $vertical_alignment{"subscripting"} = 0;    125 unle ...

  4. 并发2-Synchronized

    一.Synchronized的概念 是利用锁的机制来实现同步的. 锁机制有如下两种特性: 互斥性:即在同一时间只允许一个线程持有某个对象锁,通过这种特性来实现多线程中的协调机制,这样在同一时间只有一个 ...

  5. vue 封装自定义组件

    组件结构 sjld >index.js >sjid.vue 最好单独放一个文件夹,有依赖的话装依赖 Sjld.vue 内容 <template id="sjld" ...

  6. 查看密码存放地-shadow

    shadow 位置:/cat/shadow 作用:存放用户的密码等信息 使用查看命令以后得到以下数据 我们会看到9个字段,分别用  :隔开,如上图所示一一解释: 第一字段:用户名称 第二字段:加密密码 ...

  7. 使用sphinx

    SQL   结构化查询语言(是一种标准,所有的关系型数据库Mysql,sqlserver,oracle) sphinx的使用两种方式: 第一种:  使用sphinx的API来操作sphinx   (常 ...

  8. 对 Spring IoC 的理解

    理解 “ 控制反转(IoC)” 控制反转(IoC):用白话来讲,就是由 Spring 容器控制程序中类与类之间的关系,而非传统实现中,由程序代码直接操控.这也就是所谓 “控制反转” 的概念所在:控制权 ...

  9. 第二次:Ubuntu16.04 安装Docker

    sudo apt-get update, 就这一个命令执行了多半天,不知道网络缘故还是怎么的,管他呢,装完总是好的. # step 1: 安装必要的一些系统工具 sudo apt-get update ...

  10. buf.swap16()

    buf.swap16() 返回:{Buffer} 将 Buffer 解释执行为一个16位的无符号整数数组并以字节顺序交换到位.如果 Buffer 的长度不是16位的倍数,则抛出一个 RangeErro ...