Skip to content

Commit

Permalink
Added option to compile the library with multithreading enabled (#111)
Browse files Browse the repository at this point in the history
* Added ENABLE_MULTI_THREADING option
* Added BUILD_WASM_COMPAT_ONLY option to only build the WASM compat version for faster compiling
* Added module that can serve the examples with the correct COEP/COOP for multithreading

See discussion at #110
  • Loading branch information
jrouwe committed Feb 23, 2024
1 parent 26ac07e commit 893be84
Show file tree
Hide file tree
Showing 8 changed files with 807 additions and 47 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ Build/
dist/
node_modules
Examples/js/jolt-physics.wasm-compat.js
Examples/js/jolt-physics.wasm-compat.worker.js
101 changes: 63 additions & 38 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ set(OUTPUT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR}/dist/)
# Option to turn on memory profiling
option(ENABLE_MEMORY_PROFILER "Enable emscriptens memory profiler to help find leaks" OFF)

# Option to turn on double precision
option(DOUBLE_PRECISION "Compile the library in double precision mode" OFF)

# Option to turn multi threading on
option(ENABLE_MULTI_THREADING "Compile the library in multi threading mode (warning: doesn't work in Safari nor with any JS callbacks currently)'" OFF)

# Option to speed up compilation by only compiling the WASM compat version
option(BUILD_WASM_COMPAT_ONLY "Compile online the WASM compat version of the library (speeds up compilation)" OFF)

# The configurations we support
set(CMAKE_CONFIGURATION_TYPES "Debug;Release;Distribution")

Expand All @@ -29,6 +38,20 @@ set(GENERATE_DEBUG_SYMBOLS ON)
# Use 32-bit object layers to support more bits in ObjectLayerPairFilterMask
set(OBJECT_LAYER_BITS 32)

# Enable multi threading
if (ENABLE_MULTI_THREADING)
set(MULTI_THREADED_FLAG
-pthread
-s SHARED_MEMORY)
set(ENVIRONMENT_FLAG
-s ENVIRONMENT='web,node,worker'
-s PTHREAD_POOL_SIZE=16)
set(CMAKE_CXX_FLAGS "-pthread -s SHARED_MEMORY")
else()
set(MULTI_THREADED_FLAG "")
set(ENVIRONMENT_FLAG "-s ENVIRONMENT='web,node'")
endif()

# Include Jolt
include(FetchContent)
FetchContent_Declare(
Expand Down Expand Up @@ -59,9 +82,10 @@ set(EMCC_ARGS
--extern-pre-js ${JOLT_FRONT_MATTER_FILE}
--post-js glue.js
--closure=1
${MULTI_THREADED_FLAG}
-s ALLOW_MEMORY_GROWTH=${ALLOW_MEMORY_GROWTH}
-s ALLOW_TABLE_GROWTH=1
-s ENVIRONMENT='web,node'
${ENVIRONMENT_FLAG}
-s EXPORT_ES6=1
-s EXPORT_NAME="Jolt"
-s MODULARIZE=1
Expand Down Expand Up @@ -102,6 +126,7 @@ set(EMCC_GLUE_ARGS
-I${JoltPhysics_SOURCE_DIR}/..
-Wall
-std=c++17
${MULTI_THREADED_FLAG}
-DJPH_OBJECT_LAYER_BITS=32
-include ${JOLT_HEADER_FILE}
${MEMORY_PROFILER_FLAG})
Expand All @@ -128,48 +153,48 @@ if (DOUBLE_PRECISION)
set(EMCC_GLUE_ARGS ${EMCC_GLUE_ARGS} -DJPH_DOUBLE_PRECISION)
endif()

#######################################
project("JoltPhysics.js")

#######################################
add_custom_command(
OUTPUT glue.cpp glue.js
BYPRODUCTS parser.out WebIDLGrammar.pkl
COMMAND ${PYTHON} ${WEBIDL_BINDER_SCRIPT} ${JOLT_IDL_FILE} glue
DEPENDS ${JOLT_IDL_FILE}
COMMENT "Generating JoltPhysics.js bindings"
VERBATIM)
OUTPUT glue.cpp glue.js
BYPRODUCTS parser.out WebIDLGrammar.pkl
COMMAND ${PYTHON} ${WEBIDL_BINDER_SCRIPT} ${JOLT_IDL_FILE} glue
DEPENDS ${JOLT_IDL_FILE}
COMMENT "Generating JoltPhysics.js bindings"
VERBATIM)

add_custom_command(
OUTPUT glue.o
COMMAND emcc glue.cpp ${EMCC_GLUE_ARGS} -o glue.o
DEPENDS glue.cpp ${JOLT_HEADER_FILE}
COMMENT "Building JoltPhysics.js bindings"
VERBATIM)
OUTPUT glue.o
COMMAND emcc glue.cpp ${EMCC_GLUE_ARGS} -o glue.o
DEPENDS glue.cpp ${JOLT_HEADER_FILE}
COMMENT "Building JoltPhysics.js bindings"
VERBATIM)
add_custom_target(jolt-bindings ALL DEPENDS glue.js glue.o)

#######################################
add_custom_command(
OUTPUT ${OUTPUT_FOLDER}jolt-physics.js
COMMAND emcc glue.o $<TARGET_FILE:Jolt> ${EMCC_JS_ARGS} -o ${OUTPUT_FOLDER}jolt-physics.js
DEPENDS jolt-bindings ${JOLT_FRONT_MATTER_FILE} ${JOLT_TARGETS} ${JOLT_IDL_FILE} ${JOLT_HEADER_FILE}
COMMENT "Building JoltPhysics.js javascript"
VERBATIM)
add_custom_target(jolt-javascript ALL DEPENDS ${OUTPUT_FOLDER}jolt-physics.js)

#######################################
add_custom_command(
OUTPUT ${OUTPUT_FOLDER}jolt-physics.wasm.js ${OUTPUT_FOLDER}jolt-physics.wasm.wasm
COMMAND emcc glue.o $<TARGET_FILE:Jolt> ${EMCC_WASM_ARGS} -o ${OUTPUT_FOLDER}jolt-physics.wasm.js
DEPENDS jolt-bindings ${JOLT_FRONT_MATTER_FILE} ${JOLT_TARGETS} ${JOLT_IDL_FILE} ${JOLT_HEADER_FILE}
COMMENT "Building JoltPhysics.js webassembly"
VERBATIM)
add_custom_target(jolt-wasm ALL DEPENDS ${OUTPUT_FOLDER}jolt-physics.wasm.js ${OUTPUT_FOLDER}jolt-physics.wasm.wasm)

#######################################
if (NOT BUILD_WASM_COMPAT_ONLY)
if (NOT ENABLE_MULTI_THREADING) # Not compatible with multi threading due to error: 'void wasm::I64ToI32Lowering::visitStore(Store *): Assertion `!curr->isAtomic && "atomic store not implemented"' failed.'
add_custom_command(
OUTPUT ${OUTPUT_FOLDER}jolt-physics.js
COMMAND emcc glue.o $<TARGET_FILE:Jolt> ${EMCC_JS_ARGS} -o ${OUTPUT_FOLDER}jolt-physics.js
DEPENDS jolt-bindings ${JOLT_FRONT_MATTER_FILE} ${JOLT_TARGETS} ${JOLT_IDL_FILE} ${JOLT_HEADER_FILE}
COMMENT "Building JoltPhysics.js javascript"
VERBATIM)
add_custom_target(jolt-javascript ALL DEPENDS ${OUTPUT_FOLDER}jolt-physics.js)
endif()

add_custom_command(
OUTPUT ${OUTPUT_FOLDER}jolt-physics.wasm.js ${OUTPUT_FOLDER}jolt-physics.wasm.wasm
COMMAND emcc glue.o $<TARGET_FILE:Jolt> ${EMCC_WASM_ARGS} -o ${OUTPUT_FOLDER}jolt-physics.wasm.js
DEPENDS jolt-bindings ${JOLT_FRONT_MATTER_FILE} ${JOLT_TARGETS} ${JOLT_IDL_FILE} ${JOLT_HEADER_FILE}
COMMENT "Building JoltPhysics.js webassembly"
VERBATIM)
add_custom_target(jolt-wasm ALL DEPENDS ${OUTPUT_FOLDER}jolt-physics.wasm.js ${OUTPUT_FOLDER}jolt-physics.wasm.wasm)
endif()

add_custom_command(
OUTPUT ${OUTPUT_FOLDER}jolt-physics.wasm-compat.js
COMMAND emcc glue.o $<TARGET_FILE:Jolt> ${EMCC_WASM_COMPAT_ARGS} -o ${OUTPUT_FOLDER}jolt-physics.wasm-compat.js
DEPENDS jolt-bindings ${JOLT_FRONT_MATTER_FILE} ${JOLT_TARGETS} ${JOLT_IDL_FILE} ${JOLT_HEADER_FILE}
COMMENT "Building JoltPhysics.js compat webassembly"
VERBATIM)
OUTPUT ${OUTPUT_FOLDER}jolt-physics.wasm-compat.js
COMMAND emcc glue.o $<TARGET_FILE:Jolt> ${EMCC_WASM_COMPAT_ARGS} -o ${OUTPUT_FOLDER}jolt-physics.wasm-compat.js
DEPENDS jolt-bindings ${JOLT_FRONT_MATTER_FILE} ${JOLT_TARGETS} ${JOLT_IDL_FILE} ${JOLT_HEADER_FILE}
COMMENT "Building JoltPhysics.js compat webassembly"
VERBATIM)
add_custom_target(jolt-wasm-compat ALL DEPENDS ${OUTPUT_FOLDER}jolt-physics.wasm-compat.js)
2 changes: 1 addition & 1 deletion JoltJS.h
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ class JoltInterface

private:
TempAllocatorImpl * mTempAllocator;
JobSystemThreadPool mJobSystem { cMaxPhysicsJobs, cMaxPhysicsBarriers, (int)thread::hardware_concurrency() - 1 };
JobSystemThreadPool mJobSystem { cMaxPhysicsJobs, cMaxPhysicsBarriers, min<int>(thread::hardware_concurrency() - 1, 16) }; // Limit to 16 threads since we limit the webworker thread pool size to this as well
BroadPhaseLayerInterface *mBroadPhaseLayerInterface = nullptr;
ObjectVsBroadPhaseLayerFilter *mObjectVsBroadPhaseLayerFilter = nullptr;
ObjectLayerPairFilter * mObjectLayerPairFilter = nullptr;
Expand Down
22 changes: 15 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,25 @@ This project has only been compiled under Linux.

* Install [emscripten](https://emscripten.org/) and ensure that its environment variables have been setup
* Install [cmake](https://cmake.org/)
* Run ```./build.sh``` for the optimized build, ```./build.sh Debug``` for the debug build or ```./build.sh Debug -DENABLE_MEMORY_PROFILER=ON``` for the debug build with memory tracking
* Run ```./build.sh Distribution``` for the optimized build, ```./build.sh Debug``` for the debug build.

You can also compile the project in double precision mode using ```./build.sh Distribution -DDOUBLE_PRECISION=ON```, currently no package is provided for this.
Additional options that can be provided to ```build.sh```:

* ```-DENABLE_MEMORY_PROFILER=ON``` will enable memory tracking to detect leaks.
* ```-DDOUBLE_PRECISION=ON``` will enable the double precision mode. This allows worlds larger than a couple of km.
* ```-DENABLE_MULTI_THREADING=ON``` will enable multi threading. Note that due to a bug in Safari this currently doesn't work in that brower. It is also incompatible with any JavaScript callback function that are triggered from web workers. See [this](https://github.com/jrouwe/JoltPhysics.js/discussions/110) ticket.
* ```-DBUILD_WASM_COMPAT_ONLY=ON``` speeds up the build by only compiling the WASM compat version which the examples use.

## Running

By default the examples use the WASM version of Jolt. This requires serving the html file using a web server rather than opening the html file directly. Use e.g. [serve](https://www.npmjs.com/package/serve) to quickly host the file.
By default the examples use the WASM version of Jolt. This requires serving the html file using a web server rather than opening the html file directly.

Go to the serveexamples folder and run

```
npm install
node serveexamples
```

If you need to debug the C++ code take a look at [WASM debugging](https://developer.chrome.com/blog/wasm-debugging-2020/).

Expand Down Expand Up @@ -120,10 +132,6 @@ The Body class is also a special case, it is destroyed through BodyInterface.Des

Almost everything else can be destroyed straight after it has been passed to Jolt. [An example that shows how to properly clean up using Jolt is here](https://github.com/jrouwe/JoltPhysics.js/blob/main/Examples/proper_cleanup.html).

## Credits

This project was started from the [Ammo.js](https://github.com/kripken/ammo.js) code, but little remains of it as the Jolt Physics API is very different from the Bullet API.

## License

The project is distributed under the [MIT license](LICENSE).
2 changes: 1 addition & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ if [ $? -ne 0 ]; then
exit 1
fi

cp ./dist/jolt-physics.wasm-compat.js ./Examples/js/jolt-physics.wasm-compat.js
cp ./dist/jolt-physics.wasm-compat*.js ./Examples/js/
if [ $? -ne 0 ]; then
exit 1
fi
Loading

0 comments on commit 893be84

Please sign in to comment.