Delay buffer sync when transforming thin instances

Hello,
I have a performance related question. At my current project I deal with dense point clouds. After voxelizing them on frontend, I can have point clouds with up to 1.5 million points.
At some point I need to allow users to transform the object, let’s say apply a rotation. I’m looking for the most optimal way to apply the transformation and avoid syncing the matrix buffer which is on CPU.

Here is a simple example: https://playground.babylonjs.com/#GBKQAV#3

After loading the transformation matrices to GPU, it renders fast. However when applying transformation on the node, performance drops significantely as we are syncing the matrix buffer with CPU.
Perhaps there are a way to delay the sync?

Maybe you could add a uniform mat4 customMatrix to your material’s vertex shader and apply this matrix to the vertices of the thin instances? You could then transform all thin instances at once by setting this mat4. I never did this, just guessing…

2 Likes

Well, it sounds like a good idea. I’ll try it out. Thank you, @roland

Here’s how I manage adding and removing thin instances in bulk. Note the “false” parameter in thinInstanceSetMatrixAt() and the final thinInstanceBufferUpdated().

There is also thinInstancePartialBufferUpdate() but I don’t know if that helps you here.

Edit: and set “mesh.doNotSyncBoundingInfo = true;” if you don’t need bounding info.

    const previousPointCount = this.#contactSphere.thinInstanceCount;
    const newPointCount = this.#contactPoints.length;
    const smaller = Math.min(previousPointCount,newPointCount);

    for (var i=0; i<smaller;i++) {
        const p = this.#contactPoints.array[i];            
        this.#contactSphere.thinInstanceSetMatrixAt(i,
            BABYLON.Matrix.TranslationToRef(p.x, p.y, p.z, this.#matrix),
            false);
    }
    for (var i=smaller; i<newPointCount;i++) {                                                                                                   const p = this.#contactPoints.array[i];            
        this.#contactSphere.thinInstanceAdd(
            BABYLON.Matrix.TranslationToRef(p.x, p.y, p.z, this.#matrix),                                                                            false);
    }

    this.#contactSphere.thinInstanceCount = newPointCount;

    this.#contactSphere.thinInstanceBufferUpdated("matrix");

    if (this.#contactSphere.isVisible != this.#contactSphere.hasThinInstances)
        this.#contactSphere.isVisible = this.#contactSphere.hasThinInstances;
3 Likes

@HiGreg , thank you very much.
Apparently mesh.doNotSyncBoundingInfo = true; is the guy. Baysically when we don’t need to update bounding info on each transformation, it skips the synchronization.
When all transformations are done, I can manually reaclculate the new bounding.
Here is 1.5m points with only 1 line changes, according to your suggestion: