Three.js: DRACOLoader: Decoding should happen in a Web Worker.

Created on 21 Mar 2018  Â·  12Comments  Â·  Source: mrdoob/three.js

Decoding Draco geometries is a long, blocking task, and shouldn't be happening on the main thread. I'm hoping that with some of the LoaderSupport APIs we should be able to configure it to run just as easily in a web worker as not. Proposed API:

THREE.DRACOLoader.setDecoderPath('path/to/decoders/');

// Main thread
var loader1 = new THREE.DRACOLoader()
  // .setParser(new THREE.DRACOLoader.Parser()) // OPTIONAL
  .load('foo.drc',  () => {...});

// Web worker
var loader2 = new THREE.DRACOLoader()
  .setParser(new THREE.DRACOLoader.WWParser())
  .load('foo.drc', () => {...});

// GLTFLoader + WW
var dracoLoader = new THREE.DRACOLoader()
  .setParser(new THREE.DRACOLoader.WWParser());
var gltfLoader = new THREE.GLTFLoader()
  .setDRACOLoader(dracoLoader)
  .load('foo.gltf', () => {...});

The distinction between Loader and Parser exists because the Parser cannot know about any THREE.* types, to minimize dependencies in the WW.

/cc @takahirox @kaisalmen


Aside — In a perfect world the WASM Draco decoder would use threading, but WASM doesn't support that yet, and the decoder would need changes if it did, so using a web worker seems like the place to start.

Loaders Suggestion

Most helpful comment

Perhaps the author (Matt Greenhalgh, Stink Studios - ping @mattg73) is able to share their implementation with the community as mentioned in their new technical case study: https://medium.com/@stinkstudios/creating-qalam-d016a0a52d56

Our solution was to move the decompression task off the main thread using Web Workers. We had to modify the THREE.js Draco decoder to support this bespoke functionality. Our change stopped the main thread from being blocked during decompression but we instantly hit against another problem: the decompressed buffer sat in a different thread from the main thread that required it. Copying this data between threads created an even bigger lock-up while the large amount of data was transferred. We solved this problem by implementing a Transferable Objects solution that changes the buffer owner by pointer reference rather than moving the data between threads.

All 12 comments

Decoding Draco geometries is a long, blocking task, and shouldn't be happening on the main thread.

Agreed.

About the proposed API, what's the purpose of exporting .setParser()? new THREE.DRACOLoader( { worker: true } ) isn't good? (I'm not familiar with neither DRACOLoader nor LoaderSupport yet.)

That would be fine, too. There may be need for a Parser subclass to isolate code for three.js-independent tasks, but it doesn't need to be exposed to the user necessarily.

Related: https://github.com/kaisalmen/WWOBJLoader/issues/36#issuecomment-374842424

Content has been moved to own issue: https://github.com/mrdoob/three.js/issues/13664

Ideas are similar to yours. Let me know what you think.

@takahirox and @donmccurdy I have moved the ideas related to WorkerLoader to an isolated issue (see above). Sorry for hijacking this issue.

Do you need volunteers for a DRACOLoader utilizing Workers and if when do you need it?

No concern about hijacking it's all very related. 😅

I've been wanting to try DRACOLoader + workers for a while still haven't gotten started... if you're interested and find time please do! No time constraint.

Need to work on WorkerLoader/OBJLoader2 first, but having a real use-case apart from PCDLoader for proving the overall concept seems tempting, but it will not happen next week 😉

Perhaps the author (Matt Greenhalgh, Stink Studios - ping @mattg73) is able to share their implementation with the community as mentioned in their new technical case study: https://medium.com/@stinkstudios/creating-qalam-d016a0a52d56

Our solution was to move the decompression task off the main thread using Web Workers. We had to modify the THREE.js Draco decoder to support this bespoke functionality. Our change stopped the main thread from being blocked during decompression but we instantly hit against another problem: the decompressed buffer sat in a different thread from the main thread that required it. Copying this data between threads created an even bigger lock-up while the large amount of data was transferred. We solved this problem by implementing a Transferable Objects solution that changes the buffer owner by pointer reference rather than moving the data between threads.

@mattg73 There was some discussion about using workers in loaders in the past and it would be very helpful to understand how you solve this problem. Any chances you make a PR so we can evaluate your approach?

Fixed at https://github.com/mrdoob/three.js/pull/15249. :)

I'm really sorry I came across this issue a bit late, I did write the webworker decoder for the qalam project for @mattg73 you guys were talking about earlier. I had issues without older browsers ( ie ) in which some math functions used in the draco decoder were not defined.
I had to re-inject them all at the beginning of the decoder.

I can have a look back at this very soon

Was this page helpful?
0 / 5 - 0 ratings