安卓LibGDX游戏:因长时间EGLImpl.eglSwapBuffers调用而导致FPS下降

4
我正在开发一个使用Java和LibGDX引擎的Android平台游戏。但我遇到了一个奇怪的问题,每隔30-40秒,我的游戏FPS会从57-60降到40-45帧,然后恢复正常。下面是logcat输出的屏幕截图。在这些时刻,垃圾回收器不起作用(日志中没有过滤任何内容): LogCat part 1 LogCat part 2 我进行了一些分析,并发现问题出现在EGLImpl.eglSwapBuffers调用上,每隔30-40秒需要比平时更长的时间。在下面的屏幕截图中(在菜单渲染期间进行分析,此时什么都没有发生),它需要3.7毫秒: Profiling of game menu
在我的渲染循环中,我只是调用MyStage.act()和MyStage.draw(),它们绘制一组ImageButtons——没什么特别的。我的菜单帧渲染时间(平均17ms)也对于如此简单的渲染来说似乎太长了,但这些奇怪的周期性长缓冲区交换调用现在是我的主要关注点。
顺便说一下,如果我在游戏过程中进行分析,情况会变得更糟——这些EGLImpl.eglSwapBuffers调用需要15毫秒以上,并将FPS降至30并保持不变: profiling during the gameplay 我真的需要一些建议来解决这个问题。

1
更新:我已经优化了菜单渲染框架 - 现在只需要7毫秒,但仍然由于某种原因EGLImpl.eglSwapBuffers需要11毫秒,并且保持FPS在50左右,周期性地下降到44-46。根据我在互联网上阅读的内容,我认为eglSwapBuffers应该将图形输出“对齐”到每帧16毫秒,因此如果帧速率快于16毫秒,则结果FPS应为60... - Lez77
1个回答

4
你需要了解什么是交换缓冲区。它意味着你告诉OpenGL,你已经完成了所有的“渲染命令”,并且它现在可以将完成的渲染图像发送到屏幕上显示。
这意味着你的显卡已经完成了所有的渲染!大多数GL调用会立即返回而不阻塞。这意味着你的CPU可以继续工作,而GPU会并行处理从CPU接收到的渲染命令队列。
现在,如果你的CPU能够比GPU更快地完成,交换缓冲区意味着GPU必须在实际交换缓冲区并返回之前完成处理整个队列。
总的来说,问题不在于实际的eglSwapBuffers花费了很多时间,而只是你的GPU跟不上CPU的速度。这意味着你的场景可能过于复杂,例如,你有太多的状态变化,比如纹理绑定、着色器切换等等。
因此,通过对CPU端进行分析,你无法真正找到真正的问题所在。但我无法告诉你问题出在哪里。由于你正在使用libGDX,GLProfiler可能会对你有所帮助。
PS:FPS的突然变化也可能是由于设备切换到节能模式造成的。

但是GPU不只负责处理着色器吗?我印象中OpenGL调用是由CPU处理的...纹理交换确实很耗时间,但我现在已经优化了,我的帧渲染只需要7毫秒。我还尝试简化场景,只使用一个纹理,但swapBuffers仍然存在同样的问题... - Lez77
@noone:我遇到了一个问题...当我在imx536板上运行我的应用程序时,我得到的fps是10...但是当我注释掉eglSwapbuffers时,fps就变成了244。当我在电脑上运行时,我得到了良好的fps,但在板子上性能很差... - Gokul

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