WebGPU target (browser WASM + native Dawn)
The webgpu platform runs the engine on WebGPU instead of Vulkan. It shares a
single backend under src/modules/graphics/webgpu/ (and src/modules/gpgpu/webgpu/)
that targets the standard webgpu.h API, and can be produced two ways:
- Browser: compiled with Emscripten to WASM, rendering with the browser's
native WebGPU (Chromium/Edge/Firefox with
--enable-unsafe-webgpu). Shaders must be WGSL. - Native desktop: links Google Dawn (
dawn::dawn), which accepts WGSL (and SPIR-V) and runs on top of Vulkan/Metal/D3D12.
Prerequisites
- Emscripten (
emsdk,emcmake) with WebGPU support. Emscripten ships thewebgpu.h/webgpu_cpp.hheaders. - CMake 3.29.x (pip-installed). CMake 4.x is incompatible with the
Emscripten SDK fork of
CheckTypeSize.cmake(/CheckTypeSize.c.in does not exist), which breaks third-party configure (e.g. mpg123). Install and force CMake 3.29:python -m pip install cmake==3.29.6 # EMSCRIPTEN builds must use this cmake for BOTH the main and the # third-party aggregate — the root CMakeLists detects and forces it. - Native Dawn: fetched automatically via CMake
FetchContent(fixed commit). - A WebGPU-capable browser (Chrome 113+ / Edge 113+ / Firefox 118+).
Browser build (Emscripten / WASM)
# activate emsdk once
emsdk activate latest && emsdk_env.bat # Windows
emcmake cmake -B build/webgpu-web -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build/webgpu-web # produces eve.js / eve.wasm / eve.data
The Emscripten build trims third-party dependencies and engine modules:
- Skipped deps: Poco, OpenAL-soft, medialoader (assimp/mpg123/vorbis), FreeType,
googletest. SDL2 + zlib come from Emscripten ports (
-sUSE_SDL=2,-sUSE_ZLIB). Kept: squirrel/simplesquirrel, physfs, lz4, Box2D, xxHash, imgui, and a minimalmedialoader_image(stb/lodepng/dds/tinyexr image decoders, needed by EVImage). - Compiled-out modules (their deps were dropped):
EVAnimation EVAudio EVAvatar EVBuilding EVDatabase EVDialogue EVFont EVInventory EVMap EVModel3D EVNetwork EVParticles EVPlugins EVProcgen EVRPG EVSound EVStylize EVVoxel, plusgraphics/Font.cppand the Poco-heavyDataModule/JsonDocument/ XmlDocument. - Threads:
main()runs on the browser main thread so the WebGPU surface can reach the DOM canvas directly (noPROXY_TO_PTHREAD); pthreads stay available for the Thread module, and all TUs are compiled with-matomics -mbulk-memory(engine and third-party). The page must still be served with COOP/COEP headers soSharedArrayBufferis available.
Serving + browser verification
The output directory is build/webgpu-web/src/engine/. Serve it with a real
HTTP server that sends the cross-origin-isolation headers:
python scripts/serve_webgpu.py # serves http://127.0.0.1:8090/eve.html
# with COOP/COEP + no-store headers
Open http://127.0.0.1:8090/eve.html in Chrome/Edge (WebGPU enabled). The page
is the online playground — see the next section. Its status bar prints
crossOriginIsolated and the resolved WebGPU adapter, so init failures are
visible without DevTools.
Playground (online script editor)
shell.html is a self-contained playground UI around the running engine:
- Editor (left): write
main.nutin Squirrel with syntax highlighting.Ctrl+Enter(or 应用/Apply) writes the script to the engine VFS and soft-hot-reloads it — the next frame runs the new code. - State preservation: the engine's soft reload re-runs
main.nutand then calls the optionaleve_reload()hook; root-table state survives. Playground demos keep their state in the__pgtable (if (!("__pg" in getroottable())) __pg <- {};), so editingeve_update/eve_rendernever resets the game. - 重置状态/Restart: clears
__pg, re-applies the script and re-runseve_initto rebuild the scene from scratch. A full browser refresh always gives a completely fresh engine (and re-applies your last session from localStorage). - 暂停/Pause: freezes
eve_update(game logic) while rendering continues. - REPL (console bottom): evaluates one Squirrel expression in the running
VM, e.g.
__pg.frames. - Examples dropdown: loads
main.nutorplayground/demos/*.nutfrom the preloaded VFS into the editor. - Console: captures engine
print/printErrand script errors.
JS ↔ engine bridge
src/engine/cmdline/Run.cpp exports four functions to the page
(EMSCRIPTEN_KEEPALIVE, browser build only):
| Function | Purpose |
|---|---|
eve_playground_apply(source) |
write /game/main.nut + handle_change("main.nut") (same path as the desktop watcher: dofile → eve_reload()) |
eve_playground_eval(source) |
compile + run one Squirrel snippet, return stringified result/error |
eve_playground_read(path) |
read a file from the VFS (relative to /game) |
eve_playground_set_paused(bool) |
set the eve_playground_paused root flag checked by load.nut |
The engine signals readiness by calling window.eveEngineReady() once
load.nut has finished (this is later than onRuntimeInitialized).
Bundled demos and assets
platform/webgpu/game-shell/ is preloaded at /game:
main.nut— default 3D rotating sphere (hot-state pattern).playground/demos/2d_sprites.nut— 2D sprite + keyboard.playground/demos/3d_textured.nut— textured cube + orbiting sphere.playground/demos/hot_state.nut— explicit hot-update state demo.playground/assets/— CC0 textures (wood.jpg, background_forest.png, crate.png, tiles.png; seeATTRIBUTION.txt).
To add a demo, drop a .nut file under platform/webgpu/game-shell/playground/ demos/ and add it to the EXAMPLES array in shell.html, then rebuild (the
game-shell is embedded into eve.data).
Headless verification (optional): headless Chromium needs explicit GPU flags
for WebGPU to be exposed — plain --headless reports "No available adapters":
msedge --headless=new --no-sandbox --disable-gpu-sandbox \
--enable-unsafe-webgpu --enable-features=Vulkan --use-vulkan=swiftshader \
--timeout=15000 --screenshot=frame.png http://127.0.0.1:8090/eve.html
Note: with PROXY_TO_PTHREAD, the main loop runs on a worker; use the real-time
--timeout wait (not --virtual-time-budget, which never advances the worker
clock) so the first frames are actually presented before the screenshot.
The shell (platform/webgpu/shell.html) provides the <canvas id="canvas">
that the WebGPU surface attaches to. Game assets under
platform/webgpu/game-shell/ are preloaded at /game.
Native Dawn build
cmake -B build/webgpu-native -G Ninja -DCMAKE_BUILD_TYPE=Release \
-DBUILD_PLATFORM=webgpu
cmake --build build/webgpu-native
./build/webgpu-native/src/engine/eve run <game-dir>
Set EVENGINE_WEBGPU_GAME_DIR to point the platform helpers at a game folder
when not running from the game directory itself.
Notes / limitations
- Runtime GLSL compilation (
gfx.newShader(glsl)) is not available in the browser — shaders must ship as pre-compiled WGSL (see the*_wgsl.incgeneration step). Native Dawn builds can compile GLSL via glslang+Tint. - The Vulkan backend and
ui/imguiVulkan renderer are excluded from webgpu builds by the source scanner (EVENGINE_EXCLUDED_BACKEND_SUBDIRS). - ImGui overlays use
imgui_impl_wgpu.cpp(compiled by the EVUI module scan;imgui_impl_wgpu.cppincludescommon/config.hbefore its#if defined(EVENGINE_WEBGPU)guard so the platform define is visible). - Poco/OpenAL/medialoader/FreeType are not built on WASM; the corresponding modules are compiled out (see the trim list above). The native Dawn build still compiles them.