Benchmarking Node Material build time

I’m working on using a megatexture (see here) to combine multiple image textures into a single image file, then split them out again by quadrant using a node material, and I’d like to determine whether this has any runtime impact.

There are two areas I expect to be impacted - network load time and node material build time. I’m running a small benchmarking script using puppeteer to load a scene, build the node material, and record how much time elapses (with performance.now()) for cached/uncached and split textures/megatexture. Here’s the script I’m using on the page:

export default async function buildScene(scene: BABYLON.Scene) {
  BABYLON.SceneLoader.Append(
    assetUrl('models/apricot/model.obj'),
    undefined,
    scene,
    async scene => {
      const loadStart = performance.now();
      const variation = /* either mega or split, determined from window.location */;

      const nodeMaterial = new BABYLON.NodeMaterial('mega', scene);
      const textureUrl = assetUrl(`materials/apricot/${variation}.json`);
      await nodeMaterial.loadAsync(textureUrl);
      nodeMaterial.build();

      // Create a default arc rotate camera and light.
      scene.createDefaultCameraOrLight(true, true, true);

      // The default camera looks at the back of the asset.
      // Rotate the camera by 180 degrees to the front of the asset.
      (scene.activeCamera as BABYLON.ArcRotateCamera).alpha = 1.52;

      // Apply the node material to the model
      scene.meshes
        .filter(m => m.id.includes('apricot'))
        .forEach(m => {
          m.material = nodeMaterial;
          m.material.transparencyMode = 0;
        });

      console.log(
        'materials applied after',
        performance.now() - loadStart,
        'ms',
      );

      scene.executeWhenReady(() => {
        const loadEnd = performance.now();
        const loadTime = loadEnd - loadStart;
        loadTimeSubject.next(loadTime); // send loadTime to RxJS Subject that puppeteer's watching
        console.log('scene ready after', loadTime, 'ms');
      });
    },
  );
}

I’m curious if this will correctly measure the time it takes for the node material to pull in all required assets and compile/send them to the GPU. Running 100 iterations per variant, I’m seeing only very small variations in texture build time (~10ms).

(In the above chart, I have 3 different variations for each mega and split; mega contains a diffuse and a normal texture, mega-3 contains diffuse/normal/metallic, and mega-4 contains diffuse/normal/metallic/roughness. The split variants are the same, but using separate image texture files instead of a single megatexture.)

Does this match what is expected? Is scene.executeWhenReady() the best indicator to check?

It seems fair to me. scene.executeWhenReady is the good one to check

1 Like