SDL_PollEvent() 空闲时口吃?
SDL_PollEvent() stuttering while idle?
我使用 SDL2 在 C++ 中拼凑了一个非常基本的游戏循环,我注意到每隔几秒,SDL_PollEvent 似乎异常缓慢,即使什么都没有发生。
我发送了 deltaTime 来控制每个循环,SDL_PollEvent 滞后的循环大约有 100 毫秒的差异。我已经通过移动我的计时器确认它与此功能有关,但我不确定在哪里进一步诊断问题。
我的循环:
while (!quit) {
uint32_t startTime = SDL_GetTicks();
while (SDL_PollEvent(&e) != 0) {
std::cout << "Event: "<< e.type << std::endl; // Added later, read update
if (e.type == SDL_QUIT) {
quit = true;
}
}
if (engine.AllowUpdate()) { // Restricts updates to every 20ms
GameState::Update();
}
engine.rMan.BeginRender();
//^v Literally just SDL_RenderClear and SDL_RenderPresent
engine.rMan.FinishRender();
engine.deltaTime = SDL_GetTicks() - startTime;
std::cout << std::setw(10) << engine.deltaTime;
}
没有 Vsync 的控制台输出,注意 106。这是我的延迟:
使用垂直同步。请注意,滞后后的增量稍短。不知道为什么:
我还注意到即使我没有调试也会发生这个问题,并且至少在其他一台机器上没有出现。非常欢迎任何关于如何进行的建议。
编辑 1:尝试打印以控制正在通过队列的所有事件,以查看是否其中之一导致了问题。在上面的代码中添加了打印行。在有滞后的时候似乎没有事件触发,否则我就闲着了。
编辑 2:根据要求,一些可运行的代码,使用 C++14 在 VS2017 上使用 SDL2-2.0.9 构建:
#include <iostream>
#include <SDL.h>
void InitSDL();
void BuildWindow();
void BuildRenderer();
SDL_Window* window;
SDL_Renderer* renderer;
int main(int argc, char* args[]) {
InitSDL();
BuildWindow();
BuildRenderer();
bool quit = false;
uint32_t deltaTime = 0;
while (!quit) {
uint32_t startTime = SDL_GetTicks();
SDL_Event e;
while (SDL_PollEvent(&e) != 0) {
if (e.type == SDL_QUIT) {
quit = true;
}
}
deltaTime = SDL_GetTicks() - startTime;
std::cout << deltaTime << std::endl;
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
return 0;
}
void InitSDL() {
Uint32 flags = SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTS;
SDL_Init(flags);
}
void BuildWindow() {
window = SDL_CreateWindow
("SDL Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
800, 600, NULL);
}
void BuildRenderer() {
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC);
}
在整理这些内容时,我注意到了一些事情:
1.没有SDL_RenderPresent就没有出现卡顿经过仔细检查,情况似乎并非如此,但是,SDL_RenderPresent似乎受到了卡顿的影响。
与卡顿同时发生的 deltaTime 的增加似乎发生在 SDL_PollEvent 期间的某处,如分配 deltaTime 的位置所证明的那样
第一个 deltaTime 总是更长,但我怀疑这与启动时触发的一些默认事件有关。
编辑 3:进行了更多挖掘。试图将我的 delta 赋值移动到 SDL_RenderPresent 周围。
示例片段:
SDL_Event e;
while (SDL_PollEvent(&e) != 0) {
std::cout << "Event: "<< e.type << std::endl;
if (e.type == SDL_QUIT) {
quit = true;
}
}
uint32_t startTime = SDL_GetTicks();
//SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
//SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
deltaTime = SDL_GetTicks() - startTime;
std::cout << deltaTime << std::endl;
启用垂直同步后,得到以下控制台输出:
编辑 4:更多数据。看起来卡顿几乎每 3000 毫秒就会发生一次。我让控制台输出的只是大于 50 毫秒的增量。图片中的格式是:# of game loop cycles |增量时间 | SDL_GetTicks()
我也认为这是一个硬件问题,因为我在另一台机器上没有遇到这个问题,而且我还下载了一些其他开源 SDL 游戏并且遇到了同样的卡顿,3000 毫秒分开。我也在 Windows 10 和 Windows 7 中的相同硬件上看到相同的问题。除非有人认为有必要,否则我不会 post 我的规格,但我已经消除了当 运行 在移除我的 GPU 的情况下通过 RDP 进行游戏时,我的专用 GPU 可能会出现同样的问题。
编辑 5:看起来延迟与 USB 设备有关。 SDL 是否每 3000 毫秒或其他时间对所有设备进行一次查找?
将我的 GPU 放回我的机器后,我注意到延迟明显下降,我注意到之前和之后的唯一区别是我的 USB 耳机不再插入。
凭直觉,我再次 运行 我的循环,这次观察任何超过 3 毫秒的 deltaTime。我在删除设备时观察了控制台的变化:
尤里卡!有点。在没有插入 USB 设备的情况下,deltaTime 始终保持在 3 毫秒以下。我测试的第二台机器是笔记本电脑,因此没有插入 USB 设备。我回去用相同的 USB 鼠标对其进行测试,正如预期的那样,我每 3000 毫秒就会看到明显的卡顿。
所以当前的问题是:USB 设备如何导致这种卡顿? SDL 每 3000 毫秒执行与 (a) USB 设备和 (b) SDL_RenderPresent() 相关的什么?
我仍然不确定到底是什么导致了这个问题,但它肯定与 USB 设备有关。插入的设备越多,延迟峰值就越长,几乎每 3000 毫秒就会发生一次。
我从SDL2-2.0.9回滚到SDL2-2.0.8,问题已经停止。
编辑:在 https://hg.libsdl.org/SDL/rev/9091b20040cf 找到的变更集似乎解决了 SDL2-2.0.9 中的这个问题。
我使用 SDL2 在 C++ 中拼凑了一个非常基本的游戏循环,我注意到每隔几秒,SDL_PollEvent 似乎异常缓慢,即使什么都没有发生。
我发送了 deltaTime 来控制每个循环,SDL_PollEvent 滞后的循环大约有 100 毫秒的差异。我已经通过移动我的计时器确认它与此功能有关,但我不确定在哪里进一步诊断问题。
我的循环:
while (!quit) {
uint32_t startTime = SDL_GetTicks();
while (SDL_PollEvent(&e) != 0) {
std::cout << "Event: "<< e.type << std::endl; // Added later, read update
if (e.type == SDL_QUIT) {
quit = true;
}
}
if (engine.AllowUpdate()) { // Restricts updates to every 20ms
GameState::Update();
}
engine.rMan.BeginRender();
//^v Literally just SDL_RenderClear and SDL_RenderPresent
engine.rMan.FinishRender();
engine.deltaTime = SDL_GetTicks() - startTime;
std::cout << std::setw(10) << engine.deltaTime;
}
没有 Vsync 的控制台输出,注意 106。这是我的延迟:
使用垂直同步。请注意,滞后后的增量稍短。不知道为什么:
我还注意到即使我没有调试也会发生这个问题,并且至少在其他一台机器上没有出现。非常欢迎任何关于如何进行的建议。
编辑 1:尝试打印以控制正在通过队列的所有事件,以查看是否其中之一导致了问题。在上面的代码中添加了打印行。在有滞后的时候似乎没有事件触发,否则我就闲着了。
编辑 2:根据要求,一些可运行的代码,使用 C++14 在 VS2017 上使用 SDL2-2.0.9 构建:
#include <iostream>
#include <SDL.h>
void InitSDL();
void BuildWindow();
void BuildRenderer();
SDL_Window* window;
SDL_Renderer* renderer;
int main(int argc, char* args[]) {
InitSDL();
BuildWindow();
BuildRenderer();
bool quit = false;
uint32_t deltaTime = 0;
while (!quit) {
uint32_t startTime = SDL_GetTicks();
SDL_Event e;
while (SDL_PollEvent(&e) != 0) {
if (e.type == SDL_QUIT) {
quit = true;
}
}
deltaTime = SDL_GetTicks() - startTime;
std::cout << deltaTime << std::endl;
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
return 0;
}
void InitSDL() {
Uint32 flags = SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTS;
SDL_Init(flags);
}
void BuildWindow() {
window = SDL_CreateWindow
("SDL Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
800, 600, NULL);
}
void BuildRenderer() {
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC);
}
在整理这些内容时,我注意到了一些事情:
1.没有SDL_RenderPresent就没有出现卡顿经过仔细检查,情况似乎并非如此,但是,SDL_RenderPresent似乎受到了卡顿的影响。
与卡顿同时发生的 deltaTime 的增加似乎发生在 SDL_PollEvent 期间的某处,如分配 deltaTime 的位置所证明的那样
第一个 deltaTime 总是更长,但我怀疑这与启动时触发的一些默认事件有关。
编辑 3:进行了更多挖掘。试图将我的 delta 赋值移动到 SDL_RenderPresent 周围。
示例片段:
SDL_Event e;
while (SDL_PollEvent(&e) != 0) {
std::cout << "Event: "<< e.type << std::endl;
if (e.type == SDL_QUIT) {
quit = true;
}
}
uint32_t startTime = SDL_GetTicks();
//SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
//SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
deltaTime = SDL_GetTicks() - startTime;
std::cout << deltaTime << std::endl;
启用垂直同步后,得到以下控制台输出:
编辑 4:更多数据。看起来卡顿几乎每 3000 毫秒就会发生一次。我让控制台输出的只是大于 50 毫秒的增量。图片中的格式是:# of game loop cycles |增量时间 | SDL_GetTicks()
我也认为这是一个硬件问题,因为我在另一台机器上没有遇到这个问题,而且我还下载了一些其他开源 SDL 游戏并且遇到了同样的卡顿,3000 毫秒分开。我也在 Windows 10 和 Windows 7 中的相同硬件上看到相同的问题。除非有人认为有必要,否则我不会 post 我的规格,但我已经消除了当 运行 在移除我的 GPU 的情况下通过 RDP 进行游戏时,我的专用 GPU 可能会出现同样的问题。
编辑 5:看起来延迟与 USB 设备有关。 SDL 是否每 3000 毫秒或其他时间对所有设备进行一次查找?
将我的 GPU 放回我的机器后,我注意到延迟明显下降,我注意到之前和之后的唯一区别是我的 USB 耳机不再插入。
凭直觉,我再次 运行 我的循环,这次观察任何超过 3 毫秒的 deltaTime。我在删除设备时观察了控制台的变化:
尤里卡!有点。在没有插入 USB 设备的情况下,deltaTime 始终保持在 3 毫秒以下。我测试的第二台机器是笔记本电脑,因此没有插入 USB 设备。我回去用相同的 USB 鼠标对其进行测试,正如预期的那样,我每 3000 毫秒就会看到明显的卡顿。
所以当前的问题是:USB 设备如何导致这种卡顿? SDL 每 3000 毫秒执行与 (a) USB 设备和 (b) SDL_RenderPresent() 相关的什么?
我仍然不确定到底是什么导致了这个问题,但它肯定与 USB 设备有关。插入的设备越多,延迟峰值就越长,几乎每 3000 毫秒就会发生一次。
我从SDL2-2.0.9回滚到SDL2-2.0.8,问题已经停止。
编辑:在 https://hg.libsdl.org/SDL/rev/9091b20040cf 找到的变更集似乎解决了 SDL2-2.0.9 中的这个问题。