OpenGL RHI优化
前言
随着Vulkan的普及,OpenGL已经在被慢慢淘汰,更轻的API调用可以节省不少性能,尤其是在移动平台上,可以减少CPU开销,进而减少功耗。看起来很完美,但是问题是目前移动平台Vulkan驱动存在很多兼容性问题,大家主流的做法都是通过白名单的方式去开Vulkan,所以目前我们还是要继续以OpenGL为主。此文的目的是笔者在优化OpenGL的时候积累的一些经验,因为使用的引擎是UE4,所以这里的优化是以UE4展开的,当然大部分优化都是通用的。
优化
在诸多API中,耗时比较高的有如下这些
- 设置texture
- 设置buffer
- 设置uniform、uniform buffer
- 设置program
- 更新texture
- 更新buffer
- 编译shader
其它API也有开销,但是不是特别明显或者尽量避免即可(比如设置render target),可以针对性做些优化,一般状态缓存就能比较好的解决问题。
因为移动平台目前主流机器都是TBDR构架,不同平台有自己的减少overdraw的策略,比如高通的LRZ、ARM的FPK以及PowerVR的HSR技术。所以我们排序可以以渲染状态为主来排序,当然老的机器上因为实现不好,可能还是按距离排序能减少更多overdraw。接下来我们针对上面提到的开销大的API针对性做优化。
设置texture
- 尽量Pack纹理通道,比如Normal使用两个通道
- 使用Atlas合并贴图
- 使用Texture2DArray合并贴图
- 将通用的纹理固定到特定slot上,比如shadow map,reflection texture,cluster shading 相关buffer等
SHADER_PARAMETER_TEXTURE_EX(Texture2D, DirectionalLightShadowTexture, 3)
- UE每个DC设置完后会把没用到的texture置成None,这样是为了解决某些驱动的问题,可以优化,太过于保守了。
设置Buffer
- 相关性比较强的buffer尽量放到一起,比如normal和tangent
- 使用大buffer+offset的方式管理buffer,这个在后面更新buffer会详细讲解
设置uniform、unform buffer
在4.21之前,ES31下面是完全使用uniform buffer,从4.21之后可以使用emulated uniform buffer,这个东西就是你上层设置更新还是使用的uniform buffer的接口,但是实际上底层用的是uniform。按官方的说法是可以节省大量的内存并且会提升性能

但是实际上我们测试下来开销还是很高,因为设置的uniform数量会变很多,那么有没有更好的优化方式呢?当然是有的,既然是想省内存和性能,那么我们可以使用混合的方式,让uniform和uniform buffer共存使用。哪些适合用uniform buffer呢,像View、DirectionalLight、Shadow这种per frame或者multi frame的就适合,因为数量少,但是像Primitive这种数量特别大的就不适合。
另外UE本身实现的emulated uniform buffer因为在使用的时候并没有把数据完全Pack起来,这个地方也可以在编译期将它们pack到一起并记录下来运行时拷贝到对应的offset处。
|
优化前 |
优化后 |
|
#define View_IndirectLightingCacheShowFlag (pc0_h[11].x) #define View_ReflectionEnvironmentRoughnessMixingScaleBiasAndLargestWeight (pc0_h[10].xyz) #define View_HighResolutionReflectionCubemapMaxMip (pc0_h[9].x) #define View_ReflectionCubemapMaxMip (pc0_h[8].x) #define View_SkyLightColor (pc0_h[7].xyzw) #define View_NormalCurvatureToRoughnessScaleBias (pc0_h[6].xyz) #define View_IndirectLightingColorScale (pc0_h[5].xyz) #define View_CullingSign (pc0_h[4].x) #define View_PreExposure (pc0_h[3].x) #define View_ViewSizeAndInvSize (pc0_h[2].xyzw) #define View_ViewRectMin (pc0_h[1].xyzw) #define View_PreViewTranslation (pc0_h[0].xyz) uniform highp vec4 pc0_h[12]; |
layout(std140) uniform pb0 { vec4 Padding0[76]; highp vec3 View_PreViewTranslation; float PaddingF1228_0; vec4 Padding1228[63]; vec4 View_ViewRectMin; highp vec4 View_ViewSizeAndInvSize; vec4 Padding2272[4]; float PaddingB2272_0; highp float View_PreExposure; float PaddingF2344_0; float PaddingF2344_1; vec4 Padding2344[6]; float PaddingB2344_0; float PaddingB2344_1; float PaddingB2344_2; highp float View_CullingSign; vec4 Padding2464[13]; highp vec3 View_IndirectLightingColorScale; float PaddingF2684_0; vec4 Padding2684[54]; highp float View_IndirectLightingCacheShowFlag; } View; |
|
#define Primitive_LightingChannelMask (pc2_u[0].x) #define Primitive_UseSingleSampleShadowFromStationaryLights (pc2_h[1].x) #define Primitive_InvNonUniformScaleAndDeterminantSign (pc2_h[0].xyzw) uniform uvec4 pc2_u[1]; uniform highp vec4 pc2_h[3]; |
#define Primitive_PrimaryPrecomputedShadowMaskValue (pc2_h[1].z) #define Primitive_LightingChannelMask (floatBitsToUint(pc2_h[1].y)) #define Primitive_UseSingleSampleShadowFromStationaryLights (pc2_h[1].x) #define Primitive_InvNonUniformScaleAndDeterminantSign (pc2_h[0].xyzw) uniform highp vec4 pc2_h[2]; |
可以看到View使用了uniform buffer,而Primitve还是使用uniform,但是变量数量从4个vec4减少到了两个vec4。
设置Program
尽量减少program的数量,比如一些简单的宏可以通过?运算符之类来避免,另外是通过uniform的方式来代替宏,当然这个需要评估,因为可能会造成register spilling以及降低效率。
更新纹理
在开启了texture streaming之后并且纹理数量过多的情况下会导致纹理更新的消耗比较大,可以尝试以下优化:
- UE本身使用了PBO来做纹理更新,这个在移动平台上没必要的,还额外多了一次上传PBO的开销。
- 另外在开启RHI情况下会有一次额外的从Render到RHI的纹理数据拷贝,这个也可以优化掉。
- OpenGL本身支持multi context,可以单独起一个线程来做纹理的上传。
更新Buffer
如果你的buffer数量很多另外又需要频率的更新,这个时候在一些稍微老些的机器上(888及以下机器)很容易遇到更新buffer的过高耗时和卡顿,我们在之前的文章里面有写过。
只不过当时的文章比较久了,后面又有新的实现,现在是除了UAV之外的所有buffer都可以使用大buffer+offset方式访问内存,这个给RHI减少10%~20%的开销。
- glDrawRangeElements、glDrawElements 中有start index
- texture buffer glTexBufferRangeEXT 支持offset,这个主要是ISM、HISM中的instance数据会用到。
Shader编译
Shader编译是很耗时的操作,目前大家常见的做法就是提前收集好PSO并预热,但是很难覆盖完整,如果直接在RHI线程编译会导致卡顿,这个时候也可以复用GL的多context机制进行异步编译。但是这样会引入闪烁,需要去做平衡。
总结
上面列了一些OpengGL开销较大的函数并针对性做了优化,其它API也可以通过cache机器等来做优化,如果按照上面的思路都优化完成,相信你的GL性能一定会有不错的提升以及更低的功耗。
参考
- https://www.unrealengine.com/en-US/blog/unreal-engine-4-21-released
- https://registry.khronos.org/OpenGL/extensions/EXT/EXT_texture_buffer_object.txt
OpenGL RHI优化的更多相关文章
- iOS 中OpenGL ES 优化 笔记 1
1,避免同步和Flushing操作 OpenGL ES的命令执行通常是在command buffer中积累一定量的命令后,再做批处理执行,这样效率会更高:但是一些OpenGL ES命令必须flush ...
- 3D Computer Grapihcs Using OpenGL - 13 优化矩阵
上节说过矩阵是可以结合的,而且相乘是按照和应用顺序相反的顺序进行的.我们之前初始化translationMatrix和rotationMatrix的时候,第一个参数都是使用的一个初始矩阵 glm::m ...
- Mali GPU OpenGL ES 应用性能优化--基本方法
1. 经常使用优化工具 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvTXlBcnJvdw==/font/5a6L5L2T/fontsize/400/fil ...
- opengl performance optimization
OpenGL 性能优化 作者: Yang Jian (jyang@cad.zju.edu.cn) 日期: 2009-05-04 本文从硬件体系结构.状态机.光照.纹理.顶点数组.LOD.Cull等方面 ...
- 开源免费跨平台opengl opencv webgl gtk blender, opengl贴图程序
三维图形的这是opengl的强项,大型3D游戏都会把它作为首选.图像处理,是opencv的锁定的目标,大多都是C的api,也有少部分是C++的,工业图像表现,图像识别,都会考虑opencv的.webg ...
- UE4 RHI与Render模块简解
UE4中的RHI指的是Render hardware interface,作用像Ogre里的RenderSystem,针对Dx11,Dx12,Opengl等等平台抽象出相同的接口,我们能方便能使用相同 ...
- OpenGL 资源汇编
本文收集和汇总了 OpenGL 的文档.教程和在线书籍,供学习和开发者參考. OPENGL开发教程:http://www.linuxgraphics.cn/opengl/index.html Open ...
- cocos2d-html5 中的性能优化
游戏开发中,难免会遇到性能瓶颈.图片一多,渲染批次就会直线上升,任何动画都会变得闪动. OpenGL ES优化的问题,主要考虑两个方面:内存存储和运行速度. 2D游戏中的最占内存的就是图片资源,一张图 ...
- 【Mood-12】Android开发相关书籍推荐
新年伊始,找到Android进阶干货若干,2015拜读. 1.Android应用UI设计模式 目前,谷歌Android操作系统在移动市场中风头正劲,并且未来发展势不可挡.<Android应用UI ...
- Android大放送干:书籍、过程、工具等各种全
完全干燥分享,本文收集Android制定必要的书籍.过程.具.新闻和杂志各种资源.它们能让你在Android开发之旅的各个阶段都受益. 入门 <Learning Android(中文版)> ...
随机推荐
- 解决Python使用matplotlib绘图时出现的中文乱码问题
原文地址: https://blog.csdn.net/qq_33254766/article/details/120304721 全文略,详细见原文. 解决方法: # 设置字体的属性 # plt.r ...
- Regardless of the outcome of the Russia-Ukraine war, how can Ukraine avoid paying the weapon fees to the United States after the war?
According to the agreement between the Ukrainian government and the United States, regardless of the ...
- 终端无人机武器的克星——部署反无人机干扰机之后 —— 武器AI化势在必行
相关: 观察者网一周军评:俄乌战争对未来无人机发展影响 俄乌战争中无人机有了突出的表现,这种类似巡飞弹的无人机工具有着高可控性.易操作.廉价.易制造等优势,依靠这种攻击性的小型无人机往往具有极高的性价 ...
- 国产操作系统 “银河麒麟操作系统V10” 试用失败历程
面对外国的科技封锁,具有自主产权的国产软件已经变得迫在眉睫了,几天前在新闻上看到国产的操作"银河麒麟操作系统V10"已经发布,于是抱着尝鲜的心态想着去试着用用.虽然都是基于linu ...
- 【转载】 MPP大规模并行处理架构详解
本文来自博客园,作者:五分钟学大数据 原文链接:https://www.cnblogs.com/itlz/p/14998858.html =============================== ...
- 部署CPU与GPU通用的tensorflow:Anaconda环境
本文介绍在Anaconda环境中,下载并配置Python中机器学习.深度学习常用的新版tensorflow库的方法. 在之前的两篇文章Python TensorFlow深度学习回归代码:DNN ...
- 武汉市委郭元强书记、盛阅春代市长会见白鲸开源CEO郭炜等嘉宾代表
2024年6月14日,第二届软件创新发展大会在中国武汉举行.大会云集了来自全国的书数百位院士.专家.知名软件企业负责人,包括中国工程院院士倪光南.中国科学院院士陈十一.国家工业信息安全发展研究中心总工 ...
- 几款能容易使用的AI绘画工具
首先介绍一款软件叫做Discord,这是一个非常火爆的社交软件,目前市面上有很多ai绘画工具都可以在在其对应的社区上运行. Discord | 玩耍聊天的地方这个网站可以访问Discord网页版,也可 ...
- C语言的指定初始化
----------------版权声明:本文为CSDN博主「Supan-Yang」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明.原文链接:https://blog ...
- P4823 [TJOI2013] 拯救小矮人
感觉这个题的操作很新奇,做个记录. P4823 [TJOI2013] 拯救小矮人 大概题面: 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决 定搭一个人梯.即:一个小矮人站在另一小矮人 ...