c – SDL_PollEvent()空闲时口吃?
作者:互联网
我使用SDL2在C中拼凑了一个非常基本的游戏循环,我注意到每隔几秒,SDL_PollEvent似乎异常缓慢,即使什么也没发生.
我发送deltaTime来控制每个循环,它在SDL_PollEvent滞后的周期上差不多100ms.我已经通过移动我的计时器确认了这个功能,但我不确定在哪里进一步诊断问题.
我的循环:
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;
}
我也注意到即使我没有调试也会发生这个问题,而且至少还有一台其他机器没有.任何有关如何进行的建议都将非常受欢迎.
编辑1:尝试打印以控制通过队列的所有事件,以查看其中一个是否导致问题.在上面的代码中添加了打印行.在有滞后的时候似乎没有发生任何事件,而我却无所事事.
编辑2:根据要求,一些可运行的代码,使用带有SDL2-2.0.9的VS2017上的c 14构建:
#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:多挖一点.试图仅在SDL_RenderPresent周围移动我的delta任务.
示例代码段:
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毫秒.图像格式为:游戏循环周期数| deltaTime | SDL_GetTicks()
我也认为这是一个硬件问题,因为我没有在另一台机器上遇到这个问题,而且我还下载了一些其他开源SDL游戏,并且遇到了相同的口吃,相距3000毫秒.我也在Windows 10和Windows 7中的相同硬件上也看到了相同的问题.除非有人认为有必要,否则不会发布我的规格,但我已经通过查看相同的内容消除了我的专用GPU出错的可能性在删除GPU的情况下通过RDP运行游戏时的确切问题.
编辑5:看起来滞后与USB设备有关. SDL是否每3000毫秒或其他东西查找所有设备?
将我的GPU重新放回机器后,我注意到滞后显着下降,我注意到之前和之后的唯一区别是我的USB耳机不再插入.
在预感中,我再次运行循环,这次观察任何deltaTime超过3ms.当我移除设备时,我看到了控制台的更改:
找到了!有点.在没有插入USB设备的情况下,deltaTime始终保持在3ms以下.我测试的辅助机器是一台笔记本电脑,因此没有插入USB设备.我回去了,用相同的USB鼠标进行了测试,正如预期的那样,我每3000毫秒看到一个明显的口吃.
因此,目前的问题是:USB设备如何导致这种口吃? SDL与(a)USB设备和(b)SDL_RenderPresent()相关的每3000ms做什么?
解决方法:
我仍然不确定究竟是什么导致了这个问题,但它肯定与USB设备有关.插入的设备越多,延迟时间越长,几乎每隔3000毫秒就会出现这种情况.
我从SDL2-2.0.9回滚到SDL2-2.0.8,问题已经停止.
编辑:在https://hg.libsdl.org/SDL/rev/9091b20040cf找到的变更集似乎解决了SDL2-2.0.9中的此问题.
标签:sdl-2,c,sdl,game-engine 来源: https://codeday.me/bug/20190926/1818794.html