Skip to content

Commit

Permalink
Merge branch 'dev-wasm'
Browse files Browse the repository at this point in the history
  • Loading branch information
LukasBanana committed Aug 23, 2024
2 parents 7798c79 + 22496dc commit a8907d6
Show file tree
Hide file tree
Showing 61 changed files with 2,912 additions and 186 deletions.
231 changes: 231 additions & 0 deletions BuildWasm.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
#!/bin/bash

SOURCE_DIR=$PWD
OUTPUT_DIR="build_wasm"
CLEAR_CACHE=0
ENABLE_EXAMPLES="ON"
ENABLE_TESTS="ON"
ENABLE_PTHREADS="OFF"
BUILD_TYPE="Release"
PROJECT_ONLY=0
VERBOSE=0
GENERATOR="CodeBlocks - Unix Makefiles"

# Check whether we are on a Linux distribution or MSYS on Windows
print_help()
{
echo "USAGE:"
echo " BuildWasm.sh OPTIONS* [OUTPUT_DIR]"
echo "OPTIONS:"
echo " -c, --clear-cache ......... Clear CMake cache and rebuild"
echo " -h, --help ................ Print this help documentation and exit"
echo " -d, --debug ............... Configure Debug build (default is Release)"
echo " -p, --project-only [=G] ... Build project with CMake generator (default is CodeBlocks)"
echo " --no-examples ............. Exclude example projects"
echo " --no-tests ................ Exclude test projects"
echo " --pthreads ................ Enable pthreads (limits browser availability)"
echo "NOTES:"
echo " Default output directory is '$OUTPUT_DIR'"
}

# Parse arguments
for ARG in "$@"; do
if [ "$ARG" = "-h" ] || [ "$ARG" = "--help" ]; then
print_help
exit 0
elif [ "$ARG" = "-c" ] || [ "$ARG" = "--clear-cache" ]; then
CLEAR_CACHE=1
elif [ "$ARG" = "-d" ] || [ "$ARG" = "--debug" ]; then
BUILD_TYPE="Debug"
elif [ "$ARG" = "-p" ] || [ "$ARG" = "--project-only" ]; then
PROJECT_ONLY=1
elif [[ "$ARG" == -p=* ]]; then
PROJECT_ONLY=1
GENERATOR="${ARG:3}"
elif [[ "$ARG" == --project-only=* ]]; then
PROJECT_ONLY=1
GENERATOR="${ARG:15}"
elif [ "$ARG" = "-v" ] || [ "$ARG" = "--verbose" ]; then
VERBOSE=1
elif [ "$ARG" = "--null" ]; then
ENABLE_NULL="ON"
elif [ "$ARG" = "--vulkan" ]; then
ENABLE_VULKAN="ON"
elif [ "$ARG" = "--no-examples" ]; then
ENABLE_EXAMPLES="OFF"
elif [ "$ARG" = "--no-tests" ]; then
ENABLE_TESTS="OFF"
elif [ "$ARG" = "--pthreads" ]; then
ENABLE_PTHREADS="ON"
else
OUTPUT_DIR="$ARG"
fi
done

# Ensure we are inside the repository folder
if [ ! -f "CMakeLists.txt" ]; then
echo "Error: File not found: CMakeLists.txt"
exit 1
fi

# Make output build folder
if [ $CLEAR_CACHE = 1 ] && [ -d "$OUTPUT_DIR" ]; then
rm -rf "$OUTPUT_DIR"
fi

if [ ! -d "$OUTPUT_DIR" ]; then
mkdir "$OUTPUT_DIR"
fi

# Checkout external depenencies
GAUSSIAN_LIB_DIR="GaussianLib/include"

if [ -f "$SOURCE_DIR/external/$GAUSSIAN_LIB_DIR/Gauss/Gauss.h" ]; then
GAUSSIAN_LIB_DIR=$(realpath "$SOURCE_DIR/external/$GAUSSIAN_LIB_DIR")
else
if [ ! -d "$OUTPUT_DIR/$GAUSSIAN_LIB_DIR" ]; then
(cd "$OUTPUT_DIR" && git clone https://github.com/LukasBanana/GaussianLib.git)
fi
GAUSSIAN_LIB_DIR=$(realpath "$OUTPUT_DIR/$GAUSSIAN_LIB_DIR")
fi

# Print additional information if in verbose mode
if [ $VERBOSE -eq 1 ]; then
echo "GAUSSIAN_LIB_DIR=$GAUSSIAN_LIB_DIR"
if [ $PROJECT_ONLY -eq 0 ]; then
echo "BUILD_TYPE=$BUILD_TYPE"
else
echo "GENERATOR=$GENERATOR"
fi
fi

# Find Emscripten SDK
if [ -z "$EMSDK" ]; then
echo "Error: Missing EMSDK environment variable. Run 'source <PATH-TO-EMSDK>/emsdk_env.sh' to fix it."
exit 1
fi

EMSCRIPTEN_CMAKE_TOOLCHAIN="$EMSDK/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake"
EMSCRIPTEN_FILE_PACKAGER="$EMSDK/upstream/emscripten/tools/file_packager"

if [ ! -f "$EMSCRIPTEN_CMAKE_TOOLCHAIN" ]; then
echo "Error: Could not find file $EMSCRIPTEN_CMAKE_TOOLCHAIN"
exit 1
fi

# Build into output directory (this syntax requried CMake 3.13+)
OPTIONS=(
-DCMAKE_TOOLCHAIN_FILE="$EMSCRIPTEN_CMAKE_TOOLCHAIN"
-DLLGL_BUILD_RENDERER_WEBGL=ON
-DLLGL_GL_ENABLE_OPENGL2X=OFF
-DLLGL_BUILD_RENDERER_NULL=OFF
-DLLGL_BUILD_RENDERER_VULKAN=OFF
-DLLGL_BUILD_RENDERER_DIRECT3D11=OFF
-DLLGL_BUILD_RENDERER_DIRECT3D12=OFF
-DLLGL_BUILD_EXAMPLES=$ENABLE_EXAMPLES
-DLLGL_BUILD_TESTS=$ENABLE_TESTS
-DLLGL_BUILD_STATIC_LIB=ON
-DLLGL_ENABLE_EMSCRIPTEN_PTHREADS=$ENABLE_PTHREADS
-DGaussLib_INCLUDE_DIR:STRING="$GAUSSIAN_LIB_DIR"
-S "$SOURCE_DIR"
-B "$OUTPUT_DIR"
)

if [ $PROJECT_ONLY -eq 0 ]; then
cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE ${OPTIONS[@]}
cmake --build "$OUTPUT_DIR" -- -j 20
else
cmake ${OPTIONS[@]} -G "$GENERATOR"
fi

# Generate HTML pages
generate_html5_page()
{
CURRENT_PROJECT=$1

echo "Generate HTML5 page: $CURRENT_PROJECT"

# Get source folder
ASSET_SOURCE_DIR="$SOURCE_DIR/examples/Media"
PROJECT_SOURCE_DIR="$SOURCE_DIR/examples/Cpp"
if [[ "$CURRENT_PROJECT" == *D ]]; then
PROJECT_SOURCE_DIR="$PROJECT_SOURCE_DIR/${CURRENT_PROJECT:0:-1}"
else
PROJECT_SOURCE_DIR="$PROJECT_SOURCE_DIR/$CURRENT_PROJECT"
fi

# Get destination folder
HTML5_ROOT="${OUTPUT_DIR}/html5/Example_$CURRENT_PROJECT"
BIN_ROOT=${OUTPUT_DIR}/build

# Create folder structure
mkdir -p "$HTML5_ROOT"
BASE_FILENAME="Example_$CURRENT_PROJECT"
cp "$SOURCE_DIR/examples/Cpp/ExampleBase/Wasm/index.html" "$HTML5_ROOT/index.html"
cp "$BIN_ROOT/$BASE_FILENAME.js" "$HTML5_ROOT/$BASE_FILENAME.js"
cp "$BIN_ROOT/$BASE_FILENAME.wasm" "$HTML5_ROOT/$BASE_FILENAME.wasm"
if [ $ENABLE_PTHREADS = "ON" ]; then
cp "$BIN_ROOT/$BASE_FILENAME.worker.js" "$HTML5_ROOT/$BASE_FILENAME.worker.js"
fi

# Replace meta data
sed -i "s/LLGL_EXAMPLE_NAME/${CURRENT_PROJECT}/" "$HTML5_ROOT/index.html"
sed -i "s/LLGL_EXAMPLE_PROJECT/Example_${CURRENT_PROJECT}/" "$HTML5_ROOT/index.html"

# Find all required assets in Android.assets.txt file of respective project directory and copy them into app folder
ASSET_DIR="$HTML5_ROOT/assets"
mkdir -p "$ASSET_DIR"

ASSET_LIST_FILE="$PROJECT_SOURCE_DIR/Android.assets.txt"
if [ -f "$ASSET_LIST_FILE" ]; then
# Read Android.asset.txt file line-by-line into array and make sure '\r' character is not present (on Win32 platform)
readarray -t ASSET_FILTERS < <(tr -d '\r' < "$ASSET_LIST_FILE")
ASSET_FILES=()
for FILTER in ${ASSET_FILTERS[@]}; do
for FILE in $ASSET_SOURCE_DIR/$FILTER; do
ASSET_FILES+=( "$FILE" )
done
done

# Copy all asset file into destination folder
for FILE in ${ASSET_FILES[@]}; do
if [ $VERBOSE -eq 1 ]; then
echo "Copy asset: $(basename $FILE)"
fi
cp "$FILE" "$ASSET_DIR/$(basename $FILE)"
done
fi

# Find all shaders and copy them into app folder
for FILE in $PROJECT_SOURCE_DIR/*.vert \
$PROJECT_SOURCE_DIR/*.frag; do
if [ -f "$FILE" ]; then
if [ $VERBOSE -eq 1 ]; then
echo "Copy shader: $(basename $FILE)"
fi
cp "$FILE" "$ASSET_DIR/$(basename $FILE)"
fi
done

# Package assets into .data.js file with Emscripten packager tool
(cd "$HTML5_ROOT" && "$EMSCRIPTEN_FILE_PACKAGER" "$BASE_FILENAME.data" --preload assets "--js-output=$BASE_FILENAME.data.js" >/dev/null 2>&1)
}

if [ $PROJECT_ONLY -eq 0 ] && [ $ENABLE_EXAMPLES == "ON" ]; then

BIN_FILE_BASE="${OUTPUT_DIR}/build/Example_"
BIN_FILE_BASE_LEN=${#BIN_FILE_BASE}

if [ $BUILD_TYPE = "Debug" ]; then
EXAMPLE_BIN_FILES=(${BIN_FILE_BASE}*D.wasm)
else
EXAMPLE_BIN_FILES=(${BIN_FILE_BASE}*.wasm)
fi

for BIN_FILE in ${EXAMPLE_BIN_FILES[@]}; do
BIN_FILE_LEN=${#BIN_FILE}
PROJECT_NAME=${BIN_FILE:BIN_FILE_BASE_LEN:BIN_FILE_LEN-BIN_FILE_BASE_LEN-5}
generate_html5_page $PROJECT_NAME
done

fi
45 changes: 41 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ endif()
set(LLGL_UWP_PLATFORM OFF)
set(LLGL_IOS_PLATFORM OFF)
set(LLGL_ANDROID_PLATFORM OFF)
set(LLGL_WASM_PLATFORM OFF)

if(NOT DEFINED LLGL_TARGET_PLATFORM)
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Android")
Expand All @@ -33,6 +34,9 @@ if(NOT DEFINED LLGL_TARGET_PLATFORM)
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "WindowsStore")
set(LLGL_TARGET_PLATFORM "${CMAKE_SYSTEM_NAME} ${CMAKE_SYSTEM_VERSION}")
set(LLGL_UWP_PLATFORM ON)
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Emscripten")
set(LLGL_TARGET_PLATFORM "WebAssembly")
set(LLGL_WASM_PLATFORM ON)
elseif(WIN32)
if(LLGL_BUILD_64BIT)
set(LLGL_TARGET_PLATFORM "Win64")
Expand Down Expand Up @@ -91,7 +95,7 @@ set( BACKEND_INCLUDE_DIR "${PROJECT_INCLUDE_DIR}/LLGL/Backend" )

# === Macros ===

if(LLGL_IOS_PLATFORM OR LLGL_ANDROID_PLATFORM)
if(LLGL_IOS_PLATFORM OR LLGL_ANDROID_PLATFORM OR LLGL_WASM_PLATFORM)
set(LLGL_MOBILE_PLATFORM ON)
else()
set(LLGL_MOBILE_PLATFORM OFF)
Expand Down Expand Up @@ -380,6 +384,7 @@ endif()

set(SUMMARY_LIBRARY_TYPE "Unknown")
set(SUMMARY_TARGET_ARCH "Unknown")
set(SUMMARY_FLAGS "")


# === Options ===
Expand Down Expand Up @@ -408,7 +413,10 @@ option(LLGL_BUILD_EXAMPLES "Include example projects" OFF)
option(LLGL_BUILD_RENDERER_NULL "Include Null renderer project" ON)

if(NOT LLGL_UWP_PLATFORM)
if(LLGL_MOBILE_PLATFORM)
if(EMSCRIPTEN)
option(LLGL_BUILD_RENDERER_WEBGL "Include WebGL renderer project" ON)
option(LLGL_ENABLE_EMSCRIPTEN_PTHREADS "Build for Wasm platform with pthreads (USE_PTHREADS). This limits browser availability!" OFF)
elseif(LLGL_MOBILE_PLATFORM)
option(LLGL_BUILD_RENDERER_OPENGLES3 "Include OpenGLES 3 renderer project" ON)
else()
option(LLGL_BUILD_RENDERER_OPENGL "Include OpenGL renderer project" ON)
Expand Down Expand Up @@ -483,6 +491,22 @@ else()
set(SUMMARY_TARGET_ARCH "x86")
endif()

if(EMSCRIPTEN)
# When USE_PTHREADS is enabled, HTML5 pages cannot be opened in Chrome unless launched with '--enable-features=SharedArrayBuffer'
if(LLGL_ENABLE_EMSCRIPTEN_PTHREADS)
add_compile_options("SHELL:-s USE_PTHREADS")
add_link_options("SHELL:-s USE_PTHREADS")
set(SUMMARY_FLAGS ${SUMMARY_FLAGS} "pthreads")
endif()

# TODO: Emscripten file system pulls in a large amount of code. Consider limiting file system support to examples and tests.
add_link_options("SHELL:-s FORCE_FILESYSTEM") # for examples

# LLGL needs at least WebGL 2.0
add_link_options("SHELL:-s MIN_WEBGL_VERSION=2")
add_link_options("SHELL:-s MAX_WEBGL_VERSION=2")
endif()


# === Global files ===

Expand Down Expand Up @@ -522,7 +546,10 @@ if(LLGL_ENABLE_DEBUG_LAYER)
find_source_files(FilesRendererDbgTexture CXX "${PROJECT_SOURCE_DIR}/sources/Renderer/DebugLayer/Texture")
endif()

if(WIN32)
if(EMSCRIPTEN)
find_source_files(FilesPlatform CXX "${PROJECT_SOURCE_DIR}/sources/Platform/Wasm")
find_source_files(FilesIncludePlatform CXX "${PROJECT_INCLUDE_DIR}/LLGL/Platform/Wasm")
elseif(WIN32)
if(LLGL_UWP_PLATFORM)
find_source_files(FilesPlatform CXX "${PROJECT_SOURCE_DIR}/sources/Platform/UWP")
find_source_files(FilesIncludePlatform CXX "${PROJECT_INCLUDE_DIR}/LLGL/Platform/UWP")
Expand Down Expand Up @@ -679,6 +706,8 @@ elseif(APPLE)
if(LLGL_MACOS_ENABLE_COREVIDEO)
target_link_libraries(LLGL "-framework CoreVideo")
endif()
elseif(EMSCRIPTEN)
target_link_libraries(LLGL embind)
elseif(UNIX)
target_link_libraries(LLGL X11 pthread Xrandr)
#elseif(LLGL_UWP_PLATFORM)
Expand All @@ -697,7 +726,7 @@ if(LLGL_BUILD_RENDERER_NULL)
add_subdirectory(sources/Renderer/Null)
endif()

if(LLGL_BUILD_RENDERER_OPENGL OR LLGL_BUILD_RENDERER_OPENGLES3)
if(LLGL_BUILD_RENDERER_OPENGL OR LLGL_BUILD_RENDERER_OPENGLES3 OR LLGL_BUILD_RENDERER_WEBGL)
add_subdirectory(sources/Renderer/OpenGL)
endif()

Expand Down Expand Up @@ -787,6 +816,10 @@ if(LLGL_BUILD_RENDERER_OPENGLES3)
message(STATUS "Build Renderer: ${LLGL_GL_ENABLE_OPENGLES}")
endif()

if(LLGL_BUILD_RENDERER_WEBGL)
message(STATUS "Build Renderer: WebGL")
endif()

if(LLGL_BUILD_RENDERER_VULKAN)
message(STATUS "Build Renderer: Vulkan")
endif()
Expand Down Expand Up @@ -823,5 +856,9 @@ if(LLGL_VK_ENABLE_SPIRV_REFLECT)
message(STATUS "Including Submodule: SPIRV-Headers")
endif()

if(NOT "${SUMMARY_FLAGS}" STREQUAL "")
message(STATUS "Options: ${SUMMARY_FLAGS}")
endif()

message(STATUS "~~~~~~~~~~~~~~~~~~~~~")

35 changes: 35 additions & 0 deletions CMakePresets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"version": 3,
"configurePresets": [
{
"name": "emscripten",
"generator": "Ninja Multi-Config",
"toolchainFile": "/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake",
"binaryDir": "${sourceDir}/../llgl-build",
"architecture": {
"strategy": "external",
"value": "x86"
},
"vendor": {
"microsoft.com/VisualStudioSettings/CMake/1.0": { "hostOS": [ "Linux" ] }
}
}
],
"buildPresets": [
{
"name": "Release",
"configurePreset": "emscripten",
"configuration": "Release"
},
{
"name": "Debug",
"configurePreset": "emscripten",
"configuration": "Debug"
},
{
"name": "RelWithDebInfo",
"configurePreset": "emscripten",
"configuration": "RelWithDebInfo"
}
]
}
Loading

0 comments on commit a8907d6

Please sign in to comment.