🚧 Glyx is pre-release software. APIs may change before v1.0. Get started β†’
Documentation
Guides
Renderer Selection

Renderer & Engine Selection

Glyx has three 2D rendering backends with very different memory profiles. Understanding how the selection works lets you ship the right binary for your audience.

The numbers

Measured on the tasks example (Intel UHD 620 integrated GPU), idle and under a sustained fast-hover interaction burst β€” the burst matters as much as the idle number, since it's what separates a backend with a real, app-owned memory pool from one that doesn't:

BackendIdle RSSUnder interaction burstNotes
TinySkia (CPU + software present)~27–40 MBNo spike β€” stays flatNo wgpu, no persistent GPU buffer pool
Direct2D (Windows only, experimental)~77–114 MBNo spike β€” stays flatOS/driver-managed GPU caches, not app-owned
Vello (wgpu compute)~350–430 MBSpikes to 600–700 MB, slow/erratic recoveryPersistent GPU scene-buffer pool grows under load
Vello CPU path~340 MBAlso spikes under the same burstSee callout below β€” not recommended
⚠️

Vello's memory cost is structural, not a bug to be fixed. Both Vello modes (GPU and CPU) maintain a 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 is what buys Vello's GPU-parallel rendering throughput on genuinely complex 2D scenes (heavy path/text density, large canvases). For a typical app UI, that throughput ceiling is never reached, so the memory cost is pure downside. Vello's CPU path is worse than both alternatives: it inherits the same buffer-pool architecture and memory cost as Vello GPU, but without the GPU parallelism that cost is meant to buy. Don't reach for it unless you need a Vello-specific feature and have no GPU available at all.

TinySkia's low, flat number is architectural: a CPU rasterizer has no persistent GPU-resident pool to grow in the first place. Direct2D's flat number under the same stress is a different, real finding from the same category of question: its caches are managed by the OS/driver and shared system-wide across every app, not privately allocated per-app the way Vello's (or the removed FemtoVG's) are β€” see Renderer Roadmap for how that was verified.


How auto works

auto probes the GPU adapter at startup (a lightweight query β€” no device or swapchain is created for the probe) and classifies the hardware into one of four tiers using wgpu::DeviceType and the PCI vendor ID. When the answer is TinySkia, wgpu is never initialised at all β€” frames go straight to the window through the OS software surface:

No GPU / WARP / llvmpipe                         β†’  TinySkia
Integrated GPU (Intel UHD, iGPU, Apple Silicon)  β†’  TinySkia
Intel Arc discrete GPU (vendor 0x8086, discrete)  β†’  Vello
NVIDIA or AMD discrete GPU                         β†’  Vello

The decision is logged at startup so it's always visible:

[glyx] renderMode=auto β†’ skia    (Intel(R) UHD Graphics 770, IntegratedGpu)
[glyx] renderMode=auto β†’ vello (Intel(R) Arc A770 Graphics, DiscreteGpu)
[glyx] renderMode=auto β†’ vello   (NVIDIA GeForce RTX 4080, DiscreteGpu)

GLYX_CPU_RENDER=1 overrides all tiers and forces TinySkia regardless of hardware.

On a typical developer machine (laptop with Intel iGPU), auto picks TinySkia. Vello is selected when a dedicated GPU (NVIDIA, AMD, or Intel Arc) is present.


App persona recommendations

Use this as a starting point when choosing explicitly:

App personaRendererNotes
Showcase / portfolio (heavy 2D scenes)VelloGPU-parallel path/text throughput actually matters here
Indie game (mid-spec)VelloSmooth GPU animations on a dedicated GPU
2D casual gameTinySkiaFast, low RAM, good enough quality
2D game on weak HWTinySkiaSub-100 MB story
Productivity appTinySkiaMost common use case β€” fast, predictable, flat memory
Productivity on low-RAM laptopTinySkiaNo GPU allocation
Settings / dialog appTinySkiaJS is glue, RAM matters more than polish
Dev tool / asset pipelineTinySkiaHeadless-friendly
Headless test / CITinySkiaNo display required
Kiosk / arcade machineTinySkiaLong-running, low-end target
Windows app wanting GPU text/AA quality without Vello's memory costDirect2D (experimental)Windows-only, opt-in β€” see the callout above
3D contentVello (2D layer)Canvas3D itself always uses wgpu directly regardless of 2D backend β€” see 3D Rendering

Explicit config

Override auto when you know your target hardware:

// glyx.config.ts
export default defineConfig({
  window: {
    renderMode: 'skia',      // always TinySkia β€” minimum footprint (recommended default override)
    // renderMode: 'gpu',       // always Vello   β€” heavy 2D scenes, GPU animations
    // renderMode: 'direct2d',  // Windows-only, experimental β€” GPU quality, flat memory
    // renderMode: 'auto',      // heuristic (default)
  },
})

Force TinySkia at runtime (useful for CI or debugging):

GLYX_CPU_RENDER=1 glyx dev
GLYX_CPU_RENDER=1 glyx build

Fallback chain

If a backend fails to initialise, Glyx falls back automatically:

vello β†’ skia β†’ ERROR
skia β†’ ERROR (cannot render)
direct2d β†’ skia β†’ ERROR   (also the path taken on non-Windows targets)

The fallback is logged so it's never silent.


Edge cases

Hybrid GPU laptops (switchable graphics)

Laptops with both an iGPU and a dGPU let the OS decide which adapter wgpu sees. With PowerPreference::HighPerformance, wgpu usually gets the dGPU. If the OS pins the iGPU, auto will pick TinySkia.

Vulkan on iGPU (Linux)

The Glyx GPU adapter probe prefers DX12 on Windows to avoid the Vulkan allocator pre-reserving large pools on iGPU hardware. On Linux with Vulkan + iGPU, auto picks TinySkia which bypasses this entirely.

macOS (Apple Silicon)

Apple Silicon reports as IntegratedGpu (Metal). auto picks TinySkia. Set renderMode: 'gpu' explicitly if you want GPU rendering on macOS.

VMs and CI

wgpu::DeviceType::VirtualGpu (VMware, Hyper-V, VirtualBox with GPU passthrough) β†’ TinySkia. Software adapters (no GPU at all) β†’ TinySkia.


Direct2D (Windows, experimental)

renderMode: 'direct2d' draws through Direct2D/DirectWrite (via ID2D1DeviceContext + a DXGI swap chain) instead of Vello or TinySkia. It exists because Vello's memory cost turned out to be structural (see the callout above), and Direct2D's OS/driver-managed resource caches don't have that problem β€” verified directly: a fast-hover-and-repaint-burst stress test that spiked Vello to 600–700 MB produced zero measurable growth on Direct2D.

⚠️

Experimental and Windows-only. Never selected by auto β€” you must opt in explicitly. On non-Windows targets, requesting 'direct2d' logs a warning and falls back to 'skia' rather than failing. <Canvas3D> is not yet supported on a Direct2D-backed window (it's silently skipped with a log message) β€” use 'gpu' or 'auto'/'skia' (which upgrades to wgpu automatically) for apps that need 3D content.

// glyx.config.ts
export default defineConfig({
  window: { renderMode: 'direct2d' },
})

Keeping the numbers honest

After each release, re-measure and update this guide if the numbers change. All figures in the table above are from a single 2026-07 session on one machine (tasks example, Intel UHD 620 integrated GPU) β€” idle sampling plus a fast-hover-and-repaint-burst stress test, the same methodology for every backend so the comparison is apples-to-apples. They are not final, cross-platform, cross-hardware numbers. If you add heavy assets or large dependency trees, your app's footprint will differ β€” use glyx dev --perf to see live RSS.