SFML community forums

Help => Graphics => Topic started by: dreimalbla on July 16, 2008, 05:15:25 pm

Title: Draw(Text) performance issue
Post by: dreimalbla on July 16, 2008, 05:15:25 pm
Hi,
I've got huge performance issue when using SFML's draw text.
Let's take the SFML opengl sample as an example.
600fps while drawing the rotating cube and drawing the fps.
300fps while drawing the rotating cube and drawing the fps three times.
250fps while drawing the rotating cube and drawing the fps four times.

I'm using SFML 1.3. Is this a known issue or is it on my side only?

Code: [Select]


////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics.hpp>
#include <iostream>
#include <sstream>
#include <string>


////////////////////////////////////////////////////////////
/// Entry point of application
///
/// \return Application exit code
///
////////////////////////////////////////////////////////////
int main()
{

    // Create main window
    sf::RenderWindow App(sf::VideoMode(800, 600), "SFML OpenGL");
    App.PreserveOpenGLStates(true);

    // Create a sprite for the background
    sf::Image BackgroundImage;
    if (!BackgroundImage.LoadFromFile("datas/opengl/background.jpg"))
        return EXIT_FAILURE;
    sf::Sprite Background(BackgroundImage);

    // Load an OpenGL texture.
    // We could directly use a sf::Image as an OpenGL texture (with its Bind() member function),
    // but here we want more control on it (generate mipmaps, ...) so we create a new one
    GLuint Texture = 0;
    {
        sf::Image Image;
        if (!Image.LoadFromFile("datas/opengl/texture.jpg"))
            return EXIT_FAILURE;
        glGenTextures(1, &Texture);
        glBindTexture(GL_TEXTURE_2D, Texture);
        gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, Image.GetWidth(), Image.GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE, Image.GetPixelsPtr());
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    }

    // Enable Z-buffer read and write
    glEnable(GL_DEPTH_TEST);
    glDepthMask(GL_TRUE);
    glClearDepth(1.f);

    // Setup a perspective projection
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(90.f, 1.f, 1.f, 500.f);

    // Bind our texture
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, Texture);
    glColor4f(1.f, 1.f, 1.f, 1.f);

    // Create a clock for measuring the time elapsed
sf::Clock Clock;
double currTime = Clock.GetElapsedTime();
double lastTime = Clock.GetElapsedTime();
double deltaTime;

    // Start game loop
    while (App.IsOpened())
    {
currTime = Clock.GetElapsedTime();
deltaTime = currTime - lastTime;
        // Process events
        sf::Event Event;
        while (App.GetEvent(Event))
        {
            // Close window : exit
            if (Event.Type == sf::Event::Closed)
                App.Close();

            // Escape key : exit
            if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape))
                App.Close();

            // Adjust the viewport when the window is resized
            if (Event.Type == sf::Event::Resized)
                glViewport(0, 0, Event.Size.Width, Event.Size.Height);
        }

        // Draw background
        App.Draw(Background);

        // Clear depth buffer
        glClear(GL_DEPTH_BUFFER_BIT);

        // Apply some transformations
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        glTranslatef(0.f, 0.f, -200.f);
        glRotatef(Clock.GetElapsedTime() * 50, 1.f, 0.f, 0.f);
        glRotatef(Clock.GetElapsedTime() * 30, 0.f, 1.f, 0.f);
        glRotatef(Clock.GetElapsedTime() * 90, 0.f, 0.f, 1.f);

        //Draw a cube
        glBegin(GL_QUADS);

            glTexCoord2f(0, 0); glVertex3f(-50.f, -50.f, -50.f);
            glTexCoord2f(0, 1); glVertex3f(-50.f,  50.f, -50.f);
            glTexCoord2f(1, 1); glVertex3f( 50.f,  50.f, -50.f);
            glTexCoord2f(1, 0); glVertex3f( 50.f, -50.f, -50.f);

            glTexCoord2f(0, 0); glVertex3f(-50.f, -50.f, 50.f);
            glTexCoord2f(0, 1); glVertex3f(-50.f,  50.f, 50.f);
            glTexCoord2f(1, 1); glVertex3f( 50.f,  50.f, 50.f);
            glTexCoord2f(1, 0); glVertex3f( 50.f, -50.f, 50.f);

            glTexCoord2f(0, 0); glVertex3f(-50.f, -50.f, -50.f);
            glTexCoord2f(0, 1); glVertex3f(-50.f,  50.f, -50.f);
            glTexCoord2f(1, 1); glVertex3f(-50.f,  50.f,  50.f);
            glTexCoord2f(1, 0); glVertex3f(-50.f, -50.f,  50.f);

            glTexCoord2f(0, 0); glVertex3f(50.f, -50.f, -50.f);
            glTexCoord2f(0, 1); glVertex3f(50.f,  50.f, -50.f);
            glTexCoord2f(1, 1); glVertex3f(50.f,  50.f,  50.f);
            glTexCoord2f(1, 0); glVertex3f(50.f, -50.f,  50.f);

            glTexCoord2f(0, 1); glVertex3f(-50.f, -50.f,  50.f);
            glTexCoord2f(0, 0); glVertex3f(-50.f, -50.f, -50.f);
            glTexCoord2f(1, 0); glVertex3f( 50.f, -50.f, -50.f);
            glTexCoord2f(1, 1); glVertex3f( 50.f, -50.f,  50.f);

            glTexCoord2f(0, 1); glVertex3f(-50.f, 50.f,  50.f);
            glTexCoord2f(0, 0); glVertex3f(-50.f, 50.f, -50.f);
            glTexCoord2f(1, 0); glVertex3f( 50.f, 50.f, -50.f);
            glTexCoord2f(1, 1); glVertex3f( 50.f, 50.f,  50.f);

        glEnd();

lastTime = currTime;

std::ostringstream ss;
ss << 1/deltaTime;
std::string s = ss.str();

        // Draw some text on top of our OpenGL object
        sf::String Text(s);
        Text.SetPosition(250.f, 300.f);
        Text.SetColor(sf::Color(128, 0, 128));
        App.Draw(Text);

Text.SetText(s);
        Text.SetPosition(250.f, 330.f);
        Text.SetColor(sf::Color(128, 0, 128));
        App.Draw(Text);

Text.SetText(s);
        Text.SetPosition(250.f, 360.f);
        Text.SetColor(sf::Color(128, 0, 128));
        App.Draw(Text);

Text.SetText(s);
        Text.SetPosition(250.f, 360.f);
        Text.SetColor(sf::Color(128, 0, 128));
        App.Draw(Text);

        // Finally, display the rendered frame on screen
        App.Display();
    }

    // Don't forget to destroy our texture
    glDeleteTextures(1, &Texture);

    return EXIT_SUCCESS;
}

Title: Draw(Text) performance issue
Post by: SirJulio on July 16, 2008, 06:27:04 pm
Hi dreimalbla,

it's a known issue with String. Problem is not the String display, but SetText method which is very slow with visual studio (you use VS, right ?). Try to comment the 3 others SetText methods, and you'll have your ~600 fps back.

Another workaround is to use only std::wstring and not std::string to prevent call to String::SetText(std::string) (actually the bottleneck into this method is conversion between string and wstring because SFML String handle only wstring) and use String::SetText(std::wstring) instead.

I've already mentioned this problem to Laurent on the french forum, and he's working on it. =)
Title: Draw(Text) performance issue
Post by: dreimalbla on July 16, 2008, 07:15:34 pm
thx for the answer, let's hope he'll fix it soon ;)
Title: Draw(Text) performance issue
Post by: Laurent on July 16, 2008, 07:20:24 pm
It will probably be fixed in the next commit, actually ;)
Title: Draw(Text) performance issue
Post by: dreimalbla on July 16, 2008, 08:20:31 pm
great :)
keep up the good work
Title: Draw(Text) performance issue
Post by: dabo on July 16, 2008, 10:46:34 pm
Quote from: "SirJulio"
but SetText method which is very slow with visual studio (you use VS, right ?)


What do you mean by that? Why would it be slower using visual studio?
Title: Draw(Text) performance issue
Post by: SirJulio on July 16, 2008, 11:59:01 pm
Yep !

From string.cpp :

Code: [Select]
void String::SetText(const std::string& Text)
{
    myNeedRectUpdate = true;

    if (!Text.empty())
    {
        std::vector<wchar_t> Buffer(Text.size());

        #if defined(__MINGW32__)
                // MinGW has a bad support for wstring conversions (and wchar_t based standard classes in general)
                mbstowcs(&Buffer[0], Text.c_str(), Text.size());
        #else
                std::locale Locale("");
                std::use_facet<std::ctype<wchar_t> >(Locale).widen(Text.data(), Text.data() + Text.size(), &Buffer[0]);
        #endif

        myText.assign(&Buffer[0], Buffer.size());
    }
    else
    {
        myText = L"";
    }
}


Actually the specific Mingw part is a lot faster (by a factor of 100, maybe a little less) for all compiler I have tested (MinGW, VS9 and DMC).

Here's a test comparing the two methods, using svn, VC9 express and with SetText customized version (which doesn't use std stuff) and SetTextOriginal the actual SetText method :

Code: [Select]

int main()
{
    sf::String myString("Test");
   
    __int64 l;
    for(int i = 0; i < 10; i++)
    {
        l = __rdtsc();
        myString.SetText("Blabla");
        printf("New SetText : %d\n", __rdtsc() - l);
    }


    for(int i = 0; i < 10; i++)
    {
        l = __rdtsc();
        myString.SetTextOriginal("Blabla");
        printf("Original SetText : %d\n", __rdtsc() - l);
    }

   
    getchar();
    return EXIT_SUCCESS;
}


Quote
New SetText : 7051
New SetText : 27200
New SetText : 13952
New SetText : 10928
New SetText : 7979
New SetText : 11511
New SetText : 10730
New SetText : 11259
New SetText : 10047
New SetText : 10761
Original SetText : 1839609
Original SetText : 1165118
Original SetText : 813238
Original SetText : 783113
Original SetText : 801104
Original SetText : 774272
Original SetText : 806911
Original SetText : 775008
Original SetText : 784999
Original SetText : 718220


So, it's not an issue with Visual itself, but with String implementation when you compile with visual. =)[/code]
Title: Draw(Text) performance issue
Post by: dabo on July 17, 2008, 01:11:51 pm
So we who love visual studio will be forced to use something else in order to get great performance out of sfml? I'm currently experiencing the same performance issue as the one above.
Title: Draw(Text) performance issue
Post by: Laurent on July 17, 2008, 01:17:53 pm
Quote
So we who love visual studio will be forced to use something else in order to get great performance out of sfml?

Quote from: "Laurent"
It will probably be fixed in the next commit, actually
Title: Draw(Text) performance issue
Post by: dabo on July 17, 2008, 01:21:15 pm
Quote from: "Laurent"
Quote
So we who love visual studio will be forced to use something else in order to get great performance out of sfml?

Quote from: "Laurent"
It will probably be fixed in the next commit, actually


Ok, thanks for making me look stupid :D Should have seen that.
Title: Draw(Text) performance issue
Post by: SirJulio on July 17, 2008, 02:59:41 pm
Quote from: "dabo"
So we who love visual studio will be forced to use something else in order to get great performance out of sfml? I'm currently experiencing the same performance issue as the one above.


Quote from: "SirJulio"
Another workaround is to use only std::wstring and not std::string to prevent call to String::SetText(std::string) (actually the bottleneck into this method is conversion between string and wstring because SFML String handle only wstring) and use String::SetText(std::wstring) instead.


You missed that too. =p
Title: Draw(Text) performance issue
Post by: dabo on July 17, 2008, 03:10:43 pm
Quote from: "SirJulio"
Quote from: "SirJulio"
Another workaround is to use only std::wstring and not std::string to prevent call to String::SetText(std::string) (actually the bottleneck into this method is conversion between string and wstring because SFML String handle only wstring) and use String::SetText(std::wstring) instead.


You missed that too. =p


Well actually I saw that, but I don't know how to use wstring, I get a lot of errors all the time.
Title: Draw(Text) performance issue
Post by: Laurent on July 17, 2008, 03:21:54 pm
Don't bother with std::wstring, it will no longer be used in the new version. In fact std::wstring and wchar_t are evil : we don't know anything about them, neither their size (can be 2 or 4 bytes) nor how characters are encoded (can be UTF-32 or UTF-16 depending on the platform).

The new version will define propre unicode types, as well as functions to convert between them and locale-dependent ANSI strings.
Title: Draw(Text) performance issue
Post by: dabo on July 17, 2008, 05:09:37 pm
Ok thanks, the last part sounds great. Let us know when it's done :)
Title: Draw(Text) performance issue
Post by: Laurent on July 17, 2008, 05:37:40 pm
Should be ready in a couple of days. The only problem actually is the lack of proper unicode handling in MinGW standard library.
Title: Draw(Text) performance issue
Post by: dabo on July 17, 2008, 07:59:20 pm
Take your time, no hurry.
Title: Draw(Text) performance issue
Post by: dabo on July 29, 2008, 04:40:51 pm
I read the road map and I noticed this:

Done - ready for next version
- SYSTEM Added types and conversion functions to handle all Unicode formats
- GENERAL SFML now uses UTF-32 for all text related stuff instead of UCS-2

Will this speed up the SetText-method for visual studio that you were talking about earlier or is it something else?
Title: Draw(Text) performance issue
Post by: Laurent on July 29, 2008, 05:12:27 pm
Actually, the performances issue with strings was a stupid thing which is fixed.

I'm also going to improve the sf::String rendering code to optimize it, but it's already way faster than before.
Title: Draw(Text) performance issue
Post by: Avency on July 29, 2008, 05:45:33 pm
It definitely got faster. I got 5000 fps before, now I get 24000 fps.
I almost thought that there was something wrong with my message box rendering code. :P
Title: Draw(Text) performance issue
Post by: SirJulio on July 29, 2008, 06:03:09 pm
Quote from: "Avency"
It definitely got faster. I got 5000 fps before, now I get 24000 fps.
I almost thought that there was something wrong with my message box rendering code. :P


OMFG ! You work on a Cray XT5 ? =D

I confirm, string is now a lot faster than before.
Title: Draw(Text) performance issue
Post by: Avency on July 29, 2008, 06:20:07 pm
Nope, it's a 8800GTX, rendering nothing but a message box (only a few lines of OpenGL code) + fps string in a 320x240 window (it drops to an average 15000 fps if I change the resolution to 640x480).
Don't worry, it gets slower the more I draw on the screen. :wink:
Title: Draw(Text) performance issue
Post by: Daazku on July 29, 2008, 06:41:02 pm
Quote from: "Avency"
Nope, it's a 8800GTX, rendering nothing but a message box (only a few lines of OpenGL code) + fps string in a 320x240 window (it drops to an average 15000 fps if I change the resolution to 640x480).
Don't worry, it gets slower the more I draw on the screen. :wink:


lollll 320X240... I will draw an fps string in a 10X100 window and we will see wich fps i will get XD.
Title: Draw(Text) performance issue
Post by: dabo on July 29, 2008, 07:22:26 pm
Sounds great. So I don't have to change any of my code to get this speed up, only download the new source?
Title: Draw(Text) performance issue
Post by: SirJulio on July 29, 2008, 07:30:17 pm
@Dabo :

Yeap, maybe you'll need to do some changes on your code with the new unicode stuffs. If you don't use wchar at all, just update your svn.
Title: Draw(Text) performance issue
Post by: dabo on July 29, 2008, 08:52:37 pm
It's faster for sure  :)  Great job!
Title: Draw(Text) performance issue
Post by: Avency on July 30, 2008, 08:46:53 am
Quote from: "Daazku"

lollll 320X240... I will draw an fps string in a 10X100 window and we will see wich fps i will get XD.


Any results? :wink:
Title: Draw(Text) performance issue
Post by: Daazku on July 30, 2008, 02:19:49 pm
ROFL!!! I will do it this night if you really want a result XD.
Title: Draw(Text) performance issue
Post by: fixus971 on August 23, 2008, 11:46:47 am
Hi boys.. I have the same problem and read all but not see results..
I'm using SFML 1.3 too as wrote on first post.

updated/fixed SFML Code that work faster with SetText
is 1.3 or is in SVN source?? :?:

Thanks
Title: Draw(Text) performance issue
Post by: SirJulio on August 23, 2008, 06:24:45 pm
The svn source. =)
Title: Draw(Text) performance issue
Post by: fixus971 on August 24, 2008, 10:45:08 am
Hi Sir.
Yesterday I try svn source but without different results.
I just put svn include/lib dirs into sfml 1.3 sdk and recompile all.
I'm using VC9.
Now I'm working using wstringstream.
Title: Draw(Text) performance issue
Post by: Laurent on August 24, 2008, 11:11:25 am
Quote
I just put svn include/lib dirs into sfml 1.3 sdk and recompile all.

And what about the src dir ? :roll:
Title: Draw(Text) performance issue
Post by: fixus971 on August 24, 2008, 12:12:23 pm
Sorry boys.
I usually get SDK version..
Yesterday I was tired and get "SFML development files" of ver1.3 instead of "SVN sources".
My sentence "..and recompile all" was referred only to my source.

You don't plain to update 1.3 version?