Need some tips to improve performance

Note: the shadow stuff will render the whole scene again from the perspective of the light. So any scene problems (like 8000 draw calls) will show up there again.

If those 200 little guys are animated… that’s a lot. If you detect that they are on the back side of the planet (cam direction dot product with the up vector of the little guy) then you could turn them off: disable the animation control and set cull hint to always.

If they are not animated, that will still help… but getting them down to one mesh would be best of all. Cuts it down to 1/4th of the draw calls for them.

1 Like

@oxplay2 I understand what you are explaining, but the point is that there is something weird going on. Every human seems to count as 4 objects but I am very sure there is only one mesh in this model:
Schermafdruk van 2022-11-15 15-07-45

So where do the three other objects come from?

@pspeed: I’ll try that one right away.

With all of those attachment nodes… do they have things attached to them at runtime like spears or something?

I’ve made the assumption so far that your scene only has one light. Yes?

There is a Directional Light and an Ambient Light, the latter should not impact rendering too much, am I right?

And the guys do not hold any other objects.

what postprocessors/filters do you use?

And just in case, make sure that “hardware skinning” is enabled for animated models otherwise it may highly impact performance.

In the debug console I found there are a lot of these:

nov. 15, 2022 8:46:55 P.M. com.jme3.util.ReflectionAllocator destroyDirectBuffer
SEVERE: Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=64 cap=64]
nov. 15, 2022 8:46:55 P.M. com.jme3.util.ReflectionAllocator destroyDirectBuffer
SEVERE: Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=64 cap=64]
nov. 15, 2022 8:46:55 P.M. com.jme3.util.ReflectionAllocator destroyDirectBuffer

Could that be a timeconsumer?

I guess that is related to this issue

Are you using lwjgl2 with a new java version (16+)?

Edit:
If so, you may switch to lwjgl3 which uses its own buffer allocator and does not use the ReflectionAllocator or if you want to keep using lwjgl2 then you can switch to PrimitiveAllocator instead and let GC clean up the buffers.

Edit2:
For switching the buffer allocator you can use these VM options:

for using the lwjgl3 buffer allocator:

'-Dcom.jme3.BufferAllocatorImplementation=com.jme3.util.LWJGLBufferAllocator$ConcurrentLWJGLBufferAllocator'

for using the primitive allocator:

'-Dcom.jme3.BufferAllocatorImplementation=com.jme3.util.PrimitiveAllocator'

I think I am already using lwjgl3… but not sure and don’t know how to change it in my project.

Other weird thing: as I am working on a furr-shader to create grass, my frame rate drops from 60FPS to 30FPS. But when I start a new instance of the program, it has no problem to get to 30FPS as well. Even a third and fourth instance does not inflict the performance at all.

If it would be just the CPU being the bottleneck, I would suspect threading causing this. But it is mainly the GPU that is busy. So why does it find time to render the second application instance while it can not keep up the frame rate for the first instance?

Have you disabled pause on lost focus?

setPauseOnLostFocus(false); //In SimpleApplication.simpleInit()

I did not use that, nor will I use it. The game needs to continue when the user is doing something else.

It is enabled by default.

I could not find a way to test if it is on or not. So I set it to false first and true next, but no visible changes. The evolution continues - maybe it just pauses screen stuff?

Still, there seems to be more power in my GPU than a single instance of the game can get its hands on.

Meanwhile I did some tested on my laptop where the game is extremely slow. It does not go over 10FPS.

The laptop-specs:
image

Sure, it only has an integrated GPU. But I want this game to work on lower end platforms as well. So there is a lot of optimization to be done. I think that the moderate graphical complexity I am aiming for should be possible on a reasonable spec laptop.

Also, don’t forget the good 'ol jVisualVM profiling…

Note: it’s possible that for your type of scene that the shadow postproc filter would be more efficient than the shadow renderer. It would be easy enough to try out.

Edit: and it could be that you already are… I couldn’t tell for sure.

with setPauseOnLostFocus set to true jme stops rendering if any other application has focus.

IMHO you can postpone it, but sooner or later you have to cull the parts of the globe that are facing away. i guess you are using your globe mesh for the “fur grass” too?

Shadows, each fur layer adds up to lots of unnecessary resourse waste.

You surely can cull away 1/3 off all triangles drawn. Cut your globe mesh in pieces, cull based on the angle of camera.

Afaik, except for enqueued tasks, it should pause everything (app states, controls,…) not just rendering.

if you see no difference when enabling it then probably loseFocus() is somehow not called in your case, which is handled by lwjgl.

Also make sure that the grass gets rendered after the planet. try to put the fur geometry in the transparent bucket

Well, I can tell that the evolution continues even when I am doing something else. So it does not stop my game logic.

I found that out the hard way. So in my shader I discard every fragment of every other layer. Not the best solution but it did help a lot. I don’t think there is a possibility to skip an entire instance in JME3, is there? That would require the use of a Geometry-shader I think.

Are triangles not culled by the GPU? Otherwise that would be a great hack.

I’ll do some googling to see what htat is and if it can work for my app. Are those settings I can distribute with the game? I wouldn’t want to instruct the players to tune their Java first.

Tried it, it did not do much for performance at this moment. But I’ll check again later on.

Though the fur thing was a lot of fun - thanks for this @pspeed - I will have a look at instancing grass too. I think I will not use JME-instancing but I will move to a more tuned special purpose Instance-shader based on what I learned about instancing with this fur grass.

My guys are also not instanced or batched because animations do not work with JME batching and instancing. I think I’ll have try with a custom shader as well.

At least the vertex shader gets executed. Then depending on your cull mode the fragment shader might not.