【发布时间】:2018-03-03 19:28:32
【问题描述】:
我正在使用 SDL 制作多人游戏,但是,在某些时候,我无法同时运行它的两个实例。第一个实例运行没有问题,但是,一旦启动第二个实例,它的渲染线程就会挂起。它表现为系统范围的图形冻结,例如我无法再移动鼠标,并且屏幕上的任何内容都不会在 SDL 窗口内部或外部更新。几秒钟后,渲染线程恢复只是暂时再次冻结。如果我已发送退出事件并退出,SDL 确实设法捕捉到退出事件。然后,带有程序标准输出的终端窗口被更新(这就是我可以假设更新线程运行正常的方式,只有它的调试信息存在的间隔很大)。
通过从渲染过程中删除一段代码,我能够确定这三个未注释的 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 上,此行为略有不同(我可以移动鼠标,但一切都没有响应),但存在相同的潜在冻结问题。
【问题讨论】:
-
一个疯狂的问题,主要基于这样一个事实,即您使用的是英特尔显卡,将是,没有发出适当的缓冲区交换命令。英特尔驱动程序有点烦人,因为它们完全依赖缓冲区交换来刷新和同步表示队列。我猜想发生的是,您的渲染循环正在不受限制地运行,并且每个显示刷新间隔推送几帧。只需一个进程执行此操作,它的速率就会受到限制。如需快速检查,请在
SDL_RenderPresent之后添加usleep(20000)。 -
Alco 你能试试如果你(可靠地)从图片中删除 Wayland 会发生什么吗?也许您启动的 X 服务器只是作为 Xwayland 客户端运行。由于明显的原因,屏幕外表面(如 Wayland 客户端使用)没有“缓冲区交换”的合理定义,因此这些将不会看到呈现队列同步事件。
-
@datenwolf 这是一个幸运的疯狂猜测,哈哈
-
@datenwolf 你能把它作为答案发布吗?也是的,我用 X 试过了,看看我的编辑,发生了类似的事情
-
@datenwolf 另一个您可能感兴趣的事实是我启用了 SDL 的垂直同步,我认为它会做同样的事情。知道为什么会发生这种情况吗?