Skip to content

Commit 2df41d8

Browse files
committed
Merge pull request #104458 from marcosc90/fix-thread-collision-shape-3d
[Web] Use actual `PThread` pool size for `get_default_thread_pool_size()`
2 parents eb72ce2 + a7d18f5 commit 2df41d8

File tree

8 files changed

+50
-2
lines changed

8 files changed

+50
-2
lines changed

platform/web/detect.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ def configure(env: "SConsEnvironment"):
244244
env.Append(CCFLAGS=["-sUSE_PTHREADS=1"])
245245
env.Append(LINKFLAGS=["-sUSE_PTHREADS=1"])
246246
env.Append(LINKFLAGS=["-sDEFAULT_PTHREAD_STACK_SIZE=%sKB" % env["default_pthread_stack_size"]])
247-
env.Append(LINKFLAGS=["-sPTHREAD_POOL_SIZE=8"])
247+
env.Append(LINKFLAGS=["-sPTHREAD_POOL_SIZE='Module[\"emscriptenPoolSize\"]||8'"])
248248
env.Append(LINKFLAGS=["-sWASM_MEM_MAX=2048MB"])
249249
if not env["dlink_enabled"]:
250250
# Workaround https://github.com/emscripten-core/emscripten/issues/21844#issuecomment-2116936414.

platform/web/doc_classes/EditorExportPlatformWeb.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,17 @@
7979
- [b]Landscape:[/b] Forces a horizontal layout (wider than it is taller).
8080
- [b]Portrait:[/b] Forces a vertical layout (taller than it is wider).
8181
</member>
82+
<member name="variant/emscripten_pool_size" type="int" setter="" getter="">
83+
The number of threads that emscripten will allocate at startup. A smaller value will allocate fewer threads and consume fewer system resources, but you may run the risk of running out of threads in the pool and needing to allocate more threads at run time which may cause a deadlock.
84+
[b]Note:[/b] Some browsers have a hard cap on the number of threads that can be allocated, so it is best to be cautious and keep this number low.
85+
</member>
8286
<member name="variant/extensions_support" type="bool" setter="" getter="">
8387
If [code]true[/code] enables [GDExtension] support for this web build.
8488
</member>
89+
<member name="variant/godot_pool_size" type="int" setter="" getter="">
90+
Override for the default size of the [WorkerThreadPool]. This setting is used when [member ProjectSettings.threading/worker_pool/max_threads] size is set to -1 (which it is by default). This size must be smaller than [member variant/emscripten_pool_size] otherwise deadlocks may occur.
91+
When using threads this size needs to be large enough to accommodate features that rely on having a dedicated thread like [member ProjectSettings.physics/2d/run_on_separate_thread] or [member ProjectSettings.rendering/driver/threads/thread_model]. In general, it is best to ensure that this is at least 4 and is at least 2 or 3 less than [member variant/emscripten_pool_size].
92+
</member>
8593
<member name="variant/thread_support" type="bool" setter="" getter="">
8694
If [code]true[/code], the exported game will support threads. It requires [url=https://web.dev/articles/coop-coep]a "cross-origin isolated" website[/url], which may be difficult to set up and is limited for security reasons (such as not being able to communicate with third-party websites).
8795
If [code]false[/code], the exported game will not support threads. As a result, it is more prone to performance and audio issues, but will only require to be run on an HTTPS website.

platform/web/export/export_plugin.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,11 +143,13 @@ void EditorExportPlatformWeb::_fix_html(Vector<uint8_t> &p_html, const Ref<Edito
143143
config["canvasResizePolicy"] = p_preset->get("html/canvas_resize_policy");
144144
config["experimentalVK"] = p_preset->get("html/experimental_virtual_keyboard");
145145
config["focusCanvas"] = p_preset->get("html/focus_canvas_on_start");
146+
config["godotPoolSize"] = p_preset->get("variant/godot_pool_size");
146147
config["gdextensionLibs"] = libs;
147148
config["executable"] = p_name;
148149
config["args"] = args;
149150
config["fileSizes"] = p_file_sizes;
150151
config["ensureCrossOriginIsolationHeaders"] = (bool)p_preset->get("progressive_web_app/ensure_cross_origin_isolation_headers");
152+
config["emscriptenPoolSize"] = p_preset->get("variant/emscripten_pool_size");
151153

152154
String head_include;
153155
if (p_preset->get("html/export_icon")) {
@@ -360,6 +362,8 @@ void EditorExportPlatformWeb::get_export_options(List<ExportOption> *r_options)
360362

361363
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "variant/extensions_support"), false)); // GDExtension support.
362364
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "variant/thread_support"), false)); // Thread support (i.e. run with or without COEP/COOP headers).
365+
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "variant/emscripten_pool_size"), 8));
366+
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "variant/godot_pool_size"), 4));
363367
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "vram_texture_compression/for_desktop"), true)); // S3TC
364368
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "vram_texture_compression/for_mobile"), false)); // ETC or ETC2, depending on renderer
365369

platform/web/godot_js.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ extern void godot_js_os_fs_sync(void (*p_callback)());
5050
extern int godot_js_os_execute(const char *p_json);
5151
extern void godot_js_os_shell_open(const char *p_uri);
5252
extern int godot_js_os_hw_concurrency_get();
53+
extern int godot_js_os_thread_pool_size_get();
5354
extern int godot_js_os_has_feature(const char *p_ftr);
5455
extern int godot_js_pwa_cb(void (*p_callback)());
5556
extern int godot_js_pwa_update();

platform/web/js/engine/config.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,16 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused-
133133
* @type {Array.<string>}
134134
*/
135135
fileSizes: [],
136+
/**
137+
* @ignore
138+
* @type {number}
139+
*/
140+
emscriptenPoolSize: 8,
141+
/**
142+
* @ignore
143+
* @type {number}
144+
*/
145+
godotPoolSize: 4,
136146
/**
137147
* A callback function for handling Godot's ``OS.execute`` calls.
138148
*
@@ -259,6 +269,8 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused-
259269
this.serviceWorker = parse('serviceWorker', this.serviceWorker);
260270
this.gdextensionLibs = parse('gdextensionLibs', this.gdextensionLibs);
261271
this.fileSizes = parse('fileSizes', this.fileSizes);
272+
this.emscriptenPoolSize = parse('emscriptenPoolSize', this.emscriptenPoolSize);
273+
this.godotPoolSize = parse('godotPoolSize', this.godotPoolSize);
262274
this.args = parse('args', this.args);
263275
this.onExecute = parse('onExecute', this.onExecute);
264276
this.onExit = parse('onExit', this.onExit);
@@ -278,6 +290,7 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused-
278290
'thisProgram': this.executable,
279291
'noExitRuntime': false,
280292
'dynamicLibraries': [`${loadPath}.side.wasm`].concat(this.gdextensionLibs),
293+
'emscriptenPoolSize': this.emscriptenPoolSize,
281294
'instantiateWasm': function (imports, onSuccess) {
282295
function done(result) {
283296
onSuccess(result['instance'], result['module']);
@@ -350,6 +363,7 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused-
350363
'locale': locale,
351364
'persistentDrops': this.persistentDrops,
352365
'virtualKeyboard': this.experimentalVK,
366+
'godotPoolSize': this.godotPoolSize,
353367
'focusCanvas': this.focusCanvas,
354368
'onExecute': this.onExecute,
355369
'onExit': function (p_code) {

platform/web/js/libs/library_godot_os.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ const GodotConfig = {
6161
canvas_resize_policy: 2, // Adaptive
6262
virtual_keyboard: false,
6363
persistent_drops: false,
64+
godot_pool_size: 4,
6465
on_execute: null,
6566
on_exit: null,
6667

@@ -70,6 +71,7 @@ const GodotConfig = {
7071
GodotConfig.locale = p_opts['locale'] || GodotConfig.locale;
7172
GodotConfig.virtual_keyboard = p_opts['virtualKeyboard'];
7273
GodotConfig.persistent_drops = !!p_opts['persistentDrops'];
74+
GodotConfig.godot_pool_size = p_opts['godotPoolSize'];
7375
GodotConfig.on_execute = p_opts['onExecute'];
7476
GodotConfig.on_exit = p_opts['onExit'];
7577
if (p_opts['focusCanvas']) {
@@ -346,6 +348,17 @@ const GodotOS = {
346348
return concurrency < 2 ? concurrency : 2;
347349
},
348350

351+
godot_js_os_thread_pool_size_get__proxy: 'sync',
352+
godot_js_os_thread_pool_size_get__sig: 'i',
353+
godot_js_os_thread_pool_size_get: function () {
354+
if (typeof PThread === 'undefined') {
355+
// Threads aren't supported, so default to `1`.
356+
return 1;
357+
}
358+
359+
return GodotConfig.godot_pool_size;
360+
},
361+
349362
godot_js_os_download_buffer__proxy: 'sync',
350363
godot_js_os_download_buffer__sig: 'viiii',
351364
godot_js_os_download_buffer: function (p_ptr, p_size, p_name, p_mime) {

platform/web/os_web.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,14 @@ String OS_Web::get_unique_id() const {
148148
ERR_FAIL_V_MSG("", "OS::get_unique_id() is not available on the Web platform.");
149149
}
150150

151+
int OS_Web::get_default_thread_pool_size() const {
152+
#ifdef THREADS_ENABLED
153+
return godot_js_os_thread_pool_size_get();
154+
#else // No threads.
155+
return 1;
156+
#endif
157+
}
158+
151159
bool OS_Web::_check_internal_feature_support(const String &p_feature) {
152160
if (p_feature == "web") {
153161
return true;

platform/web/os_web.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ class OS_Web : public OS_Unix {
9191
int get_process_exit_code(const ProcessID &p_pid) const override;
9292
int get_processor_count() const override;
9393
String get_unique_id() const override;
94-
int get_default_thread_pool_size() const override { return 1; }
94+
int get_default_thread_pool_size() const override;
9595

9696
String get_executable_path() const override;
9797
Error shell_open(const String &p_uri) override;

0 commit comments

Comments
 (0)