pmndrs / react-three-fiber

🇨🇭 A React renderer for Three.js
https://docs.pmnd.rs/react-three-fiber
MIT License
27.37k stars 1.57k forks source link

Exploring asynchronous compilation of materials with Suspense #3073

Open Mike-Dax opened 11 months ago

Mike-Dax commented 11 months ago

With this PR, three.js v158 supports a compileAsync method which can compile shaders and return a Promise that resolves when they're ready.

Taking the Frosted glass example, my M1 Macbook spends several frames (74.6ms in total) blocked on shader compilation.

image

This new method sounds like a good fit for react-three-fiber's ability to leverage React's lifecycle management, to Suspend during compilation, then attach the objects to the scene.

Taking a step back, in my applications I don't mind if the 3D components 'arrive' a few frames later, but this kind of blocking of the main thread is visually noticeable.

I'm not too familiar with the internals of three or r3f at this level but I'd be happy to contribute, given some pointers in the right direction.

From what I can tell, this will only be an improvement for non-firefox browsers, due to the availability of the KHR_parallel_shader_compile extension.

CodyJasonBennett commented 11 months ago

This should be an addition in Drei at the very least. Preload suspending by default is a breaking change (similar to async/await for imperative APIs) as well as changing peer deps range, but you can have a prop to opt-in for that behavior or create an AsyncPreload with/without that prop. R3F can't assume much about the renderer since it has to support everything in three (SVGRenderer, etc.), and the API surface of renderers are increasingly volatile with the upcoming universal renderer (https://github.com/mrdoob/three.js/pull/26079). If you look into the Preload component, notice there's a guard for initTexture since it doesn't exist on the universal backend.

If you want something for Firefox, you can try a fence check to wait until GPU idle. This is a bit more crude, but it should offer comparable results if apps are idle on startup. Maybe this should be added to three now that parallel compile has finally been merged. https://gist.github.com/CodyJasonBennett/fedde93b69b8ecaefa402ee306189761