WebGPU Rendering Backend

Important

The WebGPU rendering backend is experimental. Skia remains the default renderer, and an app uses WebGPU only when it selects it on its host builder.

The WebGPU backend is an alternative to the SkiaSharp backend for drawing the UI. It renders through WebGPU: the wgpu-native library on native targets, and the browser's WebGPU support on WebAssembly.

Adding the backend

Add the WebGpu UnoFeature to the app project:

<UnoFeatures>Skia;WebGpu</UnoFeatures>

WebGpu counts as a renderer feature, so listing it stops Skia from being implied. List both, as above, to keep SkiaSharp in the app, which the fallback described below needs. Listing WebGpu without Skia produces an app with no SkiaSharp (see Apps without SkiaSharp).

The WebGpu feature also adds WebGpuCanvasElement, which draws only with the WebGPU backend.

Selecting WebGPU on the host builder

Referencing the backend doesn't turn it on: wherever SkiaSharp is present, Skia renders by default. To render with WebGPU, register it with GraphicsBackend(...) on the host builder:

using Uno.UI.Composition.Skia;
using Uno.UI.Composition.WebGpu;
using Uno.UI.Hosting;

var host = UnoPlatformHostBuilder.Create()
    .App(() => new App())
    .GraphicsBackend(WebGpuBackend.CreateGraphicsProvider())
    .GraphicsBackend(SkiaBackend.CreateGraphicsProvider())
    .UseX11()
    .UseLinuxFrameBuffer()
    .UseMacOS()
    .UseWin32()
    .Build();

host.Run();

The same two calls apply to the host builder of each target, for example before .UseAndroid(), .UseAppleUIKit() or .UseWebAssembly().

Fallback

Each GraphicsBackend(...) call adds a backend in order of preference. When a window is created, the backends are tried in that order, and the first one that initializes is used.

Registering any backend replaces the implicit Skia default. An app that registers only WebGPU therefore has no fallback: on a device or browser where WebGPU can't be initialized, startup fails with an InvalidOperationException listing each attempt. To fall back to Skia, register it after WebGPU, as in the sample above.

On Windows (Win32) and Linux (X11), the host builder's backend options also apply to WebGPU. DisableRenderingBackends(Win32RenderingBackend.WebGpu) or DisableRenderingBackends(X11RenderingBackend.WebGpu) keeps an app that registers WebGPU on the Skia backends, and forcing any other backend with ForceRenderingBackend(...) excludes WebGPU. See Vulkan Rendering Backend.

Supported hosts

Host WebGPU
Windows (Win32) Yes
Linux (X11) Yes
macOS Yes, unless the host renders in software (no Metal, or FeatureConfiguration.Rendering.UseMetalOnMacOS = false)
Android Yes
iOS Yes
WebAssembly Yes, in browsers with WebGPU support, except when software rendering is forced
tvOS No: the backend ships no native WebGPU library for it
Linux framebuffer No
Windows App SDK No: this target renders with WinUI

Where WebGPU isn't available, an app that registered Skia after it renders with Skia.

Apps without SkiaSharp

When UnoFeatures lists WebGpu without Skia, the app references neither SkiaSharp nor its native libraries. WebGPU is then the only renderer, and it is used without a GraphicsBackend(...) call. Fonts, images, geometry, SVG and Lottie use the managed engines built into Uno Platform (Uno.UI.Composition.Managed.ManagedBackend) instead of their SkiaSharp implementations.

Such an app has no fallback renderer, and can't use SkiaSharp itself, for example to draw with SKCanvasElement. An app that needs either lists Skia;WebGpu.

To configure the managed font provider, register it with FontProvider(ManagedBackend.CreateFontProvider(...)) on the host builder. Its bundledDefaultFont parameter sets the default face on platforms whose system fonts can't be enumerated (iOS and WebAssembly), and enableFallback is described in Custom fonts.

Diagnostic logging

To see which backend was selected, enable information-level logging for the negotiation:

builder.AddFilter("Uno.UI.Composition.Drawing", LogLevel.Information);

The selected backend is logged as:

Graphics backend '<backend>' won negotiation on context kind '<kind>'.

See also