Very slow render after calling `markDirty` on materials


In a large complex scene, I want to occasionally add small temporary lights (e.g. to add to a fireball projectile). Most of the materials in the scene are frozen, so I call markDirty on them in order for the new light to affect them.

My issue is that after marking materials dirty, the following one or two render calls are sometimes extremely slow - taking from 100~300ms. Profiling the slow renders looks as below, so the time appears to mostly be spent in getUniformLocation.

Does anyone have an idea what the issue might be, or if this is avoidable? The scene has roughly 20 materials, 2 lights, a few hundred meshes, and a few thousand total thin mesh instances.


This is related to the compilation of the shaders. When you mark materials as dirty and the scene/material configuration has changed (e.g. a light has been added or removed), new shaders have to be compiled and this takes time, especially if you have different objects with different shaders: more new shaders will have to be compiled.

This happens the first time the configuration has changed: if you go back to this configuration later, the change should be fast because the shaders already exist.

I’m afraid there’s not much to do here, other than to try to precompile the shaders from the start by placing the scene in the configuration where the new light is added, render the scene and make sure all the new shaders have been compiled, then revert back to the initial state without the new light. Later, when you add the new light, the shaders that the materials need will already exist and the change should be quick.

Thank you for the full explanation @Evgeni_Popov !

Just to check, is it basically just the number of lights here, or do other elements of the scene trigger recompilation? E.g. using standard vs custom materials, mesh instances, thin instances, shadow generators, and so on.

It can be a lot of things, like adding/removing a texture to a material, enabling/disabling morphs or thin instances, adding/removing a light in the scene, etc. You can have a look at the isReadyForSubMesh implementation of the standard / PBR materials to see what can trigger a recompilation.