RAM usage and fonts

Started by Garwin, 06 May 2022, 08:09:54

Garwin

I have tried to find some answers on the forum and in TGUI code, I think I find some of them but not all of them.

I have 6 buttons. If one of them is chosen, there is an animation playing to move not chosen buttons to left. The remaining chosen button is moved to center and enlarged (button itself and text) and than Fade animation is played.

This done through this code:
m_chosen->getRenderer()->setTextSize (30.0f*((m_chosen->getSize().x/unchosen->getSize().x-1.0f)*1.5f+1.0f));
m_chosen ... pointer to choosen button which will enlarge
unchosen ... temporary pointer to any other button to get ratio of enlarging of buttons to use it for enlargering text


I have found that starting to enlarge RAM usage goes dramatically up, practically more than doubling.

If I understand it correctly calling getRenderer() method copy Renderer. Does it mean that it copies even the font itself? If so is it possible to setTextSize differently than calling it through getRenderer()?

texus

#1
How drastically are you talking about, can you provide some numbers? Doubling can happen, but only if your program isn't using that much RAM in the first place. How are you checking usage? Tools like Window's task manager aren't accurate, they might show memory that has been reserved, not exact usage.

What is the maximum text size you are using?

Both SFML and TGUI store an image with all the character glyphs that have been loaded by the font (SFML doesn't allow me to access some internal things, so TGUI duplicates some of the memory).
When changing the texture size, all letters displayed on the button have to be loaded by the font and added to this font texture.
When the texture is full, a new texture is allocated with 4 times the size (twice the width and twice the height). This is the moment where you can see some memory growth, but it doesn't happen again until that texture is filled as well.
There is currently no way provided to clear the cached texture, it only keeps growing as long as you keep using new characters at different text sizes.

If the memory usage is due to the font, then this will only happen the first time. If you have a back button in your program and show the buttons again, clicking the same button should no longer increase memory usage, as all those characters are already loaded.

Garwin

Thanks, it gives a sense a lot. A probably better solution (I have thought about it by I tried achieved it through TGUI) is using in this case of enlarging the single remaining button sf::View.

I used task manager. I was just interested to know how much memory it uses and this behavior really surprised me.

Without this line of code (enlarging text), the memory shows constantly 40 MB with all resources loaded before the first screen. (Pictures with about 3M pixels in total and 2 fonts).

During testing of each screen, I set code to loop back to the same screen even if the button is pressed. Gui is destroyed and created again after each "leaving and reentering" same screen.
Just pressing 1 button means going from 40 to 130MB. Using everytime other button (5 in total as the last one is exit button) and task manager shows almost 600 MB used.
Pressing again same button means no change at all, exactly as you mentioned.

Just was surprised how much it increase RAM usage.

Trying to put into loop sf::sleep with 0.2s and the memory usage in same case reported by task manager decrease to 120MB as maximum.

Certainly making a lot of different font sizes is not good with SFML and TGUI. :-)

So I will use sf::View to achieve same effect.

Thanks a lot to point out about fonts being resource not being able to be released.

texus

You may also be able to use the setScale of widgets as alternative to sf::View.

An image with width and height equal to 4096 is 67MB. The next image size of 8192 pixels would consume 270MB. But I wonder if the texture really reached 8K, because even a 4K image would be hard to fill even with letters of 100 pixels.

Where you using a text size above 100?

Do you have a graphics card with dedicated VRAM, or integrated graphics where the GPU has to share RAM?

I should find some way in the future to not keep all the old glyphs around (which is tricky to do without creating unexpected stutter), or maybe I can add a function to explicitly clear the font memory (which would come with a serious performance hit when rendering the next frame). Because right now if the font texture grows too large, the GPU will no longer accept it and no more text will be rendered. The main reason I haven't fixed this yet is because luckily this is unlikely to happen realistically.

Garwin

Images are on a different screen, they are not scaled.

Only one button is scaled however each time can be different as it is always the chosen button.

The original size is 30. Scaling of a button is done up to 2.5 times and scaling of text inside is done up to 3.25 times. (button scale - 1)*1,5+1

I will try setScale. I tried resizeWithAnimation but it only scales the button without text.

Garwin

Thanks for everything, it works very nicely and RAM usage does not increase.

Just it takes me time to realize that Origin is the percentage of width and height, not coordinates.  Looking at coordinates changing right to the center but button disappearing. ;D