SFML community forums

Help => Graphics => Topic started by: ifinox on June 01, 2017, 10:33:41 pm

Title: sf::RenderTexture.clear() HUGE fps drop
Post by: ifinox on June 01, 2017, 10:33:41 pm
Hello. I am coding simply roguelike and I have problem with sf::RenderTexture.
Normally I have around 600-700fps, but when I add rendertexture.clear() fps drops to 200-300fps!!
This happend despite the rendertexture size - even if i set rendertexture size to 5x5 ( create(5,5) ) or 1000x1000 there would be still 200-300fps.

Any idea how to solve that?

//edit

ThatCode:
visionMaskTexture.create(6, 6);
visionMaskTexture.clear();
visionMaskTexture.create(7, 6);
visionMaskTexture.clear();
visionMaskTexture.create(8, 6);
visionMaskTexture.clear();
make game unplayable(~10fps).
Why I have such fps drop with rendertexture?
Title: Re: sf::RenderTexture.clear() HUGE fps drop
Post by: eXpl0it3r on June 01, 2017, 10:48:21 pm
Check out the following points of the forum rules (https://en.sfml-dev.org/forums/index.php?topic=5559.msg36367#msg36367). ;)
Title: Re: sf::RenderTexture.clear() HUGE fps drop
Post by: ifinox on June 01, 2017, 11:38:57 pm
Check out the following points of the forum rules (https://en.sfml-dev.org/forums/index.php?topic=5559.msg36367#msg36367). ;)

Version: SFML 2.4.0 Windows 10
Graphics : Intel HD520

Minimal Code:
#include <iostream>
#include <SFML/Graphics.hpp>

int getFramerate(sf::Clock & clock)
{
        static float lastFrameRate = 0;
        static float frameRate = 0;
        if (clock.getElapsedTime().asMilliseconds() < 1000)
        {
                frameRate++;
        }
        else
        {
                lastFrameRate = frameRate;
                frameRate = 0;
                clock.restart();
        }
        return (int)lastFrameRate;
}

int main()
{
        sf::RenderWindow window(sf::VideoMode(1280, 720), "SFML works!");
        sf::RenderTexture render;
        render.create(5, 5);
        sf::Clock framerateClock;
        while (window.isOpen())
        {
               
                sf::Event event;
                while (window.pollEvent(event))
                        if (event.type == sf::Event::Closed)
                                window.close();


                std::cout << getFramerate(framerateClock) << "fps\n";
                window.clear(); // 1300FPS
                render.clear(); // ADDING ONE CLEAR -> 500FPS

                // if we add even more clears...
                render.create(6, 6);
                render.clear();
                render.create(5, 5);
                render.clear();
                render.create(6, 6);
                render.clear();
                render.create(5, 5);
                render.clear();
                render.create(6, 6);
                render.clear();
                // :-) -> 17FPS

                window.display();
        }

        return 0;
}
Title: Re: sf::RenderTexture.clear() HUGE fps drop
Post by: eXpl0it3r on June 02, 2017, 12:07:47 am
Try upgrading to SFML 2.4.2 and make sure to test run your application in release mode and not debug mode.
Title: Re: sf::RenderTexture.clear() HUGE fps drop
Post by: ifinox on June 02, 2017, 12:24:59 pm
Try upgrading to SFML 2.4.2 and make sure to test run your application in release mode and not debug mode.
Nothing changed. If you build this minimal code and you run it you have normal fps rate? (like ~1000)
Title: Re: sf::RenderTexture.clear() HUGE fps drop
Post by: eXpl0it3r on June 02, 2017, 12:44:20 pm
The issue with your code is the recreation of the render texture. It's an expensive operation and doing so 5 times every frame will kill your performance. I don't really lose any FPS when just calling clear.

Render texture is not a cheap "resource", as such its use should be limited and at best you should create it once and then reuse it as much as possible.

Also don't forget that FPS is not linear, if you get a jump from a couple of hundred FPS down to a few hundred less, then that's not as surprising.
Title: Re: sf::RenderTexture.clear() HUGE fps drop
Post by: ifinox on June 02, 2017, 01:41:52 pm
The issue with your code is the recreation of the render texture. It's an expensive operation and doing so 5 times every frame will kill your performance. I don't really lose any FPS when just calling clear.

Render texture is not a cheap "resource", as such its use should be limited and at best you should create it once and then reuse it as much as possible.

Also don't forget that FPS is not linear, if you get a jump from a couple of hundred FPS down to a few hundred less, then that's not as surprising.

sf::RenderTexture render1;
sf::RenderTexture render2;
sf::RenderTexture render3;
sf::RenderTexture render4;
sf::RenderTexture render5;

render1.create(5, 5);
render2.create(6, 6);
render3.create(7, 7);
render4.create(8, 8);
render5.create(9, 9);

sf::Clock framerateClock;
while (window.isOpen())
{
        std::cout << getFramerate(framerateClock) << "fps\n";
        window.clear(); // 1700FPS

        // if we add even more clears...
        render1.clear();
        render2.clear();
        render3.clear();
        render4.clear();
        render5.clear();
        // FPS around 300 - ~82% framerate less
        window.display();
}
But that simply code without recreating also have huge fps drop.
More confusing is that on linux with same code I am having 1500fps
Title: Re: sf::RenderTexture.clear() HUGE fps drop
Post by: Laurent on June 02, 2017, 02:40:32 pm
It's not huge, it's less than 3 milliseconds. Don't compute the percentage, it doesn't mean anything. FPS is computed as 1/dt, it's not linear. Any program that changes from doing nothing to doing a little bit of work will show such a "drop".

Quote from: eXpl0it3r
Also don't forget that FPS is not linear, if you get a jump from a couple of hundred FPS down to a few hundred less, then that's not as surprising.
Title: Re: sf::RenderTexture.clear() HUGE fps drop
Post by: ifinox on June 02, 2017, 04:05:50 pm
Yea... But...
With this code:
int main()
{
        sf::RenderWindow window(sf::VideoMode(1280, 720), "SFML works!");
        const int size = 50;
        sf::RenderTexture render[size];
        for (int i = 0; i < size; i++)
                render[i].create(i + 1, i + 1);

        sf::Clock framerateClock;
        while (window.isOpen())
        {
                std::cout << getFramerate(framerateClock) << "fps\n";
                window.clear();
                for (int i = 0; i < size; i++)
                        render[i].clear();

                window.display();
        }

        return 0;
}

On windows10 i have 20fps but on linux i have 400fps.
Just test it yourself.
And at windows first calling clear() with RenderTexture (next calling .clear() much less but still noticeable) always take around ~50% fps.
Title: Re: sf::RenderTexture.clear() HUGE fps drop
Post by: eXpl0it3r on June 02, 2017, 05:00:33 pm
If you have 50 render texture you're doing something wrong. ;)

Don't create artificial setups that would never happen in an actually application, there is always a way to make things not perform well.

As I said before, RT are a heavy "resource" they should be handled with care and only used when really needed and then if at all possible with as few as possible.

Using a RT forces a context switch, which is a heavy operation, so yes the more you switch, the worse your performance gets. At best you just use one render texture and define the needed texture rect/position for your sprite/vertex array.