From 63099350266cda721be4b6077af7b990c4da4b19 Mon Sep 17 00:00:00 2001 From: ading2210 Date: Tue, 28 May 2024 07:07:27 -0400 Subject: [PATCH 01/25] get all dependencies to build with emscripten --- .gitignore | 2 + wasm/build_deps.sh | 163 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100755 wasm/build_deps.sh diff --git a/.gitignore b/.gitignore index 70be3aea0af..166c20e7ac0 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ CMakeFiles/ stk-editor/ .vscode/ tags.* +wasm/build/ +wasm/prefix/ # clangd .cache/ diff --git a/wasm/build_deps.sh b/wasm/build_deps.sh new file mode 100755 index 00000000000..74da11c0397 --- /dev/null +++ b/wasm/build_deps.sh @@ -0,0 +1,163 @@ +#!/bin/bash + +set -x +set -e + +CORE_COUNT="$(nproc --all)" +BASE_DIR="$(realpath "$(dirname "$0")")" +BUILD_DIR="$BASE_DIR/build" +PREFIX="$BASE_DIR/prefix" +INCLUDE="$PREFIX/include" +LIB="$PREFIX/lib" + +export PKG_CONFIG_PATH="$LIB/pkgconfig" + +clone_repo() { + local url="$1" + local tag="$2" + local path="$3" + if [ ! -d "$path" ]; then + git clone "$url" -b "$tag" --depth=1 "$path" + fi +} + +build_ogg() { + local SRC_DIR="$BUILD_DIR/ogg" + clone_repo "https://github.com/xiph/ogg" v1.3.5 "$SRC_DIR" + cd "$SRC_DIR" + + ./autogen.sh + emconfigure ./configure --host=none-linux --prefix="$PREFIX" --disable-shared + emmake make -j$CORE_COUNT + make install +} + +build_vorbis() { + local SRC_DIR="$BUILD_DIR/vorbis" + clone_repo "https://github.com/xiph/vorbis" v1.3.7 "$SRC_DIR" + cd "$SRC_DIR" + + ./autogen.sh + emconfigure ./configure --host=none-linux --prefix="$PREFIX" --with-ogg="$PREFIX" --disable-shared + emmake make -j$CORE_COUNT + make install +} + +build_openssl() { + local SRC_DIR="$BUILD_DIR/openssl" + clone_repo "https://github.com/openssl/openssl" openssl-3.3.0 "$SRC_DIR" + cd "$SRC_DIR" + + emconfigure ./Configure linux-x32 -no-asm -static -no-afalgeng -no-dso -no-threads -DOPENSSL_SYS_NETWARE -DSIG_DFL=0 -DSIG_IGN=0 -DHAVE_FORK=0 -DOPENSSL_NO_AFALGENG=1 -DOPENSSL_NO_SPEED=1 -DOPENSSL_NO_DYNAMIC_ENGINE -DDLOPEN_FLAG=0 + sed -i 's|^CROSS_COMPILE.*$|CROSS_COMPILE=|g' Makefile + emmake make -j$CORE_COUNT build_generated libssl.a libcrypto.a + cp -r include/openssl $PREFIX/include + cp libcrypto.a libssl.a $PREFIX/lib +} + +build_zlib() { + local SRC_DIR="$BUILD_DIR/zlib" + clone_repo "https://github.com/madler/zlib" v1.3.1 "$SRC_DIR" + cd "$SRC_DIR" + + emconfigure ./configure --prefix="$PREFIX" --static + emmake make -j$CORE_COUNT + make install +} + +build_curl() { + local SRC_DIR="$BUILD_DIR/curl" + clone_repo "https://github.com/curl/curl" curl-8_8_0 "$SRC_DIR" + cd "$SRC_DIR" + + autoreconf -fi + emconfigure ./configure --host none-linux --prefix="$PREFIX" --with-ssl="$PREFIX" --with-zlib="$PREFIX" --disable-shared --disable-threaded-resolver --without-libpsl --disable-netrc --disable-ipv6 --disable-tftp --disable-ntlm-wb + emmake make -j$CORE_COUNT + make install +} + +build_jpeg() { + local SRC_DIR="$BUILD_DIR/jpeg" + clone_repo "https://github.com/libjpeg-turbo/libjpeg-turbo" 3.0.3 "$SRC_DIR" + cd "$SRC_DIR" + mkdir -p build + cd build + + emcmake cmake -G"Unix Makefiles" -DCMAKE_INSTALL_PREFIX:PATH="$PREFIX" -DWITH_SIMD=0 .. + emmake make -j$CORE_COUNT + make install +} + +build_png() { + local SRC_DIR="$BUILD_DIR/png" + clone_repo "https://github.com/pnggroup/libpng" v1.6.43 "$SRC_DIR" + cd "$SRC_DIR" + + emconfigure ./configure --host none-linux --prefix="$PREFIX" --disable-shared CPPFLAGS="-I$INCLUDE" LDFLAGS="-L$LIB" + emmake make -j$CORE_COUNT + make install +} + + +build_freetype() { + local with_harfbuzz="$1" + local SRC_DIR="$BUILD_DIR/freetype" + clone_repo "https://github.com/freetype/freetype" VER-2-13-2 "$SRC_DIR" + cd "$SRC_DIR" + + ./autogen.sh + emconfigure ./configure --host=none-linux --prefix="$PREFIX" --disable-shared PKG_CONFIG_PATH="$LIB/pkgconfig" + emmake make -j$CORE_COUNT + make install +} + +build_harfbuzz() { + local SRC_DIR="$BUILD_DIR/harfbuzz" + clone_repo "https://github.com/harfbuzz/harfbuzz" 8.5.0 "$SRC_DIR" + cd "$SRC_DIR" + + ./autogen.sh + emconfigure ./configure --host=none-linux --prefix="$PREFIX" --disable-shared PKG_CONFIG_PATH="$LIB/pkgconfig" + emmake make -j$CORE_COUNT + make install +} + +if [ ! -d "$INCLUDE/ogg" ]; then + build_ogg +fi + +if [ ! -d "$INCLUDE/vorbis" ]; then + build_vorbis +fi + +if [ ! -d "$INCLUDE/openssl" ]; then + build_openssl +fi + +if [ ! -f "$INCLUDE/zlib.h" ]; then + build_zlib +fi + +if [ ! -d "$INCLUDE/curl" ]; then + build_curl +fi + +if [ ! -f "$INCLUDE/turbojpeg.h" ]; then + build_jpeg +fi + +if [ ! -f "$INCLUDE/png.h" ]; then + build_png +fi + +if [ ! -d "$INCLUDE/freetype2" ]; then + build_freetype +fi + +if [ ! -d "$INCLUDE/harfbuzz" ]; then + build_harfbuzz + + #rebuild freetype with harfbuzz support + rm -rf "$INCLUDE/freetype2" + build_freetype +fi From 73a33e0edab4ae62b97d8c8cb158c645b270d7fb Mon Sep 17 00:00:00 2001 From: ading2210 Date: Tue, 28 May 2024 07:49:57 -0400 Subject: [PATCH 02/25] allow cmake configuration to succeed --- CMakeLists.txt | 37 +++++++++++++++++++++++++++++- lib/graphics_engine/CMakeLists.txt | 10 ++++---- wasm/build.sh | 13 +++++++++++ 3 files changed, 55 insertions(+), 5 deletions(-) create mode 100755 wasm/build.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index d85449a5f58..7ebeb7fbf3f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,6 +58,41 @@ if(IOS) include(cmake/XcodeHelper.cmake) endif() +if(EMSCRIPTEN) + set(CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/wasm/prefix/") + + set(JPEG_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include/") + set(JPEG_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/") + + set(PNG_PNG_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include/") + set(PNG_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/") + + set(ZLIB_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include/") + set(ZLIB_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/") + + set(LIB_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include/") + set(ZLIB_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/") + + set(HARFBUZZ_INCLUDEDIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include/") + set(HARFBUZZ_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/") + + set(CURL_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include/") + set(CURL_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/") + + set(OPENSSL_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include/") + set(OPENSSL_CRYPTO_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/") + + #todo: avoid hardcoding this path + set(PTHREAD_LIBRARY "/usr/share/emscripten/cache/sysroot/") + + set(USE_WIIUSE 0) + set(USE_DNS_C 1) + add_definitions(-DNO_IRR_COMPILE_WITH_X11_) + add_definitions(-DNO_IRR_COMPILE_WITH_WAYLAND_DEVICE_) + add_definitions(-DNO_IRR_COMPILE_WITH_DIRECT3D_9_) + add_definitions(-DNO_IRR_COMPILE_WITH_VULKAN_) +endif() + if(APPLE AND NOT IOS) if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm") set(ARCHFLAGS "arm64") @@ -326,7 +361,7 @@ else() MESSAGE(STATUS "Use system libmcpp: ${MCPP_LIBRARY}") endif() -if (NOT SERVER_ONLY) +if (NOT SERVER_ONLY AND NOT EMSCRIPTEN) # SDL2 find_library(SDL2_LIBRARY NAMES SDL2 libSDL2) find_path(SDL2_INCLUDEDIR NAMES SDL.h PATH_SUFFIXES SDL2 include/SDL2 include PATHS) diff --git a/lib/graphics_engine/CMakeLists.txt b/lib/graphics_engine/CMakeLists.txt index b42ff383c70..a76f9109a8b 100644 --- a/lib/graphics_engine/CMakeLists.txt +++ b/lib/graphics_engine/CMakeLists.txt @@ -42,10 +42,12 @@ include_directories("${PROJECT_SOURCE_DIR}/lib/graphics_utils") include_directories("${PROJECT_SOURCE_DIR}/lib/irrlicht/include") include_directories("${PROJECT_SOURCE_DIR}/lib/bullet/src") find_path(SDL2_INCLUDEDIR NAMES SDL.h PATH_SUFFIXES SDL2 include/SDL2 include PATHS) -if (NOT SDL2_INCLUDEDIR) - message(FATAL_ERROR "SDL2 not found.") -else() - include_directories("${SDL2_INCLUDEDIR}") +if (NOT EMSCRIPTEN) + if (NOT SDL2_INCLUDEDIR) + message(FATAL_ERROR "SDL2 not found.") + else() + include_directories("${SDL2_INCLUDEDIR}") + endif() endif() if(APPLE AND NOT DLOPEN_MOLTENVK) diff --git a/wasm/build.sh b/wasm/build.sh new file mode 100755 index 00000000000..4dce929fef1 --- /dev/null +++ b/wasm/build.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +CORE_COUNT="$(nproc --all)" +BASE_DIR="$(realpath "$(dirname "$0")")" +SRC_DIR="$(dirname "$BASE_DIR")" +BUILD_DIR="$SRC_DIR/cmake_build" +PREFIX="$BASE_DIR/prefix" + +mkdir -p $BUILD_DIR +cd $BUILD_DIR + +emcmake cmake .. -DNO_SHADERC=on +make -j$CORE_COUNT \ No newline at end of file From 0830eb119608e7bcfa442d9516a9c507f8eaaca0 Mon Sep 17 00:00:00 2001 From: ading2210 Date: Tue, 28 May 2024 10:16:54 -0400 Subject: [PATCH 03/25] fix sdl compile errors --- .gitignore | 1 + CMakeLists.txt | 28 +++++++---- lib/graphics_engine/include/ge_main.hpp | 4 ++ .../src/ge_compressor_astc_4x4.cpp | 4 ++ lib/graphics_engine/src/ge_main.cpp | 2 + lib/graphics_engine/src/ge_spm_buffer.cpp | 4 ++ .../src/ge_vulkan_2d_renderer.cpp | 4 ++ .../src/ge_vulkan_array_texture.cpp | 4 ++ .../src/ge_vulkan_billboard_buffer.cpp | 4 ++ .../src/ge_vulkan_camera_scene_node.cpp | 4 ++ .../src/ge_vulkan_command_loader.cpp | 4 ++ .../src/ge_vulkan_depth_texture.cpp | 4 ++ .../src/ge_vulkan_draw_call.cpp | 4 ++ lib/graphics_engine/src/ge_vulkan_driver.cpp | 4 ++ .../src/ge_vulkan_dynamic_buffer.cpp | 4 ++ .../src/ge_vulkan_dynamic_spm_buffer.cpp | 4 ++ .../src/ge_vulkan_fbo_texture.cpp | 4 ++ .../src/ge_vulkan_features.cpp | 4 ++ .../src/ge_vulkan_mesh_cache.cpp | 4 ++ .../src/ge_vulkan_scene_manager.cpp | 4 ++ .../src/ge_vulkan_shader_manager.cpp | 4 ++ .../src/ge_vulkan_skybox_renderer.cpp | 4 ++ lib/graphics_engine/src/ge_vulkan_texture.cpp | 4 ++ .../src/ge_vulkan_texture_descriptor.cpp | 4 ++ .../source/Irrlicht/CIrrDeviceSDL.cpp | 46 ++++++++++++++++--- src/graphics/b3d_mesh_loader.cpp | 8 ++++ src/graphics/irr_driver.cpp | 6 ++- src/graphics/sp/sp_mesh_buffer.cpp | 2 +- src/graphics/sp_mesh_loader.cpp | 2 +- src/graphics/stk_tex_manager.cpp | 8 ++-- src/guiengine/widgets/CGUIEditBox.cpp | 4 +- src/karts/kart_properties_manager.cpp | 7 ++- .../dialogs/custom_video_settings.cpp | 2 +- src/states_screens/kart_selection.cpp | 2 +- .../options/options_screen_display.cpp | 2 + .../options/options_screen_video.cpp | 12 ++++- src/tracks/graph.cpp | 8 ++-- wasm/build.sh | 4 +- wasm/build_deps.sh | 4 +- wasm/get_emsdk.sh | 12 +++++ 40 files changed, 209 insertions(+), 35 deletions(-) create mode 100755 wasm/get_emsdk.sh diff --git a/.gitignore b/.gitignore index 166c20e7ac0..cca03f976ad 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ stk-editor/ tags.* wasm/build/ wasm/prefix/ +wasm/emsdk/ # clangd .cache/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ebeb7fbf3f..3b98f57818d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,25 +62,29 @@ if(EMSCRIPTEN) set(CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/wasm/prefix/") set(JPEG_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include/") - set(JPEG_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/") + set(JPEG_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/libjpeg.a") set(PNG_PNG_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include/") - set(PNG_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/") + set(PNG_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/libpng.a") set(ZLIB_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include/") - set(ZLIB_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/") - - set(LIB_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include/") - set(ZLIB_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/") + set(ZLIB_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/libz.a") set(HARFBUZZ_INCLUDEDIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include/") - set(HARFBUZZ_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/") + set(HARFBUZZ_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/libharfbuzz.a") set(CURL_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include/") - set(CURL_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/") + set(CURL_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/libcurl.a") set(OPENSSL_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include/") - set(OPENSSL_CRYPTO_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/") + set(OPENSSL_CRYPTO_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/libssl.a") + + set(OGGVORBIS_OGG_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include/") + set(OGGVORBIS_VORBIS_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include/") + set(OGGVORBIS_OGG_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/libogg.a") + set(OGGVORBIS_VORBISFILE_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/lobvorbisfile.a") + set(OGGVORBIS_VORBIS_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/libvorbis.a") + #-DFREETYPE_INCLUDE_DIRS=/home/heatingdevice/projects/freetype/include \ #todo: avoid hardcoding this path set(PTHREAD_LIBRARY "/usr/share/emscripten/cache/sysroot/") @@ -91,6 +95,8 @@ if(EMSCRIPTEN) add_definitions(-DNO_IRR_COMPILE_WITH_WAYLAND_DEVICE_) add_definitions(-DNO_IRR_COMPILE_WITH_DIRECT3D_9_) add_definitions(-DNO_IRR_COMPILE_WITH_VULKAN_) + add_definitions(-DNO_IRR_COMPILE_WITH_OPENGL_) + add_definitions(-D_IRR_COMPILE_WITH_OGLES2_) endif() if(APPLE AND NOT IOS) @@ -879,6 +885,10 @@ if(MINGW) endif() endif() +if(EMSCRIPTEN) + target_compile_options(supertuxkart PRIVATE -sUSE_SDL=2) + target_compile_options(stkirrlicht PRIVATE -sUSE_SDL=2) +endif() # Find LibGamerzilla library or build it if missing if (NOT APPLE) diff --git a/lib/graphics_engine/include/ge_main.hpp b/lib/graphics_engine/include/ge_main.hpp index 656963c99d9..cecaf98f74f 100644 --- a/lib/graphics_engine/include/ge_main.hpp +++ b/lib/graphics_engine/include/ge_main.hpp @@ -18,7 +18,9 @@ namespace irr namespace GE { +#ifdef _IRR_COMPILE_WITH_VULKAN_ class GEVulkanDriver; +#endif struct GEConfig { bool m_disable_npot_texture; @@ -34,7 +36,9 @@ float m_render_scale; void setVideoDriver(irr::video::IVideoDriver* driver); void setShaderFolder(const std::string& path); irr::video::IVideoDriver* getDriver(); +#ifdef _IRR_COMPILE_WITH_VULKAN_ GE::GEVulkanDriver* getVKDriver(); +#endif const std::string& getShaderFolder(); GEConfig* getGEConfig(); void deinit(); diff --git a/lib/graphics_engine/src/ge_compressor_astc_4x4.cpp b/lib/graphics_engine/src/ge_compressor_astc_4x4.cpp index 1b84c2175ee..0ff483f8c77 100644 --- a/lib/graphics_engine/src/ge_compressor_astc_4x4.cpp +++ b/lib/graphics_engine/src/ge_compressor_astc_4x4.cpp @@ -1,3 +1,5 @@ +#ifdef _IRR_COMPILE_WITH_VULKAN_ + #include "ge_compressor_astc_4x4.hpp" #include "ge_main.hpp" @@ -135,3 +137,5 @@ GECompressorASTC4x4::GECompressorASTC4x4(uint8_t* texture, unsigned channels, } // GECompressorASTC4x4 } + +#endif \ No newline at end of file diff --git a/lib/graphics_engine/src/ge_main.cpp b/lib/graphics_engine/src/ge_main.cpp index 04b02d9b899..9ed90cb40cc 100644 --- a/lib/graphics_engine/src/ge_main.cpp +++ b/lib/graphics_engine/src/ge_main.cpp @@ -44,10 +44,12 @@ irr::video::IVideoDriver* getDriver() return g_driver; } +#ifdef _IRR_COMPILE_WITH_VULKAN_ GE::GEVulkanDriver* getVKDriver() { return dynamic_cast(g_driver); } +#endif GEConfig* getGEConfig() { diff --git a/lib/graphics_engine/src/ge_spm_buffer.cpp b/lib/graphics_engine/src/ge_spm_buffer.cpp index 1179a732566..013a6a4c71c 100644 --- a/lib/graphics_engine/src/ge_spm_buffer.cpp +++ b/lib/graphics_engine/src/ge_spm_buffer.cpp @@ -1,3 +1,5 @@ +#ifdef _IRR_COMPILE_WITH_VULKAN_ + #include "ge_spm_buffer.hpp" #include "ge_main.hpp" @@ -117,3 +119,5 @@ void GESPMBuffer::setTCoords(u32 i, const core::vector2df& tcoords) } // setTCoords } + +#endif \ No newline at end of file diff --git a/lib/graphics_engine/src/ge_vulkan_2d_renderer.cpp b/lib/graphics_engine/src/ge_vulkan_2d_renderer.cpp index 771169eed66..4953b2f83cc 100644 --- a/lib/graphics_engine/src/ge_vulkan_2d_renderer.cpp +++ b/lib/graphics_engine/src/ge_vulkan_2d_renderer.cpp @@ -1,3 +1,5 @@ +#ifdef _IRR_COMPILE_WITH_VULKAN_ + #include "ge_vulkan_2d_renderer.hpp" #include "ge_main.hpp" @@ -439,3 +441,5 @@ void GEVulkan2dRenderer::addVerticesIndices(irr::video::S3DVertex* vertices, } // addVerticesIndices } + +#endif \ No newline at end of file diff --git a/lib/graphics_engine/src/ge_vulkan_array_texture.cpp b/lib/graphics_engine/src/ge_vulkan_array_texture.cpp index 0f817dc40fd..d37d1dd0884 100644 --- a/lib/graphics_engine/src/ge_vulkan_array_texture.cpp +++ b/lib/graphics_engine/src/ge_vulkan_array_texture.cpp @@ -1,3 +1,5 @@ +#ifdef _IRR_COMPILE_WITH_VULKAN_ + #include "ge_vulkan_array_texture.hpp" #include "ge_main.hpp" @@ -259,3 +261,5 @@ void GEVulkanArrayTexture::reloadInternal(const std::vector& list, } // reloadInternal } + +#endif \ No newline at end of file diff --git a/lib/graphics_engine/src/ge_vulkan_billboard_buffer.cpp b/lib/graphics_engine/src/ge_vulkan_billboard_buffer.cpp index 2ed6653a9c8..1b3434e3eec 100644 --- a/lib/graphics_engine/src/ge_vulkan_billboard_buffer.cpp +++ b/lib/graphics_engine/src/ge_vulkan_billboard_buffer.cpp @@ -1,3 +1,5 @@ +#ifdef _IRR_COMPILE_WITH_VULKAN_ + #include "ge_vulkan_billboard_buffer.hpp" #include "ge_main.hpp" @@ -15,3 +17,5 @@ GEVulkanBillboardBuffer::GEVulkanBillboardBuffer( } // GEVulkanBillboardBuffer } + +#endif \ No newline at end of file diff --git a/lib/graphics_engine/src/ge_vulkan_camera_scene_node.cpp b/lib/graphics_engine/src/ge_vulkan_camera_scene_node.cpp index a5b17a96921..b8816483dbf 100644 --- a/lib/graphics_engine/src/ge_vulkan_camera_scene_node.cpp +++ b/lib/graphics_engine/src/ge_vulkan_camera_scene_node.cpp @@ -1,3 +1,5 @@ +#ifdef _IRR_COMPILE_WITH_VULKAN_ + #include "ge_vulkan_camera_scene_node.hpp" #include "ge_main.hpp" @@ -68,3 +70,5 @@ irr::core::matrix4 GEVulkanCameraSceneNode::getPVM() const } // getPVM } + +#endif \ No newline at end of file diff --git a/lib/graphics_engine/src/ge_vulkan_command_loader.cpp b/lib/graphics_engine/src/ge_vulkan_command_loader.cpp index 13cadd63daf..f5209d72fb2 100644 --- a/lib/graphics_engine/src/ge_vulkan_command_loader.cpp +++ b/lib/graphics_engine/src/ge_vulkan_command_loader.cpp @@ -1,3 +1,5 @@ +#ifdef _IRR_COMPILE_WITH_VULKAN_ + #include "ge_vulkan_command_loader.hpp" #include "ge_vulkan_driver.hpp" @@ -264,3 +266,5 @@ void GEVulkanCommandLoader::waitIdle() } // waitIdle } + +#endif \ No newline at end of file diff --git a/lib/graphics_engine/src/ge_vulkan_depth_texture.cpp b/lib/graphics_engine/src/ge_vulkan_depth_texture.cpp index 0411c617df6..930c87c4c9a 100644 --- a/lib/graphics_engine/src/ge_vulkan_depth_texture.cpp +++ b/lib/graphics_engine/src/ge_vulkan_depth_texture.cpp @@ -1,3 +1,5 @@ +#ifdef _IRR_COMPILE_WITH_VULKAN_ + #include #include "ge_vulkan_depth_texture.hpp" @@ -39,3 +41,5 @@ GEVulkanDepthTexture::GEVulkanDepthTexture(GEVulkanDriver* vk, } // GEVulkanDepthTexture } + +#endif \ No newline at end of file diff --git a/lib/graphics_engine/src/ge_vulkan_draw_call.cpp b/lib/graphics_engine/src/ge_vulkan_draw_call.cpp index 3eb37616772..0b647e1ce3c 100644 --- a/lib/graphics_engine/src/ge_vulkan_draw_call.cpp +++ b/lib/graphics_engine/src/ge_vulkan_draw_call.cpp @@ -1,3 +1,5 @@ +#ifdef _IRR_COMPILE_WITH_VULKAN_ + #include "ge_vulkan_draw_call.hpp" #include "ge_culling_tool.hpp" @@ -1769,3 +1771,5 @@ void GEVulkanDrawCall::updateDataDescriptorSets(GEVulkanDriver* vk) } } // updateDataDescriptor } + +#endif \ No newline at end of file diff --git a/lib/graphics_engine/src/ge_vulkan_driver.cpp b/lib/graphics_engine/src/ge_vulkan_driver.cpp index 6ae8f7202d8..94a159414d7 100644 --- a/lib/graphics_engine/src/ge_vulkan_driver.cpp +++ b/lib/graphics_engine/src/ge_vulkan_driver.cpp @@ -1,3 +1,5 @@ +#ifdef _IRR_COMPILE_WITH_VULKAN_ + #include "ge_vulkan_driver.hpp" #include "ge_compressor_astc_4x4.hpp" @@ -2641,3 +2643,5 @@ extern "C" JNIEXPORT void JNICALL pauseRenderingJNI(JNIEnv* env, jclass cls) #endif #endif + +#endif \ No newline at end of file diff --git a/lib/graphics_engine/src/ge_vulkan_dynamic_buffer.cpp b/lib/graphics_engine/src/ge_vulkan_dynamic_buffer.cpp index 9d8cb076c04..2fd7debde53 100644 --- a/lib/graphics_engine/src/ge_vulkan_dynamic_buffer.cpp +++ b/lib/graphics_engine/src/ge_vulkan_dynamic_buffer.cpp @@ -1,3 +1,5 @@ +#ifdef _IRR_COMPILE_WITH_VULKAN_ + #include "ge_vulkan_dynamic_buffer.hpp" #include "ge_vulkan_driver.hpp" @@ -222,3 +224,5 @@ VkBuffer GEVulkanDynamicBuffer::getCurrentBuffer() const } // getCurrentBuffer } + +#endif \ No newline at end of file diff --git a/lib/graphics_engine/src/ge_vulkan_dynamic_spm_buffer.cpp b/lib/graphics_engine/src/ge_vulkan_dynamic_spm_buffer.cpp index 829727eeb38..18ec4a72a07 100644 --- a/lib/graphics_engine/src/ge_vulkan_dynamic_spm_buffer.cpp +++ b/lib/graphics_engine/src/ge_vulkan_dynamic_spm_buffer.cpp @@ -1,3 +1,5 @@ +#ifdef _IRR_COMPILE_WITH_VULKAN_ + #include "ge_vulkan_dynamic_spm_buffer.hpp" #include "ge_main.hpp" @@ -130,3 +132,5 @@ void GEVulkanDynamicSPMBuffer::setDirtyOffset(irr::u32 offset, } // setDirtyOffset } // end namespace GE + +#endif \ No newline at end of file diff --git a/lib/graphics_engine/src/ge_vulkan_fbo_texture.cpp b/lib/graphics_engine/src/ge_vulkan_fbo_texture.cpp index 834a0b43b1e..5abff834788 100644 --- a/lib/graphics_engine/src/ge_vulkan_fbo_texture.cpp +++ b/lib/graphics_engine/src/ge_vulkan_fbo_texture.cpp @@ -1,3 +1,5 @@ +#ifdef _IRR_COMPILE_WITH_VULKAN_ + #include "ge_vulkan_fbo_texture.hpp" #include "ge_main.hpp" @@ -151,3 +153,5 @@ void GEVulkanFBOTexture::createRTT() } // createRTT } + +#endif \ No newline at end of file diff --git a/lib/graphics_engine/src/ge_vulkan_features.cpp b/lib/graphics_engine/src/ge_vulkan_features.cpp index ec3dabd7543..ce227d1568d 100644 --- a/lib/graphics_engine/src/ge_vulkan_features.cpp +++ b/lib/graphics_engine/src/ge_vulkan_features.cpp @@ -1,3 +1,5 @@ +#ifdef _IRR_COMPILE_WITH_VULKAN_ + #include "ge_vulkan_features.hpp" #include "ge_compressor_astc_4x4.hpp" @@ -340,3 +342,5 @@ bool GEVulkanFeatures::supportsASTC4x4() } // supportsASTC4x4 } + +#endif \ No newline at end of file diff --git a/lib/graphics_engine/src/ge_vulkan_mesh_cache.cpp b/lib/graphics_engine/src/ge_vulkan_mesh_cache.cpp index a821ee4a962..02c6b3661cf 100644 --- a/lib/graphics_engine/src/ge_vulkan_mesh_cache.cpp +++ b/lib/graphics_engine/src/ge_vulkan_mesh_cache.cpp @@ -1,3 +1,5 @@ +#ifdef _IRR_COMPILE_WITH_VULKAN_ + #include "ge_vulkan_mesh_cache.hpp" #include "ge_main.hpp" @@ -196,3 +198,5 @@ void GEVulkanMeshCache::destroy() } // destroy } + +#endif \ No newline at end of file diff --git a/lib/graphics_engine/src/ge_vulkan_scene_manager.cpp b/lib/graphics_engine/src/ge_vulkan_scene_manager.cpp index 36b8c97545a..cb56a79dccc 100644 --- a/lib/graphics_engine/src/ge_vulkan_scene_manager.cpp +++ b/lib/graphics_engine/src/ge_vulkan_scene_manager.cpp @@ -1,3 +1,5 @@ +#ifdef _IRR_COMPILE_WITH_VULKAN_ + #include "ge_vulkan_scene_manager.hpp" #include "../source/Irrlicht/os.h" @@ -274,3 +276,5 @@ void GEVulkanSceneManager::removeDrawCall(GEVulkanCameraSceneNode* cam) } // removeDrawCall } + +#endif \ No newline at end of file diff --git a/lib/graphics_engine/src/ge_vulkan_shader_manager.cpp b/lib/graphics_engine/src/ge_vulkan_shader_manager.cpp index 9ddcd68b805..66462cf08d5 100644 --- a/lib/graphics_engine/src/ge_vulkan_shader_manager.cpp +++ b/lib/graphics_engine/src/ge_vulkan_shader_manager.cpp @@ -1,3 +1,5 @@ +#ifdef _IRR_COMPILE_WITH_VULKAN_ + #include "ge_vulkan_shader_manager.hpp" #include "ge_vulkan_command_loader.hpp" @@ -285,3 +287,5 @@ VkShaderModule GEVulkanShaderManager::getShader(const std::string& filename) } // getShader } + +#endif \ No newline at end of file diff --git a/lib/graphics_engine/src/ge_vulkan_skybox_renderer.cpp b/lib/graphics_engine/src/ge_vulkan_skybox_renderer.cpp index 82977f00785..bf509ac3313 100644 --- a/lib/graphics_engine/src/ge_vulkan_skybox_renderer.cpp +++ b/lib/graphics_engine/src/ge_vulkan_skybox_renderer.cpp @@ -1,3 +1,5 @@ +#ifdef _IRR_COMPILE_WITH_VULKAN_ + #include "ge_vulkan_skybox_renderer.hpp" #include "ge_main.hpp" @@ -385,3 +387,5 @@ void GEVulkanSkyBoxRenderer::addSkyBox(GEVulkanCameraSceneNode* cam, } // addSkyBox } + +#endif \ No newline at end of file diff --git a/lib/graphics_engine/src/ge_vulkan_texture.cpp b/lib/graphics_engine/src/ge_vulkan_texture.cpp index c3d977ec7da..c7bdf429cdd 100644 --- a/lib/graphics_engine/src/ge_vulkan_texture.cpp +++ b/lib/graphics_engine/src/ge_vulkan_texture.cpp @@ -1,3 +1,5 @@ +#ifdef _IRR_COMPILE_WITH_VULKAN_ + #include "ge_vulkan_texture.hpp" #include "ge_main.hpp" @@ -921,3 +923,5 @@ std::shared_ptr > GEVulkanTexture::getImageViewLive( } // getImageViewLive } + +#endif \ No newline at end of file diff --git a/lib/graphics_engine/src/ge_vulkan_texture_descriptor.cpp b/lib/graphics_engine/src/ge_vulkan_texture_descriptor.cpp index 84eb331bd67..6b58daf24d9 100644 --- a/lib/graphics_engine/src/ge_vulkan_texture_descriptor.cpp +++ b/lib/graphics_engine/src/ge_vulkan_texture_descriptor.cpp @@ -1,3 +1,5 @@ +#ifdef _IRR_COMPILE_WITH_VULKAN_ + #include "ge_vulkan_texture_descriptor.hpp" #include "ge_main.hpp" @@ -237,3 +239,5 @@ int GEVulkanTextureDescriptor::getTextureID(const irr::video::ITexture** list, } // getTextureID } + +#endif \ No newline at end of file diff --git a/lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp b/lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp index d71fce1fcd6..8e5e2cdd5b7 100644 --- a/lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp +++ b/lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp @@ -22,11 +22,13 @@ #include "guiengine/engine.hpp" #include "ge_main.hpp" #include "glad/gl.h" + +#ifdef _IRR_COMPILE_WITH_VULKAN_ #include "ge_vulkan_driver.hpp" #include "ge_vulkan_scene_manager.hpp" #include "MoltenVK.h" - #include +#endif extern bool GLContextDebugBit; @@ -82,16 +84,20 @@ CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters& param) Operator = 0; // Initialize SDL... Timer for sleep, video for the obvious, and // noparachute prevents SDL from catching fatal errors. +#ifndef __EMSCRIPTEN__ SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS, "1"); SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0"); +#endif #if SDL_VERSION_ATLEAST(2, 0, 18) SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1"); #endif // Switch SDL disables this hint by default: https://github.com/devkitPro/SDL/pull/55#issuecomment-633775255 +#ifndef __EMSCRIPTEN__ SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "1"); +#endif -#ifndef MOBILE_STK +#if !defined(MOBILE_STK) && !defined(__EMSCRIPTEN__) // Prevent fullscreen minimizes when losing focus if (CreationParams.Fullscreen) { @@ -205,9 +211,9 @@ CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters& param) #endif } - void CIrrDeviceSDL::updateNativeScale(u32* saving_width, u32* saving_height) { +#ifndef __EMSCRIPTEN__ int width, height = 0; SDL_GetWindowSize(Window, &width, &height); int real_width = width; @@ -227,9 +233,9 @@ void CIrrDeviceSDL::updateNativeScale(u32* saving_width, u32* saving_height) *saving_width = width; if (saving_height) *saving_height = height; +#endif } - //! destructor CIrrDeviceSDL::~CIrrDeviceSDL() { @@ -241,11 +247,13 @@ CIrrDeviceSDL::~CIrrDeviceSDL() if (h) h->clearGLExtensions(); #endif +#ifdef _IRR_COMPILE_WITH_VULKAN_ GE::GEVulkanDriver* gevk = dynamic_cast(VideoDriver); if (gevk) gevk->destroyVulkan(); VideoDriver->drop(); VideoDriver = NULL; +#endif } #ifdef DLOPEN_MOLTENVK delete m_moltenvk; @@ -360,6 +368,7 @@ bool versionCorrect(int major, int minor) // Used in OptionsScreenVideo for live fullscreen toggle for vulkan driver extern "C" void update_fullscreen_desktop(int val) { +#ifdef _IRR_COMPILE_WITH_VULKAN_ GE::GEVulkanDriver* gevk = GE::getVKDriver(); if (!gevk || !GE::getGEConfig()->m_fullscreen_desktop) return; @@ -377,6 +386,9 @@ extern "C" void update_fullscreen_desktop(int val) SDL_SetWindowSize(window, prev_width * 0.8f, prev_height * 0.8f); SDL_RaiseWindow(window); } +#else + return; +#endif } @@ -388,12 +400,14 @@ extern "C" void update_swap_interval(int swap_interval) if (swap_interval > 1) swap_interval = 1; +#ifdef _IRR_COMPILE_WITH_VULKAN_ GE::GEVulkanDriver* gevk = GE::getVKDriver(); if (gevk) { gevk->updateSwapInterval(swap_interval); return; } +#endif // Try adaptive vsync first if support if (swap_interval > 0) @@ -438,7 +452,7 @@ bool CIrrDeviceSDL::createWindow() } u32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE; -#if !defined(ANDROID) && !defined(__SWITCH__) +#if !defined(ANDROID) && !defined(__SWITCH__) && !defined(__EMSCRIPTEN__) if (CreationParams.DriverType == video::EDT_OPENGL || CreationParams.DriverType == video::EDT_OGLES2 || CreationParams.DriverType == video::EDT_VULKAN) @@ -446,7 +460,8 @@ bool CIrrDeviceSDL::createWindow() #endif if (CreationParams.Fullscreen) - { + { +#ifndef __EMSCRIPTEN__ if (GE::getGEConfig()->m_fullscreen_desktop) { flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; @@ -454,6 +469,9 @@ bool CIrrDeviceSDL::createWindow() } else flags |= SDL_WINDOW_FULLSCREEN; +#else + flags |= SDL_WINDOW_FULLSCREEN; +#endif } if (CreationParams.DriverType == video::EDT_OPENGL || @@ -472,7 +490,9 @@ bool CIrrDeviceSDL::createWindow() #if SDL_VERSION_ATLEAST(2, 0, 12) SDL_SetHint(SDL_HINT_VIDEO_EXTERNAL_CONTEXT, "1"); #endif +#ifdef _IRR_COMPILE_WITH_VULKAN_ flags |= SDL_WINDOW_VULKAN; +#endif } #ifdef MOBILE_STK @@ -517,6 +537,7 @@ void CIrrDeviceSDL::tryCreateOpenGLContext(u32 flags) SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, CreationParams.Doublebuffer); irr::video::useCoreContext = true; +#ifndef __EMSCRIPTEN__ if (GLContextDebugBit) SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG); @@ -524,6 +545,7 @@ void CIrrDeviceSDL::tryCreateOpenGLContext(u32 flags) SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); else SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); +#endif if (CreationParams.ForceLegacyDevice) goto legacy; @@ -651,10 +673,12 @@ void CIrrDeviceSDL::tryCreateOpenGLContext(u32 flags) SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); #endif +#ifndef __EMSCRIPTEN__ if (CreationParams.DriverType == video::EDT_OGLES2) SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); else SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0); +#endif Window = SDL_CreateWindow("", (float)CreationParams.WindowPosition.X, (float)CreationParams.WindowPosition.Y, @@ -1228,11 +1252,13 @@ bool CIrrDeviceSDL::getWindowPosition(int* x, int* y) //! Get DPI of current display. bool CIrrDeviceSDL::getDisplayDPI(float* ddpi, float* hdpi, float* vdpi) { +#ifndef __EMSCRIPTEN__ if (Window) { SDL_GetDisplayDPI(SDL_GetWindowDisplayIndex(Window), ddpi, hdpi, vdpi); return true; } +#endif return false; } @@ -1279,8 +1305,10 @@ bool CIrrDeviceSDL::getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightne void CIrrDeviceSDL::setWindowMinimumSize(u32 width, u32 height) { +#ifndef __EMSCRIPTEN__ if (Window) SDL_SetWindowMinimumSize(Window, width, height); +#endif } //! returns color format of the window. @@ -1576,7 +1604,11 @@ bool CIrrDeviceSDL::supportsTouchDevice() const bool CIrrDeviceSDL::hasOnScreenKeyboard() const { +#ifndef __EMSCRIPTEN__ return SDL_HasScreenKeyboardSupport() == SDL_TRUE; +#else + return false; +#endif } @@ -1681,8 +1713,10 @@ void CIrrDeviceSDL::createGUIAndVulkanScene() GUIEnvironment = gui::createGUIEnvironment(FileSystem, VideoDriver, Operator); #endif + #ifdef _IRR_COMPILE_WITH_VULKAN_ // create Scene manager SceneManager = new GE::GEVulkanSceneManager(VideoDriver, FileSystem, CursorControl, GUIEnvironment); + #endif setEventReceiver(UserReceiver); } diff --git a/src/graphics/b3d_mesh_loader.cpp b/src/graphics/b3d_mesh_loader.cpp index 38a50ae6ecf..ac60d571cf0 100644 --- a/src/graphics/b3d_mesh_loader.cpp +++ b/src/graphics/b3d_mesh_loader.cpp @@ -83,7 +83,11 @@ scene::IAnimatedMesh* B3DMeshLoader::createMesh(io::IReadFile* f) } #ifndef SERVER_ONLY + #ifdef _IRR_COMPILE_WITH_VULKAN_ bool convert_spm = CVS->isGLSL() || GE::getVKDriver() != NULL; + #else + bool convert_spm = CVS->isGLSL(); + #endif if (convert_spm) { if (!AnimatedMesh) @@ -1372,7 +1376,11 @@ void B3DMeshLoader::loadTextures(SB3dMaterial& material, scene::IMeshBuffer* mb) #endif #ifndef SERVER_ONLY + #ifdef _IRR_COMPILE_WITH_VULKAN_ bool convert_spm = CVS->isGLSL() || GE::getVKDriver() != NULL; + #else + bool convert_spm = CVS->isGLSL(); + #endif if (convert_spm) { auto& ret = m_texture_string[mb]; diff --git a/src/graphics/irr_driver.cpp b/src/graphics/irr_driver.cpp index da4fc1aea84..a437ebd1871 100644 --- a/src/graphics/irr_driver.cpp +++ b/src/graphics/irr_driver.cpp @@ -649,6 +649,7 @@ void IrrDriver::initDevice() GE::setVideoDriver(m_device->getVideoDriver()); +#ifdef _IRR_COMPILE_WITH_VULKAN_ GE::GEVulkanDriver* vk = GE::getVKDriver(); if (vk) { @@ -671,6 +672,7 @@ void IrrDriver::initDevice() break; } } +#endif // Assume sp is supported CentralVideoSettings::m_supports_sp = true; CVS->init(); @@ -1403,13 +1405,13 @@ scene::ISceneNode *IrrDriver::addSphere(float radius, } #endif -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && defined(_IRR_COMPILE_WITH_VULKAN_) bool vk = (GE::getVKDriver() != NULL); if (vk) GE::getGEConfig()->m_convert_irrlicht_mesh = true; #endif scene::IMeshSceneNode *node = m_scene_manager->addMeshSceneNode(mesh); -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && defined(_IRR_COMPILE_WITH_VULKAN_) if (vk) GE::getGEConfig()->m_convert_irrlicht_mesh = false; #endif diff --git a/src/graphics/sp/sp_mesh_buffer.cpp b/src/graphics/sp/sp_mesh_buffer.cpp index 1bcd811ed60..b1e424dc6d9 100644 --- a/src/graphics/sp/sp_mesh_buffer.cpp +++ b/src/graphics/sp/sp_mesh_buffer.cpp @@ -474,7 +474,7 @@ void SPMeshBuffer::reloadTextureCompare() void SPMeshBuffer::setSTKMaterial(Material* m) { m_stk_material[0] = std::make_tuple(0u, getIndexCount(), m); -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && defined(_IRR_COMPILE_WITH_VULKAN_) // Used by b3d mesh loader, clean up later after SP is removed if (GE::getVKDriver() != NULL) return; diff --git a/src/graphics/sp_mesh_loader.cpp b/src/graphics/sp_mesh_loader.cpp index decc7f1cc77..671e543dbe8 100644 --- a/src/graphics/sp_mesh_loader.cpp +++ b/src/graphics/sp_mesh_loader.cpp @@ -70,7 +70,7 @@ scene::IAnimatedMesh* SPMeshLoader::createMesh(io::IReadFile* f) m_frame_count = 0; m_mesh = NULL; bool ge_spm = false; -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && defined(_IRR_COMPILE_WITH_VULKAN_) if (GE::getVKDriver()) { ge_spm = true; diff --git a/src/graphics/stk_tex_manager.cpp b/src/graphics/stk_tex_manager.cpp index 348aacf72b6..b0b6a33cb7a 100644 --- a/src/graphics/stk_tex_manager.cpp +++ b/src/graphics/stk_tex_manager.cpp @@ -37,7 +37,7 @@ // ---------------------------------------------------------------------------- STKTexManager::~STKTexManager() { -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && defined(_IRR_COMPILE_WITH_VULKAN_) GE::GEVulkanDriver* gevd = GE::getVKDriver(); if (gevd) { @@ -48,7 +48,7 @@ STKTexManager::~STKTexManager() removeTexture(NULL/*texture*/, true/*remove_all*/); -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && defined(_IRR_COMPILE_WITH_VULKAN_) if (gevd) gevd->setDisableWaitIdle(false); #endif @@ -249,7 +249,7 @@ bool STKTexManager::hasTexture(const std::string& path) // ---------------------------------------------------------------------------- void STKTexManager::reloadAllTextures() { -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && defined(_IRR_COMPILE_WITH_VULKAN_) GE::GEVulkanDriver* gevd = GE::getVKDriver(); if (gevd) { @@ -265,7 +265,7 @@ void STKTexManager::reloadAllTextures() p.second->reload(); } -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && defined(_IRR_COMPILE_WITH_VULKAN_) if (gevd) gevd->setDisableWaitIdle(false); #endif diff --git a/src/guiengine/widgets/CGUIEditBox.cpp b/src/guiengine/widgets/CGUIEditBox.cpp index 865997f24e1..665b4c31173 100644 --- a/src/guiengine/widgets/CGUIEditBox.cpp +++ b/src/guiengine/widgets/CGUIEditBox.cpp @@ -244,7 +244,7 @@ CGUIEditBox::~CGUIEditBox() if (GUIEngine::ScreenKeyboard::shouldUseScreenKeyboard() && GUIEngine::ScreenKeyboard::hasSystemScreenKeyboard()) Android_toggleOnScreenKeyboard(false, 0, 0); -#elif defined(_IRR_COMPILE_WITH_SDL_DEVICE_) +#elif defined(_IRR_COMPILE_WITH_SDL_DEVICE_) && !defined(__EMSCRIPTEN__) if (SDL_IsTextInputActive()) SDL_StopTextInput(); #endif @@ -372,7 +372,7 @@ bool CGUIEditBox::OnEvent(const SEvent& event) MouseMarking = false; setTextMarkers(0,0); } -#if !defined(ANDROID) && defined(_IRR_COMPILE_WITH_SDL_DEVICE_) +#if !defined(ANDROID) && defined(_IRR_COMPILE_WITH_SDL_DEVICE_) && !defined(__EMSCRIPTEN__) if (SDL_IsTextInputActive()) SDL_StopTextInput(); #endif diff --git a/src/karts/kart_properties_manager.cpp b/src/karts/kart_properties_manager.cpp index 2eb0f09a8d5..ebe661f6cf9 100644 --- a/src/karts/kart_properties_manager.cpp +++ b/src/karts/kart_properties_manager.cpp @@ -26,6 +26,7 @@ #include "config/user_config.hpp" #include "graphics/irr_driver.hpp" #include "guiengine/engine.hpp" +#include #include "io/file_manager.hpp" #include "karts/kart_properties.hpp" #include "karts/xml_characteristic.hpp" @@ -626,12 +627,14 @@ void KartPropertiesManager::onDemandLoadKartTextures( #ifndef SERVER_ONLY if (STKProcess::getType() != PT_MAIN || kart_list.empty()) return; - + + #ifdef _IRR_COMPILE_WITH_VULKAN_ GE::GEVulkanDriver* gevd = GE::getVKDriver(); if (!gevd) return; gevd->waitIdle(); gevd->setDisableWaitIdle(true); + #endif std::set karts_folder; for (auto& dir : m_kart_search_path) @@ -690,9 +693,11 @@ void KartPropertiesManager::onDemandLoadKartTextures( } } + #ifdef _IRR_COMPILE_WITH_VULKAN_ gevd->setDisableWaitIdle(false); if (unloaded_unused) gevd->handleDeletedTextures(); + #endif #endif } // onDemandLoadKartTextures diff --git a/src/states_screens/dialogs/custom_video_settings.cpp b/src/states_screens/dialogs/custom_video_settings.cpp index 9aad0d9ba92..395ecee2685 100644 --- a/src/states_screens/dialogs/custom_video_settings.cpp +++ b/src/states_screens/dialogs/custom_video_settings.cpp @@ -214,7 +214,7 @@ GUIEngine::EventPropagation CustomVideoSettingsDialog::processEvent(const std::s ModalDialog::dismiss(); OptionsScreenVideo::getInstance()->updateGfxSlider(); OptionsScreenVideo::getInstance()->updateBlurSlider(); -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && defined(_IRR_COMPILE_WITH_VULKAN_) if (update_needed && GE::getDriver()->getDriverType() == video::EDT_VULKAN) GE::getVKDriver()->updateDriver(true); #endif diff --git a/src/states_screens/kart_selection.cpp b/src/states_screens/kart_selection.cpp index 5497bf25b50..ae62d98b4bc 100644 --- a/src/states_screens/kart_selection.cpp +++ b/src/states_screens/kart_selection.cpp @@ -455,7 +455,7 @@ void KartSelectionScreen::init() void KartSelectionScreen::tearDown() { -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && defined(_IRR_COMPILE_WITH_VULKAN_) GE::getGEConfig()->m_enable_draw_call_cache = false; GE::GEVulkanDriver* gevk = GE::getVKDriver(); if (gevk) diff --git a/src/states_screens/options/options_screen_display.cpp b/src/states_screens/options/options_screen_display.cpp index 68f1bc81434..cca86f77ade 100644 --- a/src/states_screens/options/options_screen_display.cpp +++ b/src/states_screens/options/options_screen_display.cpp @@ -390,6 +390,7 @@ void OptionsScreenDisplay::eventCallback(Widget* widget, const std::string& name rememberWinpos->setActive(!fullscreen->getState()); #ifndef SERVER_ONLY + #ifdef _IRR_COMPILE_WITH_VULKAN_ GE::GEVulkanDriver* gevk = GE::getVKDriver(); if (gevk && GE::getGEConfig()->m_fullscreen_desktop) { @@ -398,6 +399,7 @@ void OptionsScreenDisplay::eventCallback(Widget* widget, const std::string& name OptionsScreenDisplay::m_fullscreen_checkbox_focus = true; } else + #endif updateResolutionsList(); #endif } // fullscreen diff --git a/src/states_screens/options/options_screen_video.cpp b/src/states_screens/options/options_screen_video.cpp index 55a45f611c9..4b0bd59aff7 100644 --- a/src/states_screens/options/options_screen_video.cpp +++ b/src/states_screens/options/options_screen_video.cpp @@ -155,38 +155,48 @@ int OptionsScreenVideo::getImageQuality() void OptionsScreenVideo::setImageQuality(int quality) { #ifndef SERVER_ONLY + #ifdef _IRR_COMPILE_WITH_VULKAN_ GE::GEVulkanTextureDescriptor* td = NULL; if (GE::getVKDriver()) td = GE::getVKDriver()->getMeshTextureDescriptor(); + #endif switch (quality) { case 0: UserConfigParams::m_anisotropic = 4; UserConfigParams::m_high_definition_textures = 0x02; UserConfigParams::m_hq_mipmap = false; + #ifdef _IRR_COMPILE_WITH_VULKAN_ if (td) td->setSamplerUse(GE::GVS_3D_MESH_MIPMAP_2); + #endif break; case 1: UserConfigParams::m_anisotropic = 16; UserConfigParams::m_high_definition_textures = 0x02; UserConfigParams::m_hq_mipmap = false; + #ifdef _IRR_COMPILE_WITH_VULKAN_ if (td) td->setSamplerUse(GE::GVS_3D_MESH_MIPMAP_2); + #endif break; case 2: UserConfigParams::m_anisotropic = 16; UserConfigParams::m_high_definition_textures = 0x03; UserConfigParams::m_hq_mipmap = false; + #ifdef _IRR_COMPILE_WITH_VULKAN_ if (td) td->setSamplerUse(GE::GVS_3D_MESH_MIPMAP_4); + #endif break; case 3: UserConfigParams::m_anisotropic = 16; UserConfigParams::m_high_definition_textures = 0x03; UserConfigParams::m_hq_mipmap = true; + #ifdef _IRR_COMPILE_WITH_VULKAN_ if (td) td->setSamplerUse(GE::GVS_3D_MESH_MIPMAP_16); + #endif break; default: assert(false); @@ -651,7 +661,7 @@ void OptionsScreenVideo::eventCallback(Widget* widget, const std::string& name, assert(level < (int)m_scale_rtts_custom_presets.size()); UserConfigParams::m_scale_rtts_factor = m_scale_rtts_custom_presets[level].value; -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && defined(_IRR_COMPILE_WITH_VULKAN_) GE::GEVulkanDriver* gevk = GE::getVKDriver(); if (gevk && GE::getGEConfig()->m_render_scale != UserConfigParams::m_scale_rtts_factor) { diff --git a/src/tracks/graph.cpp b/src/tracks/graph.cpp index 810fbdefd91..b120e154b54 100644 --- a/src/tracks/graph.cpp +++ b/src/tracks/graph.cpp @@ -103,13 +103,13 @@ void Graph::createDebugMesh() } #endif -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && defined(_IRR_COMPILE_WITH_VULKAN_) bool vk = (GE::getVKDriver() != NULL); if (vk) GE::getGEConfig()->m_convert_irrlicht_mesh = true; #endif m_node = irr_driver->addMesh(m_mesh, "track-debug-mesh"); -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && defined(_IRR_COMPILE_WITH_VULKAN_) if (vk) GE::getGEConfig()->m_convert_irrlicht_mesh = false; #endif @@ -485,13 +485,13 @@ RenderTarget* Graph::makeMiniMap(const core::dimension2du &dimension, } #endif -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && defined(_IRR_COMPILE_WITH_VULKAN_) bool vk = (GE::getVKDriver() != NULL); if (vk) GE::getGEConfig()->m_convert_irrlicht_mesh = true; #endif m_node = irr_driver->addMesh(m_mesh, "mini_map"); -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && defined(_IRR_COMPILE_WITH_VULKAN_) if (vk) GE::getGEConfig()->m_convert_irrlicht_mesh = false; #endif diff --git a/wasm/build.sh b/wasm/build.sh index 4dce929fef1..15db7f8408e 100755 --- a/wasm/build.sh +++ b/wasm/build.sh @@ -4,10 +4,12 @@ CORE_COUNT="$(nproc --all)" BASE_DIR="$(realpath "$(dirname "$0")")" SRC_DIR="$(dirname "$BASE_DIR")" BUILD_DIR="$SRC_DIR/cmake_build" +EMSDK_DIR="$BASE_DIR/emsdk" PREFIX="$BASE_DIR/prefix" mkdir -p $BUILD_DIR cd $BUILD_DIR +source $EMSDK_DIR/emsdk_env.sh emcmake cmake .. -DNO_SHADERC=on -make -j$CORE_COUNT \ No newline at end of file +make -j4 \ No newline at end of file diff --git a/wasm/build_deps.sh b/wasm/build_deps.sh index 74da11c0397..18fc86e6d4f 100755 --- a/wasm/build_deps.sh +++ b/wasm/build_deps.sh @@ -6,10 +6,12 @@ set -e CORE_COUNT="$(nproc --all)" BASE_DIR="$(realpath "$(dirname "$0")")" BUILD_DIR="$BASE_DIR/build" +EMSDK_DIR="$BASE_DIR/emsdk" PREFIX="$BASE_DIR/prefix" INCLUDE="$PREFIX/include" LIB="$PREFIX/lib" +source $EMSDK_DIR/emsdk_env.sh export PKG_CONFIG_PATH="$LIB/pkgconfig" clone_repo() { @@ -83,7 +85,7 @@ build_jpeg() { mkdir -p build cd build - emcmake cmake -G"Unix Makefiles" -DCMAKE_INSTALL_PREFIX:PATH="$PREFIX" -DWITH_SIMD=0 .. + emcmake cmake -G"Unix Makefiles" -DCMAKE_INSTALL_PREFIX:PATH="$PREFIX" -DWITH_SIMD=0 -DENABLE_SHARED=0 .. emmake make -j$CORE_COUNT make install } diff --git a/wasm/get_emsdk.sh b/wasm/get_emsdk.sh new file mode 100755 index 00000000000..8a81f8ab994 --- /dev/null +++ b/wasm/get_emsdk.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +CORE_COUNT="$(nproc --all)" +BASE_DIR="$(realpath "$(dirname "$0")")" +EMSDK_DIR="$BASE_DIR/emsdk" + +git clone https://github.com/emscripten-core/emsdk.git --depth=1 "$EMSDK_DIR" +cd $EMSDK_DIR + +./emsdk update +./emsdk install latest +./emsdk activate latest \ No newline at end of file From 379f0521646f03c895dc4861d677f44ee29e2276 Mon Sep 17 00:00:00 2001 From: ading2210 Date: Tue, 28 May 2024 16:14:52 -0400 Subject: [PATCH 04/25] get it building and linking properly --- CMakeLists.txt | 10 +++++--- lib/graphics_engine/src/ge_main.cpp | 4 +++ lib/graphics_engine/src/ge_texture.cpp | 6 +++++ .../source/Irrlicht/CIrrDeviceSDL.cpp | 2 ++ src/graphics/b3d_mesh_loader.cpp | 12 ++------- src/graphics/central_settings.cpp | 2 ++ src/graphics/material.cpp | 2 +- src/graphics/shadow.cpp | 4 +++ src/graphics/skid_marks.cpp | 2 ++ src/graphics/slip_stream.cpp | 2 +- src/graphics/sp_mesh_loader.cpp | 2 +- src/graphics/stk_text_billboard.cpp | 2 ++ src/guiengine/widgets/CGUIEditBox.cpp | 2 +- src/input/input_manager.cpp | 12 ++++----- src/input/input_manager.hpp | 4 +-- src/input/sdl_controller.cpp | 2 +- src/items/rubber_band.cpp | 2 ++ .../controller/local_player_controller.cpp | 2 +- src/main.cpp | 2 +- wasm/build_deps.sh | 25 ++++++++++++++++--- 20 files changed, 68 insertions(+), 33 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b98f57818d..7844e891c49 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,13 +61,13 @@ endif() if(EMSCRIPTEN) set(CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/wasm/prefix/") - set(JPEG_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include/") + set(JPEG_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include") set(JPEG_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/libjpeg.a") set(PNG_PNG_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include/") - set(PNG_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/libpng.a") + set(PNG_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/libpng16.a") - set(ZLIB_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include/") + set(ZLIB_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include") set(ZLIB_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/libz.a") set(HARFBUZZ_INCLUDEDIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include/") @@ -82,10 +82,12 @@ if(EMSCRIPTEN) set(OGGVORBIS_OGG_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include/") set(OGGVORBIS_VORBIS_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include/") set(OGGVORBIS_OGG_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/libogg.a") - set(OGGVORBIS_VORBISFILE_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/lobvorbisfile.a") + set(OGGVORBIS_VORBISFILE_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/libvorbisfile.a") set(OGGVORBIS_VORBIS_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/libvorbis.a") #-DFREETYPE_INCLUDE_DIRS=/home/heatingdevice/projects/freetype/include \ + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SOURCE_DIR}/wasm/prefix/lib/ -lcrypto -lSDL2 -logg -lvorbis") + #todo: avoid hardcoding this path set(PTHREAD_LIBRARY "/usr/share/emscripten/cache/sysroot/") diff --git a/lib/graphics_engine/src/ge_main.cpp b/lib/graphics_engine/src/ge_main.cpp index 9ed90cb40cc..63dec2c9687 100644 --- a/lib/graphics_engine/src/ge_main.cpp +++ b/lib/graphics_engine/src/ge_main.cpp @@ -135,6 +135,8 @@ void mathPlaneFrustumf(float* out, const irr::core::matrix4& pvm) mathPlaneNormf(&out[5 * 4]); } +#ifdef _IRR_COMPILE_WITH_VULKAN_ + irr::scene::IAnimatedMesh* convertIrrlichtMeshToSPM(irr::scene::IMesh* mesh) { GESPM* spm = new GESPM(); @@ -174,5 +176,7 @@ irr::scene::IAnimatedMesh* convertIrrlichtMeshToSPM(irr::scene::IMesh* mesh) spm->finalize(); return spm; } +#endif } + diff --git a/lib/graphics_engine/src/ge_texture.cpp b/lib/graphics_engine/src/ge_texture.cpp index 314d266c914..28e96ca75f8 100644 --- a/lib/graphics_engine/src/ge_texture.cpp +++ b/lib/graphics_engine/src/ge_texture.cpp @@ -101,8 +101,10 @@ irr::video::ITexture* createTexture(const std::string& path, case video::EDT_DIRECT3D9: return new GEDX9Texture(path, image_mani); #endif +#ifdef _IRR_COMPILE_WITH_VULKAN_ case video::EDT_VULKAN: return new GEVulkanTexture(path, image_mani); +#endif default: return NULL; } @@ -121,8 +123,10 @@ irr::video::ITexture* createTexture(video::IImage* img, case video::EDT_DIRECT3D9: return new GEDX9Texture(img, name); #endif +#ifdef _IRR_COMPILE_WITH_VULKAN_ case video::EDT_VULKAN: return new GEVulkanTexture(img, name); +#endif default: return NULL; } @@ -141,8 +145,10 @@ irr::video::ITexture* createFontTexture(const std::string& name, case video::EDT_DIRECT3D9: return new GEDX9Texture(name, size); #endif +#ifdef _IRR_COMPILE_WITH_VULKAN_ case video::EDT_VULKAN: return new GEVulkanTexture(name, size, single_channel); +#endif default: return NULL; } diff --git a/lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp b/lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp index 8e5e2cdd5b7..4e3611f3b0a 100644 --- a/lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp +++ b/lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp @@ -1059,7 +1059,9 @@ bool CIrrDeviceSDL::run() } break; default: + #ifndef __EMSCRIPTEN__ handle_joystick(SDL_event); + #endif break; } // end switch diff --git a/src/graphics/b3d_mesh_loader.cpp b/src/graphics/b3d_mesh_loader.cpp index ac60d571cf0..7df84d1d537 100644 --- a/src/graphics/b3d_mesh_loader.cpp +++ b/src/graphics/b3d_mesh_loader.cpp @@ -82,12 +82,8 @@ scene::IAnimatedMesh* B3DMeshLoader::createMesh(io::IReadFile* f) AnimatedMesh->setMinMax(min.toIrrVector(), max.toIrrVector()); } -#ifndef SERVER_ONLY - #ifdef _IRR_COMPILE_WITH_VULKAN_ +#if !defined(SERVER_ONLY) && defined(_IRR_COMPILE_WITH_VULKAN_) bool convert_spm = CVS->isGLSL() || GE::getVKDriver() != NULL; - #else - bool convert_spm = CVS->isGLSL(); - #endif if (convert_spm) { if (!AnimatedMesh) @@ -1375,12 +1371,8 @@ void B3DMeshLoader::loadTextures(SB3dMaterial& material, scene::IMeshBuffer* mb) } #endif -#ifndef SERVER_ONLY - #ifdef _IRR_COMPILE_WITH_VULKAN_ +#if !defined(SERVER_ONLY) && defined(_IRR_COMPILE_WITH_VULKAN_) bool convert_spm = CVS->isGLSL() || GE::getVKDriver() != NULL; - #else - bool convert_spm = CVS->isGLSL(); - #endif if (convert_spm) { auto& ret = m_texture_string[mb]; diff --git a/src/graphics/central_settings.cpp b/src/graphics/central_settings.cpp index 5e353fa87a3..00950ae2453 100644 --- a/src/graphics/central_settings.cpp +++ b/src/graphics/central_settings.cpp @@ -75,12 +75,14 @@ void CentralVideoSettings::init() GE::getGEConfig()->m_disable_npot_texture = GraphicsRestrictions::isDisabled( GraphicsRestrictions::GR_NPOT_TEXTURES); + #ifdef _IRR_COMPILE_WITH_VULKAN_ if (GE::getDriver()->getDriverType() == video::EDT_VULKAN) { hasTextureCompression = GEVulkanFeatures::supportsS3TCBC3() || GEVulkanFeatures::supportsBPTCBC7() || GEVulkanFeatures::supportsASTC4x4(); } + #endif return; } diff --git a/src/graphics/material.cpp b/src/graphics/material.cpp index c50b08dff12..5db71cd1586 100644 --- a/src/graphics/material.cpp +++ b/src/graphics/material.cpp @@ -864,7 +864,7 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m tc.X = 1 - tc.X; } } -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && defined(_IRR_COMPILE_WITH_VULKAN_) if (is_vk) { GE::GESPMBuffer* spmb = static_cast(mb); diff --git a/src/graphics/shadow.cpp b/src/graphics/shadow.cpp index 5ccaf7aeedd..047c4dfb3c1 100644 --- a/src/graphics/shadow.cpp +++ b/src/graphics/shadow.cpp @@ -64,6 +64,7 @@ Shadow::Shadow(Material* shadow_mat, const AbstractKart& kart) { std::array indices = {{ 0, 1, 2, 0, 2, 3 }}; scene::IMeshBuffer* buffer = NULL; + #ifdef _IRR_COMPILE_WITH_VULKAN_ if (irr_driver->getVideoDriver()->getDriverType() == video::EDT_VULKAN) { buffer = new GE::GEVulkanDynamicSPMBuffer(); @@ -74,6 +75,9 @@ Shadow::Shadow(Material* shadow_mat, const AbstractKart& kart) buffer->append(vertices.data(), vertices.size(), indices.data(), indices.size()); } + #else + if (false) {} + #endif else { buffer = new scene::SMeshBuffer(); diff --git a/src/graphics/skid_marks.cpp b/src/graphics/skid_marks.cpp index f7d45d66964..04200f6679c 100644 --- a/src/graphics/skid_marks.cpp +++ b/src/graphics/skid_marks.cpp @@ -252,6 +252,7 @@ SkidMarks::SkidMarkQuads::SkidMarkQuads(const Vec3 &left, } else { + #ifdef _IRR_COMPILE_WITH_VULKAN_ scene::IMeshBuffer* buffer = NULL; if (irr_driver->getVideoDriver()->getDriverType() == video::EDT_VULKAN) buffer = new GE::GEVulkanDynamicSPMBuffer(); @@ -269,6 +270,7 @@ SkidMarks::SkidMarkQuads::SkidMarkQuads(const Vec3 &left, m_node->getMaterial(0).getRenderInfo() = std::make_shared(); mesh->drop(); + #endif } m_start_color = (custom_color != NULL ? *custom_color : video::SColor(255, SkidMarks::m_start_grey, SkidMarks::m_start_grey, diff --git a/src/graphics/slip_stream.cpp b/src/graphics/slip_stream.cpp index 55c91d19e53..b66e11449fe 100644 --- a/src/graphics/slip_stream.cpp +++ b/src/graphics/slip_stream.cpp @@ -399,7 +399,7 @@ scene::IAnimatedMesh* SlipStream::createMesh(unsigned material_id, mesh->recalculateBoundingBox(); buffer->drop(); -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && defined(_IRR_COMPILE_WITH_VULKAN_) if (GE::getDriver()->getDriverType() == video::EDT_VULKAN) { amesh = GE::convertIrrlichtMeshToSPM(mesh); diff --git a/src/graphics/sp_mesh_loader.cpp b/src/graphics/sp_mesh_loader.cpp index 671e543dbe8..8a774caf12b 100644 --- a/src/graphics/sp_mesh_loader.cpp +++ b/src/graphics/sp_mesh_loader.cpp @@ -448,7 +448,7 @@ void SPMeshLoader::decompressGESPM(irr::io::IReadFile* spm, bool uv_one, bool uv_two, SPVertexType vt, const video::SMaterial& m) { -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && defined(_IRR_COMPILE_WITH_VULKAN_) assert(vertices_count != 0); assert(indices_count != 0); diff --git a/src/graphics/stk_text_billboard.cpp b/src/graphics/stk_text_billboard.cpp index 2d8fde6b3e4..75a8d6fe719 100644 --- a/src/graphics/stk_text_billboard.cpp +++ b/src/graphics/stk_text_billboard.cpp @@ -381,6 +381,7 @@ void STKTextBillboard::initLegacy(const core::stringw& text, FontWithFace* face) if (SceneManager->getVideoDriver()->getDriverType() == video::EDT_VULKAN) { + #ifdef _IRR_COMPILE_WITH_VULKAN_ GE::GESPM* spm = new GE::GESPM(); for (auto& p : irr_tbs) { @@ -420,6 +421,7 @@ void STKTextBillboard::initLegacy(const core::stringw& text, FontWithFace* face) SceneManager->getMeshCache()->addMesh(oss.str().c_str(), spm); spm->drop(); m_ge_node = SceneManager->addMeshSceneNode(spm, this); + #endif } else { diff --git a/src/guiengine/widgets/CGUIEditBox.cpp b/src/guiengine/widgets/CGUIEditBox.cpp index 665b4c31173..58848e18f8f 100644 --- a/src/guiengine/widgets/CGUIEditBox.cpp +++ b/src/guiengine/widgets/CGUIEditBox.cpp @@ -1382,7 +1382,7 @@ void CGUIEditBox::calculateScrollPos() // todo: adjust scrollbar // calculate the position of input composition window -#if !defined(ANDROID) && defined(_IRR_COMPILE_WITH_SDL_DEVICE_) +#if !defined(ANDROID) && !defined(__EMSCRIPTEN__) && defined(_IRR_COMPILE_WITH_SDL_DEVICE_) SDL_Rect rect; rect.x = CurrentTextRect.UpperLeftCorner.X + m_cursor_distance - 1; rect.y = CurrentTextRect.UpperLeftCorner.Y; diff --git a/src/input/input_manager.cpp b/src/input/input_manager.cpp index 99cff967f5a..d59af49cde4 100644 --- a/src/input/input_manager.cpp +++ b/src/input/input_manager.cpp @@ -109,7 +109,7 @@ InputManager::InputManager() : m_mode(BOOTSTRAP), m_device_manager->initialize(); m_master_player_only = false; -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && !defined(__EMSCRIPTEN__) #ifdef __SWITCH__ padConfigureInput(8, HidNpadStyleSet_NpadStandard); // Otherwise we report 'B' as 'A' (like Xbox controller) @@ -135,7 +135,7 @@ InputManager::InputManager() : m_mode(BOOTSTRAP), // ----------------------------------------------------------------------------- void InputManager::addJoystick() { -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && !defined(__EMSCRIPTEN__) // When irrlicht device is reinitialized the joystick added event may be // lost, we look for them and add it back for (int i = 0; i < SDL_NumJoysticks(); i++) @@ -162,7 +162,7 @@ void InputManager::addJoystick() } // ----------------------------------------------------------------------------- -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && !defined(__EMSCRIPTEN__) // For CIrrDeviceSDL extern "C" void handle_joystick(SDL_Event& event) { @@ -258,14 +258,14 @@ void InputManager::update(float dt) it++; } -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && !defined(__EMSCRIPTEN__) for (auto& controller : m_sdl_controller) controller.second->checkPowerLevel(); #endif } //----------------------------------------------------------------------------- -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && !defined(__EMSCRIPTEN__) const irr::SEvent& InputManager::getEventForGamePad(unsigned i) const { auto it = m_sdl_controller.begin(); @@ -278,7 +278,7 @@ const irr::SEvent& InputManager::getEventForGamePad(unsigned i) const */ InputManager::~InputManager() { -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && !defined(__EMSCRIPTEN__) m_sdl_controller.clear(); #endif delete m_device_manager; diff --git a/src/input/input_manager.hpp b/src/input/input_manager.hpp index 4eedbe6fde3..7e3d2fecb82 100644 --- a/src/input/input_manager.hpp +++ b/src/input/input_manager.hpp @@ -78,7 +78,7 @@ class InputManager: public NoCopy void inputSensing(Input::InputType type, int deviceID, int btnID, Input::AxisDirection axisDirection, int value); -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && !defined(__EMSCRIPTEN__) std::map > m_sdl_controller; #endif @@ -109,7 +109,7 @@ class InputManager: public NoCopy /** Returns the ID of the player that plays with the keyboard, * or -1 if none. */ int getPlayerKeyboardID() const; -#ifdef SERVER_ONLY +#if defined(SERVER_ONLY) || defined(__EMSCRIPTEN__) size_t getGamepadCount() const { return 0; } #else /** Returns number of active connected gamepad (with SDL), notice the diff --git a/src/input/sdl_controller.cpp b/src/input/sdl_controller.cpp index 19534d886c5..b96a28448d8 100644 --- a/src/input/sdl_controller.cpp +++ b/src/input/sdl_controller.cpp @@ -15,7 +15,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && !defined(__EMSCRIPTEN__) #include "input/sdl_controller.hpp" #include "guiengine/message_queue.hpp" diff --git a/src/items/rubber_band.cpp b/src/items/rubber_band.cpp index 3e137c7361f..3bbb603c646 100644 --- a/src/items/rubber_band.cpp +++ b/src/items/rubber_band.cpp @@ -86,6 +86,7 @@ RubberBand::RubberBand(Plunger *plunger, AbstractKart *kart) scene::IMeshBuffer* buffer = NULL; if (irr_driver->getVideoDriver()->getDriverType() == video::EDT_VULKAN) { + #ifdef _IRR_COMPILE_WITH_VULKAN_ buffer = new GE::GEVulkanDynamicSPMBuffer(); video::S3DVertexSkinnedMesh v; v.m_normal = 0x1FF << 10; @@ -94,6 +95,7 @@ RubberBand::RubberBand(Plunger *plunger, AbstractKart *kart) {{ v, v, v, v }}; buffer->append(vertices.data(), vertices.size(), indices.data(), indices.size()); + #endif } else { diff --git a/src/karts/controller/local_player_controller.cpp b/src/karts/controller/local_player_controller.cpp index 88395be61ad..d811c61fe38 100644 --- a/src/karts/controller/local_player_controller.cpp +++ b/src/karts/controller/local_player_controller.cpp @@ -487,7 +487,7 @@ void LocalPlayerController::doCrashHaptics() { } void LocalPlayerController::rumble(float strength_low, float strength_high, uint16_t duration) { -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && !defined(__EMSCRIPTEN__) if (RewindManager::get()->isRewinding()) return; int count = input_manager->getGamepadCount(); diff --git a/src/main.cpp b/src/main.cpp index c69a7bd60d3..a538e5df7fb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -305,7 +305,7 @@ void runUnitTests(); void gamepadVisualisation() { -#ifndef SERVER_ONLY +#if !defined(SERVER_ONLY) && !defined(__EMSCRIPTEN__) input_manager = new InputManager(); #define GAMEPAD_COUNT 8 // const won't work diff --git a/wasm/build_deps.sh b/wasm/build_deps.sh index 18fc86e6d4f..41627a7d056 100755 --- a/wasm/build_deps.sh +++ b/wasm/build_deps.sh @@ -73,7 +73,11 @@ build_curl() { cd "$SRC_DIR" autoreconf -fi - emconfigure ./configure --host none-linux --prefix="$PREFIX" --with-ssl="$PREFIX" --with-zlib="$PREFIX" --disable-shared --disable-threaded-resolver --without-libpsl --disable-netrc --disable-ipv6 --disable-tftp --disable-ntlm-wb + emconfigure ./configure --host none-linux --prefix="$PREFIX" \ + --with-ssl="$PREFIX" --with-zlib="$PREFIX" \ + --disable-shared --disable-threaded-resolver \ + --without-libpsl --disable-netrc --disable-ipv6 \ + --disable-tftp --disable-ntlm-wb emmake make -j$CORE_COUNT make install } @@ -106,9 +110,20 @@ build_freetype() { local SRC_DIR="$BUILD_DIR/freetype" clone_repo "https://github.com/freetype/freetype" VER-2-13-2 "$SRC_DIR" cd "$SRC_DIR" + mkdir -p build + cd build - ./autogen.sh - emconfigure ./configure --host=none-linux --prefix="$PREFIX" --disable-shared PKG_CONFIG_PATH="$LIB/pkgconfig" + if [ ! "$with_harfbuzz" ]; then + emcmake cmake .. -DCMAKE_INSTALL_PREFIX:PATH="$PREFIX" \ + -DZLIB_LIBRARY="$LIB/libz.a" -DZLIB_INCLUDE_DIR="$INCLUDE" \ + -DPNG_LIBRARY="$LIB/libpng.a" -DPNG_PNG_INCLUDE_DIR="$INCLUDE" + else + emcmake cmake .. -DCMAKE_INSTALL_PREFIX:PATH="$PREFIX" \ + -DZLIB_LIBRARY="$LIB/libz.a" -DZLIB_INCLUDE_DIR="$INCLUDE" \ + -DPNG_LIBRARY="$LIB/libpng.a" -DPNG_PNG_INCLUDE_DIR="$INCLUDE" \ + -DHarfBuzz_LIBRARY="$LIB/libharfbuzz.a" -DHarfBuzz_INCLUDE_DIR="$INCLUDE/harfbuzz/" \ + -DFT_REQUIRE_HARFBUZZ=TRUE + fi emmake make -j$CORE_COUNT make install } @@ -161,5 +176,7 @@ if [ ! -d "$INCLUDE/harfbuzz" ]; then #rebuild freetype with harfbuzz support rm -rf "$INCLUDE/freetype2" - build_freetype + build_freetype true fi + +build_freetype true \ No newline at end of file From 5a1d9a181488b5f9d8f5dd9cf458a0b25815b40d Mon Sep 17 00:00:00 2001 From: ading2210 Date: Tue, 28 May 2024 17:11:02 -0400 Subject: [PATCH 05/25] create html file for launching the game --- .gitignore | 1 + src/io/file_manager.cpp | 4 ++++ wasm/build.sh | 9 ++++++++- wasm/fragments/start_later.js | 9 +++++++++ wasm/patch_js.py | 29 +++++++++++++++++++++++++++++ wasm/web/index.html | 9 +++++++++ 6 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 wasm/fragments/start_later.js create mode 100644 wasm/patch_js.py create mode 100644 wasm/web/index.html diff --git a/.gitignore b/.gitignore index cca03f976ad..c047abb4767 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ tags.* wasm/build/ wasm/prefix/ wasm/emsdk/ +wasm/web/game # clangd .cache/ diff --git a/src/io/file_manager.cpp b/src/io/file_manager.cpp index ece404d2385..c32ac869dba 100644 --- a/src/io/file_manager.cpp +++ b/src/io/file_manager.cpp @@ -213,6 +213,10 @@ FileManager::FileManager() #endif } +#ifdef __EMSCRIPTEN__ + root_dir = "/data/"; +#endif + if (!m_file_system->existFile((root_dir + version).c_str())) { Log::error("FileManager", "Could not find file '%s'in any " diff --git a/wasm/build.sh b/wasm/build.sh index 15db7f8408e..b8ce44e680e 100755 --- a/wasm/build.sh +++ b/wasm/build.sh @@ -3,8 +3,11 @@ CORE_COUNT="$(nproc --all)" BASE_DIR="$(realpath "$(dirname "$0")")" SRC_DIR="$(dirname "$BASE_DIR")" +WEB_DIR="$BASE_DIR/web" +DATA_DIR="$SRC_DIR/game" BUILD_DIR="$SRC_DIR/cmake_build" EMSDK_DIR="$BASE_DIR/emsdk" +PACKAGER="$EMSDK_DIR/upstream/emscripten/tools/file_packager.py" PREFIX="$BASE_DIR/prefix" mkdir -p $BUILD_DIR @@ -12,4 +15,8 @@ cd $BUILD_DIR source $EMSDK_DIR/emsdk_env.sh emcmake cmake .. -DNO_SHADERC=on -make -j4 \ No newline at end of file +make -j4 + +mkdir -p "$WEB_DIR/game" +cp ./bin/* "$WEB_DIR/game/" +python3 $BASE_DIR/patch_js.py $BASE_DIR/fragments $WEB_DIR/game/supertuxkart.js \ No newline at end of file diff --git a/wasm/fragments/start_later.js b/wasm/fragments/start_later.js new file mode 100644 index 00000000000..7bac1cdeb3a --- /dev/null +++ b/wasm/fragments/start_later.js @@ -0,0 +1,9 @@ +/* DELETE +;run\(\); +*/ + + +/* DELETE +if ?\(!calledRun\)\s*?run\(\); +*/ + diff --git a/wasm/patch_js.py b/wasm/patch_js.py new file mode 100644 index 00000000000..65efcc5745a --- /dev/null +++ b/wasm/patch_js.py @@ -0,0 +1,29 @@ +import re +import sys +import pathlib + +match_regex = r'/\* (.+?)\n(.+?)\n\*/\n(.*?)(\n\n|$)' + +fragments_dir = sys.argv[1] +target_dir = sys.argv[2] +fragments_path = pathlib.Path(fragments_dir) +target_path = pathlib.Path(target_dir) +target_text = target_path.read_text() + +for fragment_file in fragments_path.iterdir(): + print(f"applying patch from {fragment_file.name}") + fragment_text = fragment_file.read_text() + matches = re.findall(match_regex, fragment_text, re.S) + + for mode, patch_regex, patch_text, _ in matches: + fragment_matches = re.findall(patch_regex, target_text) + if not fragment_matches: + print(f"warning: regex did not match anything for '{patch_regex}'"); + if mode == "DELETE": + target_text = re.sub(patch_regex, "", target_text) + elif mode == "REPLACE": + target_text = re.sub(patch_regex, patch_text, target_text) + elif mode == "INSERT": + target_text = re.sub("("+patch_regex+")", r'\1'+patch_text, target_text) + +target_path.write_text(target_text) \ No newline at end of file diff --git a/wasm/web/index.html b/wasm/web/index.html new file mode 100644 index 00000000000..db31ec4d30a --- /dev/null +++ b/wasm/web/index.html @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file From 2a108ac922ba25368d8b80bf14eccaeec5aea639 Mon Sep 17 00:00:00 2001 From: ading2210 Date: Wed, 29 May 2024 11:15:14 -0400 Subject: [PATCH 06/25] load game data from tar.gz file --- wasm/build.sh | 7 +++++-- wasm/web/index.html | 1 + wasm/web/script.js | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 wasm/web/script.js diff --git a/wasm/build.sh b/wasm/build.sh index b8ce44e680e..43d9a6ba87c 100755 --- a/wasm/build.sh +++ b/wasm/build.sh @@ -4,7 +4,6 @@ CORE_COUNT="$(nproc --all)" BASE_DIR="$(realpath "$(dirname "$0")")" SRC_DIR="$(dirname "$BASE_DIR")" WEB_DIR="$BASE_DIR/web" -DATA_DIR="$SRC_DIR/game" BUILD_DIR="$SRC_DIR/cmake_build" EMSDK_DIR="$BASE_DIR/emsdk" PACKAGER="$EMSDK_DIR/upstream/emscripten/tools/file_packager.py" @@ -17,6 +16,10 @@ source $EMSDK_DIR/emsdk_env.sh emcmake cmake .. -DNO_SHADERC=on make -j4 +echo "packing game files" mkdir -p "$WEB_DIR/game" cp ./bin/* "$WEB_DIR/game/" -python3 $BASE_DIR/patch_js.py $BASE_DIR/fragments $WEB_DIR/game/supertuxkart.js \ No newline at end of file +tar -cf - -C "$SRC_DIR/data" . | gzip -9 - > "$WEB_DIR/game/data.tar.gz" + +echo "applying patches" +python3 $BASE_DIR/patch_js.py $BASE_DIR/fragments $WEB_DIR/game/supertuxkart.js diff --git a/wasm/web/index.html b/wasm/web/index.html index db31ec4d30a..88ddcd7ac2c 100644 --- a/wasm/web/index.html +++ b/wasm/web/index.html @@ -2,6 +2,7 @@ + diff --git a/wasm/web/script.js b/wasm/web/script.js new file mode 100644 index 00000000000..4f34b07fc52 --- /dev/null +++ b/wasm/web/script.js @@ -0,0 +1,32 @@ +import pako from "https://cdn.jsdelivr.net/npm/pako@2.1.0/+esm"; +import jsUntar from "https://cdn.jsdelivr.net/npm/js-untar@2.0.0/+esm"; + +async function extract_tar(url, fs_path) { + //download tar file from server and decompress + let r = await fetch(url); + let compressed = await r.arrayBuffer(); + let decompressed = pako.inflate(compressed); + let files = await jsUntar(decompressed.buffer); + + //save each file to the emscripten filesystem + for (let file of files) { + let relative_path = file.name.substring(1); + let out_path = fs_path + relative_path; + console.log(file); + if (out_path.endsWith("/")) { + FS.mkdir(out_path); + } + else { + let array = new Uint8Array(file.buffer); + FS.writeFile(out_path, array); + } + } +} + +async function load_data() { + await extract_tar("/game/data.tar.gz", "/data"); +} + +globalThis.pako = pako; +globalThis.jsUntar = jsUntar; +globalThis.load_data = load_data; \ No newline at end of file From 4a175e176588605c31a8b18129ff83182b8bd638 Mon Sep 17 00:00:00 2001 From: ading2210 Date: Wed, 29 May 2024 15:54:09 -0400 Subject: [PATCH 07/25] set compile flags for debug builds --- CMakeLists.txt | 14 ++++++++++---- wasm/build.sh | 6 ++---- wasm/web/script.js | 1 - 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7844e891c49..a50b3b1040a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,21 +84,27 @@ if(EMSCRIPTEN) set(OGGVORBIS_OGG_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/libogg.a") set(OGGVORBIS_VORBISFILE_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/libvorbisfile.a") set(OGGVORBIS_VORBIS_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/libvorbis.a") - #-DFREETYPE_INCLUDE_DIRS=/home/heatingdevice/projects/freetype/include \ - - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SOURCE_DIR}/wasm/prefix/lib/ -lcrypto -lSDL2 -logg -lvorbis") #todo: avoid hardcoding this path set(PTHREAD_LIBRARY "/usr/share/emscripten/cache/sysroot/") - + set(USE_WIIUSE 0) set(USE_DNS_C 1) + set(NO_SHADERC on) add_definitions(-DNO_IRR_COMPILE_WITH_X11_) add_definitions(-DNO_IRR_COMPILE_WITH_WAYLAND_DEVICE_) add_definitions(-DNO_IRR_COMPILE_WITH_DIRECT3D_9_) add_definitions(-DNO_IRR_COMPILE_WITH_VULKAN_) add_definitions(-DNO_IRR_COMPILE_WITH_OPENGL_) add_definitions(-D_IRR_COMPILE_WITH_OGLES2_) + + add_compile_options("-sUSE_SDL=2") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SOURCE_DIR}/wasm/prefix/lib/ -sUSE_SDL=2 -lcrypto -logg -lvorbis") + if(CMAKE_BUILD_TYPE MATCHES Debug) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -sEXCEPTION_DEBUG=1 --profiling-funcs") + add_compile_options(-g3) + endif() + endif() if(APPLE AND NOT IOS) diff --git a/wasm/build.sh b/wasm/build.sh index 43d9a6ba87c..38cfcac19f8 100755 --- a/wasm/build.sh +++ b/wasm/build.sh @@ -6,15 +6,13 @@ SRC_DIR="$(dirname "$BASE_DIR")" WEB_DIR="$BASE_DIR/web" BUILD_DIR="$SRC_DIR/cmake_build" EMSDK_DIR="$BASE_DIR/emsdk" -PACKAGER="$EMSDK_DIR/upstream/emscripten/tools/file_packager.py" -PREFIX="$BASE_DIR/prefix" mkdir -p $BUILD_DIR cd $BUILD_DIR source $EMSDK_DIR/emsdk_env.sh -emcmake cmake .. -DNO_SHADERC=on -make -j4 +emcmake cmake .. -DNO_SHADERC=on -DCMAKE_BUILD_TYPE=Debug +make -j$CORE_COUNT echo "packing game files" mkdir -p "$WEB_DIR/game" diff --git a/wasm/web/script.js b/wasm/web/script.js index 4f34b07fc52..6bb1d788d82 100644 --- a/wasm/web/script.js +++ b/wasm/web/script.js @@ -12,7 +12,6 @@ async function extract_tar(url, fs_path) { for (let file of files) { let relative_path = file.name.substring(1); let out_path = fs_path + relative_path; - console.log(file); if (out_path.endsWith("/")) { FS.mkdir(out_path); } From f1b10387b73f64155ce7ea887466fe4109309dec Mon Sep 17 00:00:00 2001 From: ading2210 Date: Wed, 29 May 2024 15:08:29 -0700 Subject: [PATCH 08/25] compile with exception support and bundle assets --- CMakeLists.txt | 12 +++++++++--- wasm/build.sh | 10 +++++++--- wasm/build_deps.sh | 10 +++++----- wasm/pack_assets.sh | 18 ++++++++++++++++++ wasm/web/index.html | 2 +- wasm/web/script.js | 12 ++++++++++-- 6 files changed, 50 insertions(+), 14 deletions(-) create mode 100755 wasm/pack_assets.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index a50b3b1040a..534700dc85d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,6 +59,9 @@ if(IOS) endif() if(EMSCRIPTEN) + #note: cmake fails the first few times you run it then works fine without changing anything + #i have no idea why this happens + set(CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/wasm/prefix/") set(JPEG_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/wasm/prefix/include") @@ -98,11 +101,14 @@ if(EMSCRIPTEN) add_definitions(-DNO_IRR_COMPILE_WITH_OPENGL_) add_definitions(-D_IRR_COMPILE_WITH_OGLES2_) - add_compile_options("-sUSE_SDL=2") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SOURCE_DIR}/wasm/prefix/lib/ -sUSE_SDL=2 -lcrypto -logg -lvorbis") + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -sUSE_SDL=2 -fwasm-exceptions -sSUPPORT_LONGJMP=wasm") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -sUSE_SDL=2 -fwasm-exceptions -sSUPPORT_LONGJMP=wasm") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SOURCE_DIR}/wasm/prefix/lib/ -lcrypto -logg -lvorbis -fwasm-exceptions") if(CMAKE_BUILD_TYPE MATCHES Debug) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -sEXCEPTION_DEBUG=1 --profiling-funcs") - add_compile_options(-g3) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g3") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3") endif() endif() diff --git a/wasm/build.sh b/wasm/build.sh index 38cfcac19f8..52d10a6574c 100755 --- a/wasm/build.sh +++ b/wasm/build.sh @@ -1,5 +1,8 @@ #!/bin/bash +set -e +set -x + CORE_COUNT="$(nproc --all)" BASE_DIR="$(realpath "$(dirname "$0")")" SRC_DIR="$(dirname "$BASE_DIR")" @@ -7,17 +10,18 @@ WEB_DIR="$BASE_DIR/web" BUILD_DIR="$SRC_DIR/cmake_build" EMSDK_DIR="$BASE_DIR/emsdk" +BUILD_TYPE="${1:-'Release'}" + mkdir -p $BUILD_DIR cd $BUILD_DIR source $EMSDK_DIR/emsdk_env.sh -emcmake cmake .. -DNO_SHADERC=on -DCMAKE_BUILD_TYPE=Debug +emcmake cmake .. -DNO_SHADERC=on -DCMAKE_BUILD_TYPE=$BUILD_TYPE make -j$CORE_COUNT -echo "packing game files" +echo "copying wasm files" mkdir -p "$WEB_DIR/game" cp ./bin/* "$WEB_DIR/game/" -tar -cf - -C "$SRC_DIR/data" . | gzip -9 - > "$WEB_DIR/game/data.tar.gz" echo "applying patches" python3 $BASE_DIR/patch_js.py $BASE_DIR/fragments $WEB_DIR/game/supertuxkart.js diff --git a/wasm/build_deps.sh b/wasm/build_deps.sh index 41627a7d056..71c03c27ce7 100755 --- a/wasm/build_deps.sh +++ b/wasm/build_deps.sh @@ -13,6 +13,9 @@ LIB="$PREFIX/lib" source $EMSDK_DIR/emsdk_env.sh export PKG_CONFIG_PATH="$LIB/pkgconfig" +export CFLAGS="-fwasm-exceptions -sSUPPORT_LONGJMP=wasm" +export CPPFLAGS="-fwasm-exceptions -sSUPPORT_LONGJMP=wasm" +export LDFLAGS="-fwasm-exceptions -sSUPPORT_LONGJMP=wasm" clone_repo() { local url="$1" @@ -99,12 +102,11 @@ build_png() { clone_repo "https://github.com/pnggroup/libpng" v1.6.43 "$SRC_DIR" cd "$SRC_DIR" - emconfigure ./configure --host none-linux --prefix="$PREFIX" --disable-shared CPPFLAGS="-I$INCLUDE" LDFLAGS="-L$LIB" + emconfigure ./configure --host none-linux --prefix="$PREFIX" --disable-shared CPPFLAGS="$CPPFLAGS -I$INCLUDE" LDFLAGS="$LDFLAGS -L$LIB" emmake make -j$CORE_COUNT make install } - build_freetype() { local with_harfbuzz="$1" local SRC_DIR="$BUILD_DIR/freetype" @@ -133,7 +135,7 @@ build_harfbuzz() { clone_repo "https://github.com/harfbuzz/harfbuzz" 8.5.0 "$SRC_DIR" cd "$SRC_DIR" - ./autogen.sh + emconfigure ./autogen.sh emconfigure ./configure --host=none-linux --prefix="$PREFIX" --disable-shared PKG_CONFIG_PATH="$LIB/pkgconfig" emmake make -j$CORE_COUNT make install @@ -178,5 +180,3 @@ if [ ! -d "$INCLUDE/harfbuzz" ]; then rm -rf "$INCLUDE/freetype2" build_freetype true fi - -build_freetype true \ No newline at end of file diff --git a/wasm/pack_assets.sh b/wasm/pack_assets.sh new file mode 100755 index 00000000000..e0c63062dc6 --- /dev/null +++ b/wasm/pack_assets.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +set -e +set -x + +BASE_DIR="$(realpath "$(dirname "$0")")" +SRC_DIR="$(dirname "$BASE_DIR")" +WEB_DIR="$BASE_DIR/web" + +if [ ! "$1" ]; then + echo "you must specify the assets directory" + exit 1 +fi + +ASSETS_DIR="$(realpath "$1")" + +tar -cf - -C "$SRC_DIR/data" . | gzip -9 - > "$WEB_DIR/game/data.tar.gz" +tar -cf - -C "$ASSETS_DIR" . | gzip -9 - > "$WEB_DIR/game/assets.tar.gz" \ No newline at end of file diff --git a/wasm/web/index.html b/wasm/web/index.html index 88ddcd7ac2c..68f8d210da6 100644 --- a/wasm/web/index.html +++ b/wasm/web/index.html @@ -5,6 +5,6 @@ - + \ No newline at end of file diff --git a/wasm/web/script.js b/wasm/web/script.js index 6bb1d788d82..e9dc89b1740 100644 --- a/wasm/web/script.js +++ b/wasm/web/script.js @@ -13,7 +13,10 @@ async function extract_tar(url, fs_path) { let relative_path = file.name.substring(1); let out_path = fs_path + relative_path; if (out_path.endsWith("/")) { - FS.mkdir(out_path); + try { + FS.mkdir(out_path); + } + catch {} } else { let array = new Uint8Array(file.buffer); @@ -23,9 +26,14 @@ async function extract_tar(url, fs_path) { } async function load_data() { + console.log("downloading and extracting game data"); await extract_tar("/game/data.tar.gz", "/data"); + console.log("downloading and extracting assets"); + await extract_tar("/game/assets.tar.gz", "/data"); } globalThis.pako = pako; globalThis.jsUntar = jsUntar; -globalThis.load_data = load_data; \ No newline at end of file +globalThis.load_data = load_data; + +Module["canvas"] = document.getElementById("canvas") \ No newline at end of file From 4da4be0a79dac218b8a34f011d3743595cc81986 Mon Sep 17 00:00:00 2001 From: ading2210 Date: Wed, 29 May 2024 18:15:03 -0700 Subject: [PATCH 09/25] the game runs! still some webgl issues though --- CMakeLists.txt | 16 +++++++++------- lib/graphics_engine/src/ge_gl_texture.cpp | 2 ++ lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp | 2 +- src/main.cpp | 12 +++++++++++- src/main_loop.cpp | 9 +++++++-- wasm/build_deps.sh | 8 ++++---- wasm/pack_assets.sh | 2 +- wasm/run_server.py | 11 +++++++++++ wasm/web/script.js | 4 +++- 9 files changed, 49 insertions(+), 17 deletions(-) create mode 100644 wasm/run_server.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 534700dc85d..6c5b2e2dba1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,6 +93,7 @@ if(EMSCRIPTEN) set(USE_WIIUSE 0) set(USE_DNS_C 1) + set(USE_GLES2 1) set(NO_SHADERC on) add_definitions(-DNO_IRR_COMPILE_WITH_X11_) add_definitions(-DNO_IRR_COMPILE_WITH_WAYLAND_DEVICE_) @@ -100,15 +101,16 @@ if(EMSCRIPTEN) add_definitions(-DNO_IRR_COMPILE_WITH_VULKAN_) add_definitions(-DNO_IRR_COMPILE_WITH_OPENGL_) add_definitions(-D_IRR_COMPILE_WITH_OGLES2_) + add_definitions(-DDISABLE_RPC) + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -sUSE_SDL=2 -fwasm-exceptions -sSUPPORT_LONGJMP=wasm -pthread") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -sUSE_SDL=2 -fwasm-exceptions -sSUPPORT_LONGJMP=wasm -pthread") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SOURCE_DIR}/wasm/prefix/lib/ -sASSERTIONS=1 -sSTACK_SIZE=30000000 -sFULL_ES2 -sINITIAL_MEMORY=512MB -sWASM_BIGINT -sALLOW_MEMORY_GROWTH -lcrypto -logg -lvorbis -fwasm-exceptions") - - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -sUSE_SDL=2 -fwasm-exceptions -sSUPPORT_LONGJMP=wasm") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -sUSE_SDL=2 -fwasm-exceptions -sSUPPORT_LONGJMP=wasm") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SOURCE_DIR}/wasm/prefix/lib/ -lcrypto -logg -lvorbis -fwasm-exceptions") if(CMAKE_BUILD_TYPE MATCHES Debug) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -sEXCEPTION_DEBUG=1 --profiling-funcs") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g3") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --profiling") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g") endif() endif() diff --git a/lib/graphics_engine/src/ge_gl_texture.cpp b/lib/graphics_engine/src/ge_gl_texture.cpp index 1dc95760847..7f26b1ef22d 100644 --- a/lib/graphics_engine/src/ge_gl_texture.cpp +++ b/lib/graphics_engine/src/ge_gl_texture.cpp @@ -60,6 +60,7 @@ GEGLTexture::GEGLTexture(const std::string& name, unsigned int size, m_size = m_orig_size; bool texture_swizzle = false; +#ifndef __EMSCRIPTEN__ if (m_driver_type == video::EDT_OGLES2) { int gl_major_version = 0; @@ -74,6 +75,7 @@ GEGLTexture::GEGLTexture(const std::string& name, unsigned int size, texture_swizzle = irr::video::useCoreContext && GE::hasGLExtension("GL_ARB_texture_swizzle"); } +#endif if (single_channel && texture_swizzle) m_single_channel = true; diff --git a/lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp b/lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp index 4e3611f3b0a..ef4412f1a9f 100644 --- a/lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp +++ b/lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp @@ -108,7 +108,7 @@ CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters& param) } #endif - u32 init_flags = SDL_INIT_TIMER | SDL_INIT_VIDEO; + u32 init_flags = SDL_INIT_VIDEO; if (SDL_Init(init_flags) < 0) { os::Printer::log("Unable to initialize SDL!", SDL_GetError()); diff --git a/src/main.cpp b/src/main.cpp index a538e5df7fb..d1330be8201 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -166,6 +166,10 @@ #include #endif +#ifdef __EMSCRIPTEN__ +#include +#endif + #ifdef __SWITCH__ extern "C" { #include @@ -2587,8 +2591,14 @@ int main(int argc, char *argv[]) // Game loaded, bring CPU / GPU clock back to normal appletSetCpuBoostMode(ApmCpuBoostMode_Normal); #endif - +#ifdef __EMSCRIPTEN__ + auto mainLoopWrapper = []() { + main_loop->run(); + }; + emscripten_set_main_loop(mainLoopWrapper, 0, 1); +#else main_loop->run(); +#endif } // try catch (std::exception &e) diff --git a/src/main_loop.cpp b/src/main_loop.cpp index af30f8e0d12..3374074f832 100644 --- a/src/main_loop.cpp +++ b/src/main_loop.cpp @@ -84,6 +84,7 @@ extern "C" { #endif MainLoop* main_loop = 0; +double left_over_time = 0; #ifdef WIN32 LRESULT CALLBACK separateProcessProc(_In_ HWND hwnd, _In_ UINT uMsg, @@ -399,11 +400,12 @@ void MainLoop::updateRace(int ticks, bool fast_forward) */ void MainLoop::run() { +#ifndef __EMSCRIPTEN__ m_curr_time = std::chrono::steady_clock::now(); +#endif // DT keeps track of the leftover time, since the race update // happens in fixed timesteps - double left_over_time = 0; - + #ifdef WIN32 HANDLE parent = 0; if (m_parent_pid != 0) @@ -417,7 +419,10 @@ void MainLoop::run() } #endif +#ifndef __EMSCRIPTEN__ while (!m_abort) +#endif + { #ifdef __SWITCH__ // This feeds us messages (like when the Switch sleeps or requests an exit) diff --git a/wasm/build_deps.sh b/wasm/build_deps.sh index 71c03c27ce7..6c14b9f73bb 100755 --- a/wasm/build_deps.sh +++ b/wasm/build_deps.sh @@ -13,9 +13,9 @@ LIB="$PREFIX/lib" source $EMSDK_DIR/emsdk_env.sh export PKG_CONFIG_PATH="$LIB/pkgconfig" -export CFLAGS="-fwasm-exceptions -sSUPPORT_LONGJMP=wasm" -export CPPFLAGS="-fwasm-exceptions -sSUPPORT_LONGJMP=wasm" -export LDFLAGS="-fwasm-exceptions -sSUPPORT_LONGJMP=wasm" +export CFLAGS="-fwasm-exceptions -sSUPPORT_LONGJMP=wasm -pthread" +export CPPFLAGS="-fwasm-exceptions -sSUPPORT_LONGJMP=wasm -pthread" +export LDFLAGS="-fwasm-exceptions -sSUPPORT_LONGJMP=wasm -pthread" clone_repo() { local url="$1" @@ -53,7 +53,7 @@ build_openssl() { clone_repo "https://github.com/openssl/openssl" openssl-3.3.0 "$SRC_DIR" cd "$SRC_DIR" - emconfigure ./Configure linux-x32 -no-asm -static -no-afalgeng -no-dso -no-threads -DOPENSSL_SYS_NETWARE -DSIG_DFL=0 -DSIG_IGN=0 -DHAVE_FORK=0 -DOPENSSL_NO_AFALGENG=1 -DOPENSSL_NO_SPEED=1 -DOPENSSL_NO_DYNAMIC_ENGINE -DDLOPEN_FLAG=0 + emconfigure ./Configure linux-x32 -no-asm -static -no-afalgeng -no-dso -DOPENSSL_SYS_NETWARE -DSIG_DFL=0 -DSIG_IGN=0 -DHAVE_FORK=0 -DOPENSSL_NO_AFALGENG=1 -DOPENSSL_NO_SPEED=1 -DOPENSSL_NO_DYNAMIC_ENGINE -DDLOPEN_FLAG=0 sed -i 's|^CROSS_COMPILE.*$|CROSS_COMPILE=|g' Makefile emmake make -j$CORE_COUNT build_generated libssl.a libcrypto.a cp -r include/openssl $PREFIX/include diff --git a/wasm/pack_assets.sh b/wasm/pack_assets.sh index e0c63062dc6..10737eef077 100755 --- a/wasm/pack_assets.sh +++ b/wasm/pack_assets.sh @@ -15,4 +15,4 @@ fi ASSETS_DIR="$(realpath "$1")" tar -cf - -C "$SRC_DIR/data" . | gzip -9 - > "$WEB_DIR/game/data.tar.gz" -tar -cf - -C "$ASSETS_DIR" . | gzip -9 - > "$WEB_DIR/game/assets.tar.gz" \ No newline at end of file +tar -cf - -C "$ASSETS_DIR" . | gzip -6 - > "$WEB_DIR/game/assets.tar.gz" \ No newline at end of file diff --git a/wasm/run_server.py b/wasm/run_server.py new file mode 100644 index 00000000000..f4004cb28bb --- /dev/null +++ b/wasm/run_server.py @@ -0,0 +1,11 @@ +from http import server + +class MyHTTPRequestHandler(server.SimpleHTTPRequestHandler): + def end_headers(self): + self.send_header("Cross-Origin-Opener-Policy", "same-origin") + self.send_header("Cross-Origin-Embedder-Policy", "require-corp") + + server.SimpleHTTPRequestHandler.end_headers(self) + +if __name__ == '__main__': + server.test(HandlerClass=MyHTTPRequestHandler) diff --git a/wasm/web/script.js b/wasm/web/script.js index e9dc89b1740..878c7d0fa02 100644 --- a/wasm/web/script.js +++ b/wasm/web/script.js @@ -30,10 +30,12 @@ async function load_data() { await extract_tar("/game/data.tar.gz", "/data"); console.log("downloading and extracting assets"); await extract_tar("/game/assets.tar.gz", "/data"); + console.log("done") } globalThis.pako = pako; globalThis.jsUntar = jsUntar; globalThis.load_data = load_data; -Module["canvas"] = document.getElementById("canvas") \ No newline at end of file +Module["canvas"] = document.getElementById("canvas") +load_data(); \ No newline at end of file From d89050e9d45685f17959abd03c54e06f6b5d209a Mon Sep 17 00:00:00 2001 From: ading2210 Date: Wed, 29 May 2024 21:28:22 -0700 Subject: [PATCH 10/25] fix some scaling problems and re-enable controller support --- CMakeLists.txt | 2 +- .../source/Irrlicht/CIrrDeviceSDL.cpp | 30 ++++--------------- src/graphics/central_settings.cpp | 4 +++ src/graphics/cpu_particle_manager.cpp | 5 ++++ src/graphics/shader_based_renderer.cpp | 1 - src/graphics/skid_marks.cpp | 4 +-- src/graphics/sp/sp_mesh_buffer.cpp | 11 +++++++ src/graphics/sp/sp_texture_manager.cpp | 6 ++++ src/input/input_manager.cpp | 14 +++++---- src/input/input_manager.hpp | 4 +-- src/input/sdl_controller.cpp | 2 +- wasm/fragments/fix_webgl.js | 4 +++ wasm/web/index.html | 2 +- 13 files changed, 50 insertions(+), 39 deletions(-) create mode 100644 wasm/fragments/fix_webgl.js diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c5b2e2dba1..eb1ef6fdcd2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,7 +105,7 @@ if(EMSCRIPTEN) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -sUSE_SDL=2 -fwasm-exceptions -sSUPPORT_LONGJMP=wasm -pthread") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -sUSE_SDL=2 -fwasm-exceptions -sSUPPORT_LONGJMP=wasm -pthread") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SOURCE_DIR}/wasm/prefix/lib/ -sASSERTIONS=1 -sSTACK_SIZE=30000000 -sFULL_ES2 -sINITIAL_MEMORY=512MB -sWASM_BIGINT -sALLOW_MEMORY_GROWTH -lcrypto -logg -lvorbis -fwasm-exceptions") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SOURCE_DIR}/wasm/prefix/lib/ -sASSERTIONS=1 -sSTACK_SIZE=30000000 -sFULL_ES2 -sUSE_SDL_MIXER=2 -sINITIAL_MEMORY=512MB -sWASM_BIGINT -sALLOW_MEMORY_GROWTH -lcrypto -fwasm-exceptions") if(CMAKE_BUILD_TYPE MATCHES Debug) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --profiling") diff --git a/lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp b/lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp index ef4412f1a9f..2d2022f32ed 100644 --- a/lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp +++ b/lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp @@ -84,20 +84,16 @@ CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters& param) Operator = 0; // Initialize SDL... Timer for sleep, video for the obvious, and // noparachute prevents SDL from catching fatal errors. -#ifndef __EMSCRIPTEN__ SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS, "1"); SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0"); -#endif #if SDL_VERSION_ATLEAST(2, 0, 18) SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1"); #endif // Switch SDL disables this hint by default: https://github.com/devkitPro/SDL/pull/55#issuecomment-633775255 -#ifndef __EMSCRIPTEN__ SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "1"); -#endif -#if !defined(MOBILE_STK) && !defined(__EMSCRIPTEN__) +#ifndef MOBILE_STK // Prevent fullscreen minimizes when losing focus if (CreationParams.Fullscreen) { @@ -213,7 +209,6 @@ CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters& param) void CIrrDeviceSDL::updateNativeScale(u32* saving_width, u32* saving_height) { -#ifndef __EMSCRIPTEN__ int width, height = 0; SDL_GetWindowSize(Window, &width, &height); int real_width = width; @@ -223,17 +218,18 @@ void CIrrDeviceSDL::updateNativeScale(u32* saving_width, u32* saving_height) { SDL_GL_GetDrawableSize(Window, &real_width, &real_height); } +#ifdef _IRR_COMPILE_WITH_VULKAN_ else if (CreationParams.DriverType == video::EDT_VULKAN) { SDL_Vulkan_GetDrawableSize(Window, &real_width, &real_height); } +#endif NativeScaleX = (f32)real_width / (f32)width; NativeScaleY = (f32)real_height / (f32)height; if (saving_width) *saving_width = width; if (saving_height) *saving_height = height; -#endif } //! destructor @@ -452,7 +448,7 @@ bool CIrrDeviceSDL::createWindow() } u32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE; -#if !defined(ANDROID) && !defined(__SWITCH__) && !defined(__EMSCRIPTEN__) +#if !defined(ANDROID) && !defined(__SWITCH__) if (CreationParams.DriverType == video::EDT_OPENGL || CreationParams.DriverType == video::EDT_OGLES2 || CreationParams.DriverType == video::EDT_VULKAN) @@ -461,7 +457,6 @@ bool CIrrDeviceSDL::createWindow() if (CreationParams.Fullscreen) { -#ifndef __EMSCRIPTEN__ if (GE::getGEConfig()->m_fullscreen_desktop) { flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; @@ -469,9 +464,6 @@ bool CIrrDeviceSDL::createWindow() } else flags |= SDL_WINDOW_FULLSCREEN; -#else - flags |= SDL_WINDOW_FULLSCREEN; -#endif } if (CreationParams.DriverType == video::EDT_OPENGL || @@ -540,12 +532,12 @@ void CIrrDeviceSDL::tryCreateOpenGLContext(u32 flags) #ifndef __EMSCRIPTEN__ if (GLContextDebugBit) SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG); +#endif if (CreationParams.DriverType == video::EDT_OGLES2) SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); else SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); -#endif if (CreationParams.ForceLegacyDevice) goto legacy; @@ -673,12 +665,10 @@ void CIrrDeviceSDL::tryCreateOpenGLContext(u32 flags) SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); #endif -#ifndef __EMSCRIPTEN__ if (CreationParams.DriverType == video::EDT_OGLES2) SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); else SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0); -#endif Window = SDL_CreateWindow("", (float)CreationParams.WindowPosition.X, (float)CreationParams.WindowPosition.Y, @@ -1059,9 +1049,7 @@ bool CIrrDeviceSDL::run() } break; default: - #ifndef __EMSCRIPTEN__ handle_joystick(SDL_event); - #endif break; } // end switch @@ -1254,13 +1242,11 @@ bool CIrrDeviceSDL::getWindowPosition(int* x, int* y) //! Get DPI of current display. bool CIrrDeviceSDL::getDisplayDPI(float* ddpi, float* hdpi, float* vdpi) { -#ifndef __EMSCRIPTEN__ if (Window) { SDL_GetDisplayDPI(SDL_GetWindowDisplayIndex(Window), ddpi, hdpi, vdpi); return true; } -#endif return false; } @@ -1307,10 +1293,8 @@ bool CIrrDeviceSDL::getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightne void CIrrDeviceSDL::setWindowMinimumSize(u32 width, u32 height) { -#ifndef __EMSCRIPTEN__ if (Window) SDL_SetWindowMinimumSize(Window, width, height); -#endif } //! returns color format of the window. @@ -1606,11 +1590,7 @@ bool CIrrDeviceSDL::supportsTouchDevice() const bool CIrrDeviceSDL::hasOnScreenKeyboard() const { -#ifndef __EMSCRIPTEN__ return SDL_HasScreenKeyboardSupport() == SDL_TRUE; -#else - return false; -#endif } diff --git a/src/graphics/central_settings.cpp b/src/graphics/central_settings.cpp index 00950ae2453..40754583ac0 100644 --- a/src/graphics/central_settings.cpp +++ b/src/graphics/central_settings.cpp @@ -358,8 +358,12 @@ bool CentralVideoSettings::isARBGeometryShadersUsable() const bool CentralVideoSettings::isARBUniformBufferObjectUsable() const { +#if 0 + return false; +#else return hasUBO || (m_gl_major_version > 3 || (m_gl_major_version == 3 && m_gl_minor_version >= 1)); +#endif } bool CentralVideoSettings::isARBExplicitAttribLocationUsable() const diff --git a/src/graphics/cpu_particle_manager.cpp b/src/graphics/cpu_particle_manager.cpp index 765c9a8d856..81485f35209 100644 --- a/src/graphics/cpu_particle_manager.cpp +++ b/src/graphics/cpu_particle_manager.cpp @@ -304,9 +304,14 @@ void CPUParticleManager::uploadAll() glBindBuffer(GL_ARRAY_BUFFER, 0); continue; } +#ifdef __EMSCRIPTEN__ + void* ptr = glMapBufferRange(GL_ARRAY_BUFFER, 0, vbo_size * 20, + GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); +#else void* ptr = glMapBufferRange(GL_ARRAY_BUFFER, 0, vbo_size * 20, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); +#endif memcpy(ptr, m_particles_generated[p.first].data(), vbo_size * 20); glUnmapBuffer(GL_ARRAY_BUFFER); glBindBuffer(GL_ARRAY_BUFFER, 0); diff --git a/src/graphics/shader_based_renderer.cpp b/src/graphics/shader_based_renderer.cpp index 943b8348fff..8bced92aba7 100644 --- a/src/graphics/shader_based_renderer.cpp +++ b/src/graphics/shader_based_renderer.cpp @@ -227,7 +227,6 @@ void ShaderBasedRenderer::renderSceneDeferred(scene::ICameraSceneNode * const ca bool hasShadow, bool forceRTT) { - if (CVS->isARBUniformBufferObjectUsable()) { glBindBufferBase(GL_UNIFORM_BUFFER, 0, diff --git a/src/graphics/skid_marks.cpp b/src/graphics/skid_marks.cpp index 04200f6679c..ec5f1713799 100644 --- a/src/graphics/skid_marks.cpp +++ b/src/graphics/skid_marks.cpp @@ -252,11 +252,12 @@ SkidMarks::SkidMarkQuads::SkidMarkQuads(const Vec3 &left, } else { - #ifdef _IRR_COMPILE_WITH_VULKAN_ scene::IMeshBuffer* buffer = NULL; +#ifdef _IRR_COMPILE_WITH_VULKAN_ if (irr_driver->getVideoDriver()->getDriverType() == video::EDT_VULKAN) buffer = new GE::GEVulkanDynamicSPMBuffer(); else +#endif buffer = new scene::SMeshBuffer(); material->setMaterialProperties(&buffer->getMaterial(), buffer); buffer->getMaterial().setTexture(0, material->getTexture()); @@ -270,7 +271,6 @@ SkidMarks::SkidMarkQuads::SkidMarkQuads(const Vec3 &left, m_node->getMaterial(0).getRenderInfo() = std::make_shared(); mesh->drop(); - #endif } m_start_color = (custom_color != NULL ? *custom_color : video::SColor(255, SkidMarks::m_start_grey, SkidMarks::m_start_grey, diff --git a/src/graphics/sp/sp_mesh_buffer.cpp b/src/graphics/sp/sp_mesh_buffer.cpp index b1e424dc6d9..590596479a0 100644 --- a/src/graphics/sp/sp_mesh_buffer.cpp +++ b/src/graphics/sp/sp_mesh_buffer.cpp @@ -158,9 +158,14 @@ void SPMeshBuffer::uploadGLMesh() unsigned v_size = (unsigned)m_vertices.size() * pitch; glBufferData(GL_ARRAY_BUFFER, v_size, NULL, GL_DYNAMIC_DRAW); size_t offset = 0; +#ifdef __EMSCRIPTEN__ + char* ptr = (char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, v_size, + GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); +#else char* ptr = (char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, v_size, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); +#endif v_size = 0; for (unsigned i = 0 ; i < m_vertices.size(); i++) { @@ -407,9 +412,15 @@ void SPMeshBuffer::uploadInstanceData() else { glBindBuffer(GL_ARRAY_BUFFER, m_ins_array[i]); +#ifdef __EMSCRIPTEN__ + void* ptr = glMapBufferRange(GL_ARRAY_BUFFER, 0, + m_ins_dat[i].size() * 44, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); +#else + void* ptr = glMapBufferRange(GL_ARRAY_BUFFER, 0, m_ins_dat[i].size() * 44, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); +#endif memcpy(ptr, m_ins_dat[i].data(), m_ins_dat[i].size() * 44); glUnmapBuffer(GL_ARRAY_BUFFER); glBindBuffer(GL_ARRAY_BUFFER, 0); diff --git a/src/graphics/sp/sp_texture_manager.cpp b/src/graphics/sp/sp_texture_manager.cpp index 307885f858c..4811b962a50 100644 --- a/src/graphics/sp/sp_texture_manager.cpp +++ b/src/graphics/sp/sp_texture_manager.cpp @@ -42,6 +42,12 @@ SPTextureManager::SPTextureManager() { m_max_threaded_load_obj.store(2); } +#ifdef __EMSCRIPTEN__ + //some browsers limit the number of web workers + if (m_max_threaded_load_obj.load() > 8) { + m_max_threaded_load_obj.store(8); + } +#endif m_max_threaded_load_obj.store(m_max_threaded_load_obj.load() + 1); for (unsigned i = 0; i < m_max_threaded_load_obj; i++) { diff --git a/src/input/input_manager.cpp b/src/input/input_manager.cpp index d59af49cde4..fc57a7d0c2e 100644 --- a/src/input/input_manager.cpp +++ b/src/input/input_manager.cpp @@ -109,7 +109,7 @@ InputManager::InputManager() : m_mode(BOOTSTRAP), m_device_manager->initialize(); m_master_player_only = false; -#if !defined(SERVER_ONLY) && !defined(__EMSCRIPTEN__) +#ifndef SERVER_ONLY #ifdef __SWITCH__ padConfigureInput(8, HidNpadStyleSet_NpadStandard); // Otherwise we report 'B' as 'A' (like Xbox controller) @@ -124,18 +124,20 @@ InputManager::InputManager() : m_mode(BOOTSTRAP), SDL_GetError()); } +#ifndef __EMSCRIPTEN__ if (SDL_InitSubSystem(SDL_INIT_HAPTIC) != 0) { Log::error("InputManager", "Failed to init SDL haptics: %s", SDL_GetError()); } +#endif #endif // SERVER_ONLY } // ----------------------------------------------------------------------------- void InputManager::addJoystick() { -#if !defined(SERVER_ONLY) && !defined(__EMSCRIPTEN__) +#ifndef SERVER_ONLY // When irrlicht device is reinitialized the joystick added event may be // lost, we look for them and add it back for (int i = 0; i < SDL_NumJoysticks(); i++) @@ -162,7 +164,7 @@ void InputManager::addJoystick() } // ----------------------------------------------------------------------------- -#if !defined(SERVER_ONLY) && !defined(__EMSCRIPTEN__) +#ifndef SERVER_ONLY // For CIrrDeviceSDL extern "C" void handle_joystick(SDL_Event& event) { @@ -258,14 +260,14 @@ void InputManager::update(float dt) it++; } -#if !defined(SERVER_ONLY) && !defined(__EMSCRIPTEN__) +#ifndef SERVER_ONLY for (auto& controller : m_sdl_controller) controller.second->checkPowerLevel(); #endif } //----------------------------------------------------------------------------- -#if !defined(SERVER_ONLY) && !defined(__EMSCRIPTEN__) +#ifndef SERVER_ONLY const irr::SEvent& InputManager::getEventForGamePad(unsigned i) const { auto it = m_sdl_controller.begin(); @@ -278,7 +280,7 @@ const irr::SEvent& InputManager::getEventForGamePad(unsigned i) const */ InputManager::~InputManager() { -#if !defined(SERVER_ONLY) && !defined(__EMSCRIPTEN__) +#ifndef SERVER_ONLY m_sdl_controller.clear(); #endif delete m_device_manager; diff --git a/src/input/input_manager.hpp b/src/input/input_manager.hpp index 7e3d2fecb82..4eedbe6fde3 100644 --- a/src/input/input_manager.hpp +++ b/src/input/input_manager.hpp @@ -78,7 +78,7 @@ class InputManager: public NoCopy void inputSensing(Input::InputType type, int deviceID, int btnID, Input::AxisDirection axisDirection, int value); -#if !defined(SERVER_ONLY) && !defined(__EMSCRIPTEN__) +#ifndef SERVER_ONLY std::map > m_sdl_controller; #endif @@ -109,7 +109,7 @@ class InputManager: public NoCopy /** Returns the ID of the player that plays with the keyboard, * or -1 if none. */ int getPlayerKeyboardID() const; -#if defined(SERVER_ONLY) || defined(__EMSCRIPTEN__) +#ifdef SERVER_ONLY size_t getGamepadCount() const { return 0; } #else /** Returns number of active connected gamepad (with SDL), notice the diff --git a/src/input/sdl_controller.cpp b/src/input/sdl_controller.cpp index b96a28448d8..19534d886c5 100644 --- a/src/input/sdl_controller.cpp +++ b/src/input/sdl_controller.cpp @@ -15,7 +15,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -#if !defined(SERVER_ONLY) && !defined(__EMSCRIPTEN__) +#ifndef SERVER_ONLY #include "input/sdl_controller.hpp" #include "guiengine/message_queue.hpp" diff --git a/wasm/fragments/fix_webgl.js b/wasm/fragments/fix_webgl.js new file mode 100644 index 00000000000..f2740a74b0d --- /dev/null +++ b/wasm/fragments/fix_webgl.js @@ -0,0 +1,4 @@ +/* INSERT +GLctx.getAttachedShaders\(\S+?\) +*/ + || [] \ No newline at end of file diff --git a/wasm/web/index.html b/wasm/web/index.html index 68f8d210da6..cd998d5cfbd 100644 --- a/wasm/web/index.html +++ b/wasm/web/index.html @@ -5,6 +5,6 @@ - + \ No newline at end of file From becfaa34e93441a8852c695fe1fe0d6f7aa58877 Mon Sep 17 00:00:00 2001 From: ading2210 Date: Wed, 29 May 2024 22:52:56 -0700 Subject: [PATCH 11/25] try to get gles3 working --- CMakeLists.txt | 2 +- src/guiengine/widgets/CGUIEditBox.cpp | 6 +++--- src/guiengine/widgets/spinner_widget.cpp | 2 ++ src/main.cpp | 2 +- wasm/pack_assets.sh | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index eb1ef6fdcd2..3d4e8f4a40d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,7 +105,7 @@ if(EMSCRIPTEN) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -sUSE_SDL=2 -fwasm-exceptions -sSUPPORT_LONGJMP=wasm -pthread") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -sUSE_SDL=2 -fwasm-exceptions -sSUPPORT_LONGJMP=wasm -pthread") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SOURCE_DIR}/wasm/prefix/lib/ -sASSERTIONS=1 -sSTACK_SIZE=30000000 -sFULL_ES2 -sUSE_SDL_MIXER=2 -sINITIAL_MEMORY=512MB -sWASM_BIGINT -sALLOW_MEMORY_GROWTH -lcrypto -fwasm-exceptions") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SOURCE_DIR}/wasm/prefix/lib/ -sENVIRONMENT=web,worker -sASSERTIONS=1 -sSTACK_SIZE=30000000 -sMIN_WEBGL_VERSION=2 -sFULL_ES2 -sFULL_ES3 -sUSE_SDL_MIXER=2 -sINITIAL_MEMORY=512MB -sWASM_BIGINT -lcrypto -fwasm-exceptions") if(CMAKE_BUILD_TYPE MATCHES Debug) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --profiling") diff --git a/src/guiengine/widgets/CGUIEditBox.cpp b/src/guiengine/widgets/CGUIEditBox.cpp index 58848e18f8f..865997f24e1 100644 --- a/src/guiengine/widgets/CGUIEditBox.cpp +++ b/src/guiengine/widgets/CGUIEditBox.cpp @@ -244,7 +244,7 @@ CGUIEditBox::~CGUIEditBox() if (GUIEngine::ScreenKeyboard::shouldUseScreenKeyboard() && GUIEngine::ScreenKeyboard::hasSystemScreenKeyboard()) Android_toggleOnScreenKeyboard(false, 0, 0); -#elif defined(_IRR_COMPILE_WITH_SDL_DEVICE_) && !defined(__EMSCRIPTEN__) +#elif defined(_IRR_COMPILE_WITH_SDL_DEVICE_) if (SDL_IsTextInputActive()) SDL_StopTextInput(); #endif @@ -372,7 +372,7 @@ bool CGUIEditBox::OnEvent(const SEvent& event) MouseMarking = false; setTextMarkers(0,0); } -#if !defined(ANDROID) && defined(_IRR_COMPILE_WITH_SDL_DEVICE_) && !defined(__EMSCRIPTEN__) +#if !defined(ANDROID) && defined(_IRR_COMPILE_WITH_SDL_DEVICE_) if (SDL_IsTextInputActive()) SDL_StopTextInput(); #endif @@ -1382,7 +1382,7 @@ void CGUIEditBox::calculateScrollPos() // todo: adjust scrollbar // calculate the position of input composition window -#if !defined(ANDROID) && !defined(__EMSCRIPTEN__) && defined(_IRR_COMPILE_WITH_SDL_DEVICE_) +#if !defined(ANDROID) && defined(_IRR_COMPILE_WITH_SDL_DEVICE_) SDL_Rect rect; rect.x = CurrentTextRect.UpperLeftCorner.X + m_cursor_distance - 1; rect.y = CurrentTextRect.UpperLeftCorner.Y; diff --git a/src/guiengine/widgets/spinner_widget.cpp b/src/guiengine/widgets/spinner_widget.cpp index 17d10af3fdf..a3a42d1462d 100644 --- a/src/guiengine/widgets/spinner_widget.cpp +++ b/src/guiengine/widgets/spinner_widget.cpp @@ -459,9 +459,11 @@ stringw SpinnerWidget::getStringValue() const return text; } else +#ifndef __EMSCRIPTEN__ { assert(false); } +#endif /** To avoid compiler warnings about missing return statements. */ return ""; } diff --git a/src/main.cpp b/src/main.cpp index d1330be8201..3b54352517b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -309,7 +309,7 @@ void runUnitTests(); void gamepadVisualisation() { -#if !defined(SERVER_ONLY) && !defined(__EMSCRIPTEN__) +#ifndef SERVER_ONLY input_manager = new InputManager(); #define GAMEPAD_COUNT 8 // const won't work diff --git a/wasm/pack_assets.sh b/wasm/pack_assets.sh index 10737eef077..8b14a1297a4 100755 --- a/wasm/pack_assets.sh +++ b/wasm/pack_assets.sh @@ -15,4 +15,4 @@ fi ASSETS_DIR="$(realpath "$1")" tar -cf - -C "$SRC_DIR/data" . | gzip -9 - > "$WEB_DIR/game/data.tar.gz" -tar -cf - -C "$ASSETS_DIR" . | gzip -6 - > "$WEB_DIR/game/assets.tar.gz" \ No newline at end of file +tar -cf - -C "$ASSETS_DIR" . | gzip -3 - > "$WEB_DIR/game/assets.tar.gz" \ No newline at end of file From 92635ab8496125cd463207d86ca51a00c67c74f2 Mon Sep 17 00:00:00 2001 From: ading2210 Date: Thu, 30 May 2024 03:44:57 -0400 Subject: [PATCH 12/25] add idb cache for data and assets --- src/graphics/central_settings.cpp | 4 -- wasm/build_deps.sh | 2 +- wasm/pack_assets.sh | 2 +- wasm/run_server.py | 7 ++- wasm/web/script.js | 98 +++++++++++++++++++++++++++---- 5 files changed, 96 insertions(+), 17 deletions(-) diff --git a/src/graphics/central_settings.cpp b/src/graphics/central_settings.cpp index 40754583ac0..00950ae2453 100644 --- a/src/graphics/central_settings.cpp +++ b/src/graphics/central_settings.cpp @@ -358,12 +358,8 @@ bool CentralVideoSettings::isARBGeometryShadersUsable() const bool CentralVideoSettings::isARBUniformBufferObjectUsable() const { -#if 0 - return false; -#else return hasUBO || (m_gl_major_version > 3 || (m_gl_major_version == 3 && m_gl_minor_version >= 1)); -#endif } bool CentralVideoSettings::isARBExplicitAttribLocationUsable() const diff --git a/wasm/build_deps.sh b/wasm/build_deps.sh index 6c14b9f73bb..89468efe268 100755 --- a/wasm/build_deps.sh +++ b/wasm/build_deps.sh @@ -135,7 +135,7 @@ build_harfbuzz() { clone_repo "https://github.com/harfbuzz/harfbuzz" 8.5.0 "$SRC_DIR" cd "$SRC_DIR" - emconfigure ./autogen.sh + NOCONFIGURE=1 ./autogen.sh emconfigure ./configure --host=none-linux --prefix="$PREFIX" --disable-shared PKG_CONFIG_PATH="$LIB/pkgconfig" emmake make -j$CORE_COUNT make install diff --git a/wasm/pack_assets.sh b/wasm/pack_assets.sh index 8b14a1297a4..e0c63062dc6 100755 --- a/wasm/pack_assets.sh +++ b/wasm/pack_assets.sh @@ -15,4 +15,4 @@ fi ASSETS_DIR="$(realpath "$1")" tar -cf - -C "$SRC_DIR/data" . | gzip -9 - > "$WEB_DIR/game/data.tar.gz" -tar -cf - -C "$ASSETS_DIR" . | gzip -3 - > "$WEB_DIR/game/assets.tar.gz" \ No newline at end of file +tar -cf - -C "$ASSETS_DIR" . | gzip -9 - > "$WEB_DIR/game/assets.tar.gz" \ No newline at end of file diff --git a/wasm/run_server.py b/wasm/run_server.py index f4004cb28bb..10c853b63ec 100644 --- a/wasm/run_server.py +++ b/wasm/run_server.py @@ -1,4 +1,9 @@ from http import server +import sys + +port = 8000 +if len(sys.argv) >= 1: + port = int(sys.argv[1]) class MyHTTPRequestHandler(server.SimpleHTTPRequestHandler): def end_headers(self): @@ -8,4 +13,4 @@ def end_headers(self): server.SimpleHTTPRequestHandler.end_headers(self) if __name__ == '__main__': - server.test(HandlerClass=MyHTTPRequestHandler) + server.test(HandlerClass=MyHTTPRequestHandler, port=port) diff --git a/wasm/web/script.js b/wasm/web/script.js index 878c7d0fa02..8904d80e0f9 100644 --- a/wasm/web/script.js +++ b/wasm/web/script.js @@ -1,14 +1,87 @@ import pako from "https://cdn.jsdelivr.net/npm/pako@2.1.0/+esm"; import jsUntar from "https://cdn.jsdelivr.net/npm/js-untar@2.0.0/+esm"; -async function extract_tar(url, fs_path) { +let db = null; +let db_name = "stk_db"; +let store_name = "stk_store"; + +function load_store() { + return new Promise((resolve, reject) => { + let request = indexedDB.open(db_name, 1); + request.onerror = (event) => { + reject(event); + }; + request.onsuccess = (event) => { + let db = event.target.result; + let transaction = db.transaction(store_name, "readwrite"); + let store = transaction.objectStore(store_name); + resolve(store); + }; + request.onupgradeneeded = (event) => { + let db = event.target.result; + db.createObjectStore(store_name); + }; + }); +} + +function check_db(key) { + return new Promise(async (resolve, reject) => { + let store = await load_store(); + let query = store.count(key); + query.onsuccess = () => { + resolve(query.result); + } + query.onerror = (event) => { + reject(event); + } + }); +} + +function read_db(key) { + return new Promise(async (resolve, reject) => { + let store = await load_store(); + let query = store.get(key); + query.onsuccess = () => { + resolve(query.result); + } + query.onerror = (event) => { + reject(event); + } + }); +} + +function write_db(key, data) { + return new Promise(async (resolve, reject) => { + let store = await load_store(); + let query = store.put(data, key); + query.onsuccess = () => { + resolve(); + } + query.onerror = (event) => { + reject(event); + } + }); +} + +async function extract_tar(url, fs_path, use_cache = false) { //download tar file from server and decompress - let r = await fetch(url); - let compressed = await r.arrayBuffer(); - let decompressed = pako.inflate(compressed); - let files = await jsUntar(decompressed.buffer); - - //save each file to the emscripten filesystem + let decompressed; + if (!use_cache || !await check_db(url)) { + let r = await fetch(url); + let compressed = await r.arrayBuffer(); + decompressed = pako.inflate(compressed).buffer; + compressed = null; + if (use_cache) { + console.log("saving to cache"); + await write_db(url, decompressed); + } + } + else { + decompressed = await read_db(url); + } + + //read the tar file and add to emscripten's fs + let files = await jsUntar(decompressed); for (let file of files) { let relative_path = file.name.substring(1); let out_path = fs_path + relative_path; @@ -21,21 +94,26 @@ async function extract_tar(url, fs_path) { else { let array = new Uint8Array(file.buffer); FS.writeFile(out_path, array); + file.buffer = null; } } } async function load_data() { console.log("downloading and extracting game data"); - await extract_tar("/game/data.tar.gz", "/data"); + await extract_tar("/game/data.tar.gz", "/data", true); console.log("downloading and extracting assets"); - await extract_tar("/game/assets.tar.gz", "/data"); + await extract_tar("/game/assets.tar.gz", "/data", true); console.log("done") } +async function main() { + await load_data(); +} + globalThis.pako = pako; globalThis.jsUntar = jsUntar; globalThis.load_data = load_data; Module["canvas"] = document.getElementById("canvas") -load_data(); \ No newline at end of file +main(); \ No newline at end of file From 59da74c0abd4f1a6686cf81f7962ad7f0bd38c0d Mon Sep 17 00:00:00 2001 From: ading2210 Date: Thu, 30 May 2024 05:10:56 -0400 Subject: [PATCH 13/25] force legacy graphics for now --- CMakeLists.txt | 2 +- .../source/Irrlicht/CIrrDeviceSDL.cpp | 4 +++ .../source/Irrlicht/COGLES2Driver.cpp | 3 ++ wasm/build.sh | 12 +++---- wasm/fragments/fix_webgl.js | 16 +++++++++- wasm/patch_js.py | 2 ++ wasm/web/index.html | 24 +++++++++++++- wasm/web/script.js | 31 ++++++++++++++++--- 8 files changed, 80 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d4e8f4a40d..ddcbcb9f598 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,7 +105,7 @@ if(EMSCRIPTEN) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -sUSE_SDL=2 -fwasm-exceptions -sSUPPORT_LONGJMP=wasm -pthread") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -sUSE_SDL=2 -fwasm-exceptions -sSUPPORT_LONGJMP=wasm -pthread") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SOURCE_DIR}/wasm/prefix/lib/ -sENVIRONMENT=web,worker -sASSERTIONS=1 -sSTACK_SIZE=30000000 -sMIN_WEBGL_VERSION=2 -sFULL_ES2 -sFULL_ES3 -sUSE_SDL_MIXER=2 -sINITIAL_MEMORY=512MB -sWASM_BIGINT -lcrypto -fwasm-exceptions") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SOURCE_DIR}/wasm/prefix/lib/ -sENVIRONMENT=web,worker -sASSERTIONS=1 -sSTACK_SIZE=30000000 -sMIN_WEBGL_VERSION=2 -sFULL_ES2 -sFULL_ES3 -sGL_FFP_ONLY -sUSE_SDL_MIXER=2 -lopenal -sINITIAL_MEMORY=512MB -sWASM_BIGINT -lcrypto -fwasm-exceptions") if(CMAKE_BUILD_TYPE MATCHES Debug) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --profiling") diff --git a/lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp b/lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp index 2d2022f32ed..c1e73fee8c9 100644 --- a/lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp +++ b/lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp @@ -500,7 +500,9 @@ bool CIrrDeviceSDL::createWindow() os::Printer::log( "Could not initialize display!" ); return false; } +#ifndef __EMSCRIPTEN__ update_swap_interval(CreationParams.SwapInterval); +#endif } else { @@ -539,7 +541,9 @@ void CIrrDeviceSDL::tryCreateOpenGLContext(u32 flags) else SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); +#ifndef __EMSCRIPTEN__ if (CreationParams.ForceLegacyDevice) +#endif goto legacy; #ifdef _IRR_COMPILE_WITH_OGLES2_ diff --git a/lib/irrlicht/source/Irrlicht/COGLES2Driver.cpp b/lib/irrlicht/source/Irrlicht/COGLES2Driver.cpp index dfc96b00ed0..5f9520b7185 100644 --- a/lib/irrlicht/source/Irrlicht/COGLES2Driver.cpp +++ b/lib/irrlicht/source/Irrlicht/COGLES2Driver.cpp @@ -82,6 +82,9 @@ namespace video egl_params.platform = CEGL_PLATFORM_DEFAULT; egl_params.window = ((struct android_app *)(params.PrivateData))->window; egl_params.display = NULL; +#elif defined(__EMSCRIPTEN__) + egl_params.platform = CEGL_PLATFORM_DEFAULT; + egl_params.display = NULL; #endif EglContext->init(egl_params); diff --git a/wasm/build.sh b/wasm/build.sh index 52d10a6574c..53027fc830d 100755 --- a/wasm/build.sh +++ b/wasm/build.sh @@ -3,20 +3,20 @@ set -e set -x +BUILD_TYPE="${1:-'Release'}" + CORE_COUNT="$(nproc --all)" BASE_DIR="$(realpath "$(dirname "$0")")" SRC_DIR="$(dirname "$BASE_DIR")" WEB_DIR="$BASE_DIR/web" -BUILD_DIR="$SRC_DIR/cmake_build" +BUILD_DIR="$SRC_DIR/cmake_build/$BUILD_TYPE" EMSDK_DIR="$BASE_DIR/emsdk" -BUILD_TYPE="${1:-'Release'}" - mkdir -p $BUILD_DIR cd $BUILD_DIR -source $EMSDK_DIR/emsdk_env.sh -emcmake cmake .. -DNO_SHADERC=on -DCMAKE_BUILD_TYPE=$BUILD_TYPE +source "$EMSDK_DIR/emsdk_env.sh" +emcmake cmake "$SRC_DIR" -DNO_SHADERC=on -DCMAKE_BUILD_TYPE=$BUILD_TYPE make -j$CORE_COUNT echo "copying wasm files" @@ -24,4 +24,4 @@ mkdir -p "$WEB_DIR/game" cp ./bin/* "$WEB_DIR/game/" echo "applying patches" -python3 $BASE_DIR/patch_js.py $BASE_DIR/fragments $WEB_DIR/game/supertuxkart.js +python3 "$BASE_DIR/patch_js.py" "$BASE_DIR/fragments" "$WEB_DIR/game/supertuxkart.js" diff --git a/wasm/fragments/fix_webgl.js b/wasm/fragments/fix_webgl.js index f2740a74b0d..86351d026d6 100644 --- a/wasm/fragments/fix_webgl.js +++ b/wasm/fragments/fix_webgl.js @@ -1,4 +1,18 @@ /* INSERT GLctx.getAttachedShaders\(\S+?\) */ - || [] \ No newline at end of file + || [] + +/* INSERT_BEFORE +GL.preDrawHandleClientVertexAttribBindings\([a-z]+?\) +*/ +try { + +/* INSERT +GL.preDrawHandleClientVertexAttribBindings\([a-z]+?\) +*/ + } catch (e) { + if (!GLctx.currentElementArrayBufferBinding) { + GLctx.bindBuffer(0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/, null); + } +} \ No newline at end of file diff --git a/wasm/patch_js.py b/wasm/patch_js.py index 65efcc5745a..f06606f9750 100644 --- a/wasm/patch_js.py +++ b/wasm/patch_js.py @@ -25,5 +25,7 @@ target_text = re.sub(patch_regex, patch_text, target_text) elif mode == "INSERT": target_text = re.sub("("+patch_regex+")", r'\1'+patch_text, target_text) + elif mode == "INSERT_BEFORE": + target_text = re.sub("("+patch_regex+")", patch_text+r'\1', target_text) target_path.write_text(target_text) \ No newline at end of file diff --git a/wasm/web/index.html b/wasm/web/index.html index cd998d5cfbd..8aef328720d 100644 --- a/wasm/web/index.html +++ b/wasm/web/index.html @@ -2,9 +2,31 @@ - + + +
+
+ +

Downloading game files...

+
\ No newline at end of file diff --git a/wasm/web/script.js b/wasm/web/script.js index 8904d80e0f9..43418158f54 100644 --- a/wasm/web/script.js +++ b/wasm/web/script.js @@ -5,17 +5,19 @@ let db = null; let db_name = "stk_db"; let store_name = "stk_store"; -function load_store() { +let start_button = document.getElementById("start_button"); +let status_text = document.getElementById("status_text"); + +function load_db() { + if (db) return db; return new Promise((resolve, reject) => { let request = indexedDB.open(db_name, 1); request.onerror = (event) => { reject(event); }; request.onsuccess = (event) => { - let db = event.target.result; - let transaction = db.transaction(store_name, "readwrite"); - let store = transaction.objectStore(store_name); - resolve(store); + db = event.target.result; + resolve(db); }; request.onupgradeneeded = (event) => { let db = event.target.result; @@ -24,6 +26,13 @@ function load_store() { }); } +async function load_store() { + await load_db(); + let transaction = db.transaction(store_name, "readwrite"); + let store = transaction.objectStore(store_name); + return store; +} + function check_db(key) { return new Promise(async (resolve, reject) => { let store = await load_store(); @@ -109,6 +118,18 @@ async function load_data() { async function main() { await load_data(); + start_button.onclick = start_game; + start_button.disabled = false; + status_text.textContent = "Ready"; +} + +function start_game() { + start_button.disabled = true; + status_text.textContent = "Initializing"; + setTimeout(() => { + run(); + status_text.textContent = "Running"; + }, 1); } globalThis.pako = pako; From 0a9e828ee25f87a1b7fb8fa8bfeac7025e651dc9 Mon Sep 17 00:00:00 2001 From: ading2210 Date: Thu, 30 May 2024 05:57:22 -0400 Subject: [PATCH 14/25] working audio --- src/audio/sfx_manager.cpp | 18 +++++++++--------- src/main.cpp | 28 +++++++++++++++++++--------- wasm/web/index.html | 11 ++++++----- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/src/audio/sfx_manager.cpp b/src/audio/sfx_manager.cpp index 66aeb38b69f..ec0d3244ad9 100644 --- a/src/audio/sfx_manager.cpp +++ b/src/audio/sfx_manager.cpp @@ -95,7 +95,7 @@ SFXManager::SFXManager() { // The thread is created even if there atm sfx are disabled // (since the user might enable it later). -#ifndef __SWITCH__ +#if !defined(__SWITCH__) && !defined(__EMSCRIPTEN__) m_thread = std::thread(std::bind(mainLoop, this)); #endif setMasterSFXVolume( UserConfigParams::m_sfx_volume ); @@ -111,7 +111,7 @@ SFXManager::SFXManager() */ SFXManager::~SFXManager() { -#if defined(ENABLE_SOUND) && !defined(__SWITCH__) +#if defined(ENABLE_SOUND) && !defined(__SWITCH__) && !defined(__EMSCRIPTEN__) if (UserConfigParams::m_enable_sound) { m_thread.join(); @@ -348,19 +348,19 @@ void SFXManager::mainLoop(void *obj) if (!UserConfigParams::m_enable_sound) return; -#ifndef __SWITCH__ +#if !defined(__SWITCH__) && !defined(__EMSCRIPTEN__) VS::setThreadName("SFXManager"); #endif SFXManager *me = (SFXManager*)obj; std::unique_lock ul = me->m_sfx_commands.acquireMutex(); -#ifdef __SWITCH__ +#if defined(__SWITCH__) || defined(__EMSCRIPTEN__) int iterCount = 0; #endif // Wait till we have an empty sfx in the queue while ( -#ifdef __SWITCH__ +#if defined(__SWITCH__) || defined(__EMSCRIPTEN__) // Don't spend too much time working on audio ++iterCount != 30 && !me->m_sfx_commands.getData().empty() #else @@ -374,7 +374,7 @@ void SFXManager::mainLoop(void *obj) // Wait in cond_wait for a request to arrive. The 'while' is necessary // since "spurious wakeups from the pthread_cond_wait ... may occur" // (pthread_cond_wait man page)! -#ifndef __SWITCH__ +#if !defined(__SWITCH__) && !defined(__EMSCRIPTEN__) while (empty) { me->m_condition_variable.wait(ul); @@ -387,7 +387,7 @@ void SFXManager::mainLoop(void *obj) if (current->m_command == SFX_EXIT) { delete current; -#ifdef __SWITCH__ +#if defined(__SWITCH__) || defined(__EMSCRIPTEN__) return; #else break; @@ -482,7 +482,7 @@ void SFXManager::mainLoop(void *obj) // need to keep the user waiting for STK to exit. me->setCanBeDeleted(); -#ifndef __SWITCH__ +#if !defined(__SWITCH__) && !defined(__EMSCRIPTEN__) // Clean up memory to avoid leak detection while(!me->m_sfx_commands.getData().empty()) { @@ -808,7 +808,7 @@ void SFXManager::update() // Wake up the sfx thread to handle all queued up audio commands. m_condition_variable.notify_one(); -#ifdef __SWITCH__ +#if defined(__SWITCH__) || defined(__EMSCRIPTEN__) mainLoop(this); #endif #endif diff --git a/src/main.cpp b/src/main.cpp index 3b54352517b..7b80921ba36 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2105,6 +2105,7 @@ void debugLoop() #endif // ---------------------------------------------------------------------------- +void endMainLoop(); #if defined(ANDROID) int android_main(int argc, char *argv[]) #elif defined(IOS_STK) @@ -2594,6 +2595,11 @@ int main(int argc, char *argv[]) #ifdef __EMSCRIPTEN__ auto mainLoopWrapper = []() { main_loop->run(); + if (main_loop->isAborted()) { + endMainLoop(); + emscripten_cancel_main_loop(); + exit(0); + } }; emscripten_set_main_loop(mainLoopWrapper, 0, 1); #else @@ -2610,6 +2616,18 @@ int main(int argc, char *argv[]) } /* Program closing...*/ + endMainLoop(); + +#ifdef IOS_STK + // App store may not like this, but this can happen if player uses keyboard to quit stk + exit(0); + return 0; +#else + return 0 ; +#endif +} // main + +void endMainLoop() { #ifdef ENABLE_WIIUSE if(wiimote_manager) @@ -2661,15 +2679,7 @@ int main(int argc, char *argv[]) socketExit(); nifmExit(); #endif - -#ifdef IOS_STK - // App store may not like this, but this can happen if player uses keyboard to quit stk - exit(0); - return 0; -#else - return 0 ; -#endif -} // main +} // ============================================================================ #ifdef WIN32 diff --git a/wasm/web/index.html b/wasm/web/index.html index 8aef328720d..d47b972fbdd 100644 --- a/wasm/web/index.html +++ b/wasm/web/index.html @@ -7,6 +7,10 @@ * { font-family: Arial, sans-serif; } + p { + font-size: 12px; + margin: 4px; + } #canvas { background-color: #222222; } @@ -14,11 +18,6 @@ display: flex; align-items: flex-start; } - #status_text { - font-size: 12px; - margin: 4px; - margin-left: 4px; - } @@ -28,5 +27,7 @@

Downloading game files...

+

This web port was made by ading2210.

+

The source code is located at github.com/ading2210/stk-code.

\ No newline at end of file From 74e4f35add63bfcc636b9f4749ac6d8dc24eae99 Mon Sep 17 00:00:00 2001 From: ading2210 Date: Thu, 30 May 2024 08:02:39 -0400 Subject: [PATCH 15/25] remove useless sleeps, add persistent config --- CMakeLists.txt | 7 +----- lib/irrlicht/source/Irrlicht/CWriteFile.cpp | 13 ++++++++++- src/audio/sfx_manager.cpp | 2 ++ src/config/user_config.cpp | 10 +++++++++ src/main_loop.cpp | 2 ++ wasm/web/script.js | 24 ++++++++++++++++++--- 6 files changed, 48 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ddcbcb9f598..cb919e3a263 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,7 +105,7 @@ if(EMSCRIPTEN) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -sUSE_SDL=2 -fwasm-exceptions -sSUPPORT_LONGJMP=wasm -pthread") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -sUSE_SDL=2 -fwasm-exceptions -sSUPPORT_LONGJMP=wasm -pthread") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SOURCE_DIR}/wasm/prefix/lib/ -sENVIRONMENT=web,worker -sASSERTIONS=1 -sSTACK_SIZE=30000000 -sMIN_WEBGL_VERSION=2 -sFULL_ES2 -sFULL_ES3 -sGL_FFP_ONLY -sUSE_SDL_MIXER=2 -lopenal -sINITIAL_MEMORY=512MB -sWASM_BIGINT -lcrypto -fwasm-exceptions") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SOURCE_DIR}/wasm/prefix/lib/ -sENVIRONMENT=web,worker -lidbfs.js -lwebsocket.js -sASSERTIONS=1 -sSTACK_SIZE=30000000 -sMIN_WEBGL_VERSION=2 -sFULL_ES2 -sFULL_ES3 -sGL_FFP_ONLY -sUSE_SDL_MIXER=2 -lopenal -sINITIAL_MEMORY=256MB -sALLOW_MEMORY_GROWTH -sWASM_BIGINT -lcrypto -fwasm-exceptions") if(CMAKE_BUILD_TYPE MATCHES Debug) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --profiling") @@ -901,11 +901,6 @@ if(MINGW) endif() endif() -if(EMSCRIPTEN) - target_compile_options(supertuxkart PRIVATE -sUSE_SDL=2) - target_compile_options(stkirrlicht PRIVATE -sUSE_SDL=2) -endif() - # Find LibGamerzilla library or build it if missing if (NOT APPLE) include(FindPkgConfig) diff --git a/lib/irrlicht/source/Irrlicht/CWriteFile.cpp b/lib/irrlicht/source/Irrlicht/CWriteFile.cpp index bcd5c5d720c..cccc3384695 100644 --- a/lib/irrlicht/source/Irrlicht/CWriteFile.cpp +++ b/lib/irrlicht/source/Irrlicht/CWriteFile.cpp @@ -7,6 +7,11 @@ #include "utils/file_utils.hpp" #include + +#if defined(__EMSCRIPTEN__) +#include +#endif + namespace irr { namespace io @@ -48,7 +53,13 @@ s32 CWriteFile::write(const void* buffer, u32 sizeToWrite) if (!isOpen()) return 0; - return (s32)fwrite(buffer, 1, sizeToWrite, File); + s32 ret = fwrite(buffer, 1, sizeToWrite, File); +#ifdef __EMSCRIPTEN__ + EM_ASM( + globalThis.sync_idbfs(); + ); +#endif + return ret; } diff --git a/src/audio/sfx_manager.cpp b/src/audio/sfx_manager.cpp index ec0d3244ad9..26e5cb9585c 100644 --- a/src/audio/sfx_manager.cpp +++ b/src/audio/sfx_manager.cpp @@ -464,6 +464,7 @@ void SFXManager::mainLoop(void *obj) current = NULL; PROFILER_POP_CPU_MARKER(); PROFILER_PUSH_CPU_MARKER("yield", 0, 0, 255); +#ifndef __EMSCRIPTEN__ if (empty_queue && me->sfxAllowed()) { // Wait some time to let other threads run, then queue an @@ -473,6 +474,7 @@ void SFXManager::mainLoop(void *obj) t = StkTime::getMonoTimeMs() - t; me->queue(SFX_UPDATE, (SFXBase*)NULL, float(t / 1000.0)); } +#endif ul = me->m_sfx_commands.acquireMutex(); PROFILER_POP_CPU_MARKER(); } // while diff --git a/src/config/user_config.cpp b/src/config/user_config.cpp index 31df64bae01..befcdfeda36 100644 --- a/src/config/user_config.cpp +++ b/src/config/user_config.cpp @@ -50,6 +50,10 @@ static std::vector all_params; #include #include +#if defined(__EMSCRIPTEN__) +#include +#endif + const int UserConfig::m_current_config_version = 8; @@ -749,6 +753,12 @@ void UserConfig::saveConfig() configfile.close(); file_manager->removeFile(filename); FileUtils::renameU8Path(filename + "new", filename); + +#ifdef __EMSCRIPTEN__ + EM_ASM( + globalThis.sync_idbfs(); + ); +#endif } catch (std::runtime_error& e) { diff --git a/src/main_loop.cpp b/src/main_loop.cpp index 3374074f832..48437585557 100644 --- a/src/main_loop.cpp +++ b/src/main_loop.cpp @@ -720,6 +720,7 @@ void MainLoop::run() (irr_driver->isRecording() && UserConfigParams::m_limit_game_fps) ? UserConfigParams::m_record_fps : UserConfigParams::m_max_fps; +#ifndef __EMSCRIPTEN__ // Throttle fps if more than maximum, which can reduce // the noise the fan on a graphics card makes. // No need to throttle if vsync is on (m_swap_interval == 1) as @@ -736,6 +737,7 @@ void MainLoop::run() std::this_thread::sleep_for(wait_time_ns); PROFILER_POP_CPU_MARKER(); } +#endif PROFILER_POP_CPU_MARKER(); // MainLoop pop PROFILER_SYNC_FRAME(); diff --git a/wasm/web/script.js b/wasm/web/script.js index 43418158f54..2a5c0e03678 100644 --- a/wasm/web/script.js +++ b/wasm/web/script.js @@ -4,6 +4,7 @@ import jsUntar from "https://cdn.jsdelivr.net/npm/js-untar@2.0.0/+esm"; let db = null; let db_name = "stk_db"; let store_name = "stk_store"; +let idbfs_mount = null; let start_button = document.getElementById("start_button"); let status_text = document.getElementById("status_text"); @@ -116,9 +117,24 @@ async function load_data() { console.log("done") } +async function load_idbfs() { + idbfs_mount = FS.mount(IDBFS, {}, "/home/web_user").mount; + await sync_idbfs(true); +} + +function sync_idbfs(populate = false) { + return new Promise((resolve, reject) => { + idbfs_mount.type.syncfs(idbfs_mount, populate, (err) => { + if (err) reject(err); + else resolve(); + }); + }) +} + async function main() { await load_data(); - start_button.onclick = start_game; + await load_idbfs(); + start_button.onclick = () => {requestAnimationFrame(start_game)}; start_button.disabled = false; status_text.textContent = "Ready"; } @@ -126,15 +142,17 @@ async function main() { function start_game() { start_button.disabled = true; status_text.textContent = "Initializing"; - setTimeout(() => { + requestAnimationFrame(() => { run(); status_text.textContent = "Running"; - }, 1); + sync_idbfs(); + }); } globalThis.pako = pako; globalThis.jsUntar = jsUntar; globalThis.load_data = load_data; +globalThis.sync_idbfs = sync_idbfs; Module["canvas"] = document.getElementById("canvas") main(); \ No newline at end of file From 1e86e18daf456c4c134717564bb4a5caa9abd934 Mon Sep 17 00:00:00 2001 From: ading2210 Date: Thu, 30 May 2024 09:31:22 -0400 Subject: [PATCH 16/25] split assets into 20mb chunks --- wasm/pack_assets.sh | 31 +++++++++++++++++++-- wasm/web/404.html | 10 +++++++ wasm/web/_headers | 3 ++ wasm/web/favicon.ico | Bin 0 -> 5430 bytes wasm/web/index.html | 2 ++ wasm/web/script.js | 64 +++++++++++++++++++++++++++++++++++++++---- 6 files changed, 102 insertions(+), 8 deletions(-) create mode 100644 wasm/web/404.html create mode 100644 wasm/web/_headers create mode 100644 wasm/web/favicon.ico diff --git a/wasm/pack_assets.sh b/wasm/pack_assets.sh index e0c63062dc6..ef5381f5392 100755 --- a/wasm/pack_assets.sh +++ b/wasm/pack_assets.sh @@ -14,5 +14,32 @@ fi ASSETS_DIR="$(realpath "$1")" -tar -cf - -C "$SRC_DIR/data" . | gzip -9 - > "$WEB_DIR/game/data.tar.gz" -tar -cf - -C "$ASSETS_DIR" . | gzip -9 - > "$WEB_DIR/game/assets.tar.gz" \ No newline at end of file +create_manifest() { + local path="$1" + local file_name="$(basename "$path")" + local data_dir="$(dirname "$path")" + local size="$(du -b "$path" | cut -f1)" + local chunks="$(find "$data_dir" -name "$file_name.*" | sort)" + + echo "$size" + for chunk in $chunks; do + local chunk_name="$(basename "$chunk")" + local ending="$(echo "$chunk_name" | rev | cut -d'.' -f1 | rev)" + if [ "$ending" = "manifest" ]; then + continue + fi + echo "$chunk_name" + done +} + +pack_dir() { + local source_dir="$1" + local out_path="$2" + tar -cf - -C "$source_dir" . | gzip -9 - > "$out_path" + split -b 20m --numeric-suffixes "$out_path" "$out_path." + create_manifest "$out_path" > "$out_path.manifest" + rm "$out_path" +} + +pack_dir "$SRC_DIR/data" "$WEB_DIR/game/data.tar.gz" +pack_dir "$ASSETS_DIR" "$WEB_DIR/game/assets.tar.gz" \ No newline at end of file diff --git a/wasm/web/404.html b/wasm/web/404.html new file mode 100644 index 00000000000..950973a5c5d --- /dev/null +++ b/wasm/web/404.html @@ -0,0 +1,10 @@ + + + + 404 + + +

404

+

Not found.

+ + \ No newline at end of file diff --git a/wasm/web/_headers b/wasm/web/_headers new file mode 100644 index 00000000000..6e0d001fdaf --- /dev/null +++ b/wasm/web/_headers @@ -0,0 +1,3 @@ +/* + Cross-Origin-Opener-Policy: same-origin + Cross-Origin-Embedder-Policy: require-corp \ No newline at end of file diff --git a/wasm/web/favicon.ico b/wasm/web/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..43d0440228fdfdaaa6c3f103cd2428a01149e1bc GIT binary patch literal 5430 zcmeHKdr*|u75^3x1r~M}c3F0L?Scyi#U(t{fCZwWAZ{WOAu2wQ_bcJ$R;3lxqSZ!i zVhrsRBUQ9ORggzekV;`v9~mblQ=4X_mNresG;taxQ$vjP*K;h|c&&cIL;u z-?``BbIv{Io^ucciC`nh4&Q43Z+fJk_tt(>Y&qvD2WcYdR zMqy4r3Uhx0FSkzU)NM#u*oKVtr%|!x2)1q8^;vjW$Syk1&T^hy<`Vo|(h6+dvIQ|w z6}WJr8yZCy{5>y2r+Eu1m&;H|-z4-x>C_D;n^Pz$DQ>f|k+^Eq%5y5EqV`!+Jo56g zk(!!JJhjBzML0%iC7dRlgu6>4f~FrrS?PArUiGY?C#p=QL2T@*D zg1vioL91wn#%*J-WzTqH(!v?9)$Yyx?2U$(p!e1y)EJEIRh8Jea|hH)S=V@btZBZU zswdZ`nl3Uea$W@9efN(zf4&qN z-6<gLe&_?M|V)s}n6}TH&ocg+N_1mMl1pj18?QD{e-8eLIdGZ9r4g3Do`aF!t|% z2`>~CjwG*0`nyV{G?QMc@$9vx1sV+d7Q{p&F+LtEscx=Yn?^Nn6V;)UklFthe;pdc zAFf@4G3XLJm3?A;QaYWbk6At6pu{y}*@_E*FTjtS`^FCnt`FXjhs;tDeAO3*uun4Ba zHR7D_SmDqlo;NCkW%Uy*vhRNdG!Ivx92?X#c=|vDhclMO!;WyGMP(^`CkU;x~9V;njo3 zq4n@SY_ZqR*K26@%qK7>%qSuxcrMuf<)IjM)%_aZE~Z`2O*qe|LHsQ(H)XW#NYG!q(Wew=!$gJe(Gf8&^an3J7_ z#Dw^J7TG*n-WbRE%H-#1|5gI`X#I3f51|tg#uwqMSpx0G%TUIWZV^9+n-AHoJOMYw zF?c9`Cf<*zH`~tsp)&$>C7_v&=nM7{`(WYcxj$O!5) zMZ5X_o8jtM^Zt0U#-n}jsmNO#YuQlp_s3_|i+9WNIR;rS=N<;VIWO=V zX&Qb&8uesesIzFdM&J{m$#Yu&#~^U|ny*T9k^_#MSW z&lh8oZRhymI>~i!GBU^RVcExDt-#jJW%smNZL-?keKFT!u7~XZ;o)KQ^qd#-1m}dVB$6?K(gJQ1adP(=T_+iVL=sfP-*#7p8b}?6S zZ%6WF6Y)O^I`_i--uNwWpYkYVJm^gB9l1w-5Z`y}kN^LN81uVV3EUNg$`L`BN)RmQ urTkPi3R@Z(l~sZSRe~*g2_u3GpAvYy+v`iT7!eqv11 + SuperTuxKart + + -
-
- -

Downloading game files...

+
+
+ +

SuperTuxKart Wasm

+
+

This is an experimental port of SuperTuxKart to the browser using WebAssembly and Emscripten. Currently, everything works except for some rendering APIs and networking.

+

There is a 700MB initial download required to play, and the game will require around 1GB of memory.

+

This web port was made by ading2210, and the source code is located at github.com/ading2210/stk-code.

+

If you want to check on the status of this port, take a look at the corresponding pull request in the SuperTuxKart repository.

+
+ +

+
-

This web port was made by ading2210.

-

The source code is located at github.com/ading2210/stk-code.

\ No newline at end of file diff --git a/wasm/web/script.js b/wasm/web/script.js index 95bd978dfa0..5dcd272886b 100644 --- a/wasm/web/script.js +++ b/wasm/web/script.js @@ -8,6 +8,7 @@ let idbfs_mount = null; let start_button = document.getElementById("start_button"); let status_text = document.getElementById("status_text"); +let info_container = document.getElementById("info_container"); function load_db() { if (db) return db; @@ -103,24 +104,33 @@ async function write_db_chunks(key, data) { } async function download_chunks(url) { + let path = url.split("/"); + let filename = path.pop(); + let base_url = path.join("/"); + + status_text.textContent = `Downloading manifest for ${filename}...`; let r1 = await fetch(url + ".manifest"); let manifest = (await r1.text()).split("\n"); let size = parseInt(manifest.shift()); manifest.pop(); - let path = url.split("/"); - path.pop(); - let base_url = path.join("/"); - let offset = 0; let chunk = null; let array = new Uint8Array(size); + let chunk_count = manifest.length; + let current_chunk = 1; + while (chunk = manifest.shift()) { + let mb_progress = Math.floor(offset / (1024 ** 2)) + let mb_total = Math.floor(size / (1024 ** 2)) + status_text.textContent = `Downloading ${filename}... (chunk ${current_chunk}/${chunk_count}, ${mb_progress}/${mb_total}MiB)`; + let r2 = await fetch(base_url + "/" + chunk); let buffer = await r2.arrayBuffer(); let chunk_array = new Uint8Array(buffer); array.set(chunk_array, offset); - offset += chunk_array.length; + offset += chunk_array.length; + current_chunk++; } return array.buffer; @@ -130,11 +140,12 @@ async function extract_tar(url, fs_path, use_cache = false) { //download tar file from server and decompress let decompressed; if (!use_cache || !await check_db(url)) { + let filename = url.split("/").pop(); let compressed = await download_chunks(url); decompressed = pako.inflate(compressed); compressed = null; if (use_cache) { - console.log("saving to cache"); + status_text.textContent = `Saving ${filename} to the cache...`; await write_db_chunks(url, decompressed); } } @@ -162,11 +173,8 @@ async function extract_tar(url, fs_path, use_cache = false) { } async function load_data() { - console.log("downloading and extracting game data"); await extract_tar("/game/data.tar.gz", "/data", true); - console.log("downloading and extracting assets"); await extract_tar("/game/assets.tar.gz", "/data", true); - console.log("done") } async function load_idbfs() { @@ -183,28 +191,41 @@ function sync_idbfs(populate = false) { }) } +function wait_for_frame() { + return new Promise((resolve) => {requestAnimationFrame(resolve)}); +} + async function main() { - await load_data(); + globalThis.ready = true; await load_idbfs(); - start_button.onclick = () => {requestAnimationFrame(start_game)}; + start_button.onclick = start_game; start_button.disabled = false; - status_text.textContent = "Ready"; } -function start_game() { +async function start_game() { + status_text.textContent = "Loading game files..."; start_button.disabled = true; - status_text.textContent = "Initializing"; - requestAnimationFrame(() => { - run(); - status_text.textContent = "Running"; - sync_idbfs(); - }); + await load_data(); + await wait_for_frame(); + status_text.textContent = "Launching game..."; + + await wait_for_frame(); + run(); + info_container.style.zIndex = 0; + info_container.style.display = "none"; + sync_idbfs(); + + console.warn("Warning: Opening devtools may harm the game's performance."); } -globalThis.pako = pako; -globalThis.jsUntar = jsUntar; -globalThis.load_data = load_data; +Module["canvas"] = document.getElementById("canvas") +globalThis.main = main; globalThis.sync_idbfs = sync_idbfs; +globalThis.load_idbfs = load_idbfs; -Module["canvas"] = document.getElementById("canvas") -main(); \ No newline at end of file +let poll_runtime_interval = setInterval(() => { + if (globalThis.ready) { + main(); + clearInterval(poll_runtime_interval); + } +}, 100); \ No newline at end of file diff --git a/wasm/web/supertuxkart_64.png b/wasm/web/supertuxkart_64.png new file mode 100644 index 0000000000000000000000000000000000000000..6beb8e609b8c40c3a8dd2b751a14e75b1ca7db6b GIT binary patch literal 2627 zcmV-J3cU4+P)b9Ht< zKtU`pGA1V}ItB}2Vq&RDPF^!LS_cdsGCp)BE4ZAVdlwy4Zho)~6}k)+vkVod3lzc( z6}1c%s|yvR3>B^m6f`wAzY7#9EiWxEG9@T0vJ4eyXlh1CN~sGJ$_y1#RaQShLQ70d z9wR0=Iz1vLD7*_486F{HV`Oe`aambfL`6qEKS5kwUY!gTH#j@f)6+sjLttTIGBY)p z3=~jNQ_#@RPESyqo1A}uf_Zy;WoBo$3>Bda6_=QqJ3Kz&;o;of-MYNIy$u%E*VlD+ zcPA<>{{H^Q$H&dh&BhB9Yi(_~3lvyeT(7UM%FD}@WP z)Ya9Bi;L;79K{S3U|(QLPEW(c#Ds>1R(+Dl8z7~pr&d)~sjI8Dx3~56^?MH&VGR~@ z4Hd{08;A=OSQ#I#2oX#_J(Xz`qNJqIoET0kFo6;qU^hCb7ayO8hoC1dYD7mnBPg__ zrLTH=5*8cI#l@i*8nLsp;c;=3A|YR7XRW27yo(j7OBJbu7j%%I>%ts*lB9--kJBL~ zMh+L6Ut)bUIg2VU$|fp+dwaC4uD5V=v0h@>P*R+SO=%-3&6^_5Iz2~pjhlNFU5A~2 zovwjxDr}LYig!BH-{g&O6YT8mTy%ty86S9RYGN=oN+T(FVPl|OU#wkWbSp7nSwpTe zH`RfJ@S>vmt*zLmAN<3@;L_8xi;S*AM}tsQ!)0w;QW0^LsrLH%h^Mva=;*7$&f>f##-}JsK_uFy8GM(e$^h8X0000&bW%=J0Pi0X z7)cES0SL7~RBS9UBsjUKhSUhn@BXf$sQ2WJ^zPVv(`5dX`M>YG#l6wW{pjJ< ztEl(xjIHMH(&mvkr+WYZ2Czv)K~z}7?N()Q8)*{t+L9$>9NyrdcFlc6^k;M!a zS+Zhdk zQSedzmJcX$zhA<$E)&0^C}#qJ*BeAHw=h=?rA@3MX>$#7`MKR!E^lII-u{cTr+b+) zH-;Mp{%x~gm#A5w$dw?_;`P0jh~AiE8kY)zH~x11{Q18xEzFI;D6l)%0RDMTL5>7X z>>F>rb@t^y2>ID$QGWAXH+=Dd2X1&5MvjfFJN1uknUie;gSQ~$dVit-YRl!;0nGmd$Li}Pf}yVaDzZ$Y60oFq zwL+PvEY$O?X}G?*xuGG|(rLakTPw)&W%eC1_|e2WO|B}5AeGAW2>gnItn7IIg$rN4 zFL|#bZ?V9MuC|u?=5<|BU0CernmAb&_wy&u{p-Rzz1@WhhneF8RSosc4PmD@U8~ny zg=`GH`lZQpe|_`SbF1HRSj}7@;EJykeLhE5*x=>4Yz)14a@FMPfBsYRo4BW${)@D0^ zs4+%MGYAXucU4!VhN{Phqq9BH$QX)}2(|lKmNq#Jx>3#O<2YGIVu%N)c0m#1)zwvi zmaa@sP1HyN5bf<(XDDJthhJlF+e|SQ6hV++Y?sw2aMi$2-O|!E-ZOi08mAC7$xzf) zXF~zs?{ACNL^slE6sPTc` z$Sd%P@BDDh3ujNC_4!`-^-kSu+fV-@=wYxr^yVuVifZ+t4u7rY>l=e=0wlDP$exf@ z*turs%iFi#v;EAOGbe&u#-7J1D6oZSL_a8#$rmrW>85w1u_weaU59_yhRs?PAyJ?R z4M{^79LKdP(0g4zgU+#S!}=iBNK|gxM2u{j z8bPJWsHFih8uxf;ijfY%g8`GTKkU}{H4ek2<-daUCVYmF;gOA-V|yQebl+DUI_EY^ zd!1TM;UFLw#326+01h$FdR8BrcGuc9Hl0{LN3a0Khu5X|u^UYP@ub7%4mnu{Q3EhF zLJuGqd?6G9bTl5^Z3>V2HElMKP&_9=2CZv08;w@h1)cd|8D zM^g*r$DRS4R5jMu z*Z=tV@n@fqu3A)(LRj1w)RO{3(fhx-FFv7J^xlmniV2_OgwUSd9yQw6P@OrdfeW^H76@Z(F$|En`^;k^mHGdyh&zde9s?LD)}Q&QOxX6sh% z-tRth_|Q`icCOtKiO0Jq>>nvBFTA3$mvaFY+&tzJO;7Hp@f|y6dVl)N;h!9Os&f`@ zu8l Date: Wed, 26 Jun 2024 19:53:12 -0400 Subject: [PATCH 19/25] compress assets better --- CMakeLists.txt | 3 +- wasm/README.md | 15 ++++++--- wasm/pack_assets.sh | 30 +++++++++++++----- wasm/run_server.py | 2 +- wasm/web/index.html | 19 ++++++++---- wasm/web/script.js | 76 ++++++++++++++++++++++++--------------------- 6 files changed, 88 insertions(+), 57 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cb919e3a263..bb24d8b6e54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,8 +88,7 @@ if(EMSCRIPTEN) set(OGGVORBIS_VORBISFILE_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/libvorbisfile.a") set(OGGVORBIS_VORBIS_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/prefix/lib/libvorbis.a") - #todo: avoid hardcoding this path - set(PTHREAD_LIBRARY "/usr/share/emscripten/cache/sysroot/") + set(PTHREAD_LIBRARY "${CMAKE_SOURCE_DIR}/wasm/emsdk/upstream") set(USE_WIIUSE 0) set(USE_DNS_C 1) diff --git a/wasm/README.md b/wasm/README.md index 0c396bdb3f3..b53e1cde1df 100644 --- a/wasm/README.md +++ b/wasm/README.md @@ -35,14 +35,19 @@ wasm/build_deps.sh ``` wasm/build.sh ``` -4. Bundle the game data and assets: +4. Compress the assets using the script from the Android port: ``` -wasm/pack_assets.sh ../stk-assets +sudo apt install imagemagick vorbis-tools pngquant advancecomp libjpeg-progs optipng +android/generate_assets.sh +(cd android/assets/data && ./optimize_data.sh) ``` -5. Host a web server: +5. Bundle the game data and assets: ``` -cd wasm/web -python3 ../run_server.py +wasm/pack_assets.sh android/assets/data/ +``` +6. Host a web server: +``` +(cd wasm/web && python3 ../run_server.py) ``` ## Project Structure: diff --git a/wasm/pack_assets.sh b/wasm/pack_assets.sh index ef5381f5392..9c42927f445 100755 --- a/wasm/pack_assets.sh +++ b/wasm/pack_assets.sh @@ -6,13 +6,12 @@ set -x BASE_DIR="$(realpath "$(dirname "$0")")" SRC_DIR="$(dirname "$BASE_DIR")" WEB_DIR="$BASE_DIR/web" - -if [ ! "$1" ]; then - echo "you must specify the assets directory" - exit 1 -fi - ASSETS_DIR="$(realpath "$1")" +ASSETS_SCRIPT="$SRC_DIR/android/generate_assets.sh" + +LOW_QUALITY_DIR="$WEB_DIR/game/data_low" +MEDIUM_QUALITY_DIR="$WEB_DIR/game/data_mid" +HIGH_QUALITY_DIR="$WEB_DIR/game/data_high" create_manifest() { local path="$1" @@ -41,5 +40,20 @@ pack_dir() { rm "$out_path" } -pack_dir "$SRC_DIR/data" "$WEB_DIR/game/data.tar.gz" -pack_dir "$ASSETS_DIR" "$WEB_DIR/game/assets.tar.gz" \ No newline at end of file +generate_dir() { + local data_dir="$1" + local output_path="$2" + local texture_size="$3" + ASSETS_PATHS="$ASSETS_DIR" OUTPUT_PATH="$data_dir" TEXTURE_SIZE="$texture_size" $ASSETS_SCRIPT + (cd $data_dir/data && ./optimize_data.sh) + pack_dir "$data_dir/data" "$output_path" +} + +if [ ! "$ASSETS_DIR" ]; then + echo "assets not found" + exit 1 +fi + +generate_dir "$LOW_QUALITY_DIR" "$WEB_DIR/game/data_low.tar.gz" 256 +generate_dir "$MEDIUM_QUALITY_DIR" "$WEB_DIR/game/data_mid.tar.gz" 512 +generate_dir "$HIGH_QUALITY_DIR" "$WEB_DIR/game/data_high.tar.gz" 1024 \ No newline at end of file diff --git a/wasm/run_server.py b/wasm/run_server.py index 10c853b63ec..f0edc713891 100644 --- a/wasm/run_server.py +++ b/wasm/run_server.py @@ -2,7 +2,7 @@ import sys port = 8000 -if len(sys.argv) >= 1: +if len(sys.argv) >= 2: port = int(sys.argv[1]) class MyHTTPRequestHandler(server.SimpleHTTPRequestHandler): diff --git a/wasm/web/index.html b/wasm/web/index.html index e5628e4f1ad..c9bb7fe5541 100644 --- a/wasm/web/index.html +++ b/wasm/web/index.html @@ -25,7 +25,7 @@ font-family: Arial, sans-serif; box-sizing: border-box; } - p { + p, label, select { font-size: 12px; margin: 4px; } @@ -45,15 +45,16 @@ position: absolute; top: 50%; left: 50%; - width: 440px; - height: 260px; + width: 450px; + height: 290px; margin-left: -220px; - margin-top: -130px; + margin-top: -145px; z-index: 2; background-color: white; padding: 12px; padding-top: 6px; border-radius: 8px; + overflow-y: auto; } #header_bar { display: flex; @@ -85,12 +86,18 @@

SuperTuxKart Wasm

This is an experimental port of SuperTuxKart to the browser using WebAssembly and Emscripten. Currently, everything works except for some rendering APIs and networking.

-

There is a 700MB initial download required to play, and the game will require around 1GB of memory.

+

There is a 120MB initial download required to play, and the game will require around 500MB of memory.

This web port was made by ading2210, and the source code is located at github.com/ading2210/stk-code.

If you want to check on the status of this port, take a look at the corresponding pull request in the SuperTuxKart repository.

+ +
-

+

Loading game code...

diff --git a/wasm/web/script.js b/wasm/web/script.js index 5dcd272886b..959fea35083 100644 --- a/wasm/web/script.js +++ b/wasm/web/script.js @@ -5,10 +5,12 @@ let db = null; let db_name = "stk_db"; let store_name = "stk_store"; let idbfs_mount = null; +let data_version = 1; let start_button = document.getElementById("start_button"); let status_text = document.getElementById("status_text"); let info_container = document.getElementById("info_container"); +let quality_select = document.getElementById("quality_select"); function load_db() { if (db) return db; @@ -28,6 +30,25 @@ function load_db() { }); } +function request_async(request) { + return new Promise((resolve, reject) => { + request.onerror = (event) => { + reject(event); + }; + request.onsuccess = () => { + resolve(request.result); + }; + }); +} + +async function delete_db() { + if (db) { + db.close(); + db = null; + } + await request_async(indexedDB.deleteDatabase(db_name)); +} + async function load_store() { await load_db(); let transaction = db.transaction(store_name, "readwrite"); @@ -35,43 +56,19 @@ async function load_store() { return store; } -function check_db(key) { - return new Promise(async (resolve, reject) => { - let store = await load_store(); - let query = store.count(key); - query.onsuccess = () => { - resolve(query.result); - } - query.onerror = (event) => { - reject(event); - } - }); +async function check_db(key) { + let store = await load_store(); + return await request_async(store.count(key)); } -function read_db(key) { - return new Promise(async (resolve, reject) => { - let store = await load_store(); - let query = store.get(key); - query.onsuccess = () => { - resolve(query.result); - } - query.onerror = (event) => { - reject(event); - } - }); +async function read_db(key) { + let store = await load_store(); + return await request_async(store.get(key)); } -function write_db(key, data) { - return new Promise(async (resolve, reject) => { - let store = await load_store(); - let query = store.put(data, key); - query.onsuccess = () => { - resolve(); - } - query.onerror = (event) => { - reject(event); - } - }); +async function write_db(key, data) { + let store = await load_store(); + return await request_async(store.put(data, key)); } async function read_db_chunks(key) { @@ -142,6 +139,7 @@ async function extract_tar(url, fs_path, use_cache = false) { if (!use_cache || !await check_db(url)) { let filename = url.split("/").pop(); let compressed = await download_chunks(url); + status_text.textContent = `Decompressing ${filename}...`; decompressed = pako.inflate(compressed); compressed = null; if (use_cache) { @@ -173,8 +171,15 @@ async function extract_tar(url, fs_path, use_cache = false) { } async function load_data() { - await extract_tar("/game/data.tar.gz", "/data", true); - await extract_tar("/game/assets.tar.gz", "/data", true); + //check if we need to update the assets bundle + if (!await check_db("/version") || !(await read_db("/version") == data_version)) { + await delete_db(); + await write_db("/version", data_version); + } + + let quality = quality_select.value; + let data_url = `/game/data_${quality}.tar.gz`; + await extract_tar(data_url, "/data", true); } async function load_idbfs() { @@ -200,6 +205,7 @@ async function main() { await load_idbfs(); start_button.onclick = start_game; start_button.disabled = false; + status_text.innerText = ""; } async function start_game() { From 885ee292b444763f1949782f8222d25e3c624c02 Mon Sep 17 00:00:00 2001 From: Allen Ding Date: Wed, 11 Sep 2024 09:19:26 -0700 Subject: [PATCH 20/25] fix compilation issues on newest emsdk --- CMakeLists.txt | 2 +- lib/angelscript/projects/cmake/CMakeLists.txt | 4 +++- lib/enet/unix.c | 2 +- wasm/README.md | 15 +++------------ wasm/build.sh | 1 + wasm/fragments/fix_webgl.js | 2 +- 6 files changed, 10 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bb24d8b6e54..8bc6f304ea5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -684,7 +684,7 @@ int main() { return 0; } " NO_LIBATOMIC_NEEDED) -if (NOT NO_LIBATOMIC_NEEDED) +if (NOT NO_LIBATOMIC_NEEDED AND NOT EMSCRIPTEN) target_link_libraries(supertuxkart atomic) endif() diff --git a/lib/angelscript/projects/cmake/CMakeLists.txt b/lib/angelscript/projects/cmake/CMakeLists.txt index 42883d5e3ab..324c7874fea 100644 --- a/lib/angelscript/projects/cmake/CMakeLists.txt +++ b/lib/angelscript/projects/cmake/CMakeLists.txt @@ -191,7 +191,9 @@ endif() # Don't override the default library output path to avoid conflicts when building for multiple target platforms #set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/../../lib) -target_link_libraries(${ANGELSCRIPT_LIBRARY_NAME} Threads::Threads) +if(NOT EMSCRIPTEN) + target_link_libraries(${ANGELSCRIPT_LIBRARY_NAME} Threads::Threads) +endif() set_target_properties(${ANGELSCRIPT_LIBRARY_NAME} PROPERTIES VERSION ${PROJECT_VERSION}) diff --git a/lib/enet/unix.c b/lib/enet/unix.c index c10a3d99d99..3f4e952b4fc 100644 --- a/lib/enet/unix.c +++ b/lib/enet/unix.c @@ -53,7 +53,7 @@ #include #endif -#ifndef HAS_SOCKLEN_T +#if !defined(HAS_SOCKLEN_T) && !defined(__EMSCRIPTEN__) typedef int socklen_t; #endif diff --git a/wasm/README.md b/wasm/README.md index b53e1cde1df..16004d03c15 100644 --- a/wasm/README.md +++ b/wasm/README.md @@ -11,15 +11,11 @@ Working features: TODO: - Fix GLES 3 (maybe someone with more experience in webgl could help here) -- Webpage theming -- Better compression for assets - Lazy load assets during gameplay - Networking Caveats: -- The RAM usage is rather high because the assets are always loaded in memory - The performance isn't great, probably because the legacy renderer is still being used -- There is a large ~700MB download required immediately - Some options, like anything related to online multiplayer, may hang the game ## Building @@ -35,17 +31,12 @@ wasm/build_deps.sh ``` wasm/build.sh ``` -4. Compress the assets using the script from the Android port: +4. Compress and bundle the game data and assets: ``` sudo apt install imagemagick vorbis-tools pngquant advancecomp libjpeg-progs optipng -android/generate_assets.sh -(cd android/assets/data && ./optimize_data.sh) +wasm/pack_assets.sh ../stk-assets ``` -5. Bundle the game data and assets: -``` -wasm/pack_assets.sh android/assets/data/ -``` -6. Host a web server: +5. Host a web server: ``` (cd wasm/web && python3 ../run_server.py) ``` diff --git a/wasm/build.sh b/wasm/build.sh index 53027fc830d..92858ed0a4c 100755 --- a/wasm/build.sh +++ b/wasm/build.sh @@ -16,6 +16,7 @@ mkdir -p $BUILD_DIR cd $BUILD_DIR source "$EMSDK_DIR/emsdk_env.sh" +embuilder build sdl2 sdl2_ttf sdl2_image sdl2_image_jpg sdl2_image_png emcmake cmake "$SRC_DIR" -DNO_SHADERC=on -DCMAKE_BUILD_TYPE=$BUILD_TYPE make -j$CORE_COUNT diff --git a/wasm/fragments/fix_webgl.js b/wasm/fragments/fix_webgl.js index 86351d026d6..a46ed7dc7ee 100644 --- a/wasm/fragments/fix_webgl.js +++ b/wasm/fragments/fix_webgl.js @@ -11,7 +11,7 @@ try { /* INSERT GL.preDrawHandleClientVertexAttribBindings\([a-z]+?\) */ - } catch (e) { + } catch (e) { //note: i don't know if this patch has any side effects. it seems to work for now even though i don't really understand why if (!GLctx.currentElementArrayBufferBinding) { GLctx.bindBuffer(0x8893 /*GL_ELEMENT_ARRAY_BUFFER*/, null); } From e50c523f6c5c9a9f7cd3d8fed26ea6f6517d954e Mon Sep 17 00:00:00 2001 From: Allen Ding Date: Wed, 11 Sep 2024 10:07:17 -0700 Subject: [PATCH 21/25] fix crash with memory access out of bounds in tracks and gp screen --- src/states_screens/tracks_and_gp_screen.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/states_screens/tracks_and_gp_screen.cpp b/src/states_screens/tracks_and_gp_screen.cpp index a8ab6542edd..a82bb915b5f 100644 --- a/src/states_screens/tracks_and_gp_screen.cpp +++ b/src/states_screens/tracks_and_gp_screen.cpp @@ -89,7 +89,8 @@ void TracksAndGPScreen::eventCallback(Widget* widget, const std::string& name, if (track) { // In favorite edit mode, switch the status of the selected track - if (getWidget("favorite")->getState()) + CheckBoxWidget* favorite_cb = getWidget("favorite"); + if (favorite_cb != NULL && favorite_cb->getState()) { if(PlayerManager::getCurrentPlayer()->isFavoriteTrack(track->getIdent())) PlayerManager::getCurrentPlayer()->removeFavoriteTrack(track->getIdent()); @@ -163,8 +164,9 @@ void TracksAndGPScreen::beforeAddingWidget() tabs->clearAllChildren(); CheckBoxWidget* favorite_cb = getWidget("favorite"); - assert( favorite_cb != NULL ); - favorite_cb->setState(false); + //assert( favorite_cb != NULL ); + if (favorite_cb != NULL) + favorite_cb->setState(false); const std::vector& groups = track_manager->getAllTrackGroups(); const int group_amount = (int)groups.size(); From 1e26980f887d31e21fdc6137ddaa5ba9f66aa781 Mon Sep 17 00:00:00 2001 From: Allen Ding Date: Tue, 3 Dec 2024 13:12:45 -0800 Subject: [PATCH 22/25] Revert "fix crash with memory access out of bounds in tracks and gp screen" This reverts commit e50c523f6c5c9a9f7cd3d8fed26ea6f6517d954e. --- src/states_screens/tracks_and_gp_screen.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/states_screens/tracks_and_gp_screen.cpp b/src/states_screens/tracks_and_gp_screen.cpp index bbe422d537b..124002d6ace 100644 --- a/src/states_screens/tracks_and_gp_screen.cpp +++ b/src/states_screens/tracks_and_gp_screen.cpp @@ -89,8 +89,7 @@ void TracksAndGPScreen::eventCallback(Widget* widget, const std::string& name, if (track) { // In favorite edit mode, switch the status of the selected track - CheckBoxWidget* favorite_cb = getWidget("favorite"); - if (favorite_cb != NULL && favorite_cb->getState()) + if (getWidget("favorite")->getState()) { if(PlayerManager::getCurrentPlayer()->isFavoriteTrack(track->getIdent())) PlayerManager::getCurrentPlayer()->removeFavoriteTrack(track->getIdent()); @@ -164,9 +163,8 @@ void TracksAndGPScreen::beforeAddingWidget() tabs->clearAllChildren(); CheckBoxWidget* favorite_cb = getWidget("favorite"); - //assert( favorite_cb != NULL ); - if (favorite_cb != NULL) - favorite_cb->setState(false); + assert( favorite_cb != NULL ); + favorite_cb->setState(false); const std::vector& groups = track_manager->getAllTrackGroups(); const int group_amount = (int)groups.size(); From 06fee78ad0e91f43f2f3c9018fb52d98afcf0578 Mon Sep 17 00:00:00 2001 From: Allen Ding Date: Tue, 3 Dec 2024 14:04:07 -0800 Subject: [PATCH 23/25] disable outdated opengl warning --- CMakeLists.txt | 2 +- src/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 545cfa61618..27509c251f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,7 +104,7 @@ if(EMSCRIPTEN) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -sUSE_SDL=2 -fwasm-exceptions -sSUPPORT_LONGJMP=wasm -pthread") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -sUSE_SDL=2 -fwasm-exceptions -sSUPPORT_LONGJMP=wasm -pthread") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SOURCE_DIR}/wasm/prefix/lib/ -sENVIRONMENT=web,worker -lidbfs.js -lwebsocket.js -sASSERTIONS=1 -sSTACK_SIZE=30000000 -sMIN_WEBGL_VERSION=2 -sFULL_ES2 -sFULL_ES3 -sGL_FFP_ONLY -sUSE_SDL_MIXER=2 -lopenal -sINITIAL_MEMORY=256MB -sALLOW_MEMORY_GROWTH -sWASM_BIGINT -lcrypto -fwasm-exceptions") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SOURCE_DIR}/wasm/prefix/lib/ -sENVIRONMENT=web,worker -lidbfs.js -lwebsocket.js -sASSERTIONS=1 -sSTACK_SIZE=30000000 -sMIN_WEBGL_VERSION=2 -sFULL_ES2 -sFULL_ES3 -sGL_FFP_ONLY -sUSE_SDL_MIXER=2 -lopenal -sINITIAL_MEMORY=768MB -sWASM_BIGINT -lcrypto -fwasm-exceptions") if(CMAKE_BUILD_TYPE MATCHES Debug) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --profiling") diff --git a/src/main.cpp b/src/main.cpp index 411843c79ea..0fdc21f78b1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2457,7 +2457,7 @@ int main(int argc, char *argv[]) } else if (!CVS->isGLSL()) { - #if !defined(MOBILE_STK) + #if !defined(MOBILE_STK) && !defined(__EMSCRIPTEN__) if (UserConfigParams::m_old_driver_popup) { #ifdef USE_GLES2 From 60e353d35421c8a83f95cfe342523d7e4a97f7b8 Mon Sep 17 00:00:00 2001 From: ading2210 Date: Fri, 31 Jan 2025 18:57:07 -0500 Subject: [PATCH 24/25] fix emscripten tcp support - working login and addon downloads --- wasm/fragments/force_wsproxy.js | 15 +++++++++++++++ wasm/web/script.js | 16 +++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 wasm/fragments/force_wsproxy.js diff --git a/wasm/fragments/force_wsproxy.js b/wasm/fragments/force_wsproxy.js new file mode 100644 index 00000000000..3890c64395f --- /dev/null +++ b/wasm/fragments/force_wsproxy.js @@ -0,0 +1,15 @@ +/* INSERT +var ?opts ?= ?undefined; +*/ +var parts = addr.split("/"); +if (!url.endsWith("/")) url += "/"; +url += parts[0] + ":" + port; + +/* REPLACE +url ?= ?SOCKFS\.websocketArgs\[['"]url['"]\]; +*/ +var parts = addr.split("/"); +url = Module.websocket.url; +if (!url.endsWith("/")) url += "/"; +url += parts[0] + ":" + port; + diff --git a/wasm/web/script.js b/wasm/web/script.js index 959fea35083..b78d2c07e2c 100644 --- a/wasm/web/script.js +++ b/wasm/web/script.js @@ -12,6 +12,8 @@ let status_text = document.getElementById("status_text"); let info_container = document.getElementById("info_container"); let quality_select = document.getElementById("quality_select"); +let syncing_fs = false; + function load_db() { if (db) return db; return new Promise((resolve, reject) => { @@ -183,13 +185,16 @@ async function load_data() { } async function load_idbfs() { - idbfs_mount = FS.mount(IDBFS, {}, "/home/web_user").mount; + idbfs_mount = FS.mount(IDBFS, {}, "/home").mount; await sync_idbfs(true); } function sync_idbfs(populate = false) { + if (syncing_fs) return; + syncing_fs = true; return new Promise((resolve, reject) => { idbfs_mount.type.syncfs(idbfs_mount, populate, (err) => { + syncing_fs = false; if (err) reject(err); else resolve(); }); @@ -200,7 +205,16 @@ function wait_for_frame() { return new Promise((resolve) => {requestAnimationFrame(resolve)}); } +function set_websocket_url(url) { + if (typeof Module.websocket === "undefined") + Module.websocket = {}; + if (typeof SOCKFS.websocketArgs !== "undefined") + SOCKFS.websocketArgs.url = url; + Module.websocket.url = url; +} + async function main() { + set_websocket_url("wss://anura.pro/"); globalThis.ready = true; await load_idbfs(); start_button.onclick = start_game; From 43d3673a765d2bc2d01adc29fc87e990b7c90a3d Mon Sep 17 00:00:00 2001 From: ading2210 Date: Fri, 31 Jan 2025 19:22:20 -0500 Subject: [PATCH 25/25] allow for a configurable websocket proxy --- .gitignore | 4 ---- wasm/.gitignore | 5 +++++ wasm/fragments/patch_ws.js | 10 ++++++++++ wasm/web/config_example.json | 4 ++++ wasm/web/script.js | 13 ++++++++++++- 5 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 wasm/.gitignore create mode 100644 wasm/fragments/patch_ws.js create mode 100644 wasm/web/config_example.json diff --git a/.gitignore b/.gitignore index c047abb4767..70be3aea0af 100644 --- a/.gitignore +++ b/.gitignore @@ -7,10 +7,6 @@ CMakeFiles/ stk-editor/ .vscode/ tags.* -wasm/build/ -wasm/prefix/ -wasm/emsdk/ -wasm/web/game # clangd .cache/ diff --git a/wasm/.gitignore b/wasm/.gitignore new file mode 100644 index 00000000000..1f7daf093ad --- /dev/null +++ b/wasm/.gitignore @@ -0,0 +1,5 @@ +/build/ +/prefix/ +/emsdk/ +/web/game +/web/config.json \ No newline at end of file diff --git a/wasm/fragments/patch_ws.js b/wasm/fragments/patch_ws.js new file mode 100644 index 00000000000..53388aa24dd --- /dev/null +++ b/wasm/fragments/patch_ws.js @@ -0,0 +1,10 @@ +/* REPLACE +ws ?= ?new WebSocketConstructor\(url, ?opts\) +*/ +if (globalThis.config.ws_enabled) { + ws = new WebSocket(url); +} +else { + console.error("websocket creation denied - disabled by config"); + throw new TypeError("ws disabled"); +} diff --git a/wasm/web/config_example.json b/wasm/web/config_example.json new file mode 100644 index 00000000000..995dd74cd44 --- /dev/null +++ b/wasm/web/config_example.json @@ -0,0 +1,4 @@ +{ + "ws_enabled": false, + "ws_proxy": "wss://example.com/" +} \ No newline at end of file diff --git a/wasm/web/script.js b/wasm/web/script.js index b78d2c07e2c..ccf14f43dfa 100644 --- a/wasm/web/script.js +++ b/wasm/web/script.js @@ -13,6 +13,7 @@ let info_container = document.getElementById("info_container"); let quality_select = document.getElementById("quality_select"); let syncing_fs = false; +let config = {}; function load_db() { if (db) return db; @@ -213,10 +214,20 @@ function set_websocket_url(url) { Module.websocket.url = url; } +async function load_config() { + let response = await fetch("/config.json"); + config = await response.json(); + globalThis.config = config; +} + async function main() { - set_websocket_url("wss://anura.pro/"); globalThis.ready = true; + await load_config(); await load_idbfs(); + if (config.ws_enabled) { + set_websocket_url(config.ws_proxy); + } + start_button.onclick = start_game; start_button.disabled = false; status_text.innerText = "";