Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SDL2 tilemap - too slow

Tags:

c

sdl

sdl-2

I'm using SDL2 to write a game that displays a tilemap at every frame, but the performance is too slow. I wrote a little program to isolate the problem. Consider that "temp.bmp" is a 16x16 image.

#include <stdio.h>

#include "SDL2/SDL.h"
#include "SDL2/SDL_timer.h"
#include "SDL2/SDL_image.h"

int main()
{
    SDL_Window* win;
    SDL_Renderer* ren;
    int x, y;

    SDL_Init(SDL_INIT_VIDEO);
    SDL_CreateWindowAndRenderer(800, 600, 0, &win, &ren);
    SDL_Surface* sf = IMG_Load("temp.bmp");
    SDL_Texture* tx = SDL_CreateTextureFromSurface(ren, sf);

    for(;;) {
        Uint32 t = SDL_GetTicks();
        for(x=0; x<800; x+=16) {
            for(y=0; y<600; y+=16) {
                SDL_Rect src = { 0, 0, 16, 16 };
                SDL_Rect dst = { x, y, 16, 16 };
                SDL_RenderCopy(ren, tx, &src, &dst);
            }
        }
        SDL_RenderPresent(ren);
        printf("%ld ms\n", SDL_GetTicks() - t);
    }
}

Running the program, I see that it takes about 16ms to render a frame. This is exactly 60 FPS (1000/60), which leaves no room for game logic. Also, I'm running it in a pretty fast computer.

I'm pretty sure I'm using the wrong strategy, but I'm not sure what be the right one. Maybe creating a big texture and updating it less often would be the way to go, but I couldn't find any documentation on how to copy one texture over another.

So, how can I improve the tilemap performance?

like image 592
André Wagner Avatar asked Oct 22 '22 01:10

André Wagner


2 Answers

On this page it mentions that SDL_RENDERER_PRESENTVSYNC flag means you are synced to refresh rate. try this

    renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);
like image 101
dzada Avatar answered Nov 03 '22 20:11

dzada


On my system with vsync I have plenty of extra time (~15ms) before SDL_RenderPresent():

#include <stdio.h>
#include <stdlib.h>

#include <SDL2/SDL.h>
#include <SDL2/SDL_timer.h>

int main( int argc, char** argv )
{
    SDL_Window* win;
    SDL_Renderer* ren;
    int x, y;

    SDL_Init( SDL_INIT_VIDEO );

    win = SDL_CreateWindow
        ( 
        "Window", 
        SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 
        800, 600, 
        0 
        );

    ren = SDL_CreateRenderer
        ( 
        win, 
        -1,
        SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC
        );

    for(;;) 
    {
        Uint32 t = SDL_GetTicks();
        for(x=0; x<800; x+=16) 
        {
            for(y=0; y<600; y+=16) 
            {
                SDL_Rect dst = { x, y, 16, 16 };
                SDL_SetRenderDrawColor( ren, rand()%255, rand()%255, rand()%255, 255 );
                SDL_RenderFillRect( ren, &dst );
            }
        }

        // adjust this up/down to figure out how much extra time you have
        // stop when you start seeing frame times exceeding ~16ms
        SDL_Delay( 15 );

        SDL_RenderPresent(ren);
        printf("%ld ms\n", SDL_GetTicks() - t);
    }
}
like image 33
genpfault Avatar answered Nov 03 '22 22:11

genpfault