安卓GPU性能分析 - OpenGL实时壁纸运行缓慢

3
我正在使用OpenGL ES 3.0开发一个Live Wallpaper。我根据http://www.learnopengles.com/how-to-use-opengl-es-2-in-an-android-live-wallpaper/上出色的教程进行设置,适配GLSurfaceView并将其用在Live Wallpaper中。
我对OpenGL/GLSL最佳实践有相当不错的了解,并设置了一个简单的渲染流水线,其中绘制循环尽可能紧密。没有重新分配,使用一个静态VBO用于不变数据,一个动态VBO用于更新,在着色器中没有分支等。通常情况下我的性能非常好,但看似随机但经常会出现帧速率下降的情况。
通过屏幕上的条纹进行剖析,我发现黄条(“等待命令完成”)的间隔超过了关键的60fps阈值。
我阅读了所有可以找到的关于剖析和解释这些数字的资源,包括此处的深入问题。然而,从那个问题中得出的主要结论似乎是黄杆表示花费时间等待阻塞操作完成,以及关于帧依赖性的问题。我不认为我有任何这样的情况,我只是在每帧都绘制一切。
我的问题很广泛 - 但我想知道什么因素会导致这种类型的帧速率下降,以及如何在确定问题方面前进。
以下是一些可能或可能没有影响的详细信息:
- 我按需渲染,在onOffsetsChanged触发器中(脏渲染)进行渲染。 - 只有一个纹理(创建并仅绑定一次),1024x1024 RGBA。用一个简单的vec4替换一个texture2D调用似乎有助于消除一些帧速率下降。将纹理大小减小到512x512对性能没有任何影响。 - 着色器不复杂,并且如上所述不包含分支。 - 场景中数据不多。只有大约300个顶点和一个纹理。 - sysTrace没有发现可疑的方法 - 与缓冲区填充和状态调用相关的GL方法不在列表的顶部。
更新: 作为一项实验,我尝试只渲染每两帧,而不是在onOffsetsChanged(向左/向右滑动)时请求每次呈现。虽然外观和感觉很糟糕,但几乎完全消除了黄色延迟峰值。这似乎告诉我每秒60次请求过多,但我无法弄清原因。

你尝试过与CPU/GPU频率相关联吗?Android非常渴望尽可能少地使用电力。 - danjo133
@danjo133 不,我没有。你有什么好的资源可以介绍吗?我以前没接触过这些概念! - Victor Sand
1个回答

1
我的问题比较广泛-我想知道什么因素会导致这种帧率下降,以及如何进一步确定问题。 (1) 渲染状态的累积。确保在每个渲染通道开始之前"glClear"颜色/深度/模板缓冲区(尽管如果您直接渲染到窗口表面,则不太可能出现此问题,因为状态保证在每个帧中被清除,除非您设置了EGL_BUFFER_PRESERVE)。 (2) 缓冲区/纹理幽灵化。渲染是深度流水线处理的,但OpenGL ES试图呈现同步编程抽象。如果您尝试写入一个缓冲区(SubBuffer更新、SubTexture更新、MapBuffer等),该缓冲区仍处于"挂起"状态,即仍在GPU操作队列中排队等待使用,那么您要么必须阻塞和等待,要么强制创建资源的副本。对于大型资源,这个复制过程可能会非常昂贵。
(3) 在一些设备上,特别是对于那些处在两个频率决策点附近的内容,设备动态频率和电压调整(DVFS)可能会非常敏感。如果GPU或CPU频率下降,则帧处理时间可能会增加。为了调试目的,一些设备提供通过sysfs固定频率的方式,但没有标准机制。
(4) 最新的移动设备如果所有运行都在高频率下,可能产生的热量超过他们可以散热的能力,因此无法维持最高性能。如果您的内容特别重,则可能会在“一段时间”后(根据我的经验,约1-10分钟)启用热管理,并强制降低频率,直到热水平在安全范围内下降。这会导致帧处理时间的相当随机的增加,而且通常在设备进入“温暖”状态后是不可预测的。
如果可能分享一个API序列以重现问题,将更容易提供更有针对性的建议-该问题实际上是相当普遍的,而OpenGL ES是一个非常广泛的API ;)

非常感谢。这个问题比较普遍,因为我不能分享所有的代码,也不知道哪些部分是关键的! :) 你的答案提供了一些很好的提示。 - Victor Sand
我还应该说,渲染更少的数据可以消除症状,因此再现是困难的(当然,标准的紧张时间表也是如此)。 - Victor Sand
这可能是由于您的GPU速度不够快而导致的症状(即在最大频率下无法跟上,因此每帧需要更多毫秒),或者是温度问题(绘制的内容越少=较低的MHZ要求=较少的热量)。 - solidpixel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接