Skip to content

Commit 992d1e9

Browse files
authored
Proxy webgpu calls back to the main thread. NFC (emscripten-core#20124)
Until we have real multi-threaded webgpu support this is probable the best we can do. I tested these locally. I don't think we actually have WebGPU support in our CI yet, but that is something else I'm working on. Fixes: emscripten-core#19645
1 parent d67dc2a commit 992d1e9

6 files changed

+49
-14
lines changed

src/library.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ addToLibrary({
7373
assert(!implicit);
7474
#endif
7575
#if PTHREADS_DEBUG
76-
dbg(`Pthread ${ptrToString(_pthread_self())} called exit(), posting exitOnMainThread.`);
76+
dbg(`Pthread ${ptrToString(_pthread_self())} called exit(${status}), posting exitOnMainThread.`);
7777
#endif
7878
// When running in a pthread we propagate the exit back to the main thread
7979
// where it can decide if the whole process should be shut down or not.
@@ -83,7 +83,7 @@ addToLibrary({
8383
throw 'unwind';
8484
}
8585
#if PTHREADS_DEBUG
86-
err(`main thread called exit: keepRuntimeAlive=${keepRuntimeAlive()} (counter=${runtimeKeepaliveCounter})`);
86+
err(`main thread called exit(${status}): keepRuntimeAlive=${keepRuntimeAlive()} (counter=${runtimeKeepaliveCounter})`);
8787
#endif // PTHREADS_DEBUG
8888
#endif // PTHREADS
8989

src/library_html5_webgpu.js

+6
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,10 @@ var LibraryHTML5WebGPU = {
9090
{{{ html5_gpu.makeImportExport('render_bundle_encoder', 'RenderBundleEncoder') }}}
9191
{{{ html5_gpu.makeImportExport('render_bundle', 'RenderBundle') }}}
9292

93+
for (const key of Object.keys(LibraryHTML5WebGPU)) {
94+
if (typeof LibraryHTML5WebGPU[key] === 'function' && !(key + '__proxy' in LibraryHTML5WebGPU)) {
95+
LibraryHTML5WebGPU[key + '__proxy'] = 'sync';
96+
}
97+
}
98+
9399
addToLibrary(LibraryHTML5WebGPU);

src/library_webgpu.js

+11-7
Original file line numberDiff line numberDiff line change
@@ -2198,7 +2198,7 @@ var LibraryWebGPU = {
21982198
#endif
21992199

22002200
var bundles = Array.from(HEAP32.subarray(bundlesPtr >> 2, (bundlesPtr >> 2) + count),
2201-
function(id) { return WebGPU.mgrRenderBundle.get(id); });
2201+
(id) => WebGPU.mgrRenderBundle.get(id));
22022202
pass["executeBundles"](bundles);
22032203
},
22042204

@@ -2586,23 +2586,22 @@ var LibraryWebGPU = {
25862586
var device = WebGPU.mgrDevice.get(deviceId);
25872587
var context = WebGPU.mgrSurface.get(surfaceId);
25882588

2589-
25902589
#if ASSERTIONS
25912590
assert({{{ gpu.PresentMode.Fifo }}} ===
25922591
{{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSwapChainDescriptor.presentMode) }}});
25932592
#endif
25942593

25952594
var canvasSize = [
2596-
{{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSwapChainDescriptor.width) }}},
2597-
{{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSwapChainDescriptor.height) }}}
2595+
{{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSwapChainDescriptor.width) }}},
2596+
{{{ gpu.makeGetU32('descriptor', C_STRUCTS.WGPUSwapChainDescriptor.height) }}}
25982597
];
25992598

26002599
if (canvasSize[0] !== 0) {
2601-
context["canvas"]["width"] = canvasSize[0];
2600+
context["canvas"]["width"] = canvasSize[0];
26022601
}
26032602

26042603
if (canvasSize[1] !== 0) {
2605-
context["canvas"]["height"] = canvasSize[1];
2604+
context["canvas"]["height"] = canvasSize[1];
26062605
}
26072606

26082607
var configuration = {
@@ -2645,7 +2644,12 @@ for (var value in LibraryWebGPU.$WebGPU.FeatureName) {
26452644
}
26462645

26472646
for (const key of Object.keys(LibraryWebGPU)) {
2648-
LibraryWebGPU[key + '__i53abi'] = true;
2647+
if (typeof LibraryWebGPU[key] === 'function') {
2648+
LibraryWebGPU[key + '__i53abi'] = true;
2649+
if (!(key + '__proxy' in LibraryWebGPU)) {
2650+
LibraryWebGPU[key + '__proxy'] = 'sync';
2651+
}
2652+
}
26492653
}
26502654

26512655
autoAddDeps(LibraryWebGPU, '$WebGPU');

test/test_browser.py

+9
Original file line numberDiff line numberDiff line change
@@ -4664,9 +4664,18 @@ def test_webgl_simple_enable_extensions(self):
46644664
def test_webgpu_basic_rendering(self, args):
46654665
self.btest_exit('webgpu_basic_rendering.cpp', args=['-sUSE_WEBGPU'] + args)
46664666

4667+
@requires_graphics_hardware
4668+
@requires_threads
4669+
def test_webgpu_basic_rendering_pthreads(self):
4670+
self.btest_exit('webgpu_basic_rendering.cpp', args=['-sUSE_WEBGPU', '-pthread', '-sPROXY_TO_PTHREAD'])
4671+
46674672
def test_webgpu_get_device(self):
46684673
self.btest_exit('webgpu_get_device.cpp', args=['-sUSE_WEBGPU', '-sASSERTIONS', '--closure=1'])
46694674

4675+
@requires_threads
4676+
def test_webgpu_get_device_pthreads(self):
4677+
self.btest_exit('webgpu_get_device.cpp', args=['-sUSE_WEBGPU', '-pthread', '-sPROXY_TO_PTHREAD'])
4678+
46704679
# Tests the feature that shell html page can preallocate the typed array and place it
46714680
# to Module.buffer before loading the script page.
46724681
# In this build mode, the -sINITIAL_MEMORY=xxx option will be ignored.

test/webgpu_basic_rendering.cpp

+11-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,16 @@ void GetDevice(void (*callback)(wgpu::Device)) {
2626
}
2727
if (status == WGPURequestAdapterStatus_Unavailable) {
2828
printf("WebGPU unavailable; exiting cleanly\n");
29-
// exit(0) (rather than emscripten_force_exit(0)) ensures there is no dangling keepalive.
29+
// exit(0) (rather than emscripten_force_exit(0)) ensures there is
30+
// no dangling keepalive.
31+
#if _REENTRANT
32+
// FIXME: In multi-threaded builds this callback runs on the main
33+
// which seems to be causing the runtime to stay alive here and
34+
// results in the 99 being returned.
35+
emscripten_force_exit(0);
36+
#else
3037
exit(0);
38+
#endif
3139
}
3240
assert(status == WGPURequestAdapterStatus_Success);
3341

@@ -410,6 +418,7 @@ int main() {
410418
// emscripten_set_main_loop, and that should keep it alive until
411419
// emscripten_cancel_main_loop.
412420
//
413-
// This code is returned when the runtime exits unless something else sets it, like exit(0).
421+
// This code is returned when the runtime exits unless something else sets
422+
// it, like exit(0).
414423
return 99;
415424
}

test/webgpu_get_device.cpp

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
1-
#include <emscripten.h>
1+
#include <stdio.h>
2+
3+
#include <emscripten/em_asm.h>
24
#include <emscripten/html5_webgpu.h>
35

4-
int main() {
6+
__attribute__((constructor)) void init() {
57
EM_ASM({
68
Module['preinitializedWebGPUDevice'] = { this_is: 'a_dummy_object' };
79
});
8-
emscripten_webgpu_get_device();
10+
}
11+
12+
int main() {
13+
WGPUDevice d = emscripten_webgpu_get_device();
14+
printf("emscripten_webgpu_get_device: %p\n", d);
15+
return 0;
916
}

0 commit comments

Comments
 (0)