Files
aego/docs/web-capabilities.md
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

91 lines
7.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 |