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

Author Topic: Drawing 100 items per frame cuts FPS by 400?  (Read 2241 times)

0 Members and 1 Guest are viewing this topic.

luke

  • Newbie
  • *
  • Posts: 3
    • View Profile
Drawing 100 items per frame cuts FPS by 400?
« on: December 18, 2012, 05:00:23 am »
Hi, I'm new to both SFML and C++ development (from C#/Java background) and I want to know if I'm doing something wrong that is negatively affecting my frame time.
I have a method that draws the current FPS in a new sf::Text, and I call this method ~100 times per frame.  This brings the app to 100 FPS.  However, when I was drawing the sf::Text object 1 time per frame, I was seeing 500 FPS.

This FPS drop is way more dramatic than I expected.  If this were a 2D tile-based game that has 10x10 tiles in your line-of-sight, that could be 100 sprites drawn per second and when you consider the Tile layer, Item layer, Player layer, Effects layer... I don't see how this would handle it.  That is unless drawing Sprites is somehow much cheaper/faster.

I'm using Windows XP, Visual C++ 2010 Express.
Dell Inspiron 6000 laptop (7 years old?), Intel processor 1.73GHz, integrated graphics.

Are CPU and GPU specs my problem?  :-X

#include <cstdlib>
#include "stdafx.h"
#include "SFML\Window.hpp"
#include "SFML\Graphics.hpp"
#include "SFML\System.hpp"
#include "SFML\System\Time.hpp"
using namespace std;

void drawString(std::string s, float x, float y, sf::RenderWindow* window)
{
        sf::String sfString(s);
        sf::Text sfText;
        sfText.setString(sfString);
        sfText.setPosition(x,y);
        (*window).draw(sfText);
}
int main()
{
    sf::RenderWindow window(sf::VideoMode(800, 600), "My window");
        sf::RenderWindow *pwindow = &window;
        window.setVerticalSyncEnabled(true); // call it once, after creating the window
        sf::Clock fps_clock;
        while(window.isOpen())
        {
                window.clear(sf::Color::Black);
                // show fps
                char *fps_str = new char[30];
                char *ct_str = new char[30];
                float frame_time = fps_clock.restart().asSeconds();
                float fps = 1.f / frame_time;
                sprintf(fps_str, "FPS: %.1f", fps);
                // draw text a few times...
                for(int i=0; i<19; i++)
                        for(int j=0; j<5; j++)
                                drawString(fps_str,j*160,i*30, pwindow);
                delete fps_str;
                delete ct_str;
                window.display();
                sf::sleep(sf::milliseconds(0));
        }
        delete pwindow;
        return 0;
}

cire

  • Full Member
  • ***
  • Posts: 138
    • View Profile
Re: Drawing 100 items per frame cuts FPS by 400?
« Reply #1 on: December 18, 2012, 06:56:38 am »
In debug mode, I get around 115 fps with that code.  Compiled with optimizations I get around 1400 fps.

If I stop allocating and deallocating boatloads of dynamic memory and also stop constructing and copying a std::string, sf::String and sf::Text 100 times per frame, I get around 3500 fps.

Btw, deleting stuff you didn't allocate with new is bad mojo.


#include <sstream>
#include "SFML\Graphics.hpp"

const std::string fontName = "sketchflow.ttf" ;
sf::Font font ;

void drawText(sf::Text& text, float x, float y, sf::RenderWindow& window)
{
    text.setPosition(x,y) ;
    window.draw(text) ;
}

template <typename T>
std::string to_string(const T& value)
{
    std::ostringstream os ;
    os << value ;
    return os.str() ;
}

int main()
{
    sf::RenderWindow window(sf::VideoMode(800, 600), "My window");

    sf::Clock fps_clock;

    font.loadFromFile(fontName) ;
    sf::Text fpsDrawable ;
    fpsDrawable.setFont(font) ;

    std::string fps ;

    while(window.isOpen())
    {
        sf::Event event ;
        while ( window.pollEvent(event) )
            if ( event.type == sf::Event::Closed )
                window.close() ;

        fps = to_string(1.0f / (fps_clock.restart().asSeconds())) ;
        fpsDrawable.setString(fps) ;

        window.clear(sf::Color::Black);

        for(int i=0; i<19; i++)
            for(int j=0; j<5; j++)
                drawText(fpsDrawable,j*160,i*30, window);

        window.display();
    }
    return 0;
}
 

Since the default font was removed from SFML, I added code to load a font.  You may have to modify that to run this code (or just remove it altogether if you're using an older version that still has the default font and it actually works for you!)

luke

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: Drawing 100 items per frame cuts FPS by 400?
« Reply #2 on: December 18, 2012, 01:57:38 pm »
So, I'm getting:
100 FPS in Release mode with my code
350 FPS in Release mode with your code with the better memory management

I knew that I was being careless with allocation and deallocation each frame, but didn't think it had too huge of a bearing on my outcome.  This test shows me that my CPU/GPU specs are much more of a limiting factor since you're seeing a 10 times faster frame rate with the same code.

Also, I was only deleting things that I had allocated with 'new' (the two char[] pointers).  Unless you mean the things that were being implicitly deleted in my drawString() method every time the method ended and they went out of scope?  Are those implicit deallocations more costly?

Thanks for the help!

cf

  • Newbie
  • *
  • Posts: 9
    • View Profile
Re: Drawing 100 items per frame cuts FPS by 400?
« Reply #3 on: December 18, 2012, 02:07:28 pm »
He's talking about "delete pwindow;" at the end of main() even though the window wasn't allocated with new.

luke

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: Drawing 100 items per frame cuts FPS by 400?
« Reply #4 on: December 18, 2012, 02:53:52 pm »
I stand corrected.  Thanks for catching that :P

FRex

  • Hero Member
  • *****
  • Posts: 1845
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Drawing 100 items per frame cuts FPS by 400?
« Reply #5 on: December 18, 2012, 04:36:48 pm »
This might all be nitpicking but:
You're supposed to use delete [] on things allocated by new []. And here it's 'ugly' java-like use.
http://www.stroustrup.com/bs_faq2.html#new-java
Also you shouldn't probably use anything C-ish in c++ anymore at this point.
And you can pass std::string directly to setString of sf::Text and it'll be implicitly converted.
And use / slashes for inclusion, even if you're on Visual there is option(means that m$ doesn't disapprove of / or something) to change auto-completion to use / which is more portable.
And clearing window with sf::Color::Black is redundant because that's default clear color while you don't supply your own as parameter.
Back to C++ gamedev with SFML in May 2023