简单的sdl游戏非常慢,而cpu为1.2%

时间:2017-12-13 18:38:42

标签: c performance rendering sdl frame

我写了一个简单的2d平铺游戏并在2台计算机上运行。在comp1上它非常慢,在comp2它的快速闪电。

Comp1的cpu有点慢,但它可以玩其他sdl游戏(甚至在emulaters中)和简单的3D游戏,足够快。

所以我只使用cpu渲染在两台计算机上运行游戏:两者都以相同的速度运行。 然后我切换到gpu渲染,第二台计算机运行速度非常快(200 + fps),但第一台计算机以相同的速度运行,大约20fps。

所以我假设hw加速不能在comp1上运行,或者cpu被我的计算阻塞了。

我记录了所有错误处理并且可以确认两台计算机都支持hw加速度和纹理大小(我知道这是因为游戏的cpu绑定版本没有翻转,因此角色总是面向相同的方式; )

那么它必须是第一台计算机上的慢CPU,对吧?但是当我检查cpu统计数据时,游戏只需要1,2%的cpu,整体负载大约是2%cpu

所以当我的游戏爬行时,cpu大部分处于空闲状态:(

游戏现在只有几千行代码,所以这里有一些我认为与这个问题有关的陈述:

主游戏循环:

while (!quit)
{

    GameEngine_Tick(gameType->fps, false, 0);

    if (SDL_PollEvent(&event) != 0))
    {
        int windowID = event.window.windowID;

        if (event.window.event == SDL_WINDOWEVENT_CLOSE &&
            event.window.windowID == screens[0].windowID) quit = true;

        switch (event.type)
        {
        case SDL_KEYDOWN:

            if (event.key.keysym.sym == SDLK_LEFT)  { Key_Left(); }
            if (event.key.keysym.sym == SDLK_RIGHT) { Key_Right();}
            if (event.key.keysym.sym == SDLK_UP)    { Key_Up(); }
            if (event.key.keysym.sym == SDLK_DOWN)  { Key_Down(); }
            break;  // end key_down.
        } // switch event type
    }

    GameEngine_Render();

   }

GameEngine_Tick中的帧速率限制:

void GameEngine_Tick(int fps, bool bIsRegTestStep, Uint8 TDir)
{
unsigned int frametime = 1000 / fps;
unsigned int currentTime;

const Uint8* keystates = SDL_GetKeyboardState(NULL); // do not free.

SDL_PumpEvents(); // upd keystates to get keyboard inputs.

    // Get KB input - todo: later GetInputFromSelectedInputDevice (checks kb/xbox etc)
    if (keystates[SDL_SCANCODE_LEFT])  GameLeft();
    else if (keystates[SDL_SCANCODE_RIGHT]) GameRight();

Sprites_Tick();

// set framerate by waiting if needed.
currentTime = SDL_GetTicks();
if (currentTime - prevTime < (frametime))
{
    //Sleep the remaining frame time 
    if (fps > 0) SDL_Delay((frametime)-(currentTime - prevTime)); /* fps-1 == MAX == no delay*/
}
prevTime = currentTime;

}

创建渲染器:

ren = nullptr;
if (bForceCPURender == false) ren = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);// | SDL_RENDERER_PRESENTVSYNC);
if (nullptr == ren)
{
    if (bForceCPURender == false)
    {
        Log("Info: SDL_CreateRenderer with SDL_RENDERER_ACCELERATED failed. Trying default.");
    }
    bForceCPURender = true;

    ren = SDL_CreateRenderer(window, -1, 0);
    if (nullptr == ren)
    {
        Log("Info: SDL_CreateRenderer with default also failed.");
        SDLDestroy();
        return -1;
    }
    else Logs("Info: success using default renderer.");
}
else Logs("Info: success, using SDL_CreateRenderer with SDL_RENDERER_ACCELERATED.");

创建纹理或曲面:

spriteMapTexture = SDL_CreateTexture(ren, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET,
    x_pixPerCharInStageMap * roomWidthInChars  * gameRoomMatrix_w,
    y_pixPerCharInStageMap * roomHeightInChars * gameRoomMatrix_h);

// If GPU cannot handle size of stage map: try to do CPU preRendering. (gpu is texture, cpu is surface).
if (NULL == spriteMapTexture || bForceCPUStageRenderAnyway == true)
{
        spriteMapSurface = GameEngine_CreateRGBSurface(x_pixPerCharInStageMap * roomWidthInChars  * gameRoomMatrix_w, y_pixPerCharInStageMap * roomHeightInChars * gameRoomMatrix_h);
}

1 个答案:

答案 0 :(得分:2)

while (!quit)
{
    GameEngine_Tick(gameType->fps, false, 0);

    if (SDL_PollEvent(&event) != 0))
    ^^ wat
    {
        // process event
    }

    GameEngine_Render();
}

现在你只是每帧处理一个事件。以前SDL只能缓冲128个事件才能丢弃它们,现在我认为它们可以达到64k。因此,例如,如果你有一个高报告率的游戏鼠标(500-1000赫兹采样),你的事件队列将比常规鼠标(125赫兹)更快地备份。对于SDL可以生成的任何其他事件类型也是如此;某些系统的事件生成率与其他系统不同。

您希望在渲染帧之前处理队列中的每个事件:

while (!quit)
{
    GameEngine_Tick(gameType->fps, false, 0);

    // NOTE: if -> while
    while( SDL_PollEvent(&event) )
    {
        // process event
    }

    GameEngine_Render();
}