Hi everyone, glad to be back now that support for threading is in its infancy.
My intro question is in the title itself, but hopefully the follow-up explanation will clarify my intentions. Here goes…
1. WebWorkers are Multiple Single Threads
The strategy of using workers to offload heavy lifting from the main thread is the preferred option from an efficiency and quality of end-user experience perspective. But, it kicks the can down the road in terms of each worker being its own separate single-threaded process. Limitations or problems on the main thread can also be encountered on each worker thread.
2. WASM Modules are Multi-Core Instances
The restriction on using WASM in the context of deploying BabylonJS is that the core of the engine would need to be ported to a native language that compiles to that target, and the resource expense of implementing WASM modules would be so great in production that their apparent benefits would not outweigh said costs. It doesn’t help any that it is anti-pattern to deploy an app designed to use WASM minimally; there must be a sufficiently high workload for the WASM module(s) to perform in order to defend their necessitation in the overall app design.
3. WebWorker as WASM Loader
Instead of porting the entire engine over to a native language that compiles to WASM, why not just port computationally expensive non-rendering code instead? The stuff that most likely will not need to be changed moving forward, in other words.
For example, a WebWorker loads a WASM module as part of its instantiation. The WASM module could be used to calculate all transformations of vertices within world space, thereby allowing the interaction with each scene to be multi-core optimized in terms of geometries. The module would only need to be sent a minimal amount of information, such as an object describing the user’s position and orientation within world space.
The WASM module could then perform all necessary operations in memory and return the data that remains after performing a frustum clip, whereupon the WebWorker would render said data using its TypeScript render routines that implement WebGPU.
This way the worker(s) could perform the light workloads that are too small for WASM to bother with, while migrating all of the heavy workloads that aren’t a good fit for a single-threaded process over to WASM.
I’m aware that WebGPU could accomplish everything in one place. However, will the initial release compensate for being single-threaded in all respects? Would it prove to be efficient to run everything through a single bottleneck like that? It reminds me when games used to run exclusively on the CPU, leading to the necessity of inventing GPU cards to offload most of the work.
I know that what I’m effectively proposing is - at best - some form of parsing exported files (from Blender, etc) into data sets that are processed in parallel, and - at worst - multiple files that collectively describe a given entity. But since WebGPU requires new file formats anyway and file conversion will be required regardless… maybe it’s time to consider creating such an option in the design of that type of utility?
I’m not an architect level engineer or super expert in this field, it just seems to me that by combining GPU-optimized worker threads with in-mem multi-core code, app designers could get the best of both worlds and reach unparalleled performance.
All of this having been said, does this make sense? Would it be feasible?
If it is, I’d love to dive into building something like this.
Thanks for reading