javascriptwebglwebassembly

Is it possible to share a WebGL context between JavaScript and WebAssembly?


I have a web app that uses JavaScript/WebGL. It loads shaders and textures and updates and draws a dynamic mesh using gl.drawArrays with gl.TRIANGLES. Now, to improve performance, I would like to move the drawing to WebAssembly.

Can I share the same WebGL context between WASM and Javascript, so I do my texture and shader loading on the JavaScript side, but my mesh generation and drawcalls on the WASM side?

If so, how (and where) should I create the context, and how do I pass handles for resources between the two?


Solution

  • You can’t share a WebGL context directly between JavaScript and WebAssembly. As Lee pointed out in a comment all access to OpenGL goes through the browser, and therefore through JavaScript. The context itself always lives on the browser side.

    To use WebGL with WebAssembly, you have two main options:

    I chose the latter. It turns out to be fairly straightforward: you can pass handles back and forth as simple unsigned integers. Mesh generation and draw calls then happen on the WASM side.

    For best performance, keep cross-boundary calls to a minimum. One effective approach is to record draw calls into a simple command buffer in WASM, then pass that buffer to JavaScript to execute in one go. Data can be shared efficiently by exposing pointers into WASM memory and accessing them from JavaScript using subarray, which avoids unnecessary copying.