From 8b7951c20cf84421b37e5ed010b6db85ac6c5f2d Mon Sep 17 00:00:00 2001 From: MatiasManevi Date: Wed, 18 Mar 2026 11:18:41 -0300 Subject: [PATCH 1/7] Add single threaded version --- .github/workflows/build_steps.sh | 22 ++++++++++++++++++++-- wasm/CMakeLists.txt | 11 +++++++++-- wasm/package.npm.json | 22 ++++++++++++++++++++-- 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build_steps.sh b/.github/workflows/build_steps.sh index 6641b9c3..c773ada5 100755 --- a/.github/workflows/build_steps.sh +++ b/.github/workflows/build_steps.sh @@ -211,8 +211,26 @@ build_test_wasm() { source emsdk/emsdk_env.sh export PATH="$(pwd)/node_modules/.bin:$PATH" - emcmake cmake -B build_wasm -DCMAKE_INTERPROCEDURAL_OPTIMIZATION:BOOL=OFF $WASM_CMAKE_ARGS - cmake --build build_wasm + echo "Building Multi-Threaded version..." + emcmake cmake -B build_wasm_mt \ + -DCMAKE_INTERPROCEDURAL_OPTIMIZATION:BOOL=OFF \ + -DMUJOCO_WASM_THREADS=ON \ + $WASM_CMAKE_ARGS + cmake --build build_wasm_mt --parallel $(nproc) + + echo "Moving Multi-Thread version under mt subfolder..." + mkdir -p wasm/dist/mt + mv wasm/dist/mujoco.js wasm/dist/mt/ + mv wasm/dist/mujoco.wasm wasm/dist/mt/ + mv wasm/dist/mujoco.d.ts wasm/dist/mt/ + mv wasm/dist/mujoco.wasm.map wasm/dist/mt/ + + echo "Building Single-Threaded version..." + emcmake cmake -B build_wasm_st \ + -DCMAKE_INTERPROCEDURAL_OPTIMIZATION:BOOL=OFF \ + -DMUJOCO_WASM_THREADS=OFF \ + $WASM_CMAKE_ARGS + cmake --build build_wasm_st --parallel $(nproc) npm run test --prefix ./wasm } diff --git a/wasm/CMakeLists.txt b/wasm/CMakeLists.txt index aa85279d..08004839 100644 --- a/wasm/CMakeLists.txt +++ b/wasm/CMakeLists.txt @@ -31,11 +31,11 @@ if(NOT MUJOCO_WASM_FILES) message(FATAL_ERROR "No source files found in codegen/generated/") endif() +option(MUJOCO_WASM_THREADS "Build with multi-threading support" ON) + # Set Emscripten linker flags set(EMCC_LINKER_FLAGS "--bind" - "-pthread" - "-s PTHREAD_POOL_SIZE=navigator.hardwareConcurrency" "-s ASSERTIONS=1" "-s ALLOW_MEMORY_GROWTH=1" "-s EXPORT_ES6=1" @@ -48,6 +48,13 @@ set(EMCC_LINKER_FLAGS "-g" "--emit-tsd mujoco.d.ts" ) +if(MUJOCO_WASM_THREADS) + list(APPEND EMCC_LINKER_FLAGS + "-pthread" + "-s PTHREAD_POOL_SIZE=navigator.hardwareConcurrency" + ) + add_definitions(-DMUJOCO_WASM_THREADS) +endif() string (REPLACE ";" " " EMCC_LINKER_FLAGS_STR "${EMCC_LINKER_FLAGS}") add_executable(mujoco_wasm ${MUJOCO_WASM_FILES}) diff --git a/wasm/package.npm.json b/wasm/package.npm.json index 6301897d..68cbf0b8 100644 --- a/wasm/package.npm.json +++ b/wasm/package.npm.json @@ -24,13 +24,31 @@ "javascript", "typescript" ], - "main": "mujoco.js", - "types": "mujoco.d.ts", + "exports": { + ".": { + "types": "./mujoco.d.ts", + "import": "./mujoco.js", + "default": "./mujoco.js" + }, + "./mt": { + "types": "./mt/mujoco.d.ts", + "import": "./mt/mujoco.js", + "default": "./mt/mujoco.js" + }, + "./mujoco.wasm": "./mujoco.wasm", + "./mujoco.wasm.map": "./mujoco.wasm.map", + "./mt/mujoco.wasm": "./mt/mujoco.wasm", + "./mt/mujoco.wasm.map": "./mt/mujoco.wasm.map" + }, "files": [ "mujoco.js", "mujoco.d.ts", "mujoco.wasm", "mujoco.wasm.map", + "mt/mujoco.js", + "mt/mujoco.d.ts", + "mt/mujoco.wasm", + "mt/mujoco.wasm.map", "README.md" ], "author": "Google DeepMind", From aa07cdde5c448c6df21e2ce5ebd6fe20167a9dac Mon Sep 17 00:00:00 2001 From: MatiasManevi Date: Wed, 18 Mar 2026 11:48:11 -0300 Subject: [PATCH 2/7] Add documentation --- wasm/README.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/wasm/README.md b/wasm/README.md index 2c2595b3..5de7570b 100644 --- a/wasm/README.md +++ b/wasm/README.md @@ -19,6 +19,7 @@ TypeScript. > (installation succeeded on one Windows 11 machine but failed on others)._ ## Installation + The easiest way to use the MuJoCo JavaScript bindings is to install the `@mujoco/mujoco` package from npm: @@ -30,6 +31,36 @@ This package is ESM (`type: module`) and includes the pre-compiled WebAssembly module, JavaScript bindings, and TypeScript declarations. Ensure your bundler or dev server serves the `.wasm` asset at runtime. +### Threading Models + +The `@mujoco/mujoco` package includes two distinct builds of the engine to +support different browser environments and performance needs. + +#### 1. Single-Threaded (Default) + +The standard single-threaded version is located at the root of the package. It +is compatible with all modern browsers and does not require special security +headers. +```typescript +import loadMujoco from '@mujoco/mujoco'; +``` + +#### 2. Multi-Threaded (MT) + +The multi-threaded version is located in the `/mt` subfolder. It utilizes Web +Workers and `SharedArrayBuffer` to parallelize physics computations. +```typeScript +import loadMujoco from '@mujoco/mujoco/mt'; +``` + +> [!CAUTION] +> Due to the use of `SharedArrayBuffer`, browsers require Cross-Origin Isolation +> to enable multi-threading. Your web server must send the following HTTP +> headers: +> - `Cross-Origin-Opener-Policy: same-origin` +> - `Cross-Origin-Embedder-Policy: require-corp` +> If these headers are missing, the module will fail to initialize. + ## Build from source ### Prerequisites @@ -98,6 +129,14 @@ This command will generate the following folders under the project root: - `build`: contains MuJoCo compiled using Emscripten. - `wasm/dist`: contains the WebAssembly module, `.js` and `.d.ts` files. +The assets inside those folders are compiled and prepared to run as +single-threaded. If you need to operate with a multi-threaded version of the +module make sure to pass the `-DMUJOCO_WASM_THREADS=ON` flag like: + +```sh +emcmake cmake -B build -DMUJOCO_WASM_THREADS=ON && cmake --build build +``` + ### Example Application After generating the bindings you will be ready to write web applications using From b694e9e951d1cdc7d44184dd8d6924d3c009b6ca Mon Sep 17 00:00:00 2001 From: MatiasManevi Date: Wed, 18 Mar 2026 11:49:19 -0300 Subject: [PATCH 3/7] Change caution for note --- wasm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wasm/README.md b/wasm/README.md index 5de7570b..8e4f5998 100644 --- a/wasm/README.md +++ b/wasm/README.md @@ -53,7 +53,7 @@ Workers and `SharedArrayBuffer` to parallelize physics computations. import loadMujoco from '@mujoco/mujoco/mt'; ``` -> [!CAUTION] +> [!NOTE] > Due to the use of `SharedArrayBuffer`, browsers require Cross-Origin Isolation > to enable multi-threading. Your web server must send the following HTTP > headers: From 65d8d26af61a74efe6ae1442cf9e9b78958e30dd Mon Sep 17 00:00:00 2001 From: MatiasManevi Date: Wed, 18 Mar 2026 11:50:06 -0300 Subject: [PATCH 4/7] Add newline --- wasm/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/wasm/README.md b/wasm/README.md index 8e4f5998..1442f082 100644 --- a/wasm/README.md +++ b/wasm/README.md @@ -59,6 +59,7 @@ import loadMujoco from '@mujoco/mujoco/mt'; > headers: > - `Cross-Origin-Opener-Policy: same-origin` > - `Cross-Origin-Embedder-Policy: require-corp` +> > If these headers are missing, the module will fail to initialize. ## Build from source From b35a5bab5e7a15827ae4e99d9d0ea4e8e90d7648 Mon Sep 17 00:00:00 2001 From: MatiasManevi Date: Wed, 18 Mar 2026 12:10:08 -0300 Subject: [PATCH 5/7] Shorten mv instruction --- .github/workflows/build_steps.sh | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/build_steps.sh b/.github/workflows/build_steps.sh index c773ada5..7286aca6 100755 --- a/.github/workflows/build_steps.sh +++ b/.github/workflows/build_steps.sh @@ -220,10 +220,7 @@ build_test_wasm() { echo "Moving Multi-Thread version under mt subfolder..." mkdir -p wasm/dist/mt - mv wasm/dist/mujoco.js wasm/dist/mt/ - mv wasm/dist/mujoco.wasm wasm/dist/mt/ - mv wasm/dist/mujoco.d.ts wasm/dist/mt/ - mv wasm/dist/mujoco.wasm.map wasm/dist/mt/ + mv wasm/dist/mujoco.* wasm/dist/mt/ echo "Building Single-Threaded version..." emcmake cmake -B build_wasm_st \ From 9561decf645c43a4a6b1fc16ecb83d4475883ece Mon Sep 17 00:00:00 2001 From: MatiasManevi Date: Wed, 18 Mar 2026 13:04:04 -0300 Subject: [PATCH 6/7] Remove PTHREAD flag --- wasm/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/wasm/CMakeLists.txt b/wasm/CMakeLists.txt index 08004839..3d47c4da 100644 --- a/wasm/CMakeLists.txt +++ b/wasm/CMakeLists.txt @@ -51,7 +51,6 @@ set(EMCC_LINKER_FLAGS if(MUJOCO_WASM_THREADS) list(APPEND EMCC_LINKER_FLAGS "-pthread" - "-s PTHREAD_POOL_SIZE=navigator.hardwareConcurrency" ) add_definitions(-DMUJOCO_WASM_THREADS) endif() From b1c7ae1c1993b9a6843d338c38f870df1cc16817 Mon Sep 17 00:00:00 2001 From: MatiasManevi Date: Wed, 18 Mar 2026 13:13:05 -0300 Subject: [PATCH 7/7] Restore PTHREAD flag --- wasm/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/wasm/CMakeLists.txt b/wasm/CMakeLists.txt index 3d47c4da..08004839 100644 --- a/wasm/CMakeLists.txt +++ b/wasm/CMakeLists.txt @@ -51,6 +51,7 @@ set(EMCC_LINKER_FLAGS if(MUJOCO_WASM_THREADS) list(APPEND EMCC_LINKER_FLAGS "-pthread" + "-s PTHREAD_POOL_SIZE=navigator.hardwareConcurrency" ) add_definitions(-DMUJOCO_WASM_THREADS) endif()