其他分享
首页 > 其他分享> > c – SDL_PollEvent()空闲时口吃?

c – SDL_PollEvent()空闲时口吃?

作者:互联网

我使用SDL2在C中拼凑了一个非常基本的游戏循环,我注意到每隔几秒,SDL_PollEvent似乎异常缓慢,即使什么也没发生.

我发送deltaTime来控制每个循环,它在SDL_PollEvent滞后的周期上差不多100ms.我已经通过移动我的计时器确认了这个功能,但我不确定在哪里进一步诊断问题.

我的循环:

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.这是我的滞后:No Vsync console output

使用Vsync.请注意,滞后后的增量略短.不确定原因:Vsync console output

我也注意到即使我没有调试也会发生这个问题,而且至少还有一台其他机器没有.任何有关如何进行的建议都将非常受欢迎.

编辑1:尝试打印以控制通过队列的所有事件,以查看其中一个是否导致问题.在上面的代码中添加了打印行.在有滞后的时候似乎没有发生任何事件,而我却无所事事.

编辑2:根据要求,一些可运行的代码,使用带有SDL2-2.0.9的VS2017上的c 14构建:

#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周围移动我的delta任务.

示例代码段:

    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后,获得以下控制台输出:Console output vsync delta on render

编辑4:更多数据.看起来口吃几乎完全是每3000毫秒发生的.我的控制台输出只是>的增量50毫秒.图像格式为:游戏循环周期数| deltaTime | SDL_GetTicks()
just bad deltas

我也认为这是一个硬件问题,因为我没有在另一台机器上遇到这个问题,而且我还下载了一些其他开源SDL游戏,并且遇到了相同的口吃,相距3000毫秒.我也在Windows 10和Windows 7中的相同硬件上也看到了相同的问题.除非有人认为有必要,否则不会发布我的规格,但我已经通过查看相同的内容消除了我的专用GPU出错的可能性在删除GPU的情况下通过RDP运行游戏时的确切问题.

编辑5:看起来滞后与USB设备有关. SDL是否每3000毫秒或其他东西查找所有设备?

将我的GPU重新放回机器后,我注意到滞后显着下降,我注意到之前和之后的唯一区别是我的USB耳机不再插入.

在预感中,我再次运行循环,这次观察任何deltaTime超过3ms.当我移除设备时,我看到了控制台的更改:
USB device impact

找到了!有点.在没有插入USB设备的情况下,deltaTime始终保持在3ms以下.我测试的辅助机器是一台笔记本电脑,因此没有插入USB设备.我回去了,用相同的USB鼠标进行了测试,正如预期的那样,我每3000毫秒看到一个明显的口吃.

因此,目前的问题是:USB设备如何导致这种口吃? SDL与(a)USB设备和(b)SDL_RenderPresent()相关的每3000ms做什么?

解决方法:

我仍然不确定究竟是什么导致了这个问题,但它肯定与USB设备有关.插入的设备越多,延迟时间越长,几乎每隔3000毫秒就会出现这种情况.

我从SDL2-2.0.9回滚到SDL2-2.0.8,问题已经停止.

编辑:在https://hg.libsdl.org/SDL/rev/9091b20040cf找到的变更集似乎解决了SDL2-2.0.9中的此问题.

标签:sdl-2,c,sdl,game-engine
来源: https://codeday.me/bug/20190926/1818794.html