eglSwapBuffers永不返回

时间:2018-10-21 18:46:37

标签: c++ raspberry-pi egl

我正在Raspberry Pi 3上开发一个简单的游戏。作为操作系统,我使用官方的Raspbian Stretch Lite。该游戏无需X服务器即可运行,并使用SFML PI库以C ++开发。

问题在于游戏会不时冻结。在运行游戏几秒钟或几小时后,它可能会发生,但迟早总会发生。冻结的堆栈跟踪指示eglSwapBuffers从不返回。更何况杀死游戏并再次运行它无济于事-它在启动eglCreatePbufferSurface时冻结。重新启动后,它将再次启动。冻结的原因可能是什么?我可以以某种方式调试它吗?我非常担心这可能是由于SFML PI或EGL实现中的错误引起的。

冻结主线程期间的主线程堆栈跟踪:

Thread 1 (Thread 0x76293000 (LWP 802)):
#0  0x76f3c014 in futex_abstimed_wait_cancelable (private=0, abstime=0x0, expected=1, 
    futex_word=0x76459b84 <pool_mem+1444>) at ../sysdeps/unix/sysv/linux/futex-internal.h:205
#1  do_futex_wait (sem=sem@entry=0x76459b84 <pool_mem+1444>, abstime=0x0) at sem_waitcommon.c:115
#2  0x76f3c158 in __new_sem_wait_slow (sem=0x76459b84 <pool_mem+1444>, abstime=0x0) at sem_waitcommon.c:282
#3  0x76804548 in eglSwapBuffers () from /opt/vc/lib/libbrcmEGL.so
#4  0x76ed14b8 in sf::Window::display() () from /usr/lib/libsfml-window.so.2.4
#5  0x000a8038 in Game::run() ()
#6  0x0013d9ec in main ()

杀死游戏后启动期间冻结的堆栈跟踪:

Thread 1 (Thread 0x76223000 (LWP 1001)):
#0  0x76ecc014 in futex_abstimed_wait_cancelable (private=0, abstime=0x0, expected=1, 
---Type <return> to continue, or q <return> to quit---
    futex_word=0x767c1a58 <khrn_queue+76>) at ../sysdeps/unix/sysv/linux/futex-internal.h:205
#1  do_futex_wait (sem=sem@entry=0x767c1a58 <khrn_queue+76>, abstime=0x0) at sem_waitcommon.c:115
#2  0x76ecc158 in __new_sem_wait_slow (sem=0x767c1a58 <khrn_queue+76>, abstime=0x0) at sem_waitcommon.c:282
#3  0x763eeb60 in vchiu_queue_pop () from /opt/vc/lib/libvchiq_arm.so
#4  0x7679b014 in rpc_recv () from /opt/vc/lib/libbrcmEGL.so
#5  0x76795b54 in egl_surface_create () from /opt/vc/lib/libbrcmEGL.so
#6  0x767923b8 in eglCreatePbufferSurface () from /opt/vc/lib/libbrcmEGL.so
#7  0x76e635f4 in sf::priv::EglContext::EglContext(sf::priv::EglContext*) () from /usr/lib/libsfml-window.so.2.4
#8  0x76e5f2b0 in sf::priv::GlContext::initResource() () from /usr/lib/libsfml-window.so.2.4
#9  0x76e5f95c in sf::GlResource::GlResource() () from /usr/lib/libsfml-window.so.2.4
#10 0x76e60f54 in sf::Window::Window() () from /usr/lib/libsfml-window.so.2.4
#11 0x76ea2d7c in sf::RenderWindow::RenderWindow(sf::VideoMode, sf::String const&, unsigned int, sf::ContextSettings const&) () from /usr/lib/libsfml-graphics.so.2.4
#12 0x000a8642 in Game::Game() ()
#13 0x0013d9e6 in main ()

1 个答案:

答案 0 :(得分:2)

免责声明:这不是解决方案,但是可以帮助您识别或解决问题的某些步骤。

  

更何况杀死游戏并再次运行它无济于事

这意味着您很可能面临驱动程序级别的问题。任何应用程序问题都可以通过重新启动来解决(假设您的应用程序运行相同)。而且,它死机了,加上对sem_waitcommon的引用以及对堆栈的查看,这当然意味着您陷入了死机,源于视频驱动程序libbrcmEGL.so。坏消息是,视频驱动程序中的错误会发生,解决起来可能非常复杂,而且由于该驱动程序是封闭源代码,因此您将无法自行修复或由社区对其进行修复...

由于您所使用的软件和版本的特定组合,我找不到与您的问题完全匹配的问题,这可能指向尚未识别的错误。

  • 您当前的发行版:内核,glibc,cbrm固件版本
  • 您的引擎:SFML,SFML PI
  • 您正在使用EGL而不是X11的事实

下面是一些步骤,从最简单的步骤开始

浏览dmesg

这是非常容易的第一步,可能会产生有价值的信息。发生问题时,在第一次和第二次冻结之后,请查看是否有任何显示。任何重要的问题都会在此提出,并为您的问题锦上添花。

报告错误

第一步可能是使用MVE报告raspberrypi/linux中的问题。这可能需要一些时间,但也许是解决该问题的最佳选择,因为GPU的固件(Videocore IV,libbrcmEGL.so为封闭源)。

SFML / SFML PI

您的错误可能是由于驱动程序上的一组特定操作最终导致触发了您所看到的错误。我建议将您的代码减少到最低限度,以尝试确定引发问题的原因。不幸的是,随机发生的事实无济于事。即使这可能无法解决核心问题,您也可以规避它。

尝试其他版本的SFML

升级或降级您正在使用的SFML和SFML PI的版本。同样,这不能解决核心问题,但可以避免。

刷新较旧的Raspbian发行版

如果这是视频驱动程序中的回归,则可以通过从here

刷新发行版的较旧版本来修复它

为最大程度地减少工作量,您可以尝试从raspberry/firmware手动检出libEGL*libbrcmEGL.so的另一个版本,但是您可能会遇到依赖关系的兼容性问题。

切换到X11

我知道... EGL肯定会为您提供更好的性能,并且您可能不需要那种桌面和合成。但是,鉴于社区和用途的扩大,您遇到麻烦的机会将大大减少。并且由于它使用libbrcmGLESv2.so,因此可以确保不会执行相同(可能是错误的)代码。