🚧 Glyx is pre-release software. APIs may change before v1.0. Get started →
Documentation
Core Concepts
Rendering Backends

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:

BackendIdle RSSUnder interaction loadRequires
TinySkia (CPU + software present)~27–40 MBNo spike — stays flatNothing — no GPU, no wgpu
Direct2D (Windows, experimental, opt-in)~77–114 MBNo spike — stays flatWindows, never auto-selected
Vello (wgpu compute)~350–430 MBSpikes to 600–700 MB, slow/erratic recoveryDX12 / 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                     →  Vello

auto 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 (tasks example)
  • 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 (wgpu device + 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 recommended

renderMode: '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 (tasks example)
  • 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

GoalSetting
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 Canvasany 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 dev

Fallback 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 → ERROR

The fallback is logged. Production apps should test on their target hardware to avoid silent fallbacks.

See also