【问题标题】:Android LibGDX game: FPS drops because of long EGLImpl.eglSwapBuffers callsAndroid LibGDX 游戏:由于长时间调用 EGLImpl.eglSwapBuffers 导致 FPS 下降
【发布时间】:2014-09-15 15:42:30
【问题描述】:

我正在开发一款适用于 Android 平台的游戏,使用 Java 和 LibGDX 引擎。

我遇到了一个奇怪的问题,我的游戏中的 FPS 每 30-40 秒从 57-60 帧下降到 40-45 帧,然后又恢复。以下是 logcat 输出的屏幕截图。垃圾收集器在这些时刻不工作(日志中没有过滤任何内容):

我进行了一些分析,发现问题是由于 EGLImpl.eglSwapBuffers 调用每 30-40 秒花费的时间比平时多。在下面的屏幕截图中(在没有任何反应的情况下分析游戏菜单时拍摄)需要 3.7 毫秒:

在我的菜单渲染周期中,我只调用 MyStage.act() 和 MyStage.draw() 来绘制一组 ImageButtons - 没什么特别的。我的菜单帧渲染时间(平均 17 毫秒)对于这种简单的渲染来说似乎也太长了,但这些定期的长缓冲区交换调用是我现在主要关心的问题。

顺便说一句,如果我在游戏过程中进行分析,情况会变得更糟 - 这些 EGLImpl.eglSwapBuffers 调用需要 15 毫秒甚至更多时间,并将 FPS 降至 30 并不断保持:

我真的可以就如何调查这个问题提出一些建议。

【问题讨论】:

  • 更新:我已经优化了菜单渲染帧 - 现在只需要 7 毫秒,但 EGLImpl.eglSwapBuffers 出于某种原因仍然需要 11 毫秒,并使 FPS 保持在 50 左右,周期性下降到 44-46。根据我在互联网上阅读的内容,我假设 eglSwapBuffers 应该将图形输出“对齐”到每帧 16 毫秒,因此如果帧的渲染速度超过 16 毫秒,则生成的 FPS 应该是 60...

标签: java android opengl-es libgdx frame-rate


【解决方案1】:

您需要了解交换缓冲区的含义。这意味着您告诉 OpenGL 您已完成所有“渲染命令”的发送,并且它现在可以将完成的渲染图像发送到屏幕以显示它。

这意味着什么?这意味着你的显卡已经完成了所有的渲染!大多数 GL 调用将立即返回而不会阻塞。这意味着您的 CPU 会继续工作,而 GPU 将并行工作,处理从 CPU 接收到的渲染命令队列。

现在,如果您的 CPU 能够比 GPU 更快地完成,那么交换缓冲区意味着 GPU 必须先完成整个队列的处理,然后才能真正交换缓冲区并返回。

总的来说,这意味着问题不在于实际的 eglSwapBuffers 需要这么多时间,而在于您的 GPU 跟不上 CPU。这意味着您的场景太复杂了,例如,您有太多的状态变化,比如纹理绑定、着色器切换或类似的东西。

因此,通过分析 CPU 端,您不会真正找到真正的问题。但我真的不能告诉你问题出在哪里。由于您使用的是 libGDX,GLProfiler 可能会在这里为您提供帮助。

PS:FPS 的突然变化也可能是由于您的设备切换到节能模式。

【讨论】:

  • 但 GPU 不只负责着色器处理吗?我的印象是 OpenGL 调用是由 CPU 处理的……纹理交换确实很耗时,但我现在已经优化了,我的帧在 7 毫秒内渲染。我还尝试将场景简化为只有一个纹理,但 swapBuffers 仍然存在同样的问题...
  • @noone :我面临一个问题 ..当我在 imx536 板上运行我的应用程序时,我得到的 fps 是 10 ..但是当我刚刚评论 eglSwapbuffers 时,fps 刚刚更改为 244 。当我在电脑上运行时,我得到了很好的 fps,但在船上的表现很差..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-18
相关资源
最近更新 更多