pmndrs / drei

🥉 useful helpers for react-three-fiber
https://docs.pmnd.rs/drei
MIT License
8.26k stars 682 forks source link

AVIF textures loaded with useGLTF yields `out-of-memory` crash #1911

Open alouis-jpg opened 5 months ago

alouis-jpg commented 5 months ago

Problem description:

I am currently loading several (7) gltf each having a 16k avif compressed texture using useGLTF in my r3f application. Both on remount of my app in dev mode and on reload of the page in production mode, the browser consistently crashes with the Out of memory error code ('Aw snap!' crash).

I'm using <primitive> as a mesh component and take care of the dispose of the primitive's object myself since primitive are not disposed automatically (unlike geometry, materials etc). I also clear the loader's cached data with useGLTF.clear(...). Interestingly, when deep-diving into chrome performance profiling, it seems that geometry and textures are not handled the same way: reading at the size taken in the cache by geometry between mountings, it doesn't change, while textures seem nowhere to be found, maybe cached somewhere else?

My current guess would be that the textures loaded to the gpu don't seem to be removed on unmounts, which could result in the browser crashing over a lack of memory.

Replacing the gltf avif compressed textures with jpeg textures prevent this crash from happening which leads me to believe maybe avif textures cleaning is not handled properly.

Relevant code:

function Scene(props) {
    return (
      <group>
           {props.models.map((model, index) => (
              <Model
                modelPath={model.path}
                key={index}
              />
            ))}
      </group>
}

function Model(props) {
  const { scene } = useGLTF(props.modelPath, false, false, (loader) => {
    loader.setDRACOLoader(draco);
  });

  useEffect(() => {
    return () => dispose(scene);
  }, [scene]);

  useEffect(() => {
    return () => useGLTF.clear(props.modelPath);
  }, [props.modelPath]);

  return <primitive object={scene} />
}

Suggested solution:

Testing with ktx2 compressed textures in the same application to see if it results in the same crash.

alouis-jpg commented 5 months ago

Testing with the same models and ktx2 compressed textures does not result in out of memory crash upon reload therefore wondering what goes wrong with avif textures disposal