The rust-webvr crate is unsound, with data being shared across threads where it doesn’t need to be. We have many, many threads involved:
main thread: kicks off everything, has to run rendering for MagicLeap
script thread: interacts with webvr/webxr api, runs RAF callbacks and stuff. kinda need this one
webgl thread: deals with taking the GL texture and rendering it onto the VR device(thus has a handle to the VR device)
webvr thread: owns the VR device, handles most state manipulation
RAF thread: script thread spawns this so that it doesn’t have to block on queries to the webgl / webvr threads. This schedules RAF callback tasks and interacts with the other threads to get device state
The API currently requires Arc<RefCell> to be used both by the client and the implementor.
Goals
An API written in safe Rust(the only unsafe code should be calls to C APIs)
Reduce the number of threads
Reduce the amount of context switching
Don’t expose Arcs anywhere
Less risk of deadlock
Move over to a webxr-first API
Reduce(eliminate?) WebXR work being done by the WebGL thread
Design constraints
script should never block for WebXR APIs(some WebVR APIs may block by design)
backends must have the ability to use the main thread for rendering
rAFs should be appropriately timed; we shouldn’t accumulate rAFs because something was slow
Non-constraint: It is okay if WebVR is not perfectly supported(i.e. we don’t need to deal with the use case of forgetting to call .submitFrame(), among other things)
There are three threads which play a major role here:
📜Script thread: Runs javascript, runs RAF callbacks. Owns a handle to an XRDevice object(which will probably, behind the scenes, proxy commands to a different thread)
🖥️ WebGL thread: Canvas’s webgl thread. Dutifully runs all WebGL commands JS wants it to. The XRSession thread can request a snapshot of the canvas’s contents, getting a GL texture, using the same API as WebRender.
👁️ XR session thread: Depending on the backend, this may be a new event loop thread, or the main thread. If the device API only provides blocking methods, then there has to be some thread involved here to make script not have to block. This thread actually owns the internal XR state objects
There are additional threads that are needed sometimes, but not during the rAF event loop:
🔍 XR discovery thread: used during device discovery.
API
Note: this API is missing features, notably gamepads, the details of an XRFrame, notifications of device changes, and multiprocess.
Current status
Goals
Design constraints
New Design