Я собрал очень простой игровой цикл в C ++ с использованием SDL2, и заметил, что каждые несколько секунд SDL_PollEvent кажется необычайно медленным, даже когда ничего не происходит.
Я отправлял свойdeltaTime для поддержки каждого цикла, и его разность составляет около 100 мс в циклах, которые запаздывает в SDL_PollEvent.Я уже подтвердил, что это что-то с этой функцией, перемещая мои таймеры, но я не уверен, где диагностировать проблему дальше.
Мой цикл:
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. Это мое отставание:
С Vsync.Обратите внимание, что дельта после лага немного короче.Не знаю, почему:
Я также заметил, что эта проблема возникает, даже если я не отлаживаю, и отсутствует по крайней мере на одном другом компьютере.Любые предложения о том, как поступить, будут очень приветствоваться.
РЕДАКТИРОВАТЬ 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: Сделал еще немного копать.Попытался переместить мое дельта-назначение только вокруг 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;
При включенном vsync получен следующий вывод консоли:
РЕДАКТИРОВАТЬ 4: БОЛЬШЕ ДАННЫХ.Похоже, заикание происходит каждые 3000 мс почти точно.У меня был вывод на консоль только дельты, которые были> 50 мс.Формат изображения: количество игровых циклов |deltaTime |SDL_GetTicks ()
Я также считал, что это аппаратная проблема, поскольку у меня нет этой проблемы на другой машине, и я также скачал несколькодругие игры с открытым исходным кодом SDL, и я испытываю то же самое заикание, на расстоянии 3000 мс.Я также вижу ту же проблему на одном и том же оборудовании как в Windows 10, так и в Windows 7. Я не собираюсь публиковать свои спецификации, если кто-то не считает это необходимым, но я уже исключил возможность ошибки моего выделенного графического процессора, увидев то же самоеТочная проблема при запуске игры через RDP с удаленным графическим процессором.
РЕДАКТИРОВАТЬ 5: Похоже, что задержка связана с USB-устройствами.Выполняет ли SDL поиск всех устройств каждые 3000 мс или что-то в этом роде?
После установки моего графического процессора обратно в компьютер я заметил, что отставание значительно уменьшилось, и я заметил, что единственное отличие до и после было в том, что мой USBгарнитура больше не была подключена.
По догадкам я снова запустил свой цикл, на этот раз, наблюдая за deltaTime более 3 мс.Я наблюдал за консолью на предмет изменений, когда убирал устройства:
Эврика!Вроде, как бы, что-то вроде.При отсутствии подключенных USB-устройств deltaTime постоянно оставалась ниже 3 мс.Вторичная машина, на которой я тестировал, была ноутбуком, и поэтому не имела подключенных USB-устройств. Я вернулся и протестировал ее с той же USB-мышью, и, как и ожидалось, каждые 3000 мс я видел заметное заикание.
Итак, текущий вопрос: как устройства USB могут вызывать такое заикание?Что делает SDL каждые 3000 мс, что связано с (а) USB-устройствами и (б) SDL_RenderPresent ()?