编程开发 购物 网址 游戏 小说 歌词 快照 开发 股票 美女 新闻 笑话 | 汉字 软件 日历 阅读 下载 图书馆 编程 China
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
移动开发 架构设计 编程语言 互联网 开发经验 Web前端 开发总结
开发杂谈 系统运维 研发管理 数据库 云 计 算 Java开发
VC(MFC) Delphi VB C++(C语言) C++ Builder 其它开发语言 云计算 Java开发 .Net开发 IOS开发 Android开发 PHP语言 JavaScript
ASP语言 HTML(CSS) HTML5 Apache MSSQL数据库 Oracle数据库 PowerBuilder Informatica 其它数据库 硬件及嵌入式开发 Linux开发资料
  编程开发知识库 -> 移动开发 -> 基于局部flush和全屏flush -> 正文阅读
 

[移动开发]基于局部flush和全屏flush[第1页]

基于区域的flush
基于区域的flush在mobile GPU中已经变得越来越重要了,这种技术能极大地缩短GPU运行当前这个flush的时间,从而带来性能上的巨大改善。然而很多用户对这个技术,或者换个词说,这种优化,仍然不是非常了解,有时候会和一些OpenGL ES的概念viewport或者scissor搞混淆掉。写这篇blog的目的就是阐述这种技术,以及OpenGL ES有哪些API可以应用这种技术。
原理
GPU为了满足一些API的需要会flush当前的framebuffer。当eglSwapbuffers调用的时候,整个framebuffer都会被flush,然后绘制到屏幕上。但是往往还有其他情况,用户可能需要flush framebuffer,但是并不需要整个framebuffer的内容,而是仅仅一部分framebuffer的内容,比如说当glReadPixels被调用的时候,如果用户只希望读取某一个点的数据,那么最理想的情况就是只把这个点给flush出来然后传给用户,而不是flush全屏的framebuffer。如果framebuffer大小是1920x1080,flush仅仅一个点和flush 1920x1080个点会是成千上万倍的差距。
基于区域的flush就是这种技术,用最小的代价来flush用户规定的区域,从而提高性能。区域外的像素在flush过程中会保持不变,这是非常重要的。到底是flush整个屏幕还是flush某一块区域,这是一个软件上的选择。
glViewport和glScissor
很多人会把基于区域的flush和glViewport以及glScissor搞混淆,是不是OpenGL ES规定了这种技术呢?首先在大多数GPU中viewport和scissor都是硬件设置,这个和之前我谈到的基于区域的flush是一种软件选择已经有区别了。
让我们先来看一下glViewport。glViewport规定的是当前绘制视窗的大小,它代表的是全屏的概念,所以很容易区分出来它和基于区域的flush是完全不一样的。
让我们再来看一下glScissor。scissor box和这里所说的区域的概念非常类似,唯一的区别是scissor是可以通过glEnable和glDisable来控制的。从我的个人角度出发,GPU的确可以为scissor专门设计这个优化,在每一个drawcall下来的时候根据scissor box来选择要flush的内容。但是如果你读了我的同事Peter Harris的blog的话,你会了解Mali GPU对每一渲染目标使用独特的两步渲染算法,首先执行所有的几何处理,然后执行所有的片段处理。这就决定了基于区块渲染的GPU不适合针对每一个drawcall来做基于区域的flush。
glCopyTexSubImage2D和glReadPixels
OpenGL ES中的这两个API函数就比较适合基于区域的flush这个技术。
在上面我们已经阐述了glReadPixels这个函数,用户仅仅需要区域内的像素内容,这个区域是由glReadPixels这个函数规定的。所以如果你选择把整个framebuffer的内容都给flush,这会是一个很大的浪费。
glCopyTexSubImage2D也很相似。这个API函数会把framebuffer的一部分拷贝到指定的texture中,从而达到替换texture部分区域的一个目的。这也和这个技术非常吻合,我们可以选择flush需要拷贝的那部分framebuffer的内容来满足用户的需求。
EGL_KHR_partial_update
不久前Khronos发布了一个新的extension - EGL_KHR_partial_update。这个extension规定用户在开始绘制前,可以通过eglSetDamageRegionKHR这个API函数来设置几个区域,接下来所有的OpenGL ES的绘制都限制在这几个区域之内,最后在eglSwapbuffers调用的时候,仅仅这几个区域的像素需要被flush并且显示,区域外的像素保持上一次绘制的结果不变。
这个extension从一个spec的角度阐释了什么叫基于区域的flush,以及如果用户想选择这种技术的话,应该选用什么API函数来实现绘制。
基于区域的flush和全屏flush的一些思考
基于区域的flush是不是一定比全屏flush的性能要好?很多人看了上面的阐述觉得答案应该是肯定的。假设我们在glReadPixels里面用了基于区域的flush这种技术,让我们思考下面这种情况,

glDraw...(...);
int val[16x16];
int x = 0, y = 0;
for (int i = 0; i < 1000; i++)
{
   glReadPixels(x++, y++, 16,16, GL_RGBA, GL_UNSIGNED_BYTE, val); // 假设x, y是一个有效的值
}








假设当前framebuffer大小是128x128,并且没有multisample。
如果是基于全屏的flush,我们只需要flush一次,然后每次调用glReadPixels的时候用已经flush的framebuffer里面读取需要的值就可以了。让我们计算下总的flush的像素个数是128x128 = 16384。
如果采取基于区域的flush,因为每一次flush的区域都不一样,所以这里就需要调用1000次flush。让我们计算下总的flush的像素个数是16x16x1000 = 256000。
看到这里,你是不是还觉得基于区域的flush的性能一定会比全屏flush的性能要好呢?
总结
从上面的阐述中我们可以看到基于区域的flush是一种非常好的优化,但是并不是万能的。这种优化很大程度上依赖于厂商自己的实现和硬件的性能。如果这个区域的大小和全屏大小相差不大,或者像上面那种情况所描述的多次flush的情况,采取基于区域的flush这种技术是得不偿失的。
如果用户对这个技术非常感兴趣,Khronos官方发布的EGL_KHR_partial_update就是一个非常好的选择。
  移动开发 最新文章
Android设计模式之——状态模式
Android解决ScrollView默认不从顶部显示
关于在QtChart中绘出的图形进行点选的问题
Android Studio入门阶段的山路弯弯之Androi
Android设计模式之——责任链模式
DialogFragment实现自定义布局的小技巧
基于局部flush和全屏flush
android 使用binder实现Service与activity进
android性能优化实战理论篇
jenkins+maven+svn实现简单的一键发布
上一篇文章      下一篇文章      查看所有文章
加:2017-08-04 12:28:46  更:2017-08-04 12:30:09 
VC(MFC) Delphi VB C++(C语言) C++ Builder 其它开发语言 云计算 Java开发 .Net开发 IOS开发 Android开发 PHP语言 JavaScript
ASP语言 HTML(CSS) HTML5 Apache MSSQL数据库 Oracle数据库 PowerBuilder Informatica 其它数据库 硬件及嵌入式开发 Linux开发资料
360图书馆 软件开发资料 文字转语音 购物精选 软件下载 新闻资讯 小游戏 Chinese Culture 股票 三丰软件 开发 中国文化 网文精选 阅读网 看图 日历 万年历 2018年11日历
2018-11-18 9:14:27
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  编程开发知识库