15
\$\begingroup\$

I'm using SDL 2 to create a small 2D game. Based on the docs, this is what I would do:

 SDL_Surface *surface = SDL_LoadBMP("image.bmp");
 SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
 SDL_FreeSurface(surface);
 ...
 SDL_RenderCopy(renderer, texture, NULL, &dest);

Since I have every single sprite in a different bmp, this would cause hundreds of texture objects to be created.

Another solution would be to create a single SDL_Surface based on all the bmp files, create a single texture object from it and then blit it with something like this:

SDL_RenderCopy(renderer, texture, &src, &dest);

I use src to select the sprite I'm interested into blitting.

I know SDL 2 takes advantage of 3D acceleration and I'm not an expert of 3D graphics programming, but I do know that selecting the current texture is an operation that is very expensive. However, I'm not sure that a SDL texture is translated into a real Texture.

So my question is: are these 2 approaches the same in terms of performance, when using SDL 2?

\$\endgroup\$
  • 4
    \$\begingroup\$ Maybe try both and measure the performances? \$\endgroup\$ – sam hocevar Oct 21 '14 at 14:23
  • \$\begingroup\$ @bummzack I don't know enough about the topic to create a valid benchmark. For example I don't know what is a significant texture size or how many textures are needed to start spotting differences. \$\endgroup\$ – Emiliano Oct 21 '14 at 18:02
17
+200
\$\begingroup\$

The short answer: Using one big texture atlas will probably be faster and should definitely not be slower than multiple small textures and here is why:

After taking a look at the SDL source code i can see that SDL supports a bunch of renderers (OpenGL, Gles2, Psp, D3D ...) and (except the software one) all of them are implemented in the same fashion:

1:BindTexture, 2:SetShader, 3:DrawQuadWithGPU

The performance difference will be given by the renderer you choose(or SDL chose), so first one, for software renderer there should be no performance difference!

With the other renderers the problem is more complex and there are too many factors to be taken into account (drivers, platform, API implementation, batching, and so on)

In general it is faster to use one big texture because in certain cases, switching the textures often (BindTexture step described above) can break the performance so it is a general practice to put all the data in as few textures as you can so you cam minimize the texture changes in the GPU. It is important however to take advantage of this and if you have textures A and B to be rendered to the screen render as much content as you can with A and then B, otherwise if you constantly switch between drawing stuff from A then B (then A then B then A and so on) it might decrease the performance. If the OpenGL implementation on the platform you are using is smart and the BindTexture step can notice that you are using one texture you will defensively see a performance increase. Also as a side note, i see no evidence of any batching done internally by SDL so you have to do this yourself.

And why is switching the textures slow?

It depends on the platform and driver implementation but in general the GPU's can process massive amounts of data without interruption and when you tell the GPU to use a new texture on each draw that causes the GPU to stop and wait for all the previous tasks to end.

\$\endgroup\$
3
\$\begingroup\$

Because this game is 2D and I doubt you'd hit the limit of VRAM and unless you are swapping through thousands of textures, I don't think it makes much difference.

There are benefits and drawbacks to both:

  • Packed textures are easier to manage and can be smaller on disk (potentially in VRAM) however require math to extract the correct sub texture.
  • Individual textures can be easier to deal with as you can simply assign a texture to an object and not worry about it requiring cropping. However, there is a small performance degradation (again most likely negligible) due to the amount of parsing required for many images, and like you said, switching (again, negligible).
  • Also, for things like animations, its usually easy to create strips as you can simply scroll through the image

Ultimately, it's up to you on whichever you think is easiest. Performance is not likely an issue.

\$\endgroup\$
1
\$\begingroup\$

Just like Raxvan said, generally a single large texture is the optimal way, but that does not mean you have to choose between either, at least as far as your assets go - it's not extremely difficult to write a texture packer that takes a number of images, and packs them into one or more larger textures, with a by-name or by-index lookup.

Depending on how much and how you have coded so far, it might be relatively simple to write a function set to pack your images into one texture atlas, and then just draw portions of the bigger image.

\$\endgroup\$
1
\$\begingroup\$

Short answer: probably not. Look here https://hg.libsdl.org/SDL/file/704a0bfecf75/src/render to see that there are implementations of generating real textures.

It depends on devices you are targetting. When current texture is being changed you call it a change of context on graphics card. It may work worse on mobile phones to often change texture, especially the older ones.

So generally it's best to have one big texture if possible. If you have more big textures then there starts the optimization part - sprites on texture should be grouped by usage.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.