SFML community forums
Help => Graphics => Topic started 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?
// 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));
}
-
Does it really take 1 - 2 sec to create a single render image??
-
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.
-
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.
-
So it should be the same with this piece of code, right?
int main()
{
sf::RenderImage rimage;
rimage.Create(128, 128);
return 0;
}
-
Just tried this out in my own system:
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.
-
Yes. I had to change it to this so I could actually tell how much time went by:
int main()
{
system("pause");
sf::RenderImage rimage;
rimage.Create(128, 128);
system("pause");
return 0;
}
Still a 1 - 2 sec lag.
-
Yes. I had to change it to this so I could actually tell how much time went by:
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:
sf::Clock clock;
sf::RenderImage image;
image.Create( 128, 128 );
std::cout << clock.GetElapsedTime() << std::endl;
-
It actually gave me 2.52619 secs when I tried that.
-
What's your graphics card and OS? Are your graphics drivers up to date?
-
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.
-
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:
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.
-
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?
-
Which revision of SFML are you using?
-
The 2nd one is slightly faster, but still ridiculously slow. It takes my 3.07967 secs to create 2 render images.
-
I am using SFML 2.
-
I know... but which SFML 2?
-
Er... the one titled "LaurentGomila-SFML-cb1f938" (I can't find the official version).
-
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.
-
Ok, I ran it under the newest version of SFML2 (after wrestling with the usual linker errors :roll: ), but the lagging issue persists.
-
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.
-
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.
-
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.
-
Or look for and try some kind of profiling solution for debugging.
-
I'll let you know if I figure it out.
-
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.
-
Can you show a minimal and complete code that reproduces the problem please?
Do you run your app in release or debug mode?
-
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):
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:
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
-
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.
-
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.
-
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. =[
-
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.
-
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?
-
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().
-
Yes, It is necessary to be able to do this, for this specific task.
Can you tell us more precisely how you use RenderImage?
-
A primitive test to see if it could handle the drawing efficiently when resized in runtime.
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.
-
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 ;)
-
Ah thankyou, that's a really neat idea. :)
Would I run into any problems with texture size limits, like 512x512 on Intel?
-
Indeed, the RenderImage size must not be greater than Image::GetMaximumSize().
-
It's good that there's a function which is aware of this limit, very helpful, thanks.
-
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:
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.
-
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 ;)