Disposal of UniformBuffer?

I notice a ton of UniformBuffers staying around in memory.

comparing 2 playgrounds:

  1. Babylon.js Playground (no sphere)
  2. https://www.babylonjs-playground.com/#KFXHQ0#1 (yes sphere, but disposed)

there is already an extra UniformBuffer present in 2.
Am I missing something obvious?

1 Like

The uniform buffer is used by the material. Disposing a mesh won’t dispose it, you need to dispose the material.

ok, I’m still missing something, because sphere.material is null

There’s a default material created by the system that the meshes use if they don’t have their own material: have a look at the scene.materials array.

it’s empty

From the default PG (https://playground.babylonjs.com/):

I have the same output from your PG (https://www.babylonjs-playground.com/#KFXHQ0#1).

yeah strange, the length was still 0…
but nonetheless, something else is going on here it seems:

The more spheres I add, the more UniformBuffers stick around. I haven’t checked in the Playground because I’m not sure how to find those in the console with the obfuscation, but it’s probably the same.

    const sphere = MeshBuilder.CreateSphere('sphere', {diameter: 2, segments: 32}, scene);
    const sphere2 = MeshBuilder.CreateSphere('sphere', {diameter: 2, segments: 32}, scene);
    const sphere3 = MeshBuilder.CreateSphere('sphere', {diameter: 2, segments: 32}, scene);
    window.addEventListener('click', () => {
        for (const m of scene.materials) {
            m.dispose();
        }
        sphere.dispose();
        sphere2.dispose();
        sphere3.dispose();
    });

How do you see this number?

in Chrome Dev Tools → Memory

image

My mistake, we do use uniform buffers in the scene, light and mesh objects. We had a leak in the mesh, this PR will fix it:

Regarding the ubo of the default material, it is not released even if you dispose of the material because the scene has a property that points to it: scene._defaultMaterial. You will need to set it to null or undefined if you don’t want to see a ubo leak from it.

Regarding:

    window.addEventListener('click', () => {
        for (const m of scene.materials) {
            m.dispose();
        }
        sphere.dispose();
        sphere2.dispose();
        sphere3.dispose();
    });

This code won’t release the ubo of the spheres because the event listener exists for the course of the script, and so sphere/sphere2/sphere3 are still reachable by this code and won’t be gargabe collected, meaning their ubo won’t be garbage collected either.

You can do this instead:

    const onclick = () => {
        for (const m of scene.materials) {
            m.dispose();
        }
        sphere.dispose();
        sphere2.dispose();
        sphere3.dispose();
        window.removeEventListener('click', onclick);
    };
    window.addEventListener('click', onclick);    
4 Likes

ah, thanks for the quick fix!

I take it the default material will always be just 1 buffer, so it will never cause the thousands of stranded ones I experience now.

I think there might be some more leaks, I will investigate further.

1 Like

That would be fantastic :slight_smile: Please let us know about anything you find

I’m quite convinced now that there are no memory leaks present concerning the parts of the Engine that I use. I still have to look into the GPU memory, but that is a bit harder.

3 Likes