运行SDL程序的第二个实例会导致系统范围冻结
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了运行SDL程序的第二个实例会导致系统范围冻结相关的知识,希望对你有一定的参考价值。
我正在使用SDL进行多人游戏,但是,在某些时候我已经停止了能够同时运行它的两个实例。第一个实例运行没有问题,但是,一旦第二个实例启动,它的渲染线程就会挂起。它表现为系统范围的图形冻结,例如我无法再移动鼠标,屏幕上的任何内容都不会在SDL窗口内部或外部更新。几秒钟后,渲染线程只会暂时恢复冻结。如果我发送并退出,SDL会设法捕获退出事件。然后,更新程序stdout的终端窗口(这就是我可以假设更新线程正常运行,有一个很大的间隔,其中只有调试信息存在)。
通过从渲染过程中删除一段代码,我能够确定这三个未注释的SDL调用是导致延迟的原因:
void Renderer::render() {
SDL_SetRenderDrawColor(sdlRenderer, 0, 0, 0, 255);
SDL_RenderClear(sdlRenderer);
// for (auto target : targets) {
// target->render(this);
// // std::cout << "rendered object with sceneId " << target->target->sceneId << std::endl;
// }
// auto targetCopy = newTargets;
// for (auto newTarget : targetCopy) {
// targets.push_back(newTarget);
// // std::cout << "adding render target" << std::endl;
// }
// newTargets.clear();
SDL_RenderPresent(sdlRenderer);
}
什么可能导致这种行为?
这是SDL初始化代码以获取更多信息,也可以在没有加速的情况下尝试:
SDL_Init(SDL_INIT_VIDEO);
int fullscreenType = 0; // SDL_WINDOW_FULLSCREEN_DESKTOP;
int windowFlags = fullscreenType | SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS |
SDL_WINDOW_ALLOW_HIGHDPI;
int rendererFlags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC;
SDL_Window *window =
SDL_CreateWindow("Game", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
1000, 1000, windowFlags);
SDL_Renderer *sdlRenderer = SDL_CreateRenderer(window, -1, rendererFlags);
SDL_RenderSetLogicalSize(sdlRenderer, 1000, 1000);
IMG_Init(IMG_INIT_PNG);
我在Wayland上运行带有GNOME的Manjaro。 Acer Swift 3. glxinfo | grep OpenGL
的输出:
OpenGL vendor string: Intel Open Source Technology Center
OpenGL renderer string: Mesa DRI Intel(R) HD Graphics 620 (Kaby Lake GT2)
OpenGL core profile version string: 4.5 (Core Profile) Mesa 17.3.5
OpenGL core profile shading language version string: 4.50
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile
OpenGL core profile extensions:
OpenGL version string: 3.0 Mesa 17.3.5
OpenGL shading language version string: 1.30
OpenGL context flags: (none)
OpenGL extensions:
OpenGL ES profile version string: OpenGL ES 3.2 Mesa 17.3.5
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.20
OpenGL ES profile extensions:
在X.Org上,这种行为略有不同(我可以移动鼠标,但一切都没有响应),但存在相同的潜在冻结问题。
狂野的 一个有根据的猜测,主要是基于这个事实,你在英特尔图形上,将是,没有发出适当的缓冲交换命令。英特尔驱动程序有点烦人,因为它们完全依赖缓冲区交换来刷新和同步表示队列。
我认为发生的事情是,你的渲染循环没有节流运行,并且每个显示刷新间隔推送大量帧。但是,如果你要求双缓冲窗口,为什么会发生这种情况呢?答案:Wayland。 Wayland模型(实际上很有意义!)是,客户端渲染到屏幕外表面,由合成器管理,合成器本身负责执行“组合”(因此得名),即将所有内容放在屏幕上并与显示屏同步。但是,要使其工作,客户端的渲染结果必须在合成开始之前就绪。
显然,屏幕外表面不会交换,因此任何“缓冲交换”或同步请求都必须转发给合成器。如果这不能正常工作,麻烦就开始了。
只有一个过程不断推动帧,它有点受限;但是有几个进程填充队列,看起来大多数GPU时间都被客户端消耗掉了,而Compositor缺乏更改以插入可以刷新/同步表示队列的缓冲区交换。
要快速检查,请在usleep(20000)
之后添加SDL_RenderPresent
。
以上是关于运行SDL程序的第二个实例会导致系统范围冻结的主要内容,如果未能解决你的问题,请参考以下文章