深度剖析OpenGL ES中的多线程和多窗口渲染技术

摘要:
传统上,OpenGLES应用程序只从一个线程渲染到一个层。OpenGLES数据上传-未优化的OpenGLES文件上传-优化的OpenGLES文件上传-在编译着色器或将数据上传到图形卡驱动程序时,未优化的多线程渲染最适合CPU资源有限的应用程序。所有这些特性组合使多线程OpenGLES更易于调试。此外,我们的PVRVFrameOpenGLES模拟器的多线程支持也得到了显著改进。结论在多线程和多窗口渲染中创建复杂且难以调试的渲染引擎时,您很容易陷入麻烦。
由 创新网小编 于 星期五, 2014-04-11 14:56 发表
深度剖析OpenGL ES中的多线程和多窗口渲染技术第1张

移动设备中的CPU和GPU已经变得很强大,到处都是配备一个或多个高分辨率屏幕的设备,需要使用带有图形驱动器的复杂交互也日益增加。在这篇博客文章中,我将讨论多线程和多窗口渲染对开发人员来讲意味着什么,同时我将介绍将这些技术应用您设计当中的条件和时机。

什么是多线程渲染?
传统上,OpenGL ES应用程序只从一个线程渲染到一个图层。然而,由于3D渲染引擎的复杂性有所增加,图形API操作的CPU开销已经成为瓶颈—尤其是加载资源时。这就使得多线程渲染引起关注。

渲染线程是与图形环境关联的CPU线程。默认情况下,每个图形环境将无法访问另一个环境中的资源(纹理、着色器和顶点缓冲区)。因此,需要使用共享环境,造成一个或多个后台负载线程可访问主线程的资源。这种渲染模式相当有效的原因有两个:

1. 主线程不会阻塞
从根本上说,一直到应用程序和驱动程序内存之间的传输完成之前,上传数据的图形API调用一定会被阻塞。此外,在许多显卡驱动程序中着色器编译就是阻塞型操作。这种阻塞造成开销较大,导致GPU无法运行。将所有上传操作迁移至后台线程,主线程可以维持统一帧率

在多核CPU上进行并行任务分配
由于图形驱动程序在CPU上运行,将这项运行分配至多个渲染线程,使得操作系统向多个CPU内核并行发布指令。这就导致与单个渲染线程相比,驱动程序的工作负载能够处理的更为迅速

使用多线程渲染?

1
2

OpenGL ES数据上传—未经优化

OpenGL ES数据上传—经优化

OpenGL ES数据上传—未经优化
多线程渲染最适合于编译着色器或上传数据至显卡驱动器时CPU资源有限的应用程序。多线程渲染(完成之后效果明显)能够更好地分配驱动程序的任务,并使得应用程序保持统一帧率。

上述简单示例当中,游戏当中从一级升至二级需要上传增加的纹理、 VBO和着色器程序。假设需要完成无缝升级(即启动画面、视频等无法降低上传开销) ,仍在渲染一级时游戏程序必须向驱动程序上传新资源。

在未经优化的情况下,向驱动程序发布调用指令时,由于增加了上传/编译操作负载,每帧所用时间并不一致。提交帧所增加的时间将会造成无法同步刷新,帧率不一致,会感觉游戏很卡。

经过优化的情况下,第二线程用于上传资源。这就使得主线程维持统一的调用递交时间,保证帧率一致。

最佳实践
在实现最佳性能时,应在启动程序时创建渲染线程。主线程应用于所有渲染。增加的线程(在共享环境中创建)应只用于着色器编译和缓存数据上传。后台线程的数量应保持在最低限度(如每个CPU内核一个线程) 。创建线程过多会导致难以维护,代码无法调试。

调用eglMakeCurrent()应保持在最低限度以降低开销(EGL specification规定在上下文一定要开启新线程之前,必须刷新所有未执行的操作)。

什么情况下不应使用多线程渲染?
不受CPU资源限制或不涉及加载次数时
如果运行显卡驱动程序时,CPU资源足够,就应该避免多线程渲染。它会增加渲染引擎的复杂性,如果处理得不好,甚至可能降低性能。

试图“简化”渲染引擎时
最糟的使用实例是不断将单一图形环境绑定至不同线程(使用eglmakeCurrent()) 。这样很糟糕,原因有两个:
The cost of context binding 上下文开销
正如以上所述,调用eglMakeCurrent()迫使驱动程序取消所有未完成的操作

API calls are serialized API调用串行化
由于图形环境在任何时点只能绑定到一个CPU线程,所有API调用将被串行提交

因此,API调用与单线程渲染的开销一致(API调用提交呈串行化),但上行文转换时需要额外开销......也就是说与单线程渲染相比,性能会较差

似乎这是较好的设计,但以这种方式渲染会导致代码复杂凌乱,提交顺序不清(甚至更难以调试! ) 。
不要这样做!

这是多窗口渲染?
多窗口渲染将一个应用程序渲染在多个窗口表面。通过操作系统窗口合成器(例如,Android系统的Surface Flinger或Linux发行版的X11)将这些窗口图层进行合成,以提交至设备屏幕。

在多窗口应用程序中,CPU线程和图形环境呈一对一映射。每个图形环境用于渲染到各自的窗口图层。
什么时候应该使用多窗口渲染?

多窗口渲染最适合用于应用程序需要渲染一个以上屏幕时,例如,当电视机作为第二屏时。
什么时候不应该使用多窗口渲染?

合成层

3

多层合成—未经优化

4

多层合成—经优化

在上述未经优化的实例中,在单个图层渲染游戏场景、触摸控件和迷你地图。应用程序利用操作系统合成器将这些图层组合成可以显示的图层。由于必须要为多个图层分配内存,因此这种方法较浪费资源,该合成器将处理未完全使用的透明像素和GPU的隐藏面消除(HSR),(即被不透明UI元素覆盖的片段冗余着色) 。

在经优化的情况下,游戏场景第一次渲染,然后触摸控件和迷你地图直接渲染于同一图层。在应用程序中FBO用于执行合成的情况下,这种方法并不适合。例如,游戏场景可以被渲染至较低分辨率FBO,将位图传输至应用程序窗口表面,UI元素可以按原始分辨率被驱动至顶点(这项技术通常用于在渲染游戏场景时增加每个像素的性能) 。

PVRTrace当中的多线程多窗口支持

自IMAGINATION发布 PowerVR Graphics 3.2 SDK以来 ,PVRTrace(OpenGL ES捕获和分析工具)支持需要执行这些复杂图形驱动程序交互的应用程序。其中还包括Call View 和Frame Selector中的每线程状态检查器、每线程过滤,线程使用时间轴图。所有这些功能组合使得多线程OpenGL ES更加便于调试。此外,我们的PVRVFrameOpenGL ES模拟器的多线程支持已经得到显著改善。

自IMAGINATION发布 PowerVR Graphics 3.2 SDK以来 ,PVRTrace(OpenGL ES捕获和分析工具)支持需要执行这些复杂图形驱动程序交互的应用程序。其中还包括Call View 和Frame Selector中的每线程状态检查器、每线程过滤,线程使用时间轴图。所有这些功能组合使得多线程OpenGL ES更加便于调试。此外,我们的 PVRVFrameOpenGL ES模拟器的多线程支持已经得到显著改善。

结论
多线程多窗口渲染当中创建复杂难以调试的渲染引擎很容易您陷入困境。然而,如果使用正确也会帮助系统实现较多功能,提高灵活性。如果你按照本篇博客指南设计,将会提升资源负载的性能,而不会带来不必要的麻烦。
原文链接:
http://blog.imgtec.com/powervr/understanding-opengl-es-multi-thread-mult...

免责声明:文章转载自《深度剖析OpenGL ES中的多线程和多窗口渲染技术》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇.NetCore 使用 Linq 动态拼接Expression表达式条件来实现 对EF、EF Core 扩展查询排序操作关于WPF中Popup控件的小记下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Delphi线程基础知识

参考http://blog.chinaunix.net/uid-10535208-id-2949323.html 一、概述 Delphi提供了好几种对象以方便进行多线程编程。多线程应用程序有以下几方面的功能: 1.避免性能瓶颈:单线程应用程序在进行比较慢的操作如磁盘读写的时候,CPU必须停下来等待,直到该操作执行完毕。而多线程应用程序在进行比较慢的操作如磁...

SendMessage()鼠标软模拟

//鼠标软模拟:好处就是不会真的移动鼠标 开始按钮 坐标 x=386y=387 SendMessage(hookHwnd,messages.WM_LBUTTONDOWN ,0,$0180017A); //按下鼠标左键 SendMessage(hookHwnd,messages.WM_LBUTTONUP ,0, $0180017A); //抬起鼠标左键...

OpenGL教程一

引自:https://blog.csdn.net/u013654125/article/details/73613644 GLEW, GLFW和GLM介绍 现在你有了工程,就让我们开始介绍下工程所用到的开源库和为啥需要这些。 The OpenGL Extension Wrangler (GLEW)是用来访问OpenGL 3.2 API函数的。不幸的是你不能...

md /mdd /ml /mt/mtd

VC编译选项 多线程(/MT)多线程调试(/MTd)多线程 DLL (/MD)多线程调试 DLL (/MDd)C 运行时库                        库文件Single thread(static link) ML            libc.libDebug single thread(static link) MLd      ...

JAVA多线程提高八:线程锁技术

前面我们讲到了synchronized;那么这节就来将lock的功效。 一、locks相关类 锁相关的类都在包java.util.concurrent.locks下,有以下类和接口: |---AbstractOwnableSynchronizer |---AbstractQueuedLongSynchronizer |---AbstractQueued...

JAVA并发理解之重排序问题

 首先我们先来了解一下什么是重排序:重排序是指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段。 从Java源代码到最终实际执行的指令序列,会分别经历下面3种重排序,如下图所示       上述的1属于编译器重排序,2和3属于处理器重排序。这些重排序可能会导致多线程程序出现内存可见性问题。在单线程程序中,对存在控制依赖的操作重排序,不会改变...