SDL_PollEvent () gagueja enquanto está ocioso?
Criei um loop de jogo muito básico em C ++ usando SDL2, e notei que, a cada poucos segundos, SDL_PollEvent parece ser extraordinariamente lento, mesmo quando nada está acontecend
Enviei meu deltaTime para consolar cada loop e sua diferença de cerca de 100ms nos ciclos em que o SDL_PollEvent está atrasado. Eu já confirmei que é algo com essa função movendo meus cronômetros, mas não tenho certeza de onde diagnosticar mais o problem
My loop:
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;
}
Saída do console sem Vsync, observe o 106. Esse é o meu atraso:
Com Vsync. Observe que o delta após o atraso é um pouco menor. Não sei por que:
Eu também notei que esse problema ocorre mesmo que eu não esteja depurando e não está presente em pelo menos uma outra máquina. Qualquer sugestão sobre como proceder será muito bem-vinda.
EDIT 1: Tentei imprimir no console todos os eventos que estavam passando na fila para ver se um deles estava causando o problema. Adicionada a linha de impressão ao código acima. Nenhum evento parecia estar disparando nos momentos em que houve atraso, e eu estava ocios
EDIT 2: Conforme solicitado, algum código executável, criado com c ++ 14 no VS2017 com 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);
}
Enquanto reunia isso, notei algumas coisas:
1. A gagueira não ocorreu sem SDL_RenderPresent Após a verificação dupla, isso não parece ser o caso, no entanto, SDL_RenderPresent parece ter sido afetado pela gagueir
O aumento no deltaTime que coincide com a gagueira parece ocorrer em algum lugar durante o SDL_PollEvent, como evidenciado por onde o deltaTime está sendo atribuído
O primeiro deltaTime é SEMPRE mais longo, embora eu suspeite que isso tenha algo a ver com alguns eventos padrão disparados na inicializaçã
EDIT 3: Fiz um pouco mais de escavação. Tentei mover minha atribuição delta apenas pelo SDL_RenderPresent.
Exemplo de trecho:
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;
Com o vsync ativado, obteve a seguinte saída do console:
EDIT 4: MAIS DADOS. Parece que a gagueira está acontecendo a cada 3000ms quase exatamente. Eu tinha o console de saída apenas os deltas que eram> 50ms. O formato da imagem é: nº de ciclos de loop do jogo | deltaTime | SDL_GetTicks ()
Eu também considerei que esse é um problema de hardware, já que não estou tendo esse problema em outra máquina e também baixei alguns outros jogos SDL de código aberto e estou enfrentando o mesmo gague, a 3000ms de distância. Também estou vendo o mesmo problema no mesmo hardware no Windows 10 e no Windows 7. Não vou postar minhas especificações, a menos que alguém ache necessário, mas já eliminei a possibilidade de falha na minha GPU dedicada ao ver o mesmo problema exato ao executar o jogo pelo RDP com minha GPU removida.
EDIT 5: Parece que o atraso tem algo a ver com dispositivos USB. O SDL faz uma pesquisa em todos os dispositivos a cada 3000ms ou algo assim?
Depois de colocar minha GPU de volta na máquina, notei que o atraso caiu significativamente e notei que a única diferença de antes e depois era que meu fone de ouvido USB não estava mais conectado.
Em um palpite, corri meu loop novamente, desta vez observando qualquer deltaTime acima de 3ms. Observei o console em busca de alterações ao remover dispositivos:
Eureka! Tipo de. Sem dispositivos USB conectados, o deltaTime permaneceu abaixo de 3ms de forma consistente. A máquina secundária em que testei era um laptop e, portanto, não havia dispositivos USB conectados. Voltei e testei-o com o mesmo mouse USB e, como esperado, vi uma gagueira perceptível a cada 3000m
Então, a pergunta atual é: como os dispositivos USB podem causar essa gagueira? O que o SDL faz a cada 3000ms relacionado a (a) dispositivos USB e (b) SDL_RenderPresent ()?