NodeMaterial materialDefines _keys array is growing over time


at the moment we are chasing a performance problem showing up after several hours or days. Chromes performance analyzer pointed me to isReadyForSubMesh() from the NodeMaterial, which takes surprisingly long (around 123ms). Also there are a couple of toString() calls showing up.

Stepping through the code reveals that _keys array of the materialDefines is growing (most likely per frame). It seems that the same entries are added, CONVERTTOLINEAR0 and CONVERTTOGAMMA0.On the other hand, the fields CONVERTTOLINEAR0 and CONVERTTOGAMMA0 remain undefined.

If I understand the internals of isReadyForSubMesh() correctly, it creates a key by combining the shader name plus the defines for looking up the compiled effect in some sort of cache (per frame or very often).

I wonder if our performance problems are coming from the conversion of the materialDefines into a string.

We are using BabylonJS 6.20.1

In the first place the main question for us is, if we have correctly identified the performance issue, because testing takes so long.


Would be amazing if you could provide a repro, I want to fix it ASAP

So we created the playground.
Its a very simplified version of the project, only the NME material and the EnvTexture set every frame.
Hope that this is accurate and gives the same results.

Meanwhile for our project we took out the NME material and put it in the code as a PBR material as the functionality is not too complicated in the end.

BTW, this refers directly to my other post about the env texture:

Thx for the help!

Hello Sebavan,

thank you for looking into that.

Also thank you Werner for isolating the node material and creating the playground.

I didn’t test if this is showing up at all in the latest Babylon version.

Best regards

Thanks for the repro!

It seems your node material has been created when convertToGammaSpace / convertToLinearSpace did not exist yet on FragmentOutputBlock, and has been updated after these properties have been added. Because of how the code is setup when we deserialize a material, these properties end up to being undefined, which explains why they are recreated each frame.

You can fix your node material by simply switching these 2 properties on/off on the fragment output block (to force another value than “undefined”) and by resaving it:

This PR will solve the problem without the need for this manual operation:

1 Like

@Evgeni_Popov is way too fast :slight_smile:

Thank you so much.
You are amazing!
Good to have this clarified.
For the sake of the project, we will not include the NME material, as we already converted it into a PBR material.
For the next project we have lined up, we will most likely make use of the NME, so supercool to see that this is production ready.
All the best.

1 Like