[Performance] What is eating up frametime in this scene with only simple 3d hexagon meshes?

I’m testing out babylon for part of a mobile game, and at what would probably be about the maximum grid size, I’m only getting like ~10fps on my phone.

Using mesh.freezeWorldMatrix() improved the framerate quite a bit (from slideshow to ~10fps), and using scene.freezeActiveMeshes(); gives a significant boost, but is very undesireable, and even with it the scene eats through battery. Turning shadows off gives a small boost as well, but still not quite that “big jump” that’s needed for it to be reasonable.

It seems to be almost entirely CPU bound, which is confusing to me. What is going on here that is hogging so much CPU time?

What sort of suggestions do you have for better optimizing the scene? The gird itself is “dynamic” in the sense that the the tiles can be added whenever, starting with just a few, so it’s not a singular static mesh.


UPDATE:

Lets summarize the perf improvements thus far, starting with a scene with no performance help.

  1. freezeWorldMatrix() +32%
  2. Using Instances: +36%
  3. Freezing Materials: +24%
  4. useRightHandedSystem: +73% :fire:

My concern is that this is essentially an empty scene for my use case, there will be scenery, building, moving objects, roads…etc all added that will bring the complexity up. It’s CPU bound, which means the game logic will have to fight for CPU time, potentially degrading it to the point of unsuitability on mid-low end mobile devices. And even on higher end devices, the power usage on this scene with only hexagons is through the roof.

My questions:

  • What eats so much CPU time?
  • Why does useRightHandedSystem fix drawcalls and nearly double the FPS?
  • How could I better setup the scene to be more performant in the first place?
1 Like

Hey!
You can dramatically improve performance using instances.
This PG using instances adds 54 FPS on my PC:

https://playground.babylonjs.com/#XEP0ZD#71

Runs 60 FPS on my Honor 20 Pro.

3 Likes

My new MacBook has no problem running at 60 FPS with avg GPU frame time of only 0.95 ms when using clone() or instantiateModelsToScene() on that PG, but using createInstance() I drop to 18 FPS with avg GPU frame time at a whopping 55 ms. :astonished:

1 Like

Thanks for the suggestion, that definitely helps!

(absolute) FPS differences:

  • Desktop: 160 -> 200
  • Pixel6: 65 -> 80
  • Z2 Force: 5 -> 20

It’s definitely an improvement, but it still seems terribly unperformant, on the pixel for example it eats battery till it thermal throttles and the FPS drops. Something is eating up all the CPU time, any ideas at what?

My GPU time is always < 1ms, but on each device a CPU thread is completely maxed out.

1 Like

@douglasg14b we can still use thin instances to improve the performance. But a little trick improved it a LOT from:
image

to:
image

by adding this:

hexTileRoot.material.freeze()

Try it out! :vulcan_salute:

https://playground.babylonjs.com/#XEP0ZD#72

2 Likes

Whaaat? :joy:

1 Like

I have experienced drastical differences in performance on Mac when using poisson sampled shadows. On windows 144fps+, on an M1 MacBook 1 to 5 fps…

1 Like

The issue with instances is only on the latest verson of BJS thou. Running it on version 4.2 the FPS is back up to 60 FPS with GPU frame time at only 3 ms.

Switch to the latest version and the FPS is back down to 18 with GPU frame time back up to 55 ms. :flushed:

1 Like

Would you please try out this PG with poisson shadows on your Mac? Any FPS issues?
https://playground.babylonjs.com/#IIZ9UU#251

1 Like

With that last PG I get 60 FPS on Mac. :+1: :slight_smile:

1 Like

Seems to be fixed since then :slight_smile: thanks!

1 Like

That one doesn’t use instances thou, it’s creating a new mesh each time? It’s the one with instances that’s killing perf on latest BJS version on my Mac.

Update, before I was testing on Chrome where the FPS dropped down to 18 FPS with instances, but I just tried it on FireFox and it’s all the way down to 7 FPS and almost completely unresponsive…

It’s this one that’s the issue . :point_down:
https://playground.babylonjs.com/#XEP0ZD#72

1 Like

Yes, it is creating new meshes. If it was a question thou :joy:

1 Like

Dude we are giving so much likes to each other that we might get a Fallen in love badge shortly :joy::joy::joy:

Edit: do not stop :joy::heart_eyes:

1 Like

I can’t understand which changes in the instance code would raise the GPU time so much… That would mean we are drawing hundreds of times the same thing to account for the change from 1ms to 55ms…

What are the number of draw calls you are seeing for the PG? A Spector snapshot would help a lot, but if you are using a laptop it won’t work…

[EDIT] Also, could you test using WebGL1 instead of WebGL2?

2 Likes

Disabling webgl 2 fixes the issue.

The inspector reports 549 draw calls whether using createInstance() or clone(), whether webgl 1 or 2.

I’m on laptop thou, so can’t get the Spector snapshot. :slightly_smiling_face:

Then it seems to be a problem on Apple side…

What I don’t understand is that it does work in 4.2… Are you also using WebGL2 in 4.2?

What is the value of engine.getCaps().instancedArrays?

1 Like

engine.getCaps().instancedArrays returns true. Yep it works on version 4.2 using WebGL2.

Also I guess the inspector is misreporting the number of draw calls, it should report much lower number using instances right, just one draw call for all of them?

Do you have a desktop Mac? Does it work there in Chrome/Firefox/Safari?

I guess someone from the team will have to repro on their laptop for us to be able to dig deeper…

No, because you are loading a glb which has right handed data. You will need to set scene.useRightHandedSystem = true; so that all instances are drawn with a single draw call.

1 Like