I have a project that I’ve converted from SDL 1.2 to 2.0. The project is a simple tiling engine. It loads a tileset as a single graphic, loads a map into a 2d array, and draws the screen based on that data.
In 1.2 I used surfaces. In 2.0 I’m trying to learn how to use textures. I’m clearly not doing it right.
The rendering loop basically looks like this:
Code:
SDL_Rect src, dest;
for (int y = 0; y < screentilesdown; y++) {
for (int x = 0; x < screentilesacross; x++) {
int tilenumber = map[y + yoffset][x + xoffset];
src.x = (tilenumber % texturetilesacross) * tilewidth;
src.y = (int)(tilenumber / texturetilesacross) * tileheight;
src.w = tilewidth;
src.h = tileheight;
dest.x = x * tilewidth;
dest.y = y * tileheight;
dest.w = src.w;
dest.h = src.h;
SDL_RenderCopy(target, tileset, &src, &dest);
if (ShowGrid) SDL_RenderCopy(target, grid, NULL, &dest);
}
}
static Uint32 framecount = 0;
Uint32 start = SDL_GetTicks();
SDL_RenderPresent(target);
fprintf(debugfile, “Frame %d Grid %s RenderPresent %d\n”, framecount++, (ShowGrid ? “ON” : “OFF”), SDL_GetTicks() - start);
“tileset” is a texture created from a surface that was loaded from a BMP file. It’s a single image that contains all of the tiles for the scene. “grid” is a single 16x16 texture that is entirely transparent except for a black line on top and a black line on the left. “map” is a 2d int array that contains the tile number to draw for each location. “ShowGrid” is toggled at runtime by pressing G on the keyboard. When true it effectively overlays a grid on the scene so you can clearly see the tile boundaries.
The issue I’m trying to solve is why I get inconsistent frame rates. I’ve put performance counters into my code and the whole thing takes less than 1ms except for SDL_RenderPresent(). This is where the inconsistencies appear.
My test runs involve a tileset with 16x16 pixel tiles being drawn onto a 1920x1080 screen (the render target). This results in a scene with 120 tiles across and 67 tiles down which is a total of 8040 tiles being drawn per update. If the grid is on then all 8040 tiles get another (mostly transparent) tile drawn over them. The grid is OFF to start.
My various tests show a huge frame rate inconsistency. The first dozen frames are all over the place, but then they smooth out. This smooth section could be good (15ms) or bad (130ms). However, after awhile, the frame rate will change, either up or down, and stay there for awhile before changing again. I’ve seen stretches of 300+ms.
In some of my tests, turning the grid ON will actually improve the frame rate dramatically. In other tests it reduces it.
Strangely enough, if I turn the grid ON during the test and then subsequently turn it back off, the frame time usually smooth out to around 15-17ms each and stays there for as long as I leave the program running. I have VSYNC turned on, so that’s where I would expect it to be.
And then, every once in awhile, my test will exhibit none of these patterns. Turning the grid ON or OFF will change the frame rate but not consistently; sometimes up, sometimes down.
All of these tests were run sequentially with no code changes whatsoever. Just shut the program down, examine the debug output, and then run it again.
I think it is clear to me that I don’t fully understand what is happening behind the scenes when I call SDL_RenderCopy() and SDL_RenderPresent(). Does anyone have any ideas on how I can figure out where my seemingly random bottlenecks are?