three.js
three.js copied to clipboard
GLTFLoader: Update MeshoptDecoder support to support WebWorkers
MeshoptDecoder can decode at ~1 GB/sec (with filters) on modern desktop CPUs, which mostly means we don't need to offload the processing to other threads... except when we're dealing with scenes with ~800 MB of geometry, at which point we might be stalling the main thread for 700-900ms.
To solve this, meshoptimizer is implementing support for WebWorkers: https://github.com/zeux/meshoptimizer/pull/454
The decoder gains a new function, decodeGltfBufferAsync, which works regardless of whether WebWorkers are enabled; when decoder.useWorkers is called with the desired worker count, it switches to asynchronous decoding which almost entirely eliminates main thread overhead, with the exception of copying the input buffer.
This change is structured to still work with the old versions of the
library, the library will be updated separately. Note that when
decodeGltfBufferAsync is used, ready promise doesn't need to be used.
It's been a little while since I've looked at three.js so I'm not sure what the jsm/js situation is; this change for now just updates the jsm version. Feedback on this change or the linked PR is welcome!
Thanks @zeux! It's a huge credit to your work on the meshopt decoder that Web Workers haven't been necessary for most use cases so far. E.g. when a 5 MB geometry decodes in only 5ms, it can fit within many frame budgets. Agreed that Web Workers make sense for these very large geometry files though, or very framerate-sensitive applications like those using WebXR.
The only downside I can see is that the round-trip to/from Web Workers does add a bit to wall time. I'm not sure if this is current anymore, but it used to take ~40ms to initialize a Web Worker. Since the user can opt in/out with useWorkers(count), this doesn't seem like a problem.
No need to update the js/ copy, it'll be autogenerated.
Right - the startup latency is less of a problem here since the workers will be started eagerly when useWorkers is called, so it will likely overlap with the latency of fetching the actual assets, but for geometry-light cases it might be the case that workers aren't a good idea because of the extra latency of decoding as you'd need to pass a few buffers back and forth. Also there's an additional copy involved to be able to transfer the data.
Either way extremely geometry heavy cases are rare enough that web workers make sense here more as an opt-in, by default this change won't change the mechanics of decoding.
Thanks!