Emscripten + GZDoom = WASM for a Web Browser, but I'm stuck

Need help running G/Q/ZDoom/ECWolf/Zandronum/3DGE/EDuke32/Raze? Did your computer break? Ask here.

Moderator: GZDoom Developers

Forum rules
Contrary to popular belief, we are not all-knowing-all-seeing magical beings!

If you want help you're going to have to provide lots of info. Like what is your hardware, what is your operating system, what version of GZDoom/LZDoom/whatever you're using, what mods you're loading, how you're loading it, what you've already tried for fixing the problem, and anything else that is even remotely relevant to the problem.

We can't magically figure out what it is if you're going to be vague, and if we feel like you're just wasting our time with guessing games we will act like that's what you're really doing and won't help you.
HyperCrab2000
Posts: 2
Joined: Thu Feb 20, 2025 4:10 am
Operating System Version (Optional): macOS
Graphics Processor: Apple M1

Emscripten + GZDoom = WASM for a Web Browser, but I'm stuck

Post by HyperCrab2000 »

I'm curious if I can port GZDoom to WASM for a web browser and I figure the only real hurdle is WebGL, and so I played around with it and got stuck and I'm not sure what's going on so I hope someone can help out?

I'm trying to build GZDoom into WASM and run it in the browser. However, I'm not very familiar with C and the instructions don't seem to be very clear to me. Here's what I did.

I modified CMakeLists.txt to add this at the very top

cmake_minimum_required(VERSION 3.10)

set(BUILD_SHARED_LIBS OFF) # Disable shared libraries
set(BUILD_STATIC ON)

Changed this block

#Change for Emscripten
include(CheckSymbolExists)
if (NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten")
check_symbol_exists(backtrace "execinfo.h" HAS_BACKTRACE)
if (HAS_BACKTRACE)
add_definitions(-DHAS_BACKTRACE)
endif()
endif()

if(CMAKE_SYSTEM_NAME MATCHES "Windows" OR CMAKE_SYSTEM_NAME MATCHES "MSYS")
set(NOX11 ON)
set(NO_GBM ON)
set(WIN32_PLATFORM ON)
if(CMAKE_C_COMPILER_ID MATCHES "MSVC" OR "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC")
set(WIN32_MSVC ON) #msvc or icl or clang-cl
endif()
endif()

#Emscripten
if (CMAKE_SYSTEM_NAME MATCHES "Emscripten")
set(STATICLIB ON)
endif()

Added this at the bottom

# Ensure the linker knows where to find libGL.a
link_directories(/Users/me/IdeaProjects/react-boilerplate/gzdoom-build/gl4es/lib)

# Define gzdoom and make sure it links AFTER GL is built
add_executable(gzdoom main.c)

# Make sure gzdoom depends on GL
add_dependencies(gzdoom GL)

# Link gzdoom against GL (the static library)
target_link_libraries(gzdoom /Users/me/IdeaProjects/react-boilerplate/gzdoom-build/gl4es/lib/libGL.a)

And added this main.c file because I needed an entry point I guess?

#include <stdio.h>
#include <stdlib.h>

// External function to initialize GL4ES
extern void initialize_gl4es();

int main() {
// Initialize GL4ES before any OpenGL functions are used
initialize_gl4es();

// Your WebAssembly application logic here
printf("GL4ES Initialized, now running WebAssembly app...\n");

return 0;
}

To build I ran this

emcmake cmake ..
emmake make -j$(sysctl -n hw.ncpu)

And finally this command:

emcc -s USE_WEBGL2=1 -s FULL_ES2=1 -s ALLOW_MEMORY_GROWTH=1 -s AUDIO_WORKLET=1 -s WASM_WORKERS=1 -pthread \
--preload-file ../doom2.wad@/doom/doom2.wad \
../main.c -L../lib -I../include -o gzdoom.html \
-s EXPORTED_FUNCTIONS="['_initialize_gl4es', '_main']" \
-s EXPORTED_RUNTIME_METHODS="['callMain']" \
../lib/libGL.a

Which gives me a .wasm file and an .html file I can serve using

python3 -m http.server 8080

However, when I do I see this:

LIBGL: Initialising gl4es
LIBGL: v1.1.7 built on Feb 20 2025 01:24:52
LIBGL: Using GLES 2.0 backend
LIBGL: Hardware test disabled, nothing activated...
LIBGL: Targeting OpenGL 2.1
LIBGL: Not forcing NPOT support
LIBGL: Not trying to batch small subsequent glDrawXXXX
LIBGL: Trying to use VBO
LIBGL: Force texture for Attachment color0 on FBO
LIBGL: Hack to trigger a SwapBuffers when a Full Framebuffer Blit on default FBO is done
LIBGL: Current folder is:/
LIBGL: Not using PSA (prgbin_n=0, notexarray=0)
GL4ES Initialized, now running WebAssembly app...

And nothing happens. What am I missing? GZDoom doesn't seem to be running and I see no console errors.

Apologies for not formatting this cleaner but I don't see a way of enabling BBCode for this post so I hope someone can help out? I'm stuck and I'm not sure what else to do.
dpJudas
 
 
Posts: 3152
Joined: Sat May 28, 2016 1:01 pm

Re: Emscripten + GZDoom = WASM for a Web Browser, but I'm stuck

Post by dpJudas »

Well at this point you have two options.

First is to install the Web assembly DWARF debugging extension for Chrome and then pray the debugger can tell you something (unfortunately its very undeveloped and borderline useless).
Or you begin adding printf/cout statements in the code to see how far it gets before going radio silent.

Also try try turn off gl_multithreaded as I'm not sure how Webassembly can do multithreading at all (as far as I know the workers can't share memory with the main UI thread, but please correct me if I'm wrong about that)
User avatar
Enjay
 
 
Posts: 26835
Joined: Tue Jul 15, 2003 4:58 pm
Location: Scotland

Re: Emscripten + GZDoom = WASM for a Web Browser, but I'm stuck

Post by Enjay »

I can't help with the main problem but, just for info:
HyperCrab2000 wrote: Thu Feb 20, 2025 4:22 am Apologies for not formatting this cleaner but I don't see a way of enabling BBCode for this post...
New users on the forum have limited access to the BBCode options until a certain number of posts have been reached (I forget the number - it's not too high). This was a deliberate anti-spam/troll decision as we did have people turning up, creating an account and then abusing the features.
dpJudas
 
 
Posts: 3152
Joined: Sat May 28, 2016 1:01 pm

Re: Emscripten + GZDoom = WASM for a Web Browser, but I'm stuck

Post by dpJudas »

Just reply to my own comment about threads, it turns out that webassembly does support sharing memory between the threads now. However, you must enable it using HTTP headers (https://web.dev/articles/coop-coep):

Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin

Return to “Technical Issues”