优化OpenGL ES 应用 (6)

175 篇文章 25 订阅
43 篇文章 6 订阅

9.4 带宽优化

OpenGL ES应用程序可能会受到内存带宽限制的瓶颈的困扰。 这是GPU在给定时间内可以访问多少数据的物理限制的体现。 该比率不是恒定的,并且根据许多因素而变化,包括但不限于:

1.数据位置–是存储在RAM,VRAM还是GPU缓存之一中?

2.访问类型–是读操作还是写操作? 它是原子的吗? 它必须是连贯的吗?

3.缓存数据的可行性–硬件能否为GPU将要进行的后续操作缓存数据,这样做是否有意义?

高速缓存未命中可能导致应用程序变得带宽受限,从而导致性能显着下降。 当应用程序绘制或生成大量图元时,或者当着色器需要访问纹理中的大量位置时,通常会导致这些高速缓存未命中。

有两种措施可以最大程度地减少缓存未命中的问题:

1.提高传输速度–确保客户端顶点数据缓冲区用于尽可能少的绘制调用; 理想情况下,应用程序永远不要使用它们。

2.减少GPU达到执行此约束的调度或绘制调用所需的数据量。

OpenGL ES提供了几种方法,开发人员可以使用这些方法来减少传输特定类型的数据所需的带宽。

第一种方法是压缩的纹理内部格式,这是为了降低Mipmap尺寸而牺牲纹理质量的。 OpenGL ES支持的许多压缩纹理格式将输入图像划分为4x4块,并对每个块分别执行压缩过程,而不是对整个图像进行操作。 尽管从数据压缩理论的角度来看它似乎效率低下,但它确实具有每个块都在4像素边界上对齐的优点。 这使GPU可以通过一条提取指令来检索更多数据,因为每个压缩纹理块都保留16个像素而不是单个像素,就像未压缩纹理的情况一样。 而且,只要着色器不需要对相距太远的纹理像素进行采样,就可以减少纹理获取的次数。

第二种方法是使用压缩顶点数据格式。 这些格式是基于这样的前提,即许多顶点数据集不会因其组件的精度降低而遭受很大的损失。 强烈建议尽可能使用打包的顶点数据格式。

对于事先知道范围跨度的某些资产,请尝试将数据映射到一种受支持的打包顶点数据格式中。 以正常数据为例,通过将10位无符号整数数据范围<0,1024>标准化到浮点范围<-1,1>,可以将XYZ组件映射到GL_UNSIGNED_INT_2_10_10_10_REV格式。

表9-1 Adreno架构中的顶点数据格式支持

列出了可以在Adreno硬件上的OpenGL ES 2.0,ES 3.0和ES 3.1中使用的顶点数据格式。 当必须使用OpenGL ES扩展名来访问给定格式时,有必要为该格式使用其他标识符-该标识符也在表中显示。

第三种方法是始终使用索引绘制调用。始终使用尽可能小的索引类型,同时仍然能够解决正在绘制的网格的所有顶点。这减少了GPU需要为每个绘制调用访问的索引数据量,但代价是稍微复杂了一些应用程序逻辑。

9.5 深度范围优化

游戏中常见的伪像是z格斗,其中两个或多个基本体在深度缓冲区中具有相似的值。 当相机视图发生轻微变化并且来自不同图元的片段争夺深度测试并变得可见时,伪影变得明显。

有几种消除z冲突的方法:

  • 修改场景几何形状,以在靠近平面的表面之间提供更大的距离(首选)。

  • 选择具有更大深度缓冲区的EGL配置,例如24位vs 16位,尽管使用更大的缓冲区可能会影响性能。

  • 收紧相机的深度范围(近裁剪平面和远裁剪平面),以便在z方向上获得更高的精度,尽管这对共面图元无济于事; 考虑渲染具有多个范围的场景,一个用于近距离物体,一个用于远距离物体。

9.6 其他优化

3D渲染过程是一项计算密集型活动。 屏幕分辨率越来越大,其中一些分辨率即将达到Ultra HD分辨率。 这意味着GPU需要在相同的固定时间段内光栅化更多片段。 假设目标帧速率为30 fps,则游戏在单帧上的花费不得超过33毫秒。 如果是这样,那么每秒的屏幕更新次数将减少,并且用户将自己完全沉浸到游戏中将变得更加困难。

而且,硬件越忙,它将产生的热量就越多。 如果在延长的时间段内,GPU在帧之间没有任何空闲时间,则设备可能会变热并且难以握持。 如果温度超过某个安全阈值,设备甚至可以自动降低GPU时钟频率以防止其过热。 这将进一步降低用户体验。

为了减少渲染硬件上的负载,应用程序可以减小使用的渲染目标的大小,例如,如果本机屏幕分辨率为1080p(1920x1080),则可以将其渲染为720p(1280x720)渲染目标。 由于两个分辨率的纵横比相同,因此图像的比例不会受到影响。 缩小尺寸的渲染目标无法完全填满屏幕,但是OpenGL ES提供了针对此问题的修复程序。

OpenGL ES 3.0引入了对帧缓冲区blit操作的支持。 绘制缓冲区的内容可以从一个帧缓冲区转移到另一个帧缓冲区。 作为blit操作的一部分,API还支持升频,该升频可用于将分辨率较低的纹理的内容复制到分辨率较高的另一个纹理。 使用放大可缩放缩小的渲染目标,以匹配完整的本机显示大小。 最佳策略取决于GPU必须为应用程序执行的计算强度。 可以在渲染过程结束时或在渲染管道中的某个点进行升级。 例如,一种方法可能是以1:1的分辨率渲染几何图形,但使用分辨率稍低的渲染目标应用后期处理效果。

注意:使用帧缓冲区blit进行缩放比将全屏四边形直接渲染到后缓冲区(以缩小尺寸的渲染目标作为纹理输入)的替代方法要快。

或者,通过Android API控制缩放比例:

  • 对于用Java编写的应用程序,请配置GLSurfaceView实例的fixed-size属性(自API级别1起可用)。 使用setFixedSize函数设置属性,该函数接受两个参数来定义最终渲染目标的分辨率。

  • 对于使用本机代码编写的应用程序,请使用函数ANativeWindow_setBuffersGeometry定义最终渲染目标的分辨率,该函数是Android 2.3(API级别9)引入的NativeActivity类的一部分。

在每个交换操作中,操作系统都会获取最终渲染目标的内容并对其进行缩放,以使其与显示的原始分辨率匹配。

该技术已成功用于主机游戏中,其中许多游戏对GPU提出了很高的要求,并且如果以全高清分辨率进行渲染,则可能会受到所讨论的硬件限制的影响。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值