SDL_PollEvent () заикается во время простоя?

Я собрал очень простой игровой цикл на C++, используя SDL2, и заметил, что каждые несколько секунд 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. Это мое отставание: SDL_PollEvent () заикается во время простоя?

С помощью Vsync. Обратите внимание, что дельта, следующая за запаздыванием, немного короче. Не знаю почему: SDL_PollEvent () заикается во время простоя?

Я также заметил, что эта проблема возникает, даже если я не занимаюсь отладкой, и ее нет хотя бы на одном другом компьютере. Любые предложения о том, как действовать дальше, будут очень приветствоваться.

РЕДАКТИРОВАТЬ 1: Пытался распечатать для консоли все события, проходящие через очередь, чтобы узнать, не вызвало ли одно из них проблему. В приведенный выше код добавлена ​​строка печати. Казалось, что никакие события не запускаются в то время, когда была задержка, а в остальном я бездействовал.

Обновлено еще раз: По запросу, некоторый исполняемый код, созданный с помощью 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 влияет заикание.

  1. Увеличение deltaTime, которое совпадает с заиканием, похоже, происходит где-то во время SDL_PollEvent, о чем свидетельствует то, где назначается deltaTime

  2. Первый 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 на консоли был получен следующий вывод: SDL_PollEvent () заикается во время простоя?

РЕДАКТИРОВАТЬ 4: БОЛЬШЕ ДАННЫХ. Похоже, что заикание происходит каждые 3000 мс почти точно. У меня на консоли были только дельты, которые были> 50 мс. Формат изображения: # циклов игрового цикла | deltaTime | SDL_GetTicks () SDL_PollEvent () заикается во время простоя?

Я также считал, что это аппаратная проблема, так как у меня нет этой проблемы на другой машине, и я также загрузил несколько других игр SDL с открытым исходным кодом и испытываю то же заикание, с разницей в 3000 мс. Я также наблюдаю ту же проблему на одном и том же оборудовании как в Windows 10, так и в Windows 7. Я не собираюсь публиковать свои спецификации, если кто-то не считает это необходимым, но я уже исключил возможность ошибки моего выделенного графического процессора, увидев то же самое. точная проблема при запуске игры через RDP с удаленным графическим процессором.

РЕДАКТИРОВАТЬ 5: Похоже, задержка как-то связана с USB-устройствами. Выполняет ли SDL поиск всех устройств каждые 3000 мс или что-то в этом роде?

После установки графического процессора обратно в машину я заметил, что задержка значительно снизилась, и я заметил, что единственное отличие от того, что было до и после, заключалось в том, что моя USB-гарнитура больше не была подключена.

Думая, я снова запустил цикл, на этот раз наблюдая за любым deltaTime более 3 мс. Я наблюдал за изменениями консоли по мере удаления устройств: SDL_PollEvent () заикается во время простоя?

Эврика! Вроде, как бы, что-то вроде. При отсутствии подключенных USB-устройств deltaTime постоянно оставался ниже 3 мс. Вторичная машина, на которой я тестировал, была ноутбуком, и поэтому к ней не было подключено никаких USB-устройств. Я вернулся и протестировал ее с той же USB-мышью, и, как и ожидалось, я заметил заметное заикание каждые 3000 мс.

Итак, текущий вопрос: как USB-устройства могут вызывать такое заикание? Что делает SDL каждые 3000 мс, что связано с (а) USB-устройствами и (б) SDL_RenderPresent ()?

Почему вы думаете, что заикание вызывает PollEvent, а не, например, RenderPresent? Можете ли вы сделать минимальный полный пример, который другие могут проверить на своих машинах (и отредактировать его в вопросе)? Вы уверены, что замедление происходит не из-за printf / cout?

keltar 06.12.2018 15:05

Я переместил свой таймер deltaTime так, чтобы он окружал только цикл SDL_PollEvent, и получил аналогичные результаты с консолью. Когда я переместил свои таймеры, чтобы исключить цикл SDL_PollEvent, консоль показывала стабильную дельту, но у меня все еще появлялось заикание. Попробую скинуть то, что есть, и обновить.

Aaron Schultheis 06.12.2018 15:29

@keltar Вопрос был обновлен запрошенным кодом.

Aaron Schultheis 06.12.2018 16:02

Что-нибудь изменится, если вы перейдете в полноэкранный режим (например, полноценный полноэкранный режим SDL_WINDOW_FULLSCREEN с изменением режима, а не окно без полей размером с рабочий стол) вместо окна?

genpfault 06.12.2018 19:04

Никаких изменений для разных типов окон, но я собираюсь немного обновить сообщение. Похоже, это как-то связано с USB-устройствами.

Aaron Schultheis 06.12.2018 19:41
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
16
5
1 494
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я до сих пор не уверен, что именно вызывает проблему, но это определенно связано с USB-устройствами. Чем больше подключено устройств, тем дольше всплеск задержки, и он происходит точно каждые 3000 мс.

Я откатился с SDL2-2.0.9 на SDL2-2.0.8, и проблема исчезла.

Обновлено: набор изменений, найденный в https://hg.libsdl.org/SDL/rev/9091b20040cf, похоже, решает эту проблему в SDL2-2.0.9.

Я предлагаю отправить отчет об ошибке регрессии.

HolyBlackCat 06.12.2018 21:08
bugzilla.libsdl.org/show_bug.cgi?id=4417 для тех, кто идет домой.
genpfault 06.12.2018 21:38

@genpfault Похоже, это исправление решает проблему. Добавлю к ответу.

Aaron Schultheis 07.12.2018 19:42

Это связано с количеством подключенных USB-устройств ?! Какого черта? Это сводило меня с ума довольно долгое время. Переключили язык и библиотеку игры, и это продолжало происходить. Большое спасибо за то, что сузили этот вопрос!

Stephen 01.02.2019 01:01

Я думал, что схожу с ума, часами отлаживая странные заикания сегодня вечером. Вернулся с v2.0.9 на v2.0.7, и проблема исчезла и для меня. Им действительно нужно выпустить v2.0.10 с вашим исправлением опроса джойстика в нем.

Sean Werkema 25.06.2019 03:48

омфг. кто в здравом уме одобрил 2.0.9. количество нелепых ошибок, которые вы должны выследить, чтобы найти еще более нелепый ответ / решение, просто ошеломляет. спасибо OP за подсказку, это не давало мне уснуть всю ночь!

LilaQ 23.07.2019 06:00

Другие вопросы по теме