Rendering Backends
Glyx ships three 2D rendering backends. The default auto mode picks the best one for the machine at startup — no configuration needed for most apps.
The memory story
The backend choice is the single biggest factor in your app's RAM footprint.
Numbers below are RSS on the tasks example, both idle and under a
sustained fast-hover-and-repaint interaction stress test — the stress
number matters as much as idle, since it's what separates a backend with a
real, app-owned memory pool from one that doesn't:
| Backend | Idle RSS | Under interaction load | Requires |
|---|---|---|---|
| TinySkia (CPU + software present) | ~27–40 MB | No spike — stays flat | Nothing — no GPU, no wgpu |
| Direct2D (Windows, experimental, opt-in) | ~77–114 MB | No spike — stays flat | Windows, never auto-selected |
| Vello (wgpu compute) | ~350–430 MB | Spikes to 600–700 MB, slow/erratic recovery | DX12 / Metal / Vulkan |
TinySkia is what makes Glyx's headline number possible. It is not a fallback or a limited mode — it is the default for most hardware and produces visually identical output to Vello at typical UI complexity.
Vello's memory cost is structural, not a bug to be fixed. It maintains
a persistent GPU scene/compute buffer pool that grows to match rendering
load and only shrinks on explicit triggers (occlusion, focus-loss, or
periodic idle checks) — never instantly. This buys real GPU-parallel
rendering throughput on genuinely GPU-bound 2D scenes (dense paths/text,
large canvases); for typical app UI, that throughput ceiling is never
reached, so the cost is pure downside. Vello's CPU path (renderMode: 'cpu') is not a lighter alternative — it inherits the same buffer-pool
memory cost without the GPU parallelism that cost is meant to buy.
Since July 2026, TinySkia presents frames through the OS software surface
(softbuffer (opens in a new tab) — Win32 DIB, X11 SHM,
CoreGraphics) instead of a wgpu swapchain. A TinySkia app creates no wgpu
device at all — no staging buffers, no GPU texture uploads, no DX12 allocator
pools. On integrated GPUs, where GPU memory is carved out of system RAM, this
cut the measured footprint of the tasks example from ~123 MB to the current
flat ~27–40 MB (idle and under load). It also improved perceived latency: a UI
frame is one memcpy to the window, not a CPU→GPU round trip.
auto (default)
auto queries the GPU adapter at startup and picks the appropriate backend:
No GPU / software adapter (WARP, llvmpipe) → TinySkia
Integrated GPU (Intel UHD, Apple M-series) → TinySkia
Intel Arc discrete GPU → Vello
NVIDIA / AMD discrete GPU → Velloauto never selects Direct2D — it's opt-in only (renderMode: 'direct2d'), since it's still experimental.
You don't need to set anything — this is the default when renderMode is omitted.
// glyx.config.ts — auto is the default, this is explicit
window: {
renderMode: 'auto'
}The selected backend and adapter are logged at startup:
[glyx] renderMode=auto → skia (Intel(R) UHD Graphics 770, IntegratedGpu)
[glyx] renderMode=auto → vello (NVIDIA GeForce RTX 4080, DiscreteGpu)auto picks TinySkia on the vast majority of laptops and office machines (all iGPU hardware). Vello is selected on machines with a dedicated GPU (NVIDIA, AMD, or Intel Arc).
skia — TinySkia (CPU rasterizer)
Pure CPU rendering via tiny-skia (opens in a new tab), presented through the OS software surface. Zero GPU memory and zero wgpu — no device, no swapchain, no buffer pools, no compute pipelines. The GPU adapter is queried once at startup (to resolve auto) and then never touched for 2D rendering.
window: { renderMode: 'skia' }- ~27–40 MB RSS, flat both idle and under interaction load (
tasksexample) - No GPU required
- Fastest cold start (no device init, no shader compilation)
- Full visual parity with Vello at typical UI density
- Best choice for: productivity apps, low-end hardware, VMs, headless/CI
<Canvas3D>still works — Glyx lazily stands up a wgpu device on first<Canvas3D>use and releases it again after 60s of 3D inactivity. TinySkia itself never needs a GPU; 3D content brings its own.
If you ever need TinySkia rasterization but wgpu presentation (e.g. debugging a
platform-specific software-present issue), set GLYX_NO_SOFT_PRESENT=1 to
restore the previous swapchain path.
gpu / cpu — Vello (wgpu compute)
GPU compute rendering via wgpu (opens in a new tab) + Vello (opens in a new tab). Real throughput advantages on genuinely GPU-bound 2D scenes — analytically anti-aliased gradients, shadows, and glyphs rendered directly on the GPU — at a real, structural memory cost (see the callout above).
window: { renderMode: 'gpu' } // Vello GPU compute path- ~350–430 MB idle, spikes to 600–700 MB under interaction (
wgpudevice + scene-buffer pool + V8) - Best throughput for GPU-bound 2D scenes: dense paths/text, large canvases, heavy gradients at scale
- Requires DX12 (Windows), Metal (macOS), or Vulkan (Linux)
- Best choice for: showcase apps whose 2D scenes are actually GPU-throughput-bound — not a default pick for typical app UI
window: { renderMode: 'cpu' } // Vello's CPU fallback path — not recommendedrenderMode: 'cpu' is Vello's Cranelift CPU path. It is not a lighter alternative to GPU Vello or to TinySkia — it inherits Vello's buffer-pool memory cost without the GPU throughput that cost buys, so it lands worse than both on memory and speed. Only use it if you need a Vello-specific rendering feature with no GPU available at all.
direct2d — Direct2D (Windows, experimental)
ID2D1DeviceContext + a DXGI swap chain, with a DirectWrite text bridge — GPU-accelerated output whose memory behavior measured flat under the same stress test that spiked Vello to 600–700 MB, because Direct2D's resource caches are managed by the OS/graphics driver and shared system-wide, not privately allocated per-app the way Vello's are.
window: { renderMode: 'direct2d' }Experimental and Windows-only. Never selected by auto — opt in
explicitly. Falls back to 'skia' with a warning on non-Windows targets.
<Canvas3D> is not yet supported on a Direct2D window — it's silently
skipped with a log message, since there's no established safe pattern yet
for sharing a GPU device between Direct2D and wgpu, or otherwise
compositing the two. Use 'gpu' or 'auto'/'skia' (which lazily
upgrades to wgpu) for apps that need 3D content.
- ~77–114 MB RSS, flat both idle and under interaction load (
tasksexample) - Shapes, gradients/brushes, text, images, and layers/opacity are all supported and verified
- Best choice for: Windows apps wanting GPU-quality 2D output without Vello's memory cost, and that don't need
<Canvas3D>
Choosing explicitly
| Goal | Setting |
|---|---|
| Minimum RAM on any hardware | 'skia' |
| GPU-bound 2D scenes (dense paths/text, large canvases) | 'gpu' |
| Windows, GPU-quality output, no 3D content | 'direct2d' (experimental) |
| Headless / CI / no display | 'skia' |
| 3D Canvas | any backend except 'direct2d' — TinySkia and Vello both support it |
| Let Glyx decide (recommended) | 'auto' (default) |
Force skia at runtime without changing config:
GLYX_CPU_RENDER=1 glyx devFallback chain
If a backend fails to initialise (driver crash, missing GPU), Glyx falls back:
vello → fail → skia
direct2d → fail → skia (also the path taken on non-Windows targets)
skia → fail → ERRORThe fallback is logged. Production apps should test on their target hardware to avoid silent fallbacks.
See also
- glyx.config.ts reference —
window.renderModefield - Renderer & engine selection guide — full heuristics matrix and persona recommendations