Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [Solved] Ways to raise FPS  (Read 8817 times)

0 Members and 1 Guest are viewing this topic.

masskiller

  • Sr. Member
  • ****
  • Posts: 284
  • Pointers to Functions rock!
    • MSN Messenger - kyogre_jb@hotmail.com
    • View Profile
    • Email
[Solved] Ways to raise FPS
« on: September 25, 2012, 03:54:32 am »
My problem is simple, my FPS count is around 30 or less when drawing around 1000 sprites and even when drawing little as 40 or less sprites I can't get it to raise from 50 (using 60 as a maximum) no matter how much I optimize, the problem seems to get worse when I use many textures.

The entire code for the issue is a bunch of classes and files, so I doubt I could post a minimal example of it that could be analyzable in an easy way. I'll just post the main function and explain what all the objects do.

const int num = 10;
const unsigned radius = 25;

int main()
{
   sf::RenderWindow window(sf::VideoMode(800, 600), "Bullet Testing");
   sf::Event event;
   sf::Time FrameTime = sf::seconds(1.f);
   sf::Time T = sf::seconds(1.5);
   bool check = false;

   TextureHolder Hold;
   Hold.setBasicTextures();
///What the name says.

   unsigned n = 0;

   BulletPlacer Put(num, num);
///Quantity as first parameter and bullets to be used as second.
   BulletPlacer Put2(num, num);
   BulletPlacer Put3(num, num);
   BulletPlacer Put4(num, num);

   Put.setBulletProperties(Hold, sf::Color(255, 0, 0, 255), sf::Vector2f(200.f, 100.f),1.f, 1);
/// TextureHolder, Color, Position, Speed, and Type (to know which texture to use).
   Put2.setBulletProperties(Hold, sf::Color(0, 255, 0, 255), sf::Vector2f(400.f, 300.f),1.5, 7);
   Put3.setBulletProperties(Hold, sf::Color(0, 0, 255, 255), sf::Vector2f(600.f, 100.f),1.f, 2);
   Put4.setBulletProperties(Hold, sf::Color(250, 50, 120, 255), sf::Vector2f(400.f, 400.f),1.f, 3);

   Put.ShotCircleCalculate(num, radius);
///Amount of bullets to be used and radius of the circle.
   Put2.ShotCircleCalculate(num, radius);
   Put3.ShotCircleCalculate(num, radius);
   Put4.ShotCircleCalculate(num, radius);

   Put.Bit = Put.ShotList.begin();
   Put2.Bit = Put2.ShotList.begin();
   Put3.Bit = Put3.ShotList.begin();
   Put4.Bit = Put4.ShotList.begin();

   std::list<Bullet>::iterator C = Put.Bit;
   std::list<Bullet>::iterator D = Put2.Bit;
   std::list<Bullet>::iterator E = Put3.Bit;
   std::list<Bullet>::iterator F = Put4.Bit;

window.setFramerateLimit(60);

sf::Clock Time, FrameCount;
///Clocks for frame counting and controlling when to draw the second BulletPlacer.
while (window.isOpen())
    {  
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
               {
                 window.close();
                 Hold.~TextureHolder();
                 Put.~BulletPlacer();
                 Put2.~BulletPlacer();
                 Put3.~BulletPlacer();
                 Put4.~BulletPlacer();
               }
        }
        window.clear();

        if(FrameCount.getElapsedTime() <= FrameTime)
        { ++n; }
        else
        { std::cout << "Frames Per Second: " << n << std::endl; n = 0; FrameCount.restart(); }

        Put.CLinearMove();
        Put3.CLinearMove();
        Put4.CLinearMove();

        if(Time.getElapsedTime() >= T)
        { Put2.CLinearMove(); check = true; }

        C = Put.ShotList.begin();
        D = Put2.ShotList.begin();
        E = Put3.ShotList.begin();
        F = Put4.ShotList.begin();

        for (unsigned i = 0; i < num; ++i)
        { if(C != Put.ShotList.end() && E != Put3.ShotList.end() && F != Put4.ShotList.end())
            { window.draw(*C); ++C; window.draw(*E); ++E; window.draw(*F); ++F; }
          else
              break;

          if (check)
          { if(D != Put2.ShotList.end())
            {window.draw(*D); ++D;}
            else
                break;
          }
        }

        window.display();
    }
    return 0;

}

 

BulletPlacer is a container for Bullets (using a std::list for bullet objects), which have many variables and methods to control movement from a contained sprite, it does inherit from drawable, but not from transformable.

TextureHolder is a container for textures and images to be used (then again a std::list for textures and images), BulletPlacer gets a reference to it in order to give the sprites within the bullets something to draw.

What the program does is draw the amount of usable bullets in the BulletPlacer object in a circle, the amount determines angle frequency in the circle, once placed they inmediately start moving linearly based on their given angle. I had a pretty inefficient code at first, then fixed it but the FPS didn't go up at all, it stayed the same. It goes slower the more bullets you put in the BulletPlacer, but even with a small amount there is still a loss of 10 FPS.

I've fixed all I know I can and still have gotten no results in that matter. If this were to be not enough I can provide a minimal code, but I'd rather only do it unless it's truly needed since I would have to compress a lot of code.  Thanks in advance for all help I may get.
« Last Edit: September 26, 2012, 07:03:47 pm by masskiller »
Programmer, Artist, Composer and Storyline/Script Writer of "Origin of Magic". If all goes well this could turn into a commercial project!

Finally back into the programming world!

eigenbom

  • Full Member
  • ***
  • Posts: 228
    • View Profile
Re: Ways to raise FPS
« Reply #1 on: September 25, 2012, 09:22:33 am »
this is not good!! :o
Hold.~TextureHolder();

some general tips:
- use a bunch of sf::clocks and break your main loop up to see what the bottleneck is.
- for large amounts of similar objects you could manage your renderstates manually to avoid state changes
- std::vector as a general rule is _much_ quicker than std::list

good luck!

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Re: Ways to raise FPS
« Reply #2 on: September 25, 2012, 10:13:38 am »
Or use a profiler to fibd out where the application spends most of its time.
And as alteady pointed out never call a destructor manually, thos leads to undefined behavior.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

masskiller

  • Sr. Member
  • ****
  • Posts: 284
  • Pointers to Functions rock!
    • MSN Messenger - kyogre_jb@hotmail.com
    • View Profile
    • Email
Re: Ways to raise FPS
« Reply #3 on: September 25, 2012, 05:22:28 pm »
Shifting to a std::vector did help, on most ocassions it gets a boost of 10 to the FPS count at best, even when drawing more than a thousand bullets. I have to get a profiler for further working, but in the cases I'll need (the over thousand count is just for testing and trying to make it faster) it'll do, however I noticed some odd issues, depending on the number (tends to happen with large numbers, but also happens with some small ones) I get a 100 FPS count for about three seconds until it normalizes.

Also, I've checked RenderStates in the doc and the question came to mind, How do you manage them manually?
For my final version of the game I'll sometimes need a thousand or over sprites getting drawn, and while that will be around a 5% of the times I'll still need it to work at the same speed. As made apparent by my question I don't exactly know how to manage them manually.

I haven't gotten a profiler yet to get further data, as soon as I do I'll post whatever I find out, thanks for helping me out.

Attached is a screenshot of when the FPS goes crazy, that was when drawing around 800 bullets. It generally starts out very slow, speeds up and normalizes as most bullets go out of bounds.

[attachment deleted by admin]
« Last Edit: September 25, 2012, 05:25:27 pm by masskiller »
Programmer, Artist, Composer and Storyline/Script Writer of "Origin of Magic". If all goes well this could turn into a commercial project!

Finally back into the programming world!

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Ways to raise FPS
« Reply #4 on: September 25, 2012, 05:29:18 pm »
Quote
Also, I've checked RenderStates in the doc and the question came to mind, How do you manage them manually?
http://www.sfml-dev.org/documentation/2.0/classsf_1_1RenderStates.php#details
Create object and set texture, shader, blend and transform of it or just pass texture pointer, shader pointer, blend or transform as last draw parameter. That's how vertices get textured and transformed in sfml classes.
Quote
Attached is a screenshot of when the FPS goes crazy, that was when drawing around 800 bullets. It generally starts out very slow, speeds up and normalizes as most bullets go out of bounds.
Do you store bullets or pointers to bullets(from code I assume bullets) and do you erase and add them often? And how heavy is bullet.

Oh, also: do a test(just render window and few k sprites) to see how much sprites you can draw and move around before your fps falls so we know it's not your gpu or cpu limitation.
« Last Edit: September 25, 2012, 05:36:35 pm by FRex »
Back to C++ gamedev with SFML in May 2023

masskiller

  • Sr. Member
  • ****
  • Posts: 284
  • Pointers to Functions rock!
    • MSN Messenger - kyogre_jb@hotmail.com
    • View Profile
    • Email
Re: Ways to raise FPS
« Reply #5 on: September 25, 2012, 07:25:13 pm »
It's bullets as you thought, I could make it so it would use a pointer to a bullet since the BulletPlacer always (or at least for now with the implementation it has) has only one bullet configuration, but I would prefer not to do it that way since it pretty much messes how I manage positions, I'm not even entirely sure if I could do it with only a bullet for each BulletPlacer.

Just did the test after closing a few windows, the FPS acceleration appears to be gone now and on debug mode it can draw 720 sprites (being the lowest rate 55) and in release mode it can draw 840 sprites (being the lowest rate 55 again) before starting to progressively fall as the amount of sprites increases in any of both modes.

I have an Intel GPU and an Intel Core 2 duo 2.00 Ghz. I know my PC is certainly not the best, but I am trying to make my game work at best in this computer as an standard (partly because it's the only thing I'll have for quite a while), so I can ensure that the game will work well from something similar to my PC to anything better.

I haven't started to manage states manually yet, and while I do understand the concept well enough, a code example would help me a lot.
Programmer, Artist, Composer and Storyline/Script Writer of "Origin of Magic". If all goes well this could turn into a commercial project!

Finally back into the programming world!

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Ways to raise FPS
« Reply #6 on: September 25, 2012, 07:33:30 pm »
Quote
I haven't started to manage states manually yet, and while I do understand the concept well enough, a code example would help me a lot.
States are more low level tool, they are additional things you want to happen, but often they'll get changed, like sprite, ignores texture passed to it in states and uses it's own.
I don't understand how changing to pointers breaks anything(except adding additional dereferencings here and there). Does bullet class look like something heavy to copy?

#define EE_MCR_AVERAGER_BEGIN(x) sf::Clock EEAV_CLOCK_##x; static sf::Int64 EEAV_MS_##x=0; static int EEAV_FR_##x=0;
#define EE_MCR_AVERAGER_END(x) std::cout<<"Averaging clock("#x"):"<<(EEAV_MS_##x+=EEAV_CLOCK_##x.getElapsedTime().asMicroseconds())/(++EEAV_FR_##x)<<std::endl;
You can measure time between lines by placing begin macro before and end macro after them. Try to find out which part of code uses most time.
« Last Edit: September 25, 2012, 07:46:48 pm by FRex »
Back to C++ gamedev with SFML in May 2023

Contadotempo

  • Full Member
  • ***
  • Posts: 167
  • Firelink Shrine
    • View Profile
Re: Ways to raise FPS
« Reply #7 on: September 25, 2012, 08:02:47 pm »
Consider using std::vector's reserve() function. Reserve the maximum number of bullets you're intending to use (5000 for example). It should solve your slowdown problems at the beginning of the program.

Think about using vertexarrays, also. You could easily reach 10000 bullets with some work.
« Last Edit: September 25, 2012, 08:05:31 pm by Contadotempo »

masskiller

  • Sr. Member
  • ****
  • Posts: 284
  • Pointers to Functions rock!
    • MSN Messenger - kyogre_jb@hotmail.com
    • View Profile
    • Email
Re: Ways to raise FPS
« Reply #8 on: September 25, 2012, 08:52:29 pm »
By using your Time macro I found out that the most time is spent at drawing, then on the CLinearMove function and finally on the ShotCircleCalculate. Time obviously increases as the amount of bullets increase. But with the optimizations I've made so far it can now draw 880 sprites without dropping beyond 55 (and it only drops once, then goes back). I want to reach a 1600 sprites without it falling beyond 50 (working with 1600 sprites/bullets halves the FPS while most are on screen, as they go out of bounds the FPS goes back up).

Quote
I don't understand how changing to pointers breaks anything(except adding additional dereferencings here and there). Does bullet class look like something heavy to copy?

Not really, while doing so I could get a frame or two, it's not worth the complications I would get with positioning. In fact, I don't even know if it could even be possible at all. I thought of the possibility at first, then threw it out due to the reasons above.

Quote
States are more low level tool, they are additional things you want to happen, but often they'll get changed, like sprite, ignores texture passed to it in states and uses it's own.

If managing them manually will get me a higher count them I'm willing to do it, if unlike making bullet pointers to one bullet this will get me a reasonable FPS count on higher amounts of bullets, then I don't mind handling them myself.

Quote
Consider using std::vector's reserve() function. Reserve the maximum number of bullets you're intending to use (5000 for example). It should solve your slowdown problems at the beginning of the program.

The reserve function does it's job well enough, it got me at least a frame, I thought there'd be no measurable difference.

Quote
Think about using vertexarrays, also. You could easily reach 10000 bullets with some work.

As far as I know VertexArrays use Primitive types such as points, quads, lines, triangles and such. Can it work with sprites?
« Last Edit: September 25, 2012, 09:00:47 pm by masskiller »
Programmer, Artist, Composer and Storyline/Script Writer of "Origin of Magic". If all goes well this could turn into a commercial project!

Finally back into the programming world!

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Ways to raise FPS
« Reply #9 on: September 25, 2012, 08:59:08 pm »
Quote
By using your Time macro I found out that the most time is spent at drawing
Well *insert profanity here*.
How much exactly? 1000 000 microseconds is one seconds so one loop has 16 666 microseconds to do it's things with 60 fps.
Quote
As far as I know VertexArrays use Primitive types such as points, quads, lines, triangles and such. Can it work with sprites?
Sprite is single quad.
If you have something like bullets moving in a pattern where they are connected and never move realative to each other you could just use array with few quads in it and move, rotate ect. it as needed(or put it in class derieved from transformable and array). You could also make yourself an 'untextured sprite' class specially for the bullets and pass texture of bulletsheet with states somewhere(I'm not sure how reliable that dev blog was but somewhere I've read that open gl binding down textures often eats up a lot of time).
« Last Edit: September 25, 2012, 09:02:39 pm by FRex »
Back to C++ gamedev with SFML in May 2023

masskiller

  • Sr. Member
  • ****
  • Posts: 284
  • Pointers to Functions rock!
    • MSN Messenger - kyogre_jb@hotmail.com
    • View Profile
    • Email
Re: Ways to raise FPS
« Reply #10 on: September 25, 2012, 09:13:23 pm »
In the 880 Bullets case the average is of 14 000 - 16 000
In the 1600 case the average is 25 000 - 26 500.
(averages taken by fast eye comparisson).

Quote
Sprite is single quad.
If you have something like bullets moving in a pattern where they are connected and never move relative to each other you could just use array with few quads in it and move, rotate ect. it as needed(or put it in class derived from transformable and array). You could also make yourself an 'untextured sprite' class specially for the bullets and pass texture of bulletsheet with states somewhere(I'm not sure how reliable that dev blog was but somewhere I've read that open gl binding down textures often eats up a lot of time).

Then it might work for me. All position calculations I have so far are based on polar coordinates and are made independent from other bullet's position, the fact that they are relative to each other is caused by the math within it which only uses the individual bullet position to keep it moving in the desired direction.

I'll try that if using a VertexArray doesn't do the trick. But from what I've read I think that'll be enough.
Programmer, Artist, Composer and Storyline/Script Writer of "Origin of Magic". If all goes well this could turn into a commercial project!

Finally back into the programming world!

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Ways to raise FPS
« Reply #11 on: September 25, 2012, 09:24:21 pm »
Quote
In the 880 Bullets case the average is of 14 000 - 16 000
In the 1600 case the average is 25 000 - 26 500.
(averages taken by fast eye comparisson).
Well, using 16 or 25k out of 16,6k you have is not good. The macro is averaging itself so that big 1 cycle spikes affect the results and there's no need to take average yourself.
Do you have sheet of bullets or is each bullet unique texture?
Back to C++ gamedev with SFML in May 2023

masskiller

  • Sr. Member
  • ****
  • Posts: 284
  • Pointers to Functions rock!
    • MSN Messenger - kyogre_jb@hotmail.com
    • View Profile
    • Email
Re: Ways to raise FPS
« Reply #12 on: September 25, 2012, 09:30:04 pm »
Quote
Do you have sheet of bullets or is each bullet unique texture?

The TextureHolder class has all textures I need in it, all I do is take a reference to it and make the sprites take the texture I want them to. For my tests I use four different textures with a quarter of the total bullets taking one texture, the next quarter another texture and so on.

As Textures are heavy I chose to keep them all in one place and have references to that given place.
Programmer, Artist, Composer and Storyline/Script Writer of "Origin of Magic". If all goes well this could turn into a commercial project!

Finally back into the programming world!

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Ways to raise FPS
« Reply #13 on: September 25, 2012, 09:34:43 pm »
Quote
For my tests I use four different textures with a quarter of the total bullets taking one texture, the next quarter another texture and so on.
If you mean four sf::Texture instances then try with single instance and setting of texture rects in sprites.
Back to C++ gamedev with SFML in May 2023

masskiller

  • Sr. Member
  • ****
  • Posts: 284
  • Pointers to Functions rock!
    • MSN Messenger - kyogre_jb@hotmail.com
    • View Profile
    • Email
Re: Ways to raise FPS
« Reply #14 on: September 25, 2012, 09:52:03 pm »
Quote
If you mean four sf::Texture instances then try with single instance and setting of texture rects in sprites.

That way the time is a 10% of what it was when using four different textures (1600 case). It can perfectly draw 8000 sprites when using only one texture without frame drops. The texture rect is always the size of the image in my program, since that's the way the images used for textures are set. The difference in time amazed me. I did know that using more than one texture did a big change in speed, but I never thought it would be so great.

My initial test was pushing for a high number with many textures, but for practical uses I'll most likely never use 4 textures with 400 elements of each so even this way should be enough. I'll still try the VertexArray approach though, since I think it'll help for when I start using backgrounds. I'll post any results I get till then.
I'll change the status to solved once I do that.

Thanks for the help, it really did a difference.
Programmer, Artist, Composer and Storyline/Script Writer of "Origin of Magic". If all goes well this could turn into a commercial project!

Finally back into the programming world!