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

Author Topic: Bullet Hell performance and optimization problems  (Read 23585 times)

0 Members and 1 Guest are viewing this topic.

SuperV1234

  • SFML Team
  • Full Member
  • *****
  • Posts: 190
    • View Profile
Bullet Hell performance and optimization problems
« Reply #15 on: June 14, 2010, 08:15:24 pm »
Quote from: "Laurent"
Quote
Code: [Select]
return new Bullet(this);

Aren't you supposed to store this one in BulletManager.Entities?


The bullet is stored in BulletManager.Entities thanks to its constructor.
 
Code: [Select]
public Bullet(Game game) : base(game)
        {
            Game.BulletManager.Entities.Add(this);
        }

Spodi

  • Full Member
  • ***
  • Posts: 150
    • View Profile
    • http://www.netgore.com/
Bullet Hell performance and optimization problems
« Reply #16 on: June 14, 2010, 09:19:19 pm »
Well if my 8800 GTS is running it just fine and your GTX 275 is not, its most likely not a problem with your code logic. Its not like my CPU is exactly powerful anymore, either.

For the sprites, you will definitely want to start pooling them instead of creating a new instance per each bullet. You probably can even just use a different Sprite instance for each bullet graphic, not each bullet. Or use one single global Sprite instance and just set it up before each time you draw it.

SuperV1234

  • SFML Team
  • Full Member
  • *****
  • Posts: 190
    • View Profile
Bullet Hell performance and optimization problems
« Reply #17 on: June 14, 2010, 09:25:45 pm »
Quote from: "Spodi"
Well if my 8800 GTS is running it just fine and your GTX 275 is not, its most likely not a problem with your code logic. Its not like my CPU is exactly powerful anymore, either.

For the sprites, you will definitely want to start pooling them instead of creating a new instance per each bullet. You probably can even just use a different Sprite instance for each bullet graphic, not each bullet. Or use one single global Sprite instance and just set it up before each time you draw it.


It runs fine on my GTX275 with less than 5000 bullets. The source code I posted before works perfectly. It's just if I add more than 4800-4900 bullets.

I can't use a single Sprite instance. Maybe you meant a single Image instance?

Ashenwraith

  • Sr. Member
  • ****
  • Posts: 270
    • View Profile
Bullet Hell performance and optimization problems
« Reply #18 on: June 15, 2010, 05:47:56 am »
You might not be able to use a single sprite, but you should be able to use a single constant instance of bounding boxes for each bullet sprite identical.

In a lot of bullet hell games the bullets come out in patterns and cannot be altered

Because of this you can do a lot of pre-guessing illusion work for example in growing rings or wave patterns of what the collision/position should be and even the graphicss.

Another example: streams/blocks of bullets can be built into rectangles for collison.

Want to go even further?

Cull collision detection for enemy bullets based on their ability to hit the character. IE, many bullets will be out of range and impossible to hit, especially if you are already surrounding the character with bullets.

Move offscreen bullets instead of destroying/creating them.

Perhaps even flickering your bullet sprites and drawing them every other frame might help too?

Make your bullets out of an sf::Shape?

SuperV1234

  • SFML Team
  • Full Member
  • *****
  • Posts: 190
    • View Profile
Bullet Hell performance and optimization problems
« Reply #19 on: June 15, 2010, 10:01:46 pm »
Latest source code: http://www.mediafire.com/?ih2kojte1uo

I think I found the problem:
Code: [Select]
public virtual void Tick()
        {
            Sprite.Position = new Vector2(X, Y);
           // Game.RenderWindow.Draw(Sprite);
        }


By commenting the Draw instruction, the game handles 20000 bullets without slowdowns.

Is it a SFML limitation, or is there any chance I'm doing something wrong drawing the sprite?

Ashenwraith

  • Sr. Member
  • ****
  • Posts: 270
    • View Profile
Bullet Hell performance and optimization problems
« Reply #20 on: June 15, 2010, 11:16:30 pm »
Well looking at the code above should you really be creating a new vector every time you change the position and draw the sprite?

If the problem is drawing speed you could try saving your images in dds and see if that helps, but I'd look closer at your data creation/management or any unnecessary loops.

SuperV1234

  • SFML Team
  • Full Member
  • *****
  • Posts: 190
    • View Profile
Bullet Hell performance and optimization problems
« Reply #21 on: June 15, 2010, 11:28:56 pm »
Quote from: "Ashenwraith"
Well looking at the code above should you really be creating a new vector every time you change the position and draw the sprite?

If the problem is drawing speed you could try saving your images in dds and see if that helps, but I'd look closer at your data creation/management or any unnecessary loops.


X and Y are read-only in Vector2.

Why should saving imgage in dds help? I've never used dds files before.

Ashenwraith

  • Sr. Member
  • ****
  • Posts: 270
    • View Profile
Bullet Hell performance and optimization problems
« Reply #22 on: June 16, 2010, 02:17:13 am »
Quote from: "SuperV1234"
Quote from: "Ashenwraith"
Well looking at the code above should you really be creating a new vector every time you change the position and draw the sprite?

If the problem is drawing speed you could try saving your images in dds and see if that helps, but I'd look closer at your data creation/management or any unnecessary loops.


X and Y are read-only in Vector2.

Why should saving imgage in dds help? I've never used dds files before.


I know it's read only because every Sprite contains an internal copy so you don't need a new Vector each time.

You can use one sf::Vector2f and use Sprite.GetPosition() to set it, transform, and then use Sprite.SetPosition(sf::Vector2f); And just repeat over and over, no?

I think the problem is there are all of these useless vectors floating around doing nothing every time you move a sprite.

DDS goes directly into video memory without any decompression/work and is much smaller so any time you are moving around lots of texture data it's a lot faster. You may just notice the initial load being faster if you aren't doing anything complex.

Mindiell

  • Hero Member
  • *****
  • Posts: 1261
    • ICQ Messenger - 41484135
    • View Profile
Bullet Hell performance and optimization problems
« Reply #23 on: June 16, 2010, 06:17:04 am »
Quote from: "SuperV1234"
By commenting the Draw instruction, the game handles 20000 bullets without slowdowns.

Is it a SFML limitation, or is there any chance I'm doing something wrong drawing the sprite?

I'm not really sure about what I'll say, because I can't open your code file (Ubuntu, so C# is hard to read).

But, what I understand is that you are not drawing all your sprites in one block. I think that SFML2 was optimized for such things. If you are drawing some sprites and doing others things, you are not using SFML optimization.
Can you show us your main loop and the place where you are doing the drawings ?
I usually do updates of all my objects, then drawing of all them.
Mindiell
----

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Bullet Hell performance and optimization problems
« Reply #24 on: June 16, 2010, 08:28:19 am »
Quote
You can use one sf::Vector2f and use Sprite.GetPosition() to set it, transform, and then use Sprite.SetPosition(sf::Vector2f); And just repeat over and over, no?

I think the problem is there are all of these useless vectors floating around doing nothing every time you move a sprite.

It's C#, not C++. So there are no GetPosition/SetPosition, and using "new Vector2" on every call is fine, the GC will take care of the unused memory.

Quote
DDS goes directly into video memory without any decompression/work and is much smaller so any time you are moving around lots of texture data it's a lot faster. You may just notice the initial load being faster if you aren't doing anything complex.

It doesn't make any difference, SFML internally handles the pixel data the same way regardless the original file format. The format information is lost right after the loading step.
Laurent Gomila - SFML developer

Ashenwraith

  • Sr. Member
  • ****
  • Posts: 270
    • View Profile
Bullet Hell performance and optimization problems
« Reply #25 on: June 16, 2010, 08:46:59 am »
Quote from: "Laurent"
Quote
You can use one sf::Vector2f and use Sprite.GetPosition() to set it, transform, and then use Sprite.SetPosition(sf::Vector2f); And just repeat over and over, no?

I think the problem is there are all of these useless vectors floating around doing nothing every time you move a sprite.

It's C#, not C++. So there are no GetPosition/SetPosition, and using "new Vector2" on every call is fine, the GC will take care of the unused memory.

Quote
DDS goes directly into video memory without any decompression/work and is much smaller so any time you are moving around lots of texture data it's a lot faster. You may just notice the initial load being faster if you aren't doing anything complex.

It doesn't make any difference, SFML internally handles the pixel data the same way regardless the original file format. The format information is lost right after the loading step.


No get and set? Well maybe the garbage man is a little fat and needs some help.  :D

Wow that's kind of disappointing to hear that about dds. I assumed that might be true because there were no sf::Uint5 or 565. That's kind of disappointing. A lot of my old tech is based on DDS optimization. I guess I have to write those in myself?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Bullet Hell performance and optimization problems
« Reply #26 on: June 16, 2010, 09:02:04 am »
But do you really need DDS optimizations?
Laurent Gomila - SFML developer

Ashenwraith

  • Sr. Member
  • ****
  • Posts: 270
    • View Profile
Bullet Hell performance and optimization problems
« Reply #27 on: June 16, 2010, 09:34:16 am »
Quote from: "Laurent"
But do you really need DDS optimizations?


Oh definitely!

When you are dealing with thousands of HD sprites DDS is a lifesaver. The vram usage is so much smaller. It's really not even possible to get the same graphics to work on the same hardware.

The average sprite set in my previous game is 1000-2000 sprites at approx 800x400 each for just one character. This fit in at about 80 megs of vram.

With png this is impossible.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Bullet Hell performance and optimization problems
« Reply #28 on: June 16, 2010, 09:37:09 am »
I see.

Unfortunately, I don't plan to add compressed texture formats to SFML.
Laurent Gomila - SFML developer

Spodi

  • Full Member
  • ***
  • Posts: 150
    • View Profile
    • http://www.netgore.com/
Bullet Hell performance and optimization problems
« Reply #29 on: June 16, 2010, 09:38:48 am »
Quote from: "SuperV1234"
Using a profiler I noticed that SFML.Graphic.Sprite instances do not get cleaned up. Running a program at 60FPS for a long time can make 60.000, 70.000 Sprite instances. How can I prevent that?


It will clean up when the GC runs as long as you have no dangling references. You can manually invoke the GC (see the static class members for the "GC" class), but doing so isn't usually needed and shouldn't be done unless you know what you are doing and have spent some time studying the GC. If you have no dangling references, the GC may just not have needed to run yet. They won't affect performance sitting there dead (until the GC runs), so that isn't much of an issue. The fact that you have so many instances is probably a bit of an issue, though, which is why I suggested just using a single global instance of Sprite. That, or design an object pool (a simple Stack<> often suffices).

Quote from: "SuperV1234"

It runs fine on my GTX275 with less than 5000 bullets. The source code I posted before works perfectly. It's just if I add more than 4800-4900 bullets.


Ah, I see. Sorry for the confusion.

Quote from: "SuperV1234"

I can't use a single Sprite instance. Maybe you meant a single Image instance?


Quote from: "Ashenwraith"
You might not be able to use a single sprite


Why not? You should definitely be using a single Image instance since its all the same image, but you can also use the same Sprite instance. Just set the values on the sprite before drawing it.

Quote from: "Ashenwraith"
Well looking at the code above should you really be creating a new vector every time you change the position and draw the sprite?


Structs are not objects in C#, they are value types and are generally considered incredibly cheap. As far as implementation goes, "new" on a struct is completely different than on an object, and structs never result in garbage collection (unless the struct constructor itself generates objects, which itself is a bad idea).

Quote from: "Ashenwraith"
DDS goes directly into video memory without any decompression/work and is much smaller so any time you are moving around lots of texture data it's a lot faster. You may just notice the initial load being faster if you aren't doing anything complex.


DDS can help with loading times like you mentioned, but once its loaded, its all the same no matter what the source was. It does nothing to help the issue of drawing tons of bullets.

Storing in memory in a DDS format can help when bandwidth is an issue, but I highly doubt that would be the case here. I wouldn't be surprised at all if API calls were the main bottleneck.