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

Author Topic: Draw(Text) performance issue  (Read 14264 times)

0 Members and 1 Guest are viewing this topic.

dreimalbla

  • Newbie
  • *
  • Posts: 6
    • View Profile
Draw(Text) performance issue
« 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;
}


SirJulio

  • Full Member
  • ***
  • Posts: 241
    • View Profile
Draw(Text) performance issue
« Reply #1 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. =)

dreimalbla

  • Newbie
  • *
  • Posts: 6
    • View Profile
Draw(Text) performance issue
« Reply #2 on: July 16, 2008, 07:15:34 pm »
thx for the answer, let's hope he'll fix it soon ;)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Draw(Text) performance issue
« Reply #3 on: July 16, 2008, 07:20:24 pm »
It will probably be fixed in the next commit, actually ;)
Laurent Gomila - SFML developer

dreimalbla

  • Newbie
  • *
  • Posts: 6
    • View Profile
Draw(Text) performance issue
« Reply #4 on: July 16, 2008, 08:20:31 pm »
great :)
keep up the good work

dabo

  • Sr. Member
  • ****
  • Posts: 260
    • View Profile
    • http://www.dabostudios.net
Draw(Text) performance issue
« Reply #5 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?

SirJulio

  • Full Member
  • ***
  • Posts: 241
    • View Profile
Draw(Text) performance issue
« Reply #6 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]

dabo

  • Sr. Member
  • ****
  • Posts: 260
    • View Profile
    • http://www.dabostudios.net
Draw(Text) performance issue
« Reply #7 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.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Draw(Text) performance issue
« Reply #8 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
Laurent Gomila - SFML developer

dabo

  • Sr. Member
  • ****
  • Posts: 260
    • View Profile
    • http://www.dabostudios.net
Draw(Text) performance issue
« Reply #9 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.

SirJulio

  • Full Member
  • ***
  • Posts: 241
    • View Profile
Draw(Text) performance issue
« Reply #10 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

dabo

  • Sr. Member
  • ****
  • Posts: 260
    • View Profile
    • http://www.dabostudios.net
Draw(Text) performance issue
« Reply #11 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.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Draw(Text) performance issue
« Reply #12 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.
Laurent Gomila - SFML developer

dabo

  • Sr. Member
  • ****
  • Posts: 260
    • View Profile
    • http://www.dabostudios.net
Draw(Text) performance issue
« Reply #13 on: July 17, 2008, 05:09:37 pm »
Ok thanks, the last part sounds great. Let us know when it's done :)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Draw(Text) performance issue
« Reply #14 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.
Laurent Gomila - SFML developer