From a5bbf0dbded3597b5a3e92935879b82d1c85dcd7 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 14 Mar 2026 22:11:36 +0100 Subject: [PATCH] Add option for experimental use of thread in Web Might not run well in certain browsers, requires rebuilding all dependencies for Web with `pthread` enabled. Disabled by default (for now). --- Source/Engine/Platform/Web/WebPlatform.h | 16 ++++++++++++++++ .../NvCloth/compiler/cmake/web/CMakeLists.txt | 2 ++ .../Flax.Build/Deps/Dependencies/NvCloth.cs | 2 ++ .../Tools/Flax.Build/Deps/Dependencies/PhysX.cs | 3 +++ .../Deps/Dependencies/basis_universal.cs | 2 ++ .../Flax.Build/Platforms/Web/WebToolchain.cs | 11 +++++++++++ 6 files changed, 36 insertions(+) diff --git a/Source/Engine/Platform/Web/WebPlatform.h b/Source/Engine/Platform/Web/WebPlatform.h index da01f9662..83d6f0e15 100644 --- a/Source/Engine/Platform/Web/WebPlatform.h +++ b/Source/Engine/Platform/Web/WebPlatform.h @@ -54,23 +54,39 @@ public: } FORCE_INLINE static int32 AtomicRead(int32 const volatile* dst) { +#ifdef __EMSCRIPTEN_PTHREADS__ int32 result; __atomic_load(dst, &result, __ATOMIC_SEQ_CST); return result; +#else + return *dst; +#endif } FORCE_INLINE static int64 AtomicRead(int64 const volatile* dst) { +#ifdef __EMSCRIPTEN_PTHREADS__ int64 result; __atomic_load(dst, &result, __ATOMIC_SEQ_CST); return result; +#else + return *dst; +#endif } FORCE_INLINE static void AtomicStore(int32 volatile* dst, int32 value) { +#ifdef __EMSCRIPTEN_PTHREADS__ __atomic_store(dst, &value, __ATOMIC_SEQ_CST); +#else + *dst = value; +#endif } FORCE_INLINE static void AtomicStore(int64 volatile* dst, int64 value) { +#ifdef __EMSCRIPTEN_PTHREADS__ __atomic_store(dst, &value, __ATOMIC_SEQ_CST); +#else + *dst = value; +#endif } FORCE_INLINE static uint64 GetCurrentThreadID() { diff --git a/Source/Platforms/Web/Binaries/Data/NvCloth/NvCloth/compiler/cmake/web/CMakeLists.txt b/Source/Platforms/Web/Binaries/Data/NvCloth/NvCloth/compiler/cmake/web/CMakeLists.txt index c4ef01d85..e1dc388c0 100644 --- a/Source/Platforms/Web/Binaries/Data/NvCloth/NvCloth/compiler/cmake/web/CMakeLists.txt +++ b/Source/Platforms/Web/Binaries/Data/NvCloth/NvCloth/compiler/cmake/web/CMakeLists.txt @@ -37,3 +37,5 @@ FIND_PACKAGE(PxShared REQUIRED) # Include all of the projects INCLUDE(NvCloth.cmake) + +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${NVCLOTH_CXX_FLAGS}") diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/NvCloth.cs b/Source/Tools/Flax.Build/Deps/Dependencies/NvCloth.cs index 3b4e0163f..2458eceec 100644 --- a/Source/Tools/Flax.Build/Deps/Dependencies/NvCloth.cs +++ b/Source/Tools/Flax.Build/Deps/Dependencies/NvCloth.cs @@ -154,6 +154,8 @@ namespace Flax.Deps.Dependencies case TargetPlatform.Web: cmakeArgs += " -DTARGET_BUILD_PLATFORM=web"; cmakeArgs += $" -DCMAKE_TOOLCHAIN_FILE=\"{EmscriptenSdk.Instance.CMakeToolchainPath}\""; + if (Configuration.WebThreads) + cmakeArgs += " -DNVCLOTH_CXX_FLAGS=\"-pthread\""; cmakeName = "web"; binariesPrefix = "lib"; diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/PhysX.cs b/Source/Tools/Flax.Build/Deps/Dependencies/PhysX.cs index b06862ffa..a636c3647 100644 --- a/Source/Tools/Flax.Build/Deps/Dependencies/PhysX.cs +++ b/Source/Tools/Flax.Build/Deps/Dependencies/PhysX.cs @@ -86,6 +86,9 @@ namespace Flax.Deps.Dependencies ConfigureCmakeSwitch(cmakeParams, "CMAKE_OSX_DEPLOYMENT_TARGET", Configuration.iOSMinVer); ConfigureCmakeSwitch(cmakeParams, "CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET", Configuration.iOSMinVer); break; + case TargetPlatform.Web: + ConfigureCmakeSwitch(cmakeParams, "PHYSX_CXX_FLAGS", Configuration.WebThreads ? "\"-pthread\"" : ""); + break; } // Save preset diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/basis_universal.cs b/Source/Tools/Flax.Build/Deps/Dependencies/basis_universal.cs index d072837c3..50f4aa84c 100644 --- a/Source/Tools/Flax.Build/Deps/Dependencies/basis_universal.cs +++ b/Source/Tools/Flax.Build/Deps/Dependencies/basis_universal.cs @@ -112,6 +112,8 @@ namespace Flax.Deps.Dependencies foreach (var define in defines) cmakeArgs += $"-D{define.Key}={define.Value} "; } + if (platform == TargetPlatform.Web && Configuration.WebThreads) + cmakeArgs += "-pthread "; cmakeArgs += "\""; var depsFolder = GetThirdPartyFolder(options, platform, architecture); diff --git a/Source/Tools/Flax.Build/Platforms/Web/WebToolchain.cs b/Source/Tools/Flax.Build/Platforms/Web/WebToolchain.cs index b10a3b272..26eb039d1 100644 --- a/Source/Tools/Flax.Build/Platforms/Web/WebToolchain.cs +++ b/Source/Tools/Flax.Build/Platforms/Web/WebToolchain.cs @@ -16,6 +16,12 @@ namespace Flax.Build /// [CommandLine("webInitialMemory", "", "Specifies the initial memory size (in MB) to use by Web app.")] public static int WebInitialMemory = 32; + + /// + /// Enables pthreads support for multithreading using SharedArrayBuffer in browsers. Changing it requires rebuilding deps for Web. + /// + [CommandLine("webThreads", "0/1", "Enables pthreads support for multithreading using SharedArrayBuffer in browsers. Changing it requires rebuilding deps for Web.")] + public static bool WebThreads = false; } } @@ -94,6 +100,8 @@ namespace Flax.Build.Platforms options.CompileEnv.PreprocessorDefinitions.Add("PLATFORM_WEB"); options.CompileEnv.PreprocessorDefinitions.Add("PLATFORM_UNIX"); options.CompileEnv.PreprocessorDefinitions.Add("__EMSCRIPTEN__"); + if (Configuration.WebThreads) + options.CompileEnv.PreprocessorDefinitions.Add("__EMSCRIPTEN_PTHREADS__"); options.CompileEnv.EnableExceptions = false; options.CompileEnv.CpuArchitecture = CpuArchitecture.SSE4_2; } @@ -163,6 +171,9 @@ namespace Flax.Build.Platforms args.Add("-fsanitize=undefined"); if (sanitizers == Sanitizer.None) args.Add("-fsanitize=null -fsanitize-minimal-runtime"); // Minimal Runtime + + if (Configuration.WebThreads) + args.Add("-pthread"); } ///