SFML community forums

Help => Graphics => Topic started by: lolz123 on May 14, 2011, 08:17:05 pm

Title: sf::RenderImage::Create extremely slow
Post by: lolz123 on May 14, 2011, 08:17:05 pm
I have a game in which I have a tile map and I want to render blood splatters to a set of RenderImages (so the blood splatters remain permanently attatched to the walls). They RenderImages are created dynamically, but the game pauses for about 1- 2 seconds every time I call .create (the dimensions are 128 x 128, so it is not that much). When not created dynamically, it takes my machine like 5 minutes to create enough textures for the entire map. What could be causing it to create the textures so extremely slowly?

Code: [Select]
// Check to see if must create a new texture (texture already in place has no dimensions)
if(pImg->GetWidth() == 0)
{
pImg->Create(128, 128, false);
pImg->Clear(sf::Color(0, 0, 0, 0));
}
Title: sf::RenderImage::Create extremely slow
Post by: Laurent on May 14, 2011, 09:08:24 pm
Does it really take 1 - 2 sec to create a single render image??
Title: sf::RenderImage::Create extremely slow
Post by: Groogy on May 14, 2011, 09:26:35 pm
I use it for the Lighting manager in Ruby and don't have that problem where I render the lighting effects onto a RenderImage before applying it to the screen every frame.
I would say it is some operations you do afterwards or before in conjunction with the creation of the RenderImage that takes so much time.
Title: sf::RenderImage::Create extremely slow
Post by: lolz123 on May 14, 2011, 10:26:35 pm
Yup, it actually takes 1-2 secs to create it, the whole game freezes for a bit when the render image creation code is executed.
I don't think it has anything to do with any operations before or afterwards as their aren't any besides rendering, which works at 60fps (after the images were created). The lag occurs even when I don't render to the image. If I simply comment out the image creation line it runs smoothly at 60fps all the time.
Title: sf::RenderImage::Create extremely slow
Post by: Laurent on May 14, 2011, 10:30:00 pm
So it should be the same with this piece of code, right?
Code: [Select]
int main()
{
    sf::RenderImage rimage;
    rimage.Create(128, 128);
    return 0;
}
Title: sf::RenderImage::Create extremely slow
Post by: Groogy on May 14, 2011, 10:56:37 pm
Just tried this out in my own system:

Code: [Select]
void Game::Update( const float aDelta )
{
myRotation += 1.f * aDelta;
myTestObject.SetRotation( 0, myRotation, 0 );
myTestObject.Render();

myTestSprite.Render();

sf::RenderImage test;
test.Create( 128, 128 );
}


There might be some truth to this. It lowered my FPS from 700 to around 20-30.

EDIT: Well actually not if things are done properly. It should not be done once every frame as I've done, it should be done once every now and then, so a drop like this is acceptable. Also this lowered my framerate a lot, but if I did like 10 it was lowered to 3 FPS. So it feels inconsistent.
Title: sf::RenderImage::Create extremely slow
Post by: lolz123 on May 14, 2011, 10:57:55 pm
Yes. I had to change it to this so I could actually tell how much time went by:

Code: [Select]

int main()
{
system("pause");
    sf::RenderImage rimage;
    rimage.Create(128, 128);
system("pause");
    return 0;
}


Still a 1 - 2 sec lag.
Title: sf::RenderImage::Create extremely slow
Post by: Groogy on May 14, 2011, 11:00:42 pm
Quote from: "lolz123"
Yes. I had to change it to this so I could actually tell how much time went by:

Code: [Select]

int main()
{
system("pause");
    sf::RenderImage rimage;
    rimage.Create(128, 128);
system("pause");
    return 0;
}


Still a 1 - 2 sec lag.


system("pause") is a system call so for it to go back to your process could add a lot time to the whole thing. You should use sf::Clock and print out the time it takes for it to get the real estimate.

Example:
Code: [Select]

sf::Clock clock;
sf::RenderImage image;
image.Create( 128, 128 );
std::cout << clock.GetElapsedTime() << std::endl;
Title: sf::RenderImage::Create extremely slow
Post by: lolz123 on May 14, 2011, 11:04:13 pm
It actually gave me 2.52619 secs when I tried that.
Title: sf::RenderImage::Create extremely slow
Post by: Laurent on May 14, 2011, 11:08:58 pm
What's your graphics card and OS? Are your graphics drivers up to date?
Title: sf::RenderImage::Create extremely slow
Post by: Groogy on May 14, 2011, 11:09:17 pm
Quote from: "lolz123"
It actually gave me 2.52619 secs when I tried that.

Without any system calls? Pheeew that is a lot. What kind of computer are you sitting on? Can I see the exact source you wrote or you wrote exactly like me?

Also for the future, you should prepare these textures on before hand. Draw them at run time but allocate them at initiation, any form of allocation at run time is just flawed and bad design. It's(new/delete/malloc/free) slow and also prohibits any threads from running, even if you don't have the OS have.
Title: sf::RenderImage::Create extremely slow
Post by: lolz123 on May 14, 2011, 11:21:25 pm
I'm running this on a laptop with a core 2 duo CPU and a HD 3670 GPU with latest drivers. I could try and throw my HD 5970 at it, but that shouldn't be necessary!

Here is the program I used, at the end the time flashes by:

Code: [Select]
int main()
{
    sf::Clock clock;
clock.Reset();
sf::RenderImage image;
image.Create( 128, 128 );
std::cout << clock.GetElapsedTime() << std::endl;

return 0;
}


Even though a system("pause") at the end wouldn't change anything, I wanted to be certain that system calls are not causing this problem.
Title: sf::RenderImage::Create extremely slow
Post by: Groogy on May 14, 2011, 11:27:34 pm
No that isn't the problem... Hmmm.... It's kind of weird. I don't have that problem at my computer. What time do you get if you create the image twice?
Title: sf::RenderImage::Create extremely slow
Post by: Laurent on May 14, 2011, 11:35:17 pm
Which revision of SFML are you using?
Title: sf::RenderImage::Create extremely slow
Post by: lolz123 on May 14, 2011, 11:35:57 pm
The 2nd one is slightly faster, but still ridiculously slow. It takes my 3.07967 secs to create 2 render images.
Title: sf::RenderImage::Create extremely slow
Post by: lolz123 on May 14, 2011, 11:36:46 pm
I am using SFML 2.
Title: sf::RenderImage::Create extremely slow
Post by: Laurent on May 14, 2011, 11:46:31 pm
I know... but which SFML 2?
Title: sf::RenderImage::Create extremely slow
Post by: lolz123 on May 14, 2011, 11:59:09 pm
Er... the one titled "LaurentGomila-SFML-cb1f938" (I can't find the official version).
Title: sf::RenderImage::Create extremely slow
Post by: Groogy on May 15, 2011, 12:25:17 am
Quote from: "lolz123"
Er... the one titled "LaurentGomila-SFML-cb1f938" (I can't find the official version).


That's a very old commit. It was done: 2011-04-05 (https://github.com/SFML/SFML/commit/cb1f9385825c4645dae1c233684699c6fcb6c0a7) If I get how Github works correctly.

Though looking in the upcoming commits I don't see anything that would have affected this. You never know though, do an update to the latest version.
Title: sf::RenderImage::Create extremely slow
Post by: lolz123 on May 15, 2011, 01:39:08 am
Ok, I ran it under the newest version of SFML2 (after wrestling with the usual linker errors :roll: ), but the lagging issue persists.
Title: sf::RenderImage::Create extremely slow
Post by: Groogy on May 15, 2011, 02:39:48 am
Well all I got left is that it's something to do with your computer/configuration that does it. Do you use visual studio or MinGW? Does it change if you change between them? Does it change if you change computer(interested in a different graphics card)? Ow yeah is the "graphic card" integrated graphics from Intel? Because that shit sucks real hard and could be the source of everything, no matter how good "card" you got.

I am not the developer(Laurent is) so if this is because of the code in sf::RenderImage I can't answer. Though I don't experience the problem your having on my computer so doesn't seem like it.
Title: sf::RenderImage::Create extremely slow
Post by: lolz123 on May 15, 2011, 02:52:05 am
I doubt it is my machine since I was able to compile and run some OpenGL render to texture demos with zero lag (same thing SFML is trying to do). I could, of course, completely ignore SFML and use the lower level OpenGL render to texture stuff, but if possible I would like to use SFML for this.
Title: sf::RenderImage::Create extremely slow
Post by: Laurent on May 15, 2011, 10:30:45 am
It's hard to debug, you're the only one who could find out what happens.

If you want to go further, you can put traces ("std::cout << clock.GetElapsedTime()") in the RenderImage creation code, to find out which line takes so long to execute.
Title: sf::RenderImage::Create extremely slow
Post by: xazax on May 15, 2011, 12:26:08 pm
Or look for and try some kind of profiling solution for debugging.
Title: sf::RenderImage::Create extremely slow
Post by: lolz123 on May 15, 2011, 02:11:23 pm
I'll let you know if I figure it out.
Title: sf::RenderImage::Create extremely slow
Post by: krisando on July 15, 2011, 09:22:19 pm
I think It's time to reincarnate this topic.

Extremely slow may be an understatement, calling create took nearly close to half a second. Doing that during runtime would be very slow. Would it not be possible to reduce this time for creating or adding a resize function to do so?

Tried this with MinGW on a quite high spec laptop, can take a few seconds on older hardware.
Title: sf::RenderImage::Create extremely slow
Post by: Laurent on July 16, 2011, 10:02:03 am
Can you show a minimal and complete code that reproduces the problem please?

Do you run your app in release or debug mode?
Title: sf::RenderImage::Create extremely slow
Post by: Haikarainen on July 16, 2011, 10:06:38 am
Viewed this topic and got bored so i made a benchmarker for sf::Image::Create.

It's creating an image the size of 1280x1280, 10 times, and calculates times + average time at the end.

Code: https://legacy.sfmluploads.org/index.php?page=view_code&id=52

My results using SFML2 - release(dont remember the branch im using):

Code: [Select]
Check started at 0.266 seconds

Pass 1:
        Start:          0.268sec
        End:            0.339sec
        Create() took   0.07sec

Pass 2:
        Start:          0.34sec
        End:            0.401sec
        Create() took   0.061sec

Pass 3:
        Start:          0.402sec
        End:            0.464sec
        Create() took   0.062sec

Pass 4:
        Start:          0.465sec
        End:            0.523sec
        Create() took   0.058sec

Pass 5:
        Start:          0.524sec
        End:            0.584sec
        Create() took   0.06sec

Pass 6:
        Start:          0.585sec
        End:            0.646sec
        Create() took   0.06sec

Pass 7:
        Start:          0.648sec
        End:            0.708sec
        Create() took   0.06sec

Pass 8:
        Start:          0.71sec
        End:            0.773sec
        Create() took   0.062sec

Pass 9:
        Start:          0.775sec
        End:            0.838sec
        Create() took   0.063sec

Pass 10:
        Start:          0.839sec
        End:            0.901sec
        Create() took   0.061sec

Check ended at 0.903 seconds

Average time of Create(): 0.061 seconds


And debug:

Code: [Select]
Check started at 0.269 seconds

Pass 1:
        Start:          0.27sec
        End:            0.366sec
        Create() took   0.096sec

Pass 2:
        Start:          0.367sec
        End:            0.455sec
        Create() took   0.088sec

Pass 3:
        Start:          0.456sec
        End:            0.541sec
        Create() took   0.085sec

Pass 4:
        Start:          0.542sec
        End:            0.625sec
        Create() took   0.083sec

Pass 5:
        Start:          0.625sec
        End:            0.708sec
        Create() took   0.082sec

Pass 6:
        Start:          0.71sec
        End:            0.793sec
        Create() took   0.082sec

Pass 7:
        Start:          0.795sec
        End:            0.878sec
        Create() took   0.082sec

Pass 8:
        Start:          0.88sec
        End:            0.964sec
        Create() took   0.083sec

Pass 9:
        Start:          0.966sec
        End:            1.051sec
        Create() took   0.084sec

Pass 10:
        Start:          1.053sec
        End:            1.138sec
        Create() took   0.085sec

Check ended at 1.14 seconds

Average time of Create(): 0.085 seconds
Title: sf::RenderImage::Create extremely slow
Post by: krisando on July 16, 2011, 12:46:09 pm
I made two important mistakes, running it once with the created object included in the time.

Even so 45-90ms is still quite high. Not sure what's involved but if it could be made more efficient or maybe a Resize() function. (Assuming it could be designed to do the job in a smaller time frame). Would be extremely beneficial.

Sure this shouldn't be run every frame, but it is a real fps killer.
Title: sf::RenderImage::Create extremely slow
Post by: xazax on July 16, 2011, 01:00:23 pm
I think, in case of such a dramatic performance drop, the first thing lolz123 should have done is some profiling. Maybe it could point out the performance bottleneck.
Title: sf::RenderImage::Create extremely slow
Post by: krisando on July 16, 2011, 01:14:10 pm
Would the SFML library have to be profiled when compiled or could the compiler manage itself.

There isn't a great deal of code in the Create() function, so it may just be unfeasible to make this any faster, the calls to the libraries SFML relies on may just be a tad slow. =[
Title: sf::RenderImage::Create extremely slow
Post by: Turbine on July 21, 2011, 08:23:45 am
Is there a chance this could be sped up at all?

This does need to be addressed, It's incredibly slow. I can sit at a stable 500fps  then dip all the way down to 17/18 on some quite capable hardware. SDL 1.2 can achieve with its software blitting surfaces nicely.
Title: sf::RenderImage::Create extremely slow
Post by: Haikarainen on July 21, 2011, 08:38:53 am
Quote from: "Turbine"
Is there a chance this could be sped up at all?

This does need to be addressed, It's incredibly slow. I can sit at a stable 500fps  then dip all the way down to 17/18 on some quite capable hardware. SDL 1.2 can achieve with its software blitting surfaces nicely.


Compile and run my benchmark that i replied with 1 page before in this thread. If you get significantly slower results, it's your code that is faulty.
Are you sure you dont sf::Image::Create() several frames in a row?
Title: sf::RenderImage::Create extremely slow
Post by: Turbine on July 21, 2011, 09:20:22 am
Yes, It is necessary to be able to do this, for this specific task.

I wouldn't be replying here if that faulty line of code weren't RenderImage's Create().
Title: sf::RenderImage::Create extremely slow
Post by: Laurent on July 21, 2011, 09:48:49 am
Quote
Yes, It is necessary to be able to do this, for this specific task.

Can you tell us more precisely how you use RenderImage?
Title: sf::RenderImage::Create extremely slow
Post by: Turbine on July 21, 2011, 10:10:33 am
A primitive test to see if it could handle the drawing efficiently when resized in runtime.
Code: [Select]

sf::RenderImage surface;
sf::Sprite surfaceSprite;
sf::Vector2i pos;  //Store mouse position, checks if changed

sf::RenderWindow window(sf::VideoMode(800, 600));
window.SetFramerateLimit(60);

while (window.IsOpened())
{
   sf::Event event;
   while (window.PollEvent(event))
   {
      // Window closed or escape key pressed : exit
      if (event.Type == sf::Event::Closed)
      {
         window.Close();
         break;
      }
   }

   window.Clear();

   //Surface test
   if (pos != sf::Mouse::GetPosition(window))  //Change if mouse moved
   {
      pos = sf::Mouse::GetPosition(window);
      surface.Create(pos.x, pos.y);  //This line
      surface.Clear(sf::Color::White);
      surface.Display();
   }

   surfaceSprite.SetImage(surface.GetImage());
   window.Draw(surfaceSprite);

   //Draw fps
   int temp = window.GetFrameTime();
   if (temp > 0)
   {
      char out[3];
      int fps = 1000 / temp;   //Some computers 1 / time works, for this pc only 1000 gives accurate amount
      itoa(fps, out, 10);
      sf::Text text(out);
      window.Draw(text);
   }

   //
   window.Display();
}


Reallocating an area for a surface per frame may be extreme, but achieving 17-18 of these a second is quite limiting. Just need a way to resize in a reasonable amount of time.
Title: sf::RenderImage::Create extremely slow
Post by: Laurent on July 21, 2011, 10:14:42 am
Ok I see. RenderImages are not meant to be created every frame (or every mouse move), this is really a slow operation -- it allocates and initializes a rendering texture on the graphics card. That's the cost of having accelerated draw-to-texture. In comparison, SDL is fast to create a surface but then slow to draw to it.

A better strategy for your example would be to create the surface with the same size as the window, and simply adjusting the subrect of the sprite when the mouse moves. The render-image doesn't need to be resized when you just want to show a smaller area of it ;)
Title: sf::RenderImage::Create extremely slow
Post by: krisando on July 21, 2011, 12:04:50 pm
Ah thankyou, that's a really neat idea. :)

Would I run into any problems with texture size limits, like 512x512 on Intel?
Title: sf::RenderImage::Create extremely slow
Post by: Laurent on July 21, 2011, 12:21:44 pm
Indeed, the RenderImage size must not be greater than Image::GetMaximumSize().
Title: sf::RenderImage::Create extremely slow
Post by: Turbine on July 21, 2011, 09:53:23 pm
It's good that there's a function which is aware of this limit, very helpful, thanks.
Title: sf::RenderImage::Create extremely slow
Post by: Ryder on July 24, 2011, 01:47:04 pm
Having a similar issue, I added some traces in RenderImage::Create().
The slow operation is the call to XGetWindowAttributes() in GlxContext::CreateContext() which tooks 170ms.

I'm using the last git version (99b33e8) with Intel HD Graphics 3000.
Also, RenderImage does not seem work at all (which is not uncommon with Intel graphics, according to other topics).
For instance, the following code produces a black PNG image instead of a blue one:
Code: [Select]
sf::RenderImage img;
img.Create(32, 32);
img.SetActive(true);
img.Clear(sf::Color::Blue);
img.Display();
img.GetImage().SaveToFile("a.png");


On Windows 7, everything works fine, RenderImage is not slow and images are rendered as expected.
Title: sf::RenderImage::Create extremely slow
Post by: Laurent on July 24, 2011, 03:27:32 pm
Quote
The slow operation is the call to XGetWindowAttributes() in GlxContext::CreateContext() which tooks 170ms.

Thanks, that's good to know.

I don't consider this a problem, but... XGetWindowAttributes won't be called anymore when I fix another bug, so render-image creation will be a little faster one day ;)