@genpfault Это исправление, похоже, решает проблему. Я добавлю это к ответу.
рал очень простой игровой цикл в 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 с моим удаленным GPU.
РЕДАКТИРОВАТЬ 5: Похоже, что лаг имеет какое-то отношение к USB-устройствам. SDL выполняет поиск всех устройств каждые 3000 мс или что-то?
После установки моего графического процессора обратно в компьютер я заметил, что задержка значительно уменьшилась, и я заметил, что единственное отличие до и после заключалось в том, что моя USB-гарнитура больше не была подключена.
По догадкам, я снова запустил свой цикл, на этот раз, наблюдая за deltaTime более 3 мс. Я наблюдал за консолью на предмет изменений при удалении устройств:
Эврика! Вроде, как бы, что-то вроде. При отсутствии подключенных USB-устройств deltaTime постоянно оставалась ниже 3 мс. Вторичная машина, на которой я тестировал, была ноутбуком, и поэтому не имела подключенных USB-устройств. Я вернулся и протестировал ее с той же USB-мышью, и, как и ожидалось, каждые 3000 мс я видел заметное заикание.
Итак, текущий вопрос: как устройства USB могут вызывать такое заикание? Что делает SDL каждые 3000 мс, что связано с (а) USB-устройствами и (б) SDL_RenderPresent ()?