Files
aego/docs/web-capabilities.md
T
sanspie 5eb1832907
ci-platforms / darwin amd64 smoke (push) Skipped
ci / build (amd64, linux, ubuntu-24.04) (push) Failing after 15m28s
ci / release (push) Skipped
ci-platforms / windows amd64 smoke (push) Skipped
ci-platforms / darwin arm64 smoke (push) Skipped
ci / checks (push) Successful in 7m47s
Complete Stage 12 for v0.12.0
2026-11-05 11:46:53 +03:00

7.6 KiB
Raw Permalink Blame History

Web capabilities

What the browser build (GOOS=js GOARCH=wasm, platform/web + gpu/webgl2) supports compared with the native build. Decisions: D289, D290.

Platform

Feature Web Notes
Window works one canvas; size from CSS, pixels from devicePixelRatio
Resize, DPI change works ResizeObserver, resize, DPR check every frame
Keyboard works code → scancode; browser shortcuts (Ctrl/Cmd, F5, F11, F12) stay with the browser
Text input degraded single characters only, no IME composition
Mouse works pointer capture while a button is held
Wheel works 100 px = one line; trackpads are precise
Pointer lock degraded granted on the next click or key press after the request
Touch degraded primary pointer as the left button; multi-touch in Stage 18
Gamepads works standard mapping; Chrome reports a pad only after a button press
Focus loss works held keys and buttons are released
Hidden tab works the platform clock excludes hidden time. Any background animation callback leaves the simulation paused. The first visible frame rebases the live clock and delivers queued input. Explicit fixed timelines retain their configured step
Frame pacing works VSync; the frame limit skips animation frames
Fullscreen degraded entered on the next click or key press
Display modes, monitors missing the display module has no modes to apply; the pixel ratio is capped at 1.5 by default (display.maxPixelRatio)
Clipboard write works navigator.clipboard.writeText (secure contexts)
Clipboard read degraded only what was pasted into the page or copied by the game
Cursors works CSS cursor names
Drag and drop of files missing
Player profile, saves works localStorage, limited to a few MB; a full store reports a write error
Files outside the bundle missing no OS file system

GPU

Feature Web Notes
Buffers, instancing works
Textures RGBA8, SRGB8_ALPHA8, R8 works
RGBA16F degraded EXT_color_buffer_float plus actual framebuffer/blend/readback probe; no requirement for 32-bit EXT_float_blend; honest LDR fallback
2D array textures works layer/mip allocation, update, framebuffer attachment and restore; shared shadow/cookie bindings
Depth24/stencil8 targets works
sRGB output works offscreen backbuffer plus an encoding pass
Samplers, mipmaps works
Scissor, viewport, blend, cull works
ReadPixels works resolved RGBA8 targets keep the screenshot contract; RGBA16F diagnostics use RGBA/FLOAT
GPU timer degraded needs EXT_disjoint_timer_query_webgl2; unavailable/disjoint/context-canceled intervals are invalid, not zero GPU time
Debug output, object labels missing Options.Debug checks getError after creation calls
Context loss works objects are recreated from CPU copies; textures cost twice the memory
Shaders works GLSL ES 3.00 copies generated by make shaders

Audio

Feature Web Notes
Output works AudioWorklet at the context's rate: 48 kHz is asked, Safari may give 44.1 kHz and the mixer runs at what it gets
Start degraded silent until the first click, key or touch on the page; a page started by a click (the docs Try it) plays at once; audio written before that is dropped
Mute works web exports show a mute button; the choice is kept in localStorage for the site
Hidden tab works the context is suspended and resumed
Transport works a SharedArrayBuffer ring when the page is cross-origin isolated (COOP same-origin and COEP require-corp), otherwise blocks posted to the worklet
Latency degraded minimum targets of 3 blocks with SharedArrayBuffer and 6 with messages; at 48 kHz/512 frames these are ~32 and ~64 ms, plus the browser's output buffer. Reported device latency or long frames can raise the target
Device events missing the browser follows the default output device itself

Exported games

aego export --target web (D295) runs the same runtime as the desktop export on this platform and GPU backend. Differences from desktop: data is loaded into memory before the game starts, there are no log files or crash bundles, saves and settings share the site's localStorage quota.

Performance

make web-bench (D365) runs the exported platformer with its input recording in Chromium and Firefox: 1280×720, device pixel ratio 1, render scale 1, seed 1, 120 warmup frames, 600 measured, 5 runs. While it measures, every frame advances the game by exactly one fixed step, so each run plays the same frames. It writes .cache/web-bench.json and a table in .cache/web-bench.md.

Level Metrics
Go allocations and bytes per frame, bytes allocated inside the engine frame, allocations per engine zone (phases, gpu, poll), GC cycles, heap
Bridge WebGL calls, timer query calls counted apart, draw calls, buffer and texture uploads and their size, program and render-target switches, time spent in WebGL calls
Browser frame time p50/p95/p99 from requestAnimationFrame gaps, main-thread work per frame, frames over 33 ms, long tasks, JS heap, GPU time

Options: WEB_BENCH_BROWSERS=chromium, WEB_BENCH_ARGS="--gpu=hard --headed" for the real GPU, --gogc=100,150,200 for GC experiments, --trace for a Chrome trace of the first run. make web-bench-baseline saves the machine's baseline, one per GPU mode. Later runs fail when a count (draw calls, WebGL calls, uploads, switches per frame) differs from the baseline or between runs, when Go allocates more than 24 bytes per frame over the baseline inside the engine frame, or when frame or work time is more than 10% slower; time is compared only with at least 5 runs. make web-smoke runs Chromium once and checks the counts, not the time. On the reference machine with --gpu=hard frame p95 must stay at or under 20 ms with at most 1% of frames over 33 ms.

make ci compares its Chromium/SwiftShader run with the versioned Stage 12 baseline in tools/websmoke/bench-stage12-baseline.json. A missing, incomplete or incompatible baseline, disabled allocation profile, wrong actual renderer, or attempt to update the baseline while gating is a failure. Direct make web-bench and make web-smoke keep using .cache/web-bench.base.json by default; CI does not replace that local file.

The engine-frame probe uses runtime.ReadMemStats at each end of a frame: runtime/metrics can publish small allocations in a later frame when an allocator cache is flushed. The frame count now includes tiny allocations, unlike the per-zone runtime/metrics counts. These stop-the-world reads happen only while the probe is enabled, and benchmark timings include their overhead; do not compare frame-byte values or timing baselines made with the older probe as if the method were unchanged. The separate stack-profile allocation gate and its exemptions remain in force.

Historical Stage 12w measurements on the reference machine, hardware GPU, 1280×720, device pixel ratio 1, 600 measured frames. These values do not measure Stage 12b lighting or its updated platformer:

Chromium before 12w Chromium after Firefox before 12w Firefox after
frame p95, ms 16.7 16.8 17.2 17.2
frames over 33 ms 0 0 0 0
Go allocations per frame (runtime/metrics) 7.2 3.8 6.1 2.5
allocations in the engine frame, not exempt — 0 — 0
GC cycles in 3600 frames 0 0 — —
WebGL calls per frame 50.5 50.5 50.5 50.5
draw calls per frame 3.3 3.3 3.3 3.3