【问题标题】:SDL2 hardware accelerated renderer crashes linux when using Proprietary drivers on xubuntu 12.04?在 xubuntu 12.04 上使用专有驱动程序时,SDL2 硬件加速渲染器会导致 linux 崩溃?
【发布时间】:2016-06-23 14:43:44
【问题描述】:

我正在使用 SDL 在 C++ 中创建一个小型 2D 游戏库(这是正确的世界,另一个!),我终于开始在 linux(xubuntu 12.04)上测试它的当前状态(正在进行中的工作)。到目前为止,我大部分时间都在安装 Windows 10。注意:我的 linux 和 windows 10 安装在同一台机器上。

起初我使用的是 xorg nvidia 驱动程序,我的代码使用的是硬件加速渲染(即在创建 SDL_Renderer 时使用 SDL_RENDERER_ACCELERATED 标志)但是当我运行我的代码时,我的帧速率很差~100FPS,请记住在这一点上,我只是通过在屏幕上绘制一个小动画来测试它,在 Windows 上我得到了 ~1200FPS。

我的想法可能是由于图形驱动程序。所以我为我的 GPU 切换到推荐的 nvidia 专有驱动程序,重新启动、重新编译并再次运行我的游戏。然后出现了一个空窗口,我的电脑死机了,但窗口标题中的 FPS 计数器报告了 ~15000 FPS(哇哦!)。我叹了口气,开始敲击键盘,按 ctrl-alt-del 将我注销,然后我又重新登录到与以前相同的冻结屏幕。

硬重启后,我检查了我的测试程序的日志,它报告它成功进入游戏循环,即开始渲染帧。

现在,如果我在主循环中添加延迟或使用 vsync 一切都很好(使用专有的 nvidia 驱动程序时速度更快),没有崩溃。一切按照定义。

我对正在发生的事情感到困惑,我知道如果我没有在那里睡觉,我的程序会尽可能快地运行,但我不会想到调度程序会给它这么多处理器时间忽略系统的其余部分。我尝试研究 Windows 和 linux 调度程序之间的差异,但我可以找到一个充分的理由来解释为什么我的程序会在 linux 上失控。

您可以在此处查看库代码:https://github.com/callumW/Howler 库在 Howler/ 中,测试程序在 testsrc/ 中,主循环在 Game.cpp 中:run()。

(附带说明,如果您对库代码有任何建议,我很乐意收到)。

有人对正在发生的事情有任何想法吗?

很明显,我需要限制帧速率,因为我并不缺少 FPS,所以这不是问题。我还认为这是一种很好的做法,因为它不会不必要地使用电源。但这引起了我的兴趣,我想知道是否有人能回答我。

【问题讨论】:

    标签: c++ linux sdl


    【解决方案1】:

    未来提示 - 无需重新启动。启用 X 终止序列(通常是 ctrl-alt-backspace,但在现代发行版中默认禁用,您必须手动启用它)作为最后的手段,但通常它只是 ctrl-alt-f1,登录到 tty,杀死有问题的进程,然后使用 ctrl-alt-fN 返回 X(X 所在的 tty 数量,通常为 7)。如果您正在使用图形,您可能迟早会需要它。

    不确定您的问题是否与我在运行程序时看到的完全相同,但很可能是这样。您在窗口标题中显示 FPS,每帧将其发送到窗口管理器,每秒 15,000 次。窗口管理器被如此多的窗口标题更新弄糊涂了(至少 openbox 确实如此。尚未使用不同的 WM 进行测试)。不确定它是否最终会刷新累积的更改或永远挂起;没等。

    基本上每秒更新窗口标题的频率不会超过 10 次。

    【讨论】:

    • 谢谢!你是 100% 正确的。我禁用了标题更改和中提琴。也感谢您的提示,我会确保下次使用它们。顺便说一句,你是怎么知道窗口管理器和更新标题的?这是你多年来学到的东西吗?
    • 没什么特别的,真的。杀死了这个过程, - 仍然挂起。文本控制台上使用的进程监视器(在我的情况下为 htop)-openbox(我使用的窗口管理器)占用了 100% 的单个 CPU 内核。很少有东西可以这么重地加载 WM,而且代码也不大,所以之后很容易找出其余的东西。
    【解决方案2】:

    我会在主循环中添加SDL_Delay()。类似的东西:-

    while(running) {
        while(SDL_PollEvent(&e) != 0) {
            if(e.type == SDL_KEYDOWN) {
                if(e.key.keysym.sym == SDLK_ESCAPE) {
                    running = false;
                    break;
                }
            }
            else if(e.type == SDL_QUIT) {
                running = false;
                break;
            }
        }
        update();
        frames++;
        //Add a delay here
        SDL_Delay(0);
    }
    

    这是为了将 CPU 时间还给操作系统。在某些操作系统(如果我没记错的话,比如旧版 Windows)中,如果您无限旋转循环,您的应用程序将冻结,操作系统会认为您的应用程序没有响应并试图杀死它。等等。

    我不确定这是否是您的情况,请尝试一下。您可能想要更改参数的值(本质上是您想要延迟的时间长度,但不能保证准确)。在我不想限制帧率的情况下,我通常使用0 或1。 13 会将您的帧速率限制在 60fps 左右。

    【讨论】:

      猜你喜欢
      • 2020-05-20
      • 1970-01-01
      • 2011-09-05
      • 2023-02-03
      • 2021-06-26
      • 1970-01-01
      相关资源
      最近更新 更多