Is This Algorithm Good For Texture Management?

So, i don’t know how graphics hardware works, but from SDL knowledge i know that a texture uses the memory of the GPU for faster performance. So every time i use CreateTextureFromSurface() i will probably exhaust the memory of the GPU, or if someone else makes sure to handle this i will still probably cause some performance issues.

In my game engine i have a sprite class that can have the following rules:

You can make clones of this sprite.
On scene initialization, multiple sprites can load a texture from the same path (image).
So what if n sprites load the same image? I will have n copies of the same texture? This applies also when i clone the sprite.

So this is my solution:

I will create a tree (in main memory) that will use the path (of an image) as the key. This tree will store 3 things, the path , a reference to the texture and a reference counter.

Every time a sprite tries to load a texture, first it will search in the tree to see if the path of the image is already registered. If it is then it will take a copy of the texture’s reference and it will increase the ref counter, else it will load the texture and add a new node into the tree.

Also each sprite object will have a reference to its relative node so when the sprite object is destroyed, will decrease the ref counter. When the ref counter reaches zero we delete the node from the tree and we also call SDL_DestroyTexture() to destroy the texture.

So if we have 500 sprites that uses the same image, only one texture will be rendered!
This might be similar to garbage collection but its a lot faster!!!

The only think i’m loosing is Ram (for the tree) and some speed (when i search in the tree) but still if i make sure that this tree is balanced the search algorithm will be very fast.

Also all of this will probably only happen at scene loading except when at run time the player creates clones of a sprite (like bullets from a gun).

I think this is a good solution, but because i don’t really know how textures and graphics hardware works, i want your advice.

Thanks.

On-demand loading of textures and reuse is a good idea, and it sounds like you’re doing that, but deleting it when all references are gone? If a sprite blinks or is only alive for a short time, but spawns rapidly, doesn’t this mean you’re doing a lot of loading and unloading? And I’m not understanding your tree thing, but I’m sure it’s awesome :slight_smile:

Can’t you have a simple array that stores (caches) the textures and have a zero-index for your PNGs? Sprites can then request a texture from this array each time they want to draw (also very fast). If the texture hasn’t been loaded yet, then load it and cache it.

I do something similar, and if memory allocation fails, or a texture fails to create (maybe due to GPU RAM limit) then I unload the oldest texture (that isn’t locked) until it doesn’t fail - this is the garbage collection part. It pretty much asserts that you’ll never get out of memory errors.

I was also curious about GPU memory usage, so I did some experimenting. My game has 426 PNG files, totalling 5MB. I can’t begin to imagine how many MB they expand to when all loaded? I tested my game using on-board video, and adjusted the BIOS to allocate less and less video memory. It failed when I dropped it below 32MB GPU RAM. The thing is, it failed off-the-bat. Failed to init the video. So it was quite happy loading 5mb worth of PNGs into 32MB of GPU memory. I didn’t go further and test how often it was collecting the garbage - I didn’t notice any visual stuttering at least.

Hope this helps.

Heres my suggestion

A simple container that holds your textures.

  1. You can make a copy of the texture and store it, delete from container when you change scene.

  2. Request the texture when you render / draw and don’t store it.

  3. Not every object needs to hold a texture. “FlyWeight Pattern”
    In this example you can see that the level holds the texture for all the tiles,
    rather then each tile holding its own texture.
    Tiles can be drawn by passing texture to tile draw function or the level can draw all the tiles
    based on id and or position.

struct Tile {
    int32_t id;
}

struct Level {
    std::vector<Tiles> m_tiles
    SDL_Texture *m_texture;
}