address issues

This commit is contained in:
BinBashBanana 2025-03-06 15:38:40 -08:00
parent f6eb1ed5c5
commit c672730259
6 changed files with 86 additions and 85 deletions

View File

@ -56,6 +56,7 @@ HAVE_BSV_MOVIE = 1
HAVE_AL = 1
HAVE_CHD ?= 0
HAVE_NETPLAYDISCOVERY ?= 0
HAVE_THREADS ?= 0
# WARNING -- READ BEFORE ENABLING
# The rwebaudio driver is known to have several audio bugs, such as
@ -79,7 +80,6 @@ PROXY_TO_PTHREAD ?= 0
ASYNC ?= 0
LTO ?= 0
PTHREAD ?= 0
PTHREAD_POOL_SIZE ?= 4
STACK_SIZE ?= 4194304
@ -121,7 +121,8 @@ endif
ifeq ($(PROXY_TO_PTHREAD), 1)
LIBS += -s OFFSCREENCANVAS_SUPPORT
DEFINES += -DPROXY_TO_PTHREAD -DEMSCRIPTEN_STACK_SIZE=$(STACK_SIZE)
override PTHREAD = 1
override HAVE_THREADS = 1
# use the default stack size for the browser thread; the RetroArch thread will be created with the specified stack size
override STACK_SIZE = 4194304
else ifeq ($(HAVE_AL), 1)
override ASYNC = 1
@ -169,19 +170,16 @@ ifeq ($(HAVE_AL), 1)
DEFINES += -DHAVE_AL
endif
ifeq ($(PTHREAD), 1)
ifeq ($(HAVE_THREADS), 1)
LDFLAGS += -pthread -s PTHREAD_POOL_SIZE=$(PTHREAD_POOL_SIZE)
CFLAGS += -pthread -s SHARED_MEMORY
HAVE_THREADS = 1
else
HAVE_THREADS = 0
endif
ifeq ($(ASYNC), 1)
DEFINES += -DEMSCRIPTEN_ASYNCIFY
LDFLAGS += -s ASYNCIFY=1 -s ASYNCIFY_STACK_SIZE=8192
ifeq ($(DEBUG), 1)
# LDFLAGS += -s ASYNCIFY_DEBUG=1 # -s ASYNCIFY_ADVISE
LDFLAGS += -s ASYNCIFY_DEBUG=1 # -s ASYNCIFY_ADVISE
endif
endif
@ -205,7 +203,8 @@ endif
ifeq ($(DEBUG), 1)
LDFLAGS += -O0 -g -gsource-map -s SAFE_HEAP=1 -s STACK_OVERFLOW_CHECK=2 -s ASSERTIONS=1
CFLAGS += -O0 -g -gsource-map
# -O0 in cflags gives "too many locals" errors
CFLAGS += -O1 -g -gsource-map
else
LDFLAGS += -O3
# WARNING: some optimizations can break some cores (ex: LTO breaks tyrquake)

View File

@ -214,7 +214,7 @@ for f in `ls -v *_${platform}.${EXT}`; do
fi
if [ $PLATFORM = "emscripten" ]; then
async=${ASYNC:-0}
pthread=${PTHREAD:-0}
have_threads=${HAVE_THREADS:-0}
proxy_to_pthread=${PROXY_TO_PTHREAD:-0}
gles3=${HAVE_OPENGLES3:-0}
stack_mem=4194304
@ -249,7 +249,7 @@ for f in `ls -v *_${platform}.${EXT}`; do
echo LTO: $lto
if [ $PLATFORM = "emscripten" ]; then
echo ASYNC: $async
echo PTHREAD: $pthread
echo HAVE_THREADS: $have_threads
echo PROXY_TO_PTHREAD: $proxy_to_pthread
echo GLES3: $gles3
echo STACK_MEMORY: $stack_mem
@ -261,7 +261,7 @@ for f in `ls -v *_${platform}.${EXT}`; do
if [ $MAKEFILE_GRIFFIN = "yes" ]; then
make -C ../ -f Makefile.griffin platform=${platform} clean || exit 1
elif [ $PLATFORM = "emscripten" ]; then
make -C ../ -f Makefile.emscripten PTHREAD=$pthread ASYNC=$async LTO=$lto HAVE_OPENGLES3=$gles3 -j7 clean || exit 1
make -C ../ -f Makefile.emscripten HAVE_THREADS=$have_threads ASYNC=$async LTO=$lto HAVE_OPENGLES3=$gles3 -j7 clean || exit 1
elif [ $PLATFORM = "unix" ]; then
make -C ../ -f Makefile LINK=g++ LTO=$lto -j7 clean || exit 1
else
@ -273,8 +273,8 @@ for f in `ls -v *_${platform}.${EXT}`; do
if [ $MAKEFILE_GRIFFIN = "yes" ]; then
make -C ../ -f Makefile.griffin $OPTS platform=${platform} $whole_archive $big_stack -j3 || exit 1
elif [ $PLATFORM = "emscripten" ]; then
echo "BUILD COMMAND: make -C ../ -f Makefile.emscripten $OPTS LTO=$lto ASYNC=$async PTHREAD=$pthread PROXY_TO_PTHREAD=$proxy_to_pthread HAVE_OPENGLES3=$gles3 STACK_SIZE=$stack_mem INITIAL_HEAP=$heap_mem -j7 LIBRETRO=${name} TARGET=${name}_libretro.js"
make -C ../ -f Makefile.emscripten $OPTS LTO=$lto ASYNC=$async PTHREAD=$pthread PROXY_TO_PTHREAD=$proxy_to_pthread HAVE_OPENGLES3=$gles3 STACK_SIZE=$stack_mem INITIAL_HEAP=$heap_mem -j7 LIBRETRO=${name} TARGET=${name}_libretro.js || exit 1
echo "BUILD COMMAND: make -C ../ -f Makefile.emscripten $OPTS LTO=$lto ASYNC=$async HAVE_THREADS=$have_threads PROXY_TO_PTHREAD=$proxy_to_pthread HAVE_OPENGLES3=$gles3 STACK_SIZE=$stack_mem INITIAL_HEAP=$heap_mem -j7 LIBRETRO=${name} TARGET=${name}_libretro.js"
make -C ../ -f Makefile.emscripten $OPTS LTO=$lto ASYNC=$async HAVE_THREADS=$have_threads PROXY_TO_PTHREAD=$proxy_to_pthread HAVE_OPENGLES3=$gles3 STACK_SIZE=$stack_mem INITIAL_HEAP=$heap_mem -j7 LIBRETRO=${name} TARGET=${name}_libretro.js || exit 1
elif [ $PLATFORM = "unix" ]; then
make -C ../ -f Makefile LINK=g++ $whole_archive $big_stack -j3 || exit 1
elif [ $PLATFORM = "ctr" ]; then
@ -393,7 +393,7 @@ for f in `ls -v *_${platform}.${EXT}`; do
if [ $MAKEFILE_GRIFFIN = "yes" ]; then
make -C ../ -f Makefile.griffin platform=${platform} clean || exit 1
elif [ $PLATFORM = "emscripten" ]; then
make -C ../ -f Makefile.emscripten PTHREAD=$pthread ASYNC=$async LTO=$lto -j7 clean || exit 1
make -C ../ -f Makefile.emscripten HAVE_THREADS=$have_threads ASYNC=$async LTO=$lto -j7 clean || exit 1
elif [ $PLATFORM = "unix" ]; then
make -C ../ -f Makefile LTO=$lto -j7 clean || exit 1
else

View File

@ -3,7 +3,7 @@
var LibraryPlatformEmscripten = {
$RPE: {
powerStateChange: function(e) {
Module._update_power_state(true, Number.isFinite(e.target.dischargingTime) ? e.target.dischargingTime : 0x7FFFFFFF, e.target.level, e.target.charging);
_update_power_state(true, Number.isFinite(e.target.dischargingTime) ? e.target.dischargingTime : 0x7FFFFFFF, e.target.level, e.target.charging);
},
updateMemoryUsage: function() {
@ -11,7 +11,7 @@ var LibraryPlatformEmscripten = {
var used = BigInt(performance.memory.usedJSHeapSize || 0);
var limit = BigInt(performance.memory.jsHeapSizeLimit || 0);
// emscripten currently only supports passing 32 bit ints, so pack it
Module._update_memory_usage(Number(used & 0xFFFFFFFFn), Number(used >> 32n), Number(limit & 0xFFFFFFFFn), Number(limit >> 32n));
_update_memory_usage(Number(used & 0xFFFFFFFFn), Number(used >> 32n), Number(limit & 0xFFFFFFFFn), Number(limit >> 32n));
setTimeout(RPE.updateMemoryUsage, 5000);
},
command_queue: [],
@ -37,7 +37,7 @@ var LibraryPlatformEmscripten = {
}
// doubles are too big to pass as an argument to exported functions
{{{ makeSetValue("dpr", "0", "window.devicePixelRatio", "double") }}};
Module._update_canvas_dimensions(width, height, dpr);
_update_canvas_dimensions(width, height, dpr);
});
RPE.observer.observe(Module.canvas);
window.addEventListener("resize", function() {
@ -48,7 +48,7 @@ var LibraryPlatformEmscripten = {
PlatformEmscriptenWatchWindowVisibility: function() {
document.addEventListener("visibilitychange", function() {
Module._update_window_hidden(document.visibilityState == "hidden");
_update_window_hidden(document.visibilityState == "hidden");
}, false);
},

View File

@ -63,8 +63,10 @@
#include <emscripten/proxying.h>
#include <emscripten/atomic.h>
#define PLATFORM_SETVAL(type, addr, val) emscripten_atomic_store_##type(addr, val)
#define PLATFORM_GETVAL(type, addr) emscripten_atomic_load_##type(addr)
#else
#define PLATFORM_SETVAL(type, addr, val) *addr = val
#define PLATFORM_GETVAL(type, addr) *addr
#endif
void emscripten_mainloop(void);
@ -73,39 +75,6 @@ void PlatformEmscriptenWatchWindowVisibility(void);
void PlatformEmscriptenPowerStateInit(void);
void PlatformEmscriptenMemoryUsageInit(void);
static bool command_flag = false;
void PlatformEmscriptenCommandReply(const char *msg, size_t len)
{
MAIN_THREAD_EM_ASM({
var message = UTF8ToString($0, $1);
RPE.command_reply_queue.push(message);
}, msg, len);
}
size_t PlatformEmscriptenCommandRead(char **into, size_t max_len)
{
if (!command_flag) { return 0; }
return MAIN_THREAD_EM_ASM_INT({
var next_command = RPE.command_queue.shift();
var length = lengthBytesUTF8(next_command);
if (length > $2) {
console.error("[CMD] Command too long, skipping", next_command);
return 0;
}
stringToUTF8(next_command, $1, $2);
if (RPE.command_queue.length == 0) {
setValue($0, 0, 'i8');
}
return length;
}, &command_flag, into, max_len);
}
void PlatformEmscriptenCommandRaiseFlag()
{
command_flag = true;
}
typedef struct
{
uint64_t memory_used;
@ -118,6 +87,7 @@ typedef struct
volatile bool power_state_charging;
volatile bool power_state_supported;
volatile bool window_hidden;
volatile bool command_flag;
} emscripten_platform_data_t;
static emscripten_platform_data_t *emscripten_platform_data = NULL;
@ -288,27 +258,62 @@ void update_memory_usage(uint32_t used1, uint32_t used2, uint32_t limit1, uint32
PLATFORM_SETVAL(u64, &emscripten_platform_data->memory_limit, limit1 | ((uint64_t)limit2 << 32));
}
void PlatformEmscriptenCommandRaiseFlag()
{
if (!emscripten_platform_data)
return;
emscripten_platform_data->command_flag = true;
}
/* platform specific c helpers */
void PlatformEmscriptenCommandReply(const char *msg, size_t len)
{
MAIN_THREAD_EM_ASM({
var message = UTF8ToString($0, $1);
RPE.command_reply_queue.push(message);
}, msg, len);
}
size_t PlatformEmscriptenCommandRead(char **into, size_t max_len)
{
if (!emscripten_platform_data || !emscripten_platform_data->command_flag)
return 0;
return MAIN_THREAD_EM_ASM_INT({
var next_command = RPE.command_queue.shift();
var length = lengthBytesUTF8(next_command);
if (length > $2) {
console.error("[CMD] Command too long, skipping", next_command);
return 0;
}
stringToUTF8(next_command, $1, $2);
if (RPE.command_queue.length == 0) {
setValue($0, 0, 'i8');
}
return length;
}, &emscripten_platform_data->command_flag, into, max_len);
}
void platform_emscripten_get_canvas_size(int *width, int *height)
{
if (!emscripten_platform_data ||
(emscripten_platform_data->canvas_width == 0 && emscripten_platform_data->canvas_height == 0))
{
*width = 800;
*height = 600;
RARCH_ERR("[EMSCRIPTEN]: Could not get screen dimensions!\n");
}
else
{
*width = emscripten_platform_data->canvas_width;
*height = emscripten_platform_data->canvas_height;
}
if (!emscripten_platform_data)
goto error;
*width = PLATFORM_GETVAL(u32, &emscripten_platform_data->canvas_width);
*height = PLATFORM_GETVAL(u32, &emscripten_platform_data->canvas_height);
if (*width != 0 || *height != 0)
return;
error:
*width = 800;
*height = 600;
RARCH_ERR("[EMSCRIPTEN]: Could not get screen dimensions!\n");
}
double platform_emscripten_get_dpr(void)
{
return emscripten_platform_data->device_pixel_ratio;
return PLATFORM_GETVAL(f64, &emscripten_platform_data->device_pixel_ratio);
}
bool platform_emscripten_is_window_hidden(void)
@ -440,19 +445,22 @@ static void frontend_emscripten_get_env(int *argc, char *argv[],
static enum frontend_powerstate frontend_emscripten_get_powerstate(int *seconds, int *percent)
{
enum frontend_powerstate ret = FRONTEND_POWERSTATE_NONE;
int level;
if (!emscripten_platform_data || !emscripten_platform_data->power_state_supported)
return ret;
level = PLATFORM_GETVAL(f32, &emscripten_platform_data->power_state_level);
if (!emscripten_platform_data->power_state_charging)
ret = FRONTEND_POWERSTATE_ON_POWER_SOURCE;
else if (emscripten_platform_data->power_state_level == 1)
else if (level == 1)
ret = FRONTEND_POWERSTATE_CHARGED;
else
ret = FRONTEND_POWERSTATE_CHARGING;
*seconds = emscripten_platform_data->power_state_discharge_time;
*percent = (int)(emscripten_platform_data->power_state_level * 100);
*seconds = PLATFORM_GETVAL(u32, &emscripten_platform_data->power_state_discharge_time);
*percent = (int)(level * 100);
return ret;
}
@ -461,7 +469,7 @@ static uint64_t frontend_emscripten_get_total_mem(void)
{
if (!emscripten_platform_data)
return 0;
return emscripten_platform_data->memory_limit;
return PLATFORM_GETVAL(u64, &emscripten_platform_data->memory_limit);
}
static uint64_t frontend_emscripten_get_free_mem(void)
@ -469,11 +477,11 @@ static uint64_t frontend_emscripten_get_free_mem(void)
if (!emscripten_platform_data)
return 0;
#ifndef PROXY_TO_PTHREAD
uint64_t used = emscripten_platform_data->memory_used;
uint64_t used = PLATFORM_GETVAL(u64, &emscripten_platform_data->memory_used);
#else
uint64_t used = mallinfo().uordblks;
#endif
return (emscripten_platform_data->memory_limit - used);
return (PLATFORM_GETVAL(u64, &emscripten_platform_data->memory_limit) - used);
}
/* program entry and startup */
@ -510,7 +518,7 @@ void platform_emscripten_mount_filesystems(void)
abort();
}
}
#if false
if (fetch_manifest)
{
/* fetch_manifest should be a path to a manifest file.
@ -575,7 +583,6 @@ void platform_emscripten_mount_filesystems(void)
fclose(file);
free(line);
}
#endif
}
#endif /* HAVE_WASMFS */
@ -608,6 +615,10 @@ static void *main_pthread(void* arg)
int main(int argc, char *argv[])
{
int ret = 0;
#ifdef PROXY_TO_PTHREAD
pthread_attr_t attr;
pthread_t thread;
#endif
// this never gets freed
emscripten_platform_data = (emscripten_platform_data_t *)calloc(1, sizeof(emscripten_platform_data_t));
@ -619,8 +630,6 @@ int main(int argc, char *argv[])
#ifdef PROXY_TO_PTHREAD
_main_argc = argc;
_main_argv = argv;
pthread_attr_t attr;
pthread_t thread;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_attr_setstacksize(&attr, EMSCRIPTEN_STACK_SIZE);

View File

@ -62,13 +62,10 @@ static void gfx_ctx_emscripten_webgl_check_window(void *data, bool *quit,
*quit = false;
}
/* https://github.com/emscripten-core/emscripten/issues/17816#issuecomment-1249719343 */
static void gfx_ctx_emscripten_webgl_swap_buffers(void *data)
{
#ifdef PROXY_TO_PTHREAD
emscripten_webgl_commit_frame();
#else
(void)data;
#endif
}
static void gfx_ctx_emscripten_webgl_get_video_size(void *data,
@ -134,11 +131,7 @@ static void *gfx_ctx_emscripten_webgl_init(void *video_driver)
#endif
attrs.minorVersion = 0;
attrs.enableExtensionsByDefault = true;
#ifdef PROXY_TO_PTHREAD
attrs.explicitSwapControl = true;
#else
attrs.explicitSwapControl = false;
#endif
attrs.renderViaOffscreenBackBuffer = false;
attrs.proxyContextToMainThread = EMSCRIPTEN_WEBGL_CONTEXT_PROXY_DISALLOW;

View File

@ -83,11 +83,11 @@ emmake make -f Makefile platform=emscripten
cp melonds_libretro_emscripten.bc ~/retroarch/RetroArch/libretro_emscripten.bc
```
Now build the frontend with the pthreads env variable: (2 is the number of workers; this can be any integer, but many browsers limit the number of workers)
Now build the frontend with the pthreads env variable:
```
cd ~/retroarch/RetroArch
emmake make -f Makefile.emscripten LIBRETRO=melonds PTHREAD=2 && cp melonds_libretro.* pkg/emscripten/libretro
emmake make -f Makefile.emscripten LIBRETRO=melonds HAVE_THREADS=1 && cp melonds_libretro.* pkg/emscripten/libretro
```
Your resulting output will be located in:
@ -153,7 +153,7 @@ git clone https://github.com/libretro/RetroArch.git ~/retroarch/RetroArch
cp ~/retroarch/libretro-fceumm/fceumm_libretro_emscripten.bc ~/retroarch/RetroArch/libretro_emscripten.bc
cd ~/retroarch
emmake make -f Makefile.emscripten LIBRETRO=fceumm PROXY_TO_PTHREAD=1 PTHREAD=4 HAVE_WASMFS=1 ASYNC=0 HAVE_EGL=0 -j all
emmake make -f Makefile.emscripten LIBRETRO=fceumm PROXY_TO_PTHREAD=1 HAVE_WASMFS=1 -j all
cp fceumm_libretro.{js,wasm} pkg/emscripten/libretro-thread
```