SFML community forums

Help => Graphics => Topic started by: TheEnigmist on March 09, 2012, 03:06:00 pm

Title: Better FPS drawing 10.000 sprite
Post by: TheEnigmist on March 09, 2012, 03:06:00 pm
I'm testing this code to lern how can i get more FPS. Running it in Release without debugging mode:
Code: [Select]
#include <iostream>
#include <SFML/Graphics.hpp>

int main()
{
sf::Clock clock;
sf::Texture prova;
prova.LoadFromFile("icon.png");
std::vector<sf::Sprite> test;
for (int i=0; i<10000; ++i){
test.push_back(sf::Sprite(prova));
test[i].SetPosition(0.1*i,0.05*i);
}
sf::RenderWindow App(sf::VideoMode(1024,768,32),"Test Test",sf::Style::Close);
App.SetFramerateLimit(300);
sf::RenderTexture renderTest;
clock.Restart();
renderTest.Create(1024,768);
std::cout << clock.GetElapsedTime().AsMilliseconds() << std::endl;
while(App.IsOpen()){
sf::Event events;
while(App.PollEvent(events)){
if (events.Type == sf::Event::KeyPressed && events.Key.Code == sf::Keyboard::Escape)
App.Close();
}
renderTest.Clear(sf::Color::Blue);
clock.Restart();
for (unsigned int i=0; i<test.size(); ++i)
renderTest.Draw(test[i]);
std::cout << clock.GetElapsedTime().AsMilliseconds()<<std::endl;
renderTest.Display();

App.Clear();

// Draw the texture
sf::Sprite sprite(renderTest.GetTexture());
App.Draw(sprite);
App.Display();
}
return EXIT_SUCCESS;
}

Using playclaw/fraps i get 14~19 FPS to draw all item and less than 50ms to draw all 10.000 item into renderTest.
How can i get more FPS drawing all this 10.000 sprites?
Title: Better FPS drawing 10.000 sprite
Post by: luiscubal on March 09, 2012, 03:27:24 pm
For starters, console IO does lower the performance.
Perhaps it would be better to only show the FPS every few frames(sum the total times of every 20 frames, and then divide by 20 when showing).
Title: Better FPS drawing 10.000 sprite
Post by: mateandmetal on March 10, 2012, 07:12:26 am
Fraps will lower your fps to hell.. Make your own fps class.. its very easy.. there is an example on the wiki
Title: Better FPS drawing 10.000 sprite
Post by: TheEnigmist on March 10, 2012, 10:28:13 am
Quote from: "mateandmetal"
Fraps will lower your fps to hell.. Make your own fps class.. its very easy.. there is an example on the wiki

Ok i will and we will see how much FPS i do with 10.000 sprite drawing :lol:
Some1 can explain me how can i use VertexArray to draw all these 10.000 sprites?
Title: Better FPS drawing 10.000 sprite
Post by: dydya-stepa on March 10, 2012, 11:23:13 am
i want to hear why are you doing this test. this sounds completely useless. what are going to do with the result when you finally measure your fps?
Title: Better FPS drawing 10.000 sprite
Post by: TheEnigmist on March 10, 2012, 11:28:23 am
Quote from: "dydya-stepa"
i want to hear why are you doing this test. this sounds completely useless. what are going to do with the result when you finally measure your fps?


I was thinking to make a game with 10.000+ object to draw/update! And i want to see how can i manage this as well as i can!
Title: Better FPS drawing 10.000 sprite
Post by: Laurent on March 10, 2012, 05:41:45 pm
Quote
Fraps will lower your fps to hell.

Hm? It's very lightweight, it has no impact on the performances.

Quote
I was thinking to make a game with 10.000+ object to draw/update! And i want to see how can i manage this as well as i can!

It's not enough to know how to manage them in the most efficient way. It really depends on what you'll do with these objects, there's no generic answer.
If they are static and all share the same texture, then put them all in one big vertex array and that's it.
Otherwise, you'll have to tell us more details.
Title: Better FPS drawing 10.000 sprite
Post by: TheEnigmist on March 10, 2012, 08:01:52 pm
Quote from: "Laurent"
Quote
Fraps will lower your fps to hell.

Hm? It's very lightweight, it has no impact on the performances.

Quote
I was thinking to make a game with 10.000+ object to draw/update! And i want to see how can i manage this as well as i can!

It's not enough to know how to manage them in the most efficient way. It really depends on what you'll do with these objects, there's no generic answer.
If they are static and all share the same texture, then put them all in one big vertex array and that's it.
Otherwise, you'll have to tell us more details.


I was thinking to make a city in 2d! So houses, npcs, objects, enemies, all sprite to write and update.
Maybe for enemies and npcs i can use the same texture! House maybe will be different! But this is still an idea of what i want to make. Maybe i will open a new thread when i'm ready to start this project!
Title: Better FPS drawing 10.000 sprite
Post by: Mjonir on March 10, 2012, 08:06:16 pm
Quote from: "TheEnigmist"
I was thinking to make a city in 2d! So houses, npcs, objects, enemies, all sprite to write and update.
Maybe for enemies and npcs i can use the same texture! House maybe will be different! But this is still an idea of what i want to make. Maybe i will open a new thread when i'm ready to start this project!


But you won't draw the whole city at once on the scree, will you? :o
Title: Better FPS drawing 10.000 sprite
Post by: TheEnigmist on March 11, 2012, 11:49:39 am
Quote from: "Mjonir"
Quote from: "TheEnigmist"
I was thinking to make a city in 2d! So houses, npcs, objects, enemies, all sprite to write and update.
Maybe for enemies and npcs i can use the same texture! House maybe will be different! But this is still an idea of what i want to make. Maybe i will open a new thread when i'm ready to start this project!


But you won't draw the whole city at once on the scree, will you? :o

Uhm i think no, i wont :O A good way is to draw only object in view+little offset, isn't it?
Title: Better FPS drawing 10.000 sprite
Post by: Mjonir on March 11, 2012, 01:55:06 pm
Yep. Also depending on what you want to do, you don't have to simulate de whole city either. If you can, separate it block by block and just simulate/draw the visible blocks and possibly its surroundings.
Title: Better FPS drawing 10.000 sprite
Post by: TheEnigmist on March 11, 2012, 02:10:19 pm
Quote from: "Mjonir"
Yep. Also depending on what you want to do, you don't have to simulate de whole city either. If you can, separate it block by block and just simulate/draw the visible blocks and possibly its surroundings.


Updating the city is faster and doesn't affect game's FPS?
Title: Better FPS drawing 10.000 sprite
Post by: Groogy on March 11, 2012, 03:08:18 pm
Look the problem will most probably(Haven't tested especially for SFML but for 3D this is valid) be the fill rate of the GPU and the driver calls(draw calls). Any overdraw of pixels that have already been painted on is a waste and GPU's rasterizers are pretty slow for modern graphics. The vertex assembler, shader, etc. etc. is insanely fast and you must reach several millions vertexes before it becomes a problem. Though the rasterizer is starting to have a problem as soon as you reach the pixel amount of the max resolution. Some GPU's can't even handle the max resolution.(mine for instance can't, it just about manages)

So if you want to draw ~10 000 sprites on screen you will face two bottlenecks. The draw calls for each sprite and the pixel overdraw.

So what are your options? Well since SFML doesn't have a depth buffer you can't do a front to back render to remove the pixel overdraw so your stuck with that. What you can do is render static environment to in-memory textures and render those only once and such remove the overdraw from there. And then we have the draw calls. First step is to cull and only render stuff that is shown on the screen. But that won't be enough because you most probably will still be showing a lot of sprites at once on the screen. The solution here is Instancing but is only supported on later hardware(OpenGL 3+) but kind Almighty Laurent have provided us with an alternative ;) Vertex arrays. If possible you can link the sprites together into one vertex array and render them with one draw call.

These things might be seen as pretty advanced but when it comes to optimizing the GPU it becomes pretty advanced ^^
Summary is more or less, limit your draw calls and the amount of pixels you render and your performance will go up.

If needed I can give the research and data and explanation for why these things are valid ^^
Though thumb of rule, never trust anything until you've tested it yourself. Always benchmark and profile everything when you are optimizing.
Title: Better FPS drawing 10.000 sprite
Post by: Mjonir on March 11, 2012, 03:26:16 pm
Quote from: "TheEnigmist"
Updating the city is faster and doesn't affect game's FPS?


It depends on what you simulate. And even if your display is very fast, it might still cause problems if you can only simulate once out of ten display frames for example.

It really depends on what you're doing though but for my own project (which is roughly about displaying between 500 and 1000 objects on screen, each having its own complex logic), I'm pretty sure the bottleneck is in the simulation, not drawing.

Quote from: "Groogy"
Though thumb of rule, never trust anything until you've tested it yourself. Always benchmark and profile everything when you are optimizing.


On that subject, which tools do you use for profiling?
Title: Better FPS drawing 10.000 sprite
Post by: Groogy on March 11, 2012, 04:22:37 pm
Quote from: "Mjonir"
Quote from: "Groogy"
Though thumb of rule, never trust anything until you've tested it yourself. Always benchmark and profile everything when you are optimizing.


On that subject, which tools do you use for profiling?


For CPU we have my own profiling library, Intel VTune Performance Analyzer and for GPU I use Nvidia Parallell Nsight and Pix. I don't use VTune anymore since my profiling library replaces it without the gigantic overhead Vtune adds but for really hard tracked bottlenecks(I have NO idea where they are more or less) I still use Vtune.

And no I can''t give out the library as it's closed source and not owned by me. I can however answer questions and write code-snippets based on the library. More or less I am allowed to educate someone in how it works and show example code.

A quick way to see if you are GPU/Graphics bound or CPU/Logic bound is to check your CPU usage and compare to your framerate. So open up the task manager, if you are having low FPS and your CPU usage is low then something is wrong on the GPU and if you have high usage and low FPS then something is wrong on the CPU. That's probably the simplest test.
Title: Better FPS drawing 10.000 sprite
Post by: Ptlomej on March 11, 2012, 07:47:06 pm
i draw about 100*random(100,500) Sprites with a little trick and high performance :)
Title: Better FPS drawing 10.000 sprite
Post by: TheEnigmist on March 11, 2012, 08:50:31 pm
Quote from: "Ptlomej"
i draw about 100*random(100,500) Sprites with a little trick and high performance :)

Can you explain how or it's a secret? :)
Title: Better FPS drawing 10.000 sprite
Post by: Ptlomej on March 11, 2012, 10:00:39 pm
Here and example :)

i have an Area 1000x1000.
I create now 100 sf::Images

Code: [Select]

for(int x = 0; x != 100; x++){
    sf::Image *Chunk = new sf::Image;
    Chunk->Create(1000,1000);
}


Then i add all the Objects that are on this area schould be with
Code: [Select]

Chunk->Copy(Exampleimage,X,Y,IntRect(0,0,Exampleimage.GetWidth(),Exampleimage.GetHeight()),true);


then convert to the sprites and add too sprite list
Code: [Select]
Texture *tChunk = new Texture;
tChunk->LoadFromImage(Chunk,IntRect(0,0,1000,1000));
Sprite *sChunk = new sf::Sprite(*tChunk);
sChunk->SetOrigin(0,0);
sChunk->SetPosition(sf::Vector2f((float)xCount,(float)yCount));
BackgroundChunks.push_back(sChunk);


generate new position for the next "chunk"
Code: [Select]
xCount += 1000;
xCounter++;
if(xCount == 5000){
xCount = -5000;
yCount += 1000;
xCounter = 0;
yCounter++;
}


and then Draw the 100 Sprites
Code: [Select]
for(list<sf::Sprite*>::iterator IT = BackgroundChunks.begin(); IT != BackgroundChunks.end(); IT++){
_RenderWindow->Draw(**IT);
}


its very simple ;)
Title: Better FPS drawing 10.000 sprite
Post by: Nexus on March 12, 2012, 11:56:42 am
Ptolemaj, why are you using pointers and new? There's no reason, just use std::vector<sf::Sprite> or std::vector<sf::Texture>. It's even faster, since not every sprite/texture is allocated on its own. Same applies for the usage of vector instead of list. And avoiding manual memory management is simpler and less error-prone.

And why don't you directly have a sf::Texture with the needed sub-rects?
Title: Better FPS drawing 10.000 sprite
Post by: Mjonir on March 12, 2012, 09:21:15 pm
Just a word on SFML performance in drawing a lot of sprites:

I have a benchmark for my engines that creates 500 animated objects, each with an independent and quite complex (voluntarily unoptimized! It could easily be!) move sequence that is computed in Lua. I get about 35 FPS.  A simpler move sequence gives me around 110 FPS.

I was curious so I programmed a little profiling lib today and checked where the horsepower was going:

- 95% of the time is spent calculating the next frame.
- Which means only 5% of the frame is spent drawing.
- Out of the 95%, about 1 or 2% is checking keyboard/mouse/window events
- I'd say 2% for the engine itself (collision detection, etc.)
- 90% spent computing the move sequences (it's sequential, unoptimized, very complex and goes through a Lua interpreter, but still that's the kind of complexity you could easily get for a "whole city" above :)).

Even better, I have an option on my engine that separates the update from display, and thus on a dual core display doesn't even matter at all.

That's to say: Don't worry too much about drawing lots of sprites, that's maybe not your bottleneck thanks to SFML.
Title: Better FPS drawing 10.000 sprite
Post by: mateandmetal on March 13, 2012, 12:10:08 am
Quote from: "Ptlomej"

Code: [Select]

for(int x = 0; x != 100; x++){
    sf::Image *Chunk = new sf::Image;
    Chunk->Create(1000,1000);
}


I see memory leaks  :lol:

Btw..What about using tilemaps for the city? Drawing a tilemap using VertexArray is very fast
Title: Better FPS drawing 10.000 sprite
Post by: Nexus on March 13, 2012, 06:45:21 pm
I agree with Mjonir. You also have to make sure you are compiling with the right features, e.g. release mode. Also start without debugger (even in release mode), it can make a huge difference, especially for dynamic allocations. Also, some STL implementations use error checks that need to be disabled manually.
Title: Better FPS drawing 10.000 sprite
Post by: TheEnigmist on March 13, 2012, 08:07:52 pm
Quote from: "Nexus"
I agree with Mjonir. You also have to make sure you are compiling with the right features, e.g. release mode. Also start without debugger (even in release mode), it can make a huge difference, especially for dynamic allocations. Also, some STL implementations use error checks that need to be disabled manually.


Is it a good idea to disable STL error checks? Do they take much memory to check errors?
Title: Re: Better FPS drawing 10.000 sprite
Post by: drifton on March 29, 2012, 01:41:32 pm
two things that will greatly improve tiles on today's hardware,  vba/vbo and texture atlas/ ie compiling all your sprites and tiles into one texture/image,

steps process map to determine number of quads needed for background, fringes , transitions, buildings, ect...

apply uv that reference the tile image in the atlas/tilesheet what ever you really want to call it

draw base tile/fringe vbos
draw objects (characters, chests, npc's , enemies)  vbo
draw cover tile vbo
done

even with alpha blendening you are looking at very few triangles being drawn for today'a hardware
point in case 1920x1080 screen filled with 16x16 tiles with 4 layers = 32,400 tiles per frame or ~ 3.89 million triangles per-second and even the old geforce 2 could draw ~25 million triangles per second



and that really is all brute force with out you dropping the tiles in the 3 top layers that are not drawn out of the vertex buffer and in most cases are just empty space in my game and i actually have several smaller buffer so that it's easier on me to just update tiles like water animation every few frames / characters