Rust-webxr plans

Current status


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)



New Design


Note: this is a new new design. For the old new design, see https://paper.dropbox.com/doc/revert/xmqpUtCzy8yNMGWwUUxsz/6993

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.

There are two traits implemented by devices: