Open-Source Wikis

/

wgpu

/

Features

/

Cross-platform backends

gfx-rs/wgpu

Cross-platform backends

wgpu runs on five fundamentally different APIs (Vulkan, Metal, D3D12, OpenGL ES, the browser's WebGPU) with one user-facing API. This page summarizes how that's done and what the trade-offs are.

What "supported" means here

API Crate that implements it Status
Vulkan wgpu-hal/src/vulkan/ First-class
Metal wgpu-hal/src/metal/ First-class
DX12 wgpu-hal/src/dx12/ First-class
OpenGL / GLES / WebGL2 wgpu-hal/src/gles/ Best-effort / downlevel
WebGPU (browser) wgpu/src/backend/webgpu.rs First-class on web
Noop wgpu-hal/src/noop/ Test-only
Custom wgpu/src/backend/custom.rs User-pluggable

The wgpu-core triangle (wgpu + wgpu-core + wgpu-hal) handles the four native + GLES backends. The browser path skips wgpu-core entirely: when compiled for wasm with the webgpu feature, wgpu/src/backend/webgpu.rs calls navigator.gpu via web-sys, and the browser provides validation.

How runtime selection works

graph TD
    User[User code] -->|Instance::new| Inst[wgpu::Instance]
    Inst -->|"Backends bitflags<br/>+ feature gates<br/>+ env WGPU_BACKEND"| Try[try_add_hal per backend]
    Try -->|cfg vulkan| Vk[vulkan::Instance]
    Try -->|cfg metal| Mt[metal::Instance]
    Try -->|cfg dx12| Dx[dx12::Instance]
    Try -->|cfg gles| Gl[gles::Instance]
    Try -->|cfg noop| No[noop::Instance]
    Vk --> Adapters
    Mt --> Adapters
    Dx --> Adapters
    Gl --> Adapters
    No --> Adapters
  1. Instance::new reads InstanceDescriptor::backends (or WGPU_BACKEND) to decide which backends to try.
  2. For each compiled-in backend whose bit is set, wgpu-core/src/instance.rs::Instance::try_add_hal constructs the corresponding hal::Instance.
  3. Instance::request_adapter enumerates each constructed instance's adapters and returns the one that best matches the requester's RequestAdapterOptions.

A single physical GPU can be exposed by multiple backends (e.g. on Windows, both Vulkan and DX12). Setting WGPU_BACKEND is the easiest way to disambiguate during testing.

Feature flags vs runtime detection

Features (wgpu-types/src/features.rs) is a runtime bitflag. Every adapter reports the features it actually supports. You enable the ones you want at request_device time; the device fails to create if any aren't available.

Cargo features (vulkan, metal, dx12, gles, webgpu, vulkan-portability, angle, static-dxc, ...) are compile-time. They control which HAL backends get built into the binary. CI builds with most features enabled; downstream applications usually leave them at their default.

Surface integration

Each platform exposes its own surface type. wgpu accepts raw-window-handle handles via Instance::create_surface, and each HAL backend's create_surface knows how to handle the platform-specific variants:

  • Win32 / WinRT (DX12, Vulkan, GLES via WGL).
  • Cocoa via raw-window-metal (Metal, GLES via ANGLE).
  • Wayland and X11 (Vulkan, GLES via EGL).
  • Android NDK (Vulkan, GLES via EGL).
  • DRM file descriptor (Vulkan, GLES via EGL — supported by some Linux compositors).
  • WASM canvas via web-sys (WebGPU, GLES via WebGL2).

The common surface shape is in wgpu-hal/src/lib.rs::Surface; the per-backend impls are in wgpu-hal/src/<backend>/surface*.rs (or swapchain/).

Per-backend feature surface

Different backends support different parts of WebGPU. The truth is in wgpu-hal/src/<backend>/adapter.rs's feature-detection code and the per-backend pages:

  • Vulkan — most complete coverage.
  • Metal — close behind, with macOS-specific quirks.
  • DX12 — good coverage; some features tied to specific Agility SDK versions.
  • GLES — explicit downlevel reporting; many features unsupported.
  • Noop — no GPU support; for tests only.

wgpu-info (cargo run -p wgpu-info) prints the supported feature set per adapter.

The web path

When you build wgpu for wasm32-unknown-unknown with the webgpu feature:

  • wgpu/src/backend/webgpu.rs becomes the active backend.
  • It calls navigator.gpu via web-sys.
  • It does not link wgpu-core or wgpu-hal.

When you build for wasm with the webgl feature:

  • wgpu/src/backend/wgpu_core.rs is the active backend.
  • wgpu-core is linked in, but only the GLES wgpu-hal backend is enabled.
  • The result runs on WebGL2 via web-sys's WebGl2RenderingContext.

When you build for wasm with both: WebGPU is preferred at runtime, with WebGL2 as a fallback when WebGPU isn't available in the browser.

Adding a backend

Adding a new backend is a major undertaking:

  1. New module under wgpu-hal/src/. Implement hal::Api and every trait method.
  2. New cfg gate in Cargo.toml's feature list and in cfg_aliases in build.rs.
  3. Plumb through wgpu-core/src/instance.rs::Instance::try_add_hal.
  4. Add the backend to Backends/Backend in wgpu-types/src/backend.rs (this is a public API change).
  5. Wire up shader translation if needed (a new naga::back::* target, possibly).
  6. Add tests under tests/tests/wgpu-gpu/ and CI configuration.

Per CONTRIBUTING.md, large changes like this need to be socialized before being implemented.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Cross-platform backends – wgpu wiki | Factory