SDL2 tilemap - too slow

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.

Hacking a little into it, I found out that:

  • acceleration is active;
  • vsync is disabled;
  • most of the time (90%) is spent in SDL_RenderPreset.

So, how can I improve the tilemap performance?

Thank you in advance,

Andr?–
Ars longa, vita brevis, occasio praeceps, experientia fallax, iudicium
difficile.

The one thing I’d recommend is only redrawing when necessary. This means
making a image (according to your loop) 800x600, and drawing once on this
buffer, then perform a render copy/present using this buffer. Only update
the buffer when you need to redraw (like character movement, etc.) and only
update the tiles that have been changed (player moving from one tile to
another, means those two tiles get updated). So you should almost never be
doing a full redraw unless the player is scrolling the tiles (if that even
happens in your application).

Hope that helps,
-AlexOn Tue, Sep 3, 2013 at 12:49 PM, Andr? Wagner <andre.nho at gmail.com> wrote:

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.

Hacking a little into it, I found out that:

  • acceleration is active;
  • vsync is disabled;
  • most of the time (90%) is spent in SDL_RenderPreset.

So, how can I improve the tilemap performance?

Thank you in advance,

Andr?


Ars longa, vita brevis, occasio praeceps, experientia fallax, iudicium
difficile.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

What do you mean by “image”? A SDL_Surface or a SDL_Texture? Looks
like a SDL_Texture would be the way to go, but I couldn’t find any
documentation on how to copy one SDL_Texture in another…

Andr?On Tue, Sep 3, 2013 at 1:56 PM, Alex Barry <alex.barry at gmail.com> wrote:

The one thing I’d recommend is only redrawing when necessary. This means making a image (according to your loop) 800x600, and drawing once on this buffer, then perform a render copy/present using this buffer.


Ars longa, vita brevis, occasio praeceps, experientia fallax, iudicium
difficile.

I’d recommend making an SDL_surface, and convert it to a texture - then on
any updates to the surface, you can just toss it in a new texture (or there
may be a way to update a texture with a region from a surface?). If you
create it as a texture, then you could make sure it has streaming enabled
so you can read and write to it. I don’t know what sort of performance
either option gives you, but I’m sure someone here might have some
information off hand, or browse through the wiki - maybe someone has made
an article comparing those options and their pros/cons? If not, you could
do the comparison yourself and then write up an article. That would be
very useful wiki information, if not directly for SDL, I’m sure gamedev or
some similar website would appreciate the contribution.On Tue, Sep 3, 2013 at 1:01 PM, Andr? Wagner <andre.nho at gmail.com> wrote:

On Tue, Sep 3, 2013 at 1:56 PM, Alex Barry <@Alex_Barry> wrote:

The one thing I’d recommend is only redrawing when necessary. This means
making a image (according to your loop) 800x600, and drawing once on this
buffer, then perform a render copy/present using this buffer.

What do you mean by “image”? A SDL_Surface or a SDL_Texture? Looks
like a SDL_Texture would be the way to go, but I couldn’t find any
documentation on how to copy one SDL_Texture in another…

Andr?


Ars longa, vita brevis, occasio praeceps, experientia fallax, iudicium
difficile.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

El sep 3, 2013 2:02 p.m., “Andr? Wagner” <andre.nho at gmail.com> escribi?:

The one thing I’d recommend is only redrawing when necessary. This
means making a image (according to your loop) 800x600, and drawing once on
this buffer, then perform a render copy/present using this buffer.

What do you mean by “image”? A SDL_Surface or a SDL_Texture? Looks
like a SDL_Texture would be the way to go, but I couldn’t find any
documentation on how to copy one SDL_Texture in another…

Andr?

Take a look at the Render Target functionality, it’s designed so you can
render textures on other textures.> On Tue, Sep 3, 2013 at 1:56 PM, Alex Barry <alex.barry at gmail.com> wrote:

I would suggest that you move your timing printf so that it does not count
SDL_RenderPresent(). Chances are that you’ll notice most of the time being
spent in that function. The reason? Vsync. Even though you say it is
disabled, the framerate you mention seems like quite the coincidence.

Jonny DOn Tue, Sep 3, 2013 at 1:15 PM, Gabriel Jacobo wrote:

El sep 3, 2013 2:02 p.m., “Andr? Wagner” <andre.nho at gmail.com> escribi?:

On Tue, Sep 3, 2013 at 1:56 PM, Alex Barry <alex.barry at gmail.com> wrote:

The one thing I’d recommend is only redrawing when necessary. This
means making a image (according to your loop) 800x600, and drawing once on
this buffer, then perform a render copy/present using this buffer.

What do you mean by “image”? A SDL_Surface or a SDL_Texture? Looks
like a SDL_Texture would be the way to go, but I couldn’t find any
documentation on how to copy one SDL_Texture in another…

Andr?

Take a look at the Render Target functionality, it’s designed so you can
render textures on other textures.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Well, I am pretty sure vsync is enabled even if you say it isnt. exact 60 fps is not a coincidence.

try putting some high processing stuff before the render call, you will see it will still run at 60fps------------------------
Rodrigo Cardoso Rocha
@RodrigoRodrigoR - twitter.com/RodrigoRodrigoR
Chibata Creations - chibatacreations.com

This is probably because SDL_RenderPresent() is waiting for the vertical
retrace, hence the drawing is locked to 60FPS.
Consider creating setting video mode and creating a renderer yourself
(instead of just using SDL_CreateWindowAndRenderer()) , and setting it
to not wait for vertical retrace.On 9/3/2013 10:19 PM, Andr? Wagner wrote:

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.

Hacking a little into it, I found out that:

  • acceleration is active;
  • vsync is disabled;
  • most of the time (90%) is spent in SDL_RenderPreset.

So, how can I improve the tilemap performance?

Thank you in advance,

Andr?


Pallav Nawani
Game Designer/CEO
http://www.ironcode.com
Twitter: http://twitter.com/Ironcode_Gaming
Facebook: http://www.facebook.com/Ironcode.Gaming

What platform are you running on? It may be that the video driver has
vsync turned on by default even if the application doesn’t request it.On Tue, Sep 3, 2013 at 9:49 AM, Andr? Wagner <andre.nho at gmail.com> wrote:

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.

Hacking a little into it, I found out that:

  • acceleration is active;
  • vsync is disabled;
  • most of the time (90%) is spent in SDL_RenderPreset.

So, how can I improve the tilemap performance?

Thank you in advance,

Andr?


Ars longa, vita brevis, occasio praeceps, experientia fallax, iudicium
difficile.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Yes. Thank you all for your replies, I now also believe that it is the
VSYNC. Two tests proved this: I removed the tilemap copying, and added
a 5ms delay in the loop, and in both times the timing remained the
same.

My surprise was that SDL_RENDERER_PRESENTVSYNC = 0. I’m running in
Arch Linux inside a VirtualBox.

Regards,

Andr?On Wed, Sep 4, 2013 at 4:58 AM, Sam Lantinga wrote:

What platform are you running on? It may be that the video driver has vsync
turned on by default even if the application doesn’t request it.

On Tue, Sep 3, 2013 at 9:49 AM, Andr? Wagner <@Andre_Wagner> wrote:

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.

Hacking a little into it, I found out that:

  • acceleration is active;
  • vsync is disabled;
  • most of the time (90%) is spent in SDL_RenderPreset.

So, how can I improve the tilemap performance?

Thank you in advance,

Andr?


Ars longa, vita brevis, occasio praeceps, experientia fallax, iudicium
difficile.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


Ars longa, vita brevis, occasio praeceps, experientia fallax, iudicium
difficile.