Android GPU分析 – OpenGL动态壁纸很慢

我正在使用OpenGL ES 3.0开发动态壁纸。 我根据http://www.learnopengles.com/how-to-use-opengl-es-2-in-an-android-live-wallpaper/上的优秀教程进行设置,调整GLSurfaceView并在里面使用它动态壁纸。

我对OpenGL / GLSL最佳实践有很好的了解,并且我已经设置了一个简单的渲染管道,其中绘制循环尽可能紧密。 没有重新分配,使用一个静态VBO用于非变化数据,一个动态VBO用于更新,仅使用一个绘制调用,在着色器等中没有分支。 我通常会获得非常好的表现,但在看似随机但又重复的时候,帧速率会下降。

使用屏幕栏进行分析可以得到黄色条(“等待命令完成”)射击的间隔,并将所有内容都高于关键的60fps阈值。

截图

我已经阅读了任何关于剖析和解释我可以得到的数字的资源,包括这里非常深入的SO问题 。 然而,该问题的主要内容似乎是黄色条表示等待阻塞操作完成所花费的时间,以及帧依赖性 。 我不相信我有任何这些,我只是在每一帧画出一切。 没有阅读

我的问题很广泛 – 但我想知道什么事情会导致这种类型的帧率下降,以及如何推进这个问题。

以下是可能会或可能不会产生影响的一些细节:

  • 我正在按需渲染,onOffsetsChanged是触发器(脏时渲染)。
  • 有一个单一纹理(仅创建并绑定一次),1024×1024 RGBA。 用普通的vec4替换一个texture2D调用似乎有助于删除一些帧率下降。 将纹理大小减小到512×512对性能没有任何帮助。
  • 着色器并不复杂,如前所述,不包含分支。
  • 场景中没有太多数据。 只有约300个顶点和一个纹理。
  • systrace没有显示可疑方法 – GL相关方法(如缓冲区填充和状态调用)不在列表的顶部。

更新:作为一个实验,我试图渲染每一个帧 ,而不是每次onOffsetsChanged(向左/向右滑动)请求渲染。 这对于外观和感觉来说太可怕了,但几乎完全摆脱了黄色的滞后尖峰。 这似乎告诉我,每帧做60个请求太多了,但我无法弄清楚为什么。

我的问题很广泛 – 但我想知道什么事情会导致这种类型的帧率下降,以及如何推进这个问题。

(1)渲染状态的累积。 确保在开始每个渲染过程之前“glClear”颜色/深度/模板缓冲区(尽管如果直接渲染到窗口表面,这不太可能是问题,因为除非您设置状态,否则保证每帧都清除状态EGL_BUFFER_PRESERVE)。

(2)缓冲/纹理重影。 渲染是深度流水线的,但OpenGL ES试图呈现同步编程抽象。 如果您尝试写入缓冲区(SubBuffer更新,SubTexture更新,MapBuffer等)仍然在“待处理”中使用仍然在管道中排队的GPU操作,那么您必须阻止并等待,或者您强制复制要创建的资源。 对于大型资源,此复制过程可能“非常昂贵”。

(3)设备DVFS(动态频率和电压缩放)在某些设备上可能非常敏感,特别是对于恰好位于两个频率之间的水平决策点附近的内容。 如果GPU或CPU频率下降,那么您可能会在帧处理的时间内出现峰值。 出于调试目的,某些设备提供了通过sysfs修复频率的方法 – 尽管没有标准的机制。

(4)散热限制 – 如果一切都以高频率运行,大多数现代移动设备可以产生比散热更多的热量,因此最大性能点无法持续。 如果您的内容特别沉重,那么您可能会发现热管理在“一段时间”(1-10分钟,取决于设备,根据我的经验)开始,并强制降低频率,直到热水平下降到安全边缘内。 这表示帧处理时间有些随机增加,并且一旦设备达到“暖”状态,通常是不可预测的。

如果可以共享再现问题的API序列,那么提供更有针对性的建议会更容易 – 这个问题非常普遍,OpenGL ES是一个非常广泛的API;)