I'm using a custom particle system for my LibGDX / Java based game project (because I used Slick2D earlier on, need more parameters so I made my own and then ported). The system is fairly standard as far as I'm concerned, uses particle pooling (each emitter has its own fixed size particle pool) and renders each particle in a batch and uses one single (2048x1028) packed texture with all particle textures on it. Here is how I render the particles in semi-pseudo-code (because the entire code isn't relevant):
//ParticleSystem class
//Note: ExtendedBatch is my custom sprite batch implementation, largely just the normal SpriteBatch with two additional vertices for grayscale factor and additive tinting
void renderEmitter(ParticleEmitter emitter, ExtendedBatch batch)
{
ParticlePool pool = particlePools.get(emitter);
if (emitter.shouldScissor)
Renderer.pushScissor(emitter.scissor);
for (Particle particle : pool.particles)
{
if (particle.inUse)
particle.render(batch);
}
if (emitter.shouldScissor)
Renderer.popScissor();
}
//Particle class
void render(ExtendedBatch batch)
{
relativeX = getRelativeX();
relativeY = getRelativeY();
if (isInScreenBounds(relativeX, relativeY))
{
batch.setColor(myColor);
batch.draw(myTexture, position, origin, size, scale, rotation);
}
}
Now for some reason with only around 300 particles (split up into 10 emitters with varying sizes) the performance drops to awful ~30FPS on my notebook's integrated GPU (Intel HD 4400) when I need / want 60FPS at all times. I know iGPUs aren't great, but that one is one of the better ones out there and games like Ori or Braid which have thousands of similar particles run without any problems at 60FPS on that very chip. I also doubt (and hope) that it's not just Java vs C++ which is causing this huge performance drop here.
Looking at in-game profiling data:
The in-game profiling data however shows a few things: Particles aren't really taking that long to render and there is a lot of idle time. To me, that doesn't really make much sense. It looks like there would be enough resources to easily render everything at 200FPS or more, but it is stuck at a horrible 30FPS.
There are a lot of things I already tried that didn't help:
- Packing all particle textures into one (which is 2048x1024)
- Batching all particle draw calls
- Profiling to find out the cause (see above)
- VisualVM to find potential memory issues, didn't help
- Disabling vSync and FPS locks doesn't help
For the record, here's a VisualVM CPU sample over a timespan of 2 minutes:
There must be something I'm doing wrong and I also want / need more particles than just 300 so I definitely have to fix this - but I don't know how.
Update: Using the default SpriteBatch implementation and default shaders doesn't improve performance either.
Update - Solution:
I forgot to turn off MSAA. I had it running at 2x sampling rate for smoother antialising, I completely forgot to check for that. In the meantime I improved performance in a lot of other parts, but that's what finally did it.