Skip to content

Commit 56014a2

Browse files
authored
Enable pthreads on Emscripten (#17586)
* workerized RA * Workerized (non-async) web player, using OPFS This patch eliminates the need for asyncify and uses modern filesystem APIs instead of the deprecated, unmaintained BrowserFS. This is a WIP patch because it won't fully work until these two Emscripten PRs land and are released: emscripten-core/emscripten#23518 emscripten-core/emscripten#23021 The former fixes an offscreen canvas context recreation bug, and the latter adds an equivalent to BrowserFS's XHR filesystem (but without the hazardous running-XHR-on-the-main-thread problem). The biggest issue is that local storage of users who were using the old version of the webplayer will be gone when they switch to the new webplayer. I don't have a good story for converting the old BrowserFS IDBFS contents into the new OPFS filesystem (the move is worth doing because OPFS supports seeking and reading only bits of a file, and because BrowserFS is dead). I've kept around the old libretro webplayer under pkg/emscripten/libretro-classic, and with these make flags you can build a non-workerized RA that uses asyncify to sleep as before: make -f Makefile.emscripten libretro=$CORE HAVE_WORKER=0 HAVE_WASMFS=0 PTHREAD=0 HAVE_AL=1 I also moved the default directory for core content on emscripten to not be a subdirectory of the local filesystem mount, because it's confusing to have a subdirectory that's lazily fetched and not mirrored to the local storage. I think it won't impact existing users of the classic web player because they already have a retroarch.cfg in place. * Get fetchfs working without manifest support * makefile fixes * fix scaling, remove zip dependency * Support asset/cheats/etc downloaders for emscripten - Add http transfer support for emscripten - At the task_http level, not the net_http level --- so no netplay or webdav. - Change default paths to be more like other platforms - Gives us smaller bundles and a faster boot time - Had to work around a task queue bug on Emscripten - I made the smallest possible change to do it, but it may be better to fix in rthread.c * Load an emscripten file_packager package on first run If no ozone assets are present, load a libretro_minimal package created using Emscripten's built-in file packager. * updated readme, removed indexer from wasmfs libretro-web * Put back zip dependency, load asset bundle into opfs on first run * fix upload path * Remove unused function * easy testing setup for two multithreaded conditions 1. make PROXY_TO_PTHREAD=1 (slower) 2. make PROXY_TO_PTHREAD=0 (bad audio, because doesn't sleep in openal.c) * Remove condition on sleep in openal also make input_driver check existence of drv->axis, drv->button before calling them. * Fix resizing under EGL * Don't force config file path on emscripten * Add time.h include to netplay, default HAVE_NETPLAYDISCOVERY to 0 * Remove nearly all proxied joypad calls under emscripten * Fix file uploads under firefox * Fix safari API uses, but Safari still hangs in OPFS filesystem mount I think this can be fixed by moving the backend creation off the main thread. * Move filesystem init into emscripten C entry point * Setup filesystems off of main thread * re-set default player to async Also improve Safari compatibility under proxy-to-pthread condition * Safari upload file fixes * Remove some excess prints * Fix typo
1 parent 6ec4ffb commit 56014a2

File tree

26 files changed

+1739
-166
lines changed

26 files changed

+1739
-166
lines changed

Makefile.common

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,7 +1536,10 @@ ifeq ($(HAVE_GL_CONTEXT), 1)
15361536
endif
15371537

15381538
ifeq ($(HAVE_EMSCRIPTEN), 1)
1539-
OBJ += gfx/drivers_context/emscriptenegl_ctx.o
1539+
ifeq ($(HAVE_EGL), 1)
1540+
OBJ += gfx/drivers_context/emscriptenegl_ctx.o
1541+
endif
1542+
OBJ += gfx/drivers_context/emscriptenwebgl_ctx.o
15401543
endif
15411544

15421545
ifeq ($(HAVE_MALI_FBDEV), 1)
@@ -2203,11 +2206,16 @@ ifeq ($(HAVE_NETWORKING), 1)
22032206
$(LIBRETRO_COMM_DIR)/net/net_socket.o \
22042207
core_updater_list.o \
22052208
network/natt.o \
2206-
tasks/task_http.o \
22072209
tasks/task_netplay_lan_scan.o \
22082210
tasks/task_netplay_nat_traversal.o \
22092211
tasks/task_netplay_find_content.o
22102212

2213+
ifeq ($(HAVE_EMSCRIPTEN), 1)
2214+
OBJ += tasks/task_http_emscripten.o
2215+
else
2216+
OBJ += tasks/task_http.o
2217+
endif
2218+
22112219
ifeq ($(HAVE_MENU), 1)
22122220
OBJ += tasks/task_pl_thumbnail_download.o
22132221
endif

Makefile.emscripten

Lines changed: 71 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,18 @@ HAVE_PATCH = 1
1919
HAVE_DSP_FILTER = 1
2020
HAVE_VIDEO_FILTER = 1
2121
HAVE_OVERLAY = 1
22+
HAVE_NETWORKING = 1
23+
HAVE_LIBRETRODB = 1
24+
HAVE_COMPRESSION = 1
25+
HAVE_UPDATE_ASSETS = 1
26+
HAVE_ONLINE_UPDATER = 1
2227
HAVE_GLSL = 1
2328
HAVE_SCREENSHOTS = 1
2429
HAVE_REWIND = 1
2530
HAVE_AUDIOMIXER = 1
2631
HAVE_CC_RESAMPLER = 1
27-
HAVE_EGL = 1
32+
HAVE_EGL ?= 1
33+
HAVE_OPENGLES = 1
2834
HAVE_RJPEG = 0
2935
HAVE_RPNG = 1
3036
HAVE_EMSCRIPTEN = 1
@@ -48,6 +54,12 @@ HAVE_7ZIP = 1
4854
HAVE_BSV_MOVIE = 1
4955
HAVE_AL = 1
5056
HAVE_CHD ?= 0
57+
HAVE_WASMFS ?= 0
58+
PROXY_TO_PTHREAD ?= 0
59+
HAVE_NETPLAYDISCOVERY ?= 0
60+
61+
DEFINES += -DHAVE_NETWORKING -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_ASSETS -DHAVE_COMPRESSION
62+
DEFINES += -DHAVE_UPDATE_CORE_INFO
5163

5264
# WARNING -- READ BEFORE ENABLING
5365
# The rwebaudio driver is known to have several audio bugs, such as
@@ -61,12 +73,12 @@ HAVE_RWEBAUDIO = 0
6173
GL_DEBUG ?= 0
6274

6375
# enable javascript filesystem tracking
64-
FS_DEBUG = 1
76+
FS_DEBUG = 0
6577

6678
HAVE_OPENGLES ?= 1
6779
HAVE_OPENGLES3 ?= 0
6880

69-
ASYNC ?= 0
81+
ASYNC ?= 1
7082
LTO ?= 0
7183
PTHREAD ?= 0
7284

@@ -92,61 +104,86 @@ _cmd_toggle_menu,_cmd_reload_config,_cmd_toggle_grab_mouse,_cmd_toggle_game_focu
92104
_cmd_set_volume,_cmd_set_shader,_cmd_cheat_set_code,_cmd_cheat_get_code,_cmd_cheat_toggle_index,_cmd_cheat_get_code_state,_cmd_cheat_realloc,\
93105
_cmd_cheat_get_size,_cmd_cheat_apply_cheats
94106

95-
LIBS := -s USE_ZLIB=1
96-
LDFLAGS := -L. --no-heap-copy -s $(LIBS) -s STACK_SIZE=$(STACK_SIZE) -s INITIAL_MEMORY=$(INITIAL_HEAP) \
97-
-s EXPORTED_RUNTIME_METHODS=callMain,FS,PATH,ERRNO_CODES,stringToNewUTF8,UTF8ToString \
107+
EXPORTS := callMain,FS,PATH,ERRNO_CODES,ENV,stringToNewUTF8,UTF8ToString,Browser,GL
108+
109+
LIBS := -s USE_ZLIB=1 -lbrowser.js
110+
111+
ifeq ($(HAVE_WASMFS), 1)
112+
DEFINES += -DHAVE_WASMFS=1
113+
LIBS += -sWASMFS -sFORCE_FILESYSTEM=1 -lfetchfs.js -lopfs.js
114+
EXPORTS := $(EXPORTS),FETCHFS,OPFS
115+
ifeq ($(PTHREAD),0)
116+
$(error ERROR: WASMFS requires threading support)
117+
endif
118+
endif
119+
120+
ifeq ($(PROXY_TO_PTHREAD),1)
121+
LIBS += -sUSE_ES6_IMPORT_META=0 -sENVIRONMENT=worker,web
122+
LIBS += -sPROXY_TO_PTHREAD -sOFFSCREENCANVAS_SUPPORT
123+
DEFINES += -DUSE_OFFSCREENCANVAS=1 -DPROXY_TO_PTHREAD=1
124+
else
125+
override ASYNC = 1
126+
endif
127+
128+
ifeq ($(HAVE_SDL2), 1)
129+
LIBS += -s USE_SDL=2
130+
DEFINES += -DHAVE_SDL2
131+
endif
132+
133+
134+
LDFLAGS := -L. --no-heap-copy -s STACK_SIZE=$(STACK_SIZE) -s INITIAL_MEMORY=$(INITIAL_HEAP) \
135+
-s EXPORTED_RUNTIME_METHODS=$(EXPORTS) \
98136
-s ALLOW_MEMORY_GROWTH=1 -s EXPORTED_FUNCTIONS="$(EXPORTED_FUNCTIONS)" \
99137
-s MODULARIZE=1 -s EXPORT_ES6=1 -s EXPORT_NAME="libretro_$(subst -,_,$(LIBRETRO))" \
138+
-s DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR=0 \
100139
--extern-pre-js emscripten/pre.js \
101140
--js-library emscripten/library_rwebcam.js \
141+
-gsource-map -g2 \
102142
--js-library emscripten/library_platform_emscripten.js
103143

144+
ifeq ($(HAVE_OPENGLES), 1)
145+
ifeq ($(HAVE_OPENGLES3), 1)
146+
LDFLAGS += -s FULL_ES3=1 -s MIN_WEBGL_VERSION=2 -s MAX_WEBGL_VERSION=2 -lGL
147+
else
148+
LDFLAGS += -s FULL_ES2=1 -s MIN_WEBGL_VERSION=1 -s MAX_WEBGL_VERSION=2 -lGL
149+
endif
150+
endif
151+
152+
ifeq ($(GL_DEBUG), 1)
153+
LDFLAGS += -s GL_ASSERTIONS=1 -s GL_DEBUG=1 -DHAVE_GL_DEBUG_ES=1
154+
endif
155+
156+
ifeq ($(FS_DEBUG), 1)
157+
LDFLAGS += -s FS_DEBUG=1
158+
endif
159+
104160
ifeq ($(HAVE_RWEBAUDIO), 1)
105161
LDFLAGS += --js-library emscripten/library_rwebaudio.js
106162
DEFINES += -DHAVE_RWEBAUDIO
107163
endif
164+
108165
ifeq ($(HAVE_AL), 1)
109166
LDFLAGS += -lopenal
110167
DEFINES += -DHAVE_AL
111-
override ASYNC = 1
112168
endif
113169

114170
ifneq ($(PTHREAD), 0)
115-
LDFLAGS += -s MAXIMUM_MEMORY=1073741824 -pthread -s PTHREAD_POOL_SIZE=$(PTHREAD)
116-
CFLAGS += -pthread
171+
LDFLAGS += -s WASM_MEM_MAX=1073741824 -pthread -s PTHREAD_POOL_SIZE=$(PTHREAD)
172+
CFLAGS += -pthread -s SHARED_MEMORY
117173
HAVE_THREADS=1
118174
else
119175
HAVE_THREADS=0
120176
endif
121177

178+
122179
ifeq ($(ASYNC), 1)
180+
DEFINES += -DEMSCRIPTEN_ASYNCIFY
123181
LDFLAGS += -s ASYNCIFY=$(ASYNC) -s ASYNCIFY_STACK_SIZE=8192
124182
ifeq ($(DEBUG), 1)
125183
LDFLAGS += -s ASYNCIFY_DEBUG=1 # -s ASYNCIFY_ADVISE
126184
endif
127185
endif
128186

129-
ifeq ($(HAVE_OPENGLES), 1)
130-
ifeq ($(HAVE_OPENGLES3), 1)
131-
LDFLAGS += -s FULL_ES3=1 -s MIN_WEBGL_VERSION=2 -s MAX_WEBGL_VERSION=2
132-
else
133-
LDFLAGS += -s FULL_ES2=1
134-
endif
135-
endif
136-
137-
ifeq ($(GL_DEBUG), 1)
138-
LDFLAGS += -s GL_ASSERTIONS=1 -s GL_DEBUG=1
139-
endif
140-
141-
ifeq ($(FS_DEBUG), 1)
142-
LDFLAGS += -s FS_DEBUG=1
143-
endif
144-
145-
ifeq ($(HAVE_SDL2), 1)
146-
LIBS += -s USE_SDL=2
147-
DEFINES += -DHAVE_SDL2
148-
endif
149-
150187
include Makefile.common
151188

152189
CFLAGS += $(DEF_FLAGS) -Ideps -Ideps/stb
@@ -183,8 +220,10 @@ RARCH_OBJ := $(addprefix $(OBJDIR)/,$(OBJ))
183220

184221
all: $(TARGET)
185222

186-
$(TARGET): $(RARCH_OBJ) $(libretro)
187-
@$(if $(libretro), mv -f $(libretro) $(libretro_new),)
223+
$(libretro_new) : $(libretro)
224+
mv -f $(libretro) $(libretro_new)
225+
226+
$(TARGET): $(RARCH_OBJ) $(libretro_new)
188227
@$(if $(Q), $(shell echo echo "LD $@ \<obj\> $(libretro_new) $(LIBS) $(LDFLAGS)"),)
189228
$(Q)$(LD) -o $@ $(RARCH_OBJ) $(libretro_new) $(LIBS) $(LDFLAGS)
190229

config.def.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1833,7 +1833,11 @@
18331833
#define DEFAULT_BUILDBOT_SERVER_URL ""
18341834
#endif
18351835

1836+
#ifdef EMSCRIPTEN
1837+
#define DEFAULT_BUILDBOT_ASSETS_SERVER_URL "https://buildbot.libretro.com/assets/"
1838+
#else
18361839
#define DEFAULT_BUILDBOT_ASSETS_SERVER_URL "http://buildbot.libretro.com/assets/"
1840+
#endif
18371841

18381842
#define DEFAULT_DISCORD_APP_ID "475456035851599874"
18391843

emscripten/library_platform_emscripten.js

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,28 +15,6 @@ var LibraryPlatformEmscripten = {
1515
}
1616
},
1717

18-
PlatformEmscriptenWatchCanvasSize: function() {
19-
RPE.observer = new ResizeObserver(function(e) {
20-
var width, height;
21-
var entry = e.find(i => i.target == Module.canvas);
22-
if (!entry) return;
23-
if (entry.devicePixelContentBoxSize) {
24-
width = entry.devicePixelContentBoxSize[0].inlineSize;
25-
height = entry.devicePixelContentBoxSize[0].blockSize;
26-
} else {
27-
width = Math.round(entry.contentRect.width * window.devicePixelRatio);
28-
height = Math.round(entry.contentRect.height * window.devicePixelRatio);
29-
}
30-
Module.setCanvasSize(width, height);
31-
Module.print("Setting real canvas size: " + width + " x " + height);
32-
});
33-
RPE.observer.observe(Module.canvas);
34-
window.addEventListener("resize", function(e) {
35-
RPE.observer.unobserve(Module.canvas);
36-
RPE.observer.observe(Module.canvas);
37-
}, false);
38-
},
39-
4018
PlatformEmscriptenPowerStateInit: function() {
4119
if (!navigator.getBattery) return;
4220
navigator.getBattery().then(function(battery) {

0 commit comments

Comments
 (0)