@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 ()?

Ответы на вопрос(1)

Ваш ответ на вопрос