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

Need help running various source ports? Did your computer break? Ask here.

Moderators: GZDoom Developers, LZDoom Developers, UZDoom Developers

Forum rules
Please be as descriptive as possible in your posts (list your hardware and operating system, the version of the source port you are using, any mods you are running and how they're being loaded, etc.)
This will help others to give you a solution!
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: 3177
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: 27597
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: 3177
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
milpool
Posts: 2
Joined: Mon Mar 13, 2023 4:06 pm
Preferred Pronouns: He/Him
Graphics Processor: ATI/AMD with Vulkan/Metal Support

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

Post by milpool »

I've been looking for an Emscripten port of GZDoom. Would trying to get LZDoom (or even ZDoom) to run on WASM be any easier?
ololoken

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

Post by ololoken »

Well, I made some progress with porting gzdoom to emscripten.
https://github.com/ololoken/gzdoom
build options: -DHAVE_VULKAN=OFF -DHAVE_GLES2=ON -DDYN_OPENAL=ON -DBUILD_SHARED_LIBS=OFF -DBUILD_STATIC=ON -DHAVE_VM_JIT=OFF -DNO_GTK=ON -DDYN_GTK=OFF
Main problems as usual are texture formats, shaders and framebuffers. It definitely can work in browser, but requires expert's hand.
ololoken

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

Post by ololoken »

Ok, here is PoC https://turch.in/gzdoom.png gzdoom is running in browser.

There is still plenty of work:
1. statically link emscripten AL
2. fix textures formats handling
3. fix VATTR_BONESELECTOR
ololoken
Posts: 9
Joined: Wed Dec 17, 2025 2:24 am

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

Post by ololoken »

Here is (semi-)working gzdoom: no sound, some textures remain broken

https://turch.in/gzdoom+freedoom/index.html

repo: https://github.com/ololoken/gzdoom

milpool, HyperCrab2000 we can collaborate our efforts
Riax

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

Post by Riax »

ololoken wrote:
> Here is (semi-)working gzdoom: no sound, some textures remain broken
>
> https://turch.in/gzdoom+freedoom/index.html
>
> repo: https://github.com/ololoken/gzdoom
>
> milpool, HyperCrab2000 we can collaborate our efforts

Hello ololoken,
impressive work, compiled your project and it seems to be pretty stable, except the obvious zmusic issues and occasional stutters.
I have been working on a GZDOOM WASM port for the past couple of months, since March of this year, and I got to a state where it ran somewhat smoothly but I stopped due to a lack of motivation.

I would be down for a collab, as I could use this for personal needs. If youd like, you can add me on Discord; cochcetepomnedpc
-Riax
ololoken
Posts: 9
Joined: Wed Dec 17, 2025 2:24 am

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

Post by ololoken »

@Riax yep, there is problem with synchronisation of AsyncBackgroundProc in oalsound.cpp and rest code.
You can try to rid of AsyncBackgroundProc and build with -pthread support, I'm sure it will fix stability issue.
ololoken
Posts: 9
Joined: Wed Dec 17, 2025 2:24 am

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

Post by ololoken »

Well I hope sound is not source of crashes anymore.
Build at https://turch.in/gzdoom+freedoom/index.html is updated. Let's think someone will have enough time to test it.

@Riax unable to find you on discord, try ping me turch.in1878
Riax
Posts: 1
Joined: Sat Dec 20, 2025 12:27 pm
Preferred Pronouns: He/Him
Operating System Version (Optional): Arch, Fedora, Windows 10
Graphics Processor: ATI/AMD (Modern GZDoom)

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

Post by Riax »

ololoken wrote:
> Well I hope sound is not source of crashes anymore.
> Build at https://turch.in/gzdoom+freedoom/index.html is updated. Let's
> think someone will have enough time to test it.
>
> @Riax unable to find you on discord, try ping me turch.in1878

Hi, perfect, runs very well on Chromium-based browsers when loaded in cache.
I would love to discuss this further with you, I have sent you a friend request on Discord. My nick is adam, "cochcetepomnedpc" is my tagline. (without "")
ololoken
Posts: 9
Joined: Wed Dec 17, 2025 2:24 am

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

Post by ololoken »

Let's continue ITT.
Remaining big issue is not working weapons in mods like brutal doom and ashes 2063
In brutal mod works only melee attacks, machine gun, bfg and daemonic flamethrower.
In ashes I can zoom with rifles, attack melee and that's it.
I guess it's somehow connected to reload weapon logic in zscript, but I have no ideas how to debug it. Any ideas?
@dpJudas @Enjay
ololoken
Posts: 9
Joined: Wed Dec 17, 2025 2:24 am

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

Post by ololoken »

Small update.
I've found root cause: A_JumpIfInventory
A value returned ResolveState() is ignored. Internally state is resolved properly both for indexes and string literals, but it just ignored and next state is executed without jumping.
Where I can find info where does vm handle jumps?
User avatar
Jay0
 
 
Posts: 98
Joined: Tue Aug 21, 2018 9:31 pm
Preferred Pronouns: She/Her
Graphics Processor: ATI/AMD with Vulkan/Metal Support
Location: Brazil

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

Post by Jay0 »

ololoken wrote: Sat Dec 27, 2025 8:08 pm Small update.
I've found root cause: A_JumpIfInventory
A value returned ResolveState() is ignored. Internally state is resolved properly both for indexes and string literals, but it just ignored and next state is executed without jumping.
Where I can find info where does vm handle jumps?
the jump issue isn't from emscripten, it's because GZDoom master's VM is currently broken due to this commit, i'd recommend switching your upstream to UZDoom instead, that's where most devs other than graf (me included) went (as for the reason, you can find it here)

Return to “Technical Issues”