wasmerio/wasmer

Wasmer can't run Doom

Opened this issue ยท 11 comments

I understand that this is a somewhat nebulous, perhaps frivolous issue. Here it is anyway.

Wasmer fails to run a Doom Wasm port. This article by Cornelius Diekmann documents the process of porting Doom to WebAssembly and results in this demo. In my own explorations of the subject, I found that the Doom Wasm module runs as expected in the browser (tested on Chrome, Safari, Firefox) and Wasmtime, but fails using Wasmer.

The only clue as to what is going on is the following trap message on invocation of the main export function.

out of bounds memory access

Wasmer version: 4.2.0

Steps to reproduce

Descriptions for recreating the issue can be found in my write up. Alternatively, the module can be initialized with relatively few imports. I've attached the Wasm module in question.

doom.wasm.zip

Expected behaviour

Invocation of the main export function should result in the following expected logs.

Hello, World, from JS Console! Answer=42 (101010 in binary)
Hello, world from rust! ๐Ÿฆ€๐Ÿฆ€๐Ÿฆ€ (println! working)
Starting D_DoomMain
Triggering a printf
Doom's screen is 320x200
mallocing 12 bytes at 7078176

Actual behavior

Invocation of the main export function results in the following logs before the function invocation fails.

Hello, World, from JS Console! Answer=42 (101010 in binary)
Hello, world from rust! ๐Ÿฆ€๐Ÿฆ€๐Ÿฆ€ (println! working)

@ashtonmeuser Thanks for reporting this! This may in fact help us with something we're working on right now, so I'll investigate the issue.

Glad to hear it! Shouldn't be hard to create a minimal Rust-only reproduction. If I find the time, I'll do so and post here.

@ashtonmeuser that would be a big help in identifying the issue.

@ashtonmeuser we may need more context from your side to reproduce the issue. I believe I have the example mostly working (aside from drawing, I'm running it in a CLI app), and I'm not seeing an out of bounds access error so far. This is the output I get from calling main, which is in line with what should be printed AFAICT:

Hello, World, from JS Console! Answer=42 (101010 in binary)
Hello, world from rust! ๐Ÿฆ€๐Ÿฆ€๐Ÿฆ€ (println! working)
Starting D_DoomMain


Triggering a printf

Doom's screen is 320x200


mallocing 12 bytes at 7078176
mallocing 11 bytes at 7078272
mallocing 11 bytes at 7078288
mallocing 12 bytes at 7078304
mallocing 15 bytes at 7078192
mallocing 12 bytes at 7078216
mallocing 13 bytes at 7078232
mallocing 12 bytes at 7078256
                            DOOM Shareware Startup v1.10                           


V_Init: allocate screens.

mallocing 256000 bytes at 7078744
M_LoadDefaults: Load system defaults.

Z_Init: Init zone memory allocation daemon. 

mallocing 2097152 bytes at 7334752
W_Init: Init WADfiles.

mallocing 1 bytes at 7078320
 adding ./doom1.wad

reallocing 25280 bytes. old ptr: 7078320, new ptr: 9431912
mallocing 5056 bytes at 9464688
===========================================================================
                                Shareware!
===========================================================================

M_Init: Init miscellaneous info.

R_Init: Init DOOM refresh daemon - 
[
 
 
 
 
 
 
 
 
 
 
         ]











.
.

InitTextures

InitFlats
.
.
.
.
.
.
.
.

InitSprites

InitColormaps

R_InitData

R_InitPointToAngle

R_InitTables

R_InitPlanes

R_InitLightTables

R_InitSkyMap

R_InitTranslationsTables

P_Init: Init Playloop state.

I_Init: Setting up machine state.

D_CheckNetGame: Checking network game status.

mallocing 140 bytes at 7078320
startskill 2  deathmatch: 0  startmap: 1  startepisode: 1

player 1 of 1 (1 nodes)

S_Init: Setting up sound.

S_Init: default sfx volume 8

HU_Init: Setting up heads up display.

ST_Init: Init status bar.

I_InitGraphics (TODO)

@ashtonmeuser Also, which OS and which compiler backend were you using to run it?

@Arshia001 Thanks for following up and apologies for the delayed reply.

I've gone ahead and created a simple repro here: https://github.com/ashtonmeuser/wasmer-doom. There is a Rust repro as well as a C++ repro using the Wasm C API to which Wasmer adheres.

You are correct; the Rust example works as expected and prints past "Hello, world from rust! ๐Ÿฆ€๐Ÿฆ€๐Ÿฆ€ (println! working)". However, the equivalent C++ example fails.

Note that simply using the Wasmtime library instead of Wasmer while not changing any source files (see wasmtime target in Makefile) produces a binary which initializes Doom as expected. This, to me, indicates an issue specifically with Wasmer.

OS: macOS Sonoma 14.4.1
Wasmer: 4.2.8
Wasmer Backend: Cranelift (I believe; using default)
Wasmtime: 20.0.0

@Arshia001 Just want to confirm you're seeing the same thing re: Wasm C API. Are you able to run the repro project I mentioned?

@ashtonmeuser I got it running with rust (even got a few frames back, though I didn't render them), didn't try the C api. I'll try the repro tomorrow. This is quite peculiar though; I'm not very familiar with the C api, but AFAIK it's just an interface to the same code.

@theduke @syrusakbary do you have any idea what might be happening here?

@Arshia001 Any progress? A discrepancy in behaviour between the C API and Rust crate seems troublesome.

@ashtonmeuser sorry for the radio silence, we were very busy with the 4.3.0 release that happened last Friday. I'm looking into this right now.

Edit: I've successfully reproduced the issue with the latest 4.3.0.

Not a problem. Congrats on the release!

Glad you're seeing the same thing I am. Let me know if I can do anything to help but as it stands, I am at a bit of a loss because I lack context re: Wasmer's C++ โ†’ Rust bindings.