【问题标题】:eglSwapBuffers never returnseglSwapBuffers 永远不会返回
【发布时间】:2018-10-21 18:46:37
【问题描述】:

我正在 Raspberry Pi 3 上开发一个简单的游戏。作为操作系统,我使用官方的 Raspbian Stretch Lite。该游戏在没有 X 服务器的情况下运行,并使用 SFML PI 库在 C++ 中开发。

问题是游戏时常卡顿。它可能在运行游戏几秒钟或几个小时后发生,但迟早总会发生。 freeze 的堆栈跟踪表明 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 ()

【问题讨论】:

  • 您能提供更多信息吗?您的所有驱动程序都是最新的吗?游戏是多线程的吗?您可以做些什么来实现它(即使只是以更快的速度)?
  • 除非您正在做一些时髦的事情,否则这对我来说似乎是一个驱动程序问题。当这种情况发生时,您的dmesg 日志中是否有任何相关错误?了解您拥有的确切主板、内核版本和驱动程序版本也很重要
  • @gabe870 我不知道,你能提出一些建议吗?尽快致电sf::Window::display?是的,不幸的是游戏是多线程的,但我没有从不同于主线程的线程调用任何SFMLEGL/OpenGL API。 @AdrienLeravat 我没有检查dmesg 日志。它发生在 Raspberry Pi 3 B 和 Raspberry Pi 3 B+ 上。内核版本:4.14.87-v7+ 固件:2018 年 12 月 4 日 16:50:03 版本 1f3414729f43ef3b977a910a0d811a759562e1cf(干净)(发布)

标签: c++ raspberry-pi egl


【解决方案1】:

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

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

这意味着您很可能面临驱动程序级别的问题。任何应用程序问题都可以通过重新启动来解决(假设您的应用程序运行相同)。它冻结的事实,加上对sem_waitcommon 的引用和对堆栈的查看,当然意味着你遇到了一个死锁,它源自视频驱动程序libbrcmEGL.so。坏消息是,视频驱动程序中出现错误,解决起来可能非常复杂,而且由于驱动程序是闭源的,你将无法自己修复它,或者让社区修复它......

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

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

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

偷看dmesg

这是一个非常简单的第一步,可能会产生有价值的信息。当问题发生时,在第一次和第二次冻结后,看看是否有任何显示。任何重要的问题都会在那里提出,并为您的问题提供一些启示。

报告错误

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

SFML / SFML PI

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

尝试不同版本的 SFML

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

Flash 较旧的 Raspbian 发行版

如果这是视频驱动程序中的回归,您可以通过刷新旧版本的发行版来修复它,来自 here

为了最大程度地减少工作量,您可以尝试手动签出与raspberry/firmware 不同的libEGL*libbrcmEGL.so 版本,但您可能会遇到与它们的依赖关系的兼容性问题。

切换到 X11

我知道...EGL 肯定会给您带来更好的性能,而且您可能不需要那种桌面和合成。但是考虑到更大的社区和使用,您遇到的麻烦可能会少得多。因为它使用libbrcmGLESv2.so,所以保证不会执行相同的(可能是错误的)代码。

【讨论】:

  • dmesg 没有显示任何与 GPU 相关的内容。你的想法非常有道理,但是这个错误的这种不确定性使得它们很难验证。我怎么知道更改是否修复了错误,或者我只是幸运并且没有发生冻结?有几次我以为问题“自己解决了”,因为游戏运行了 24 小时没有任何问题,但我总是错了。
  • 对于任何随机发生的问题,不幸的是,知道它是否已修复的唯一方法是让它运行很长时间(足够长)。如果您找到一种更可靠/更频繁地重现它的方法,这可能会更容易,也许是通过给驱动程序施加更多压力。比赛条件最差!这也是为什么我认为出票要容易得多,并希望他们能在合理的时间内为您修好。由于无法调试或检测 brcm 驱动程序,它只是猜测。让我知道进展情况!
猜你喜欢
  • 2019-11-15
  • 2011-07-25
  • 1970-01-01
  • 2012-10-02
  • 2013-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多