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 --> AdaptersInstance::newreadsInstanceDescriptor::backends(orWGPU_BACKEND) to decide which backends to try.- For each compiled-in backend whose bit is set,
wgpu-core/src/instance.rs::Instance::try_add_halconstructs the correspondinghal::Instance. Instance::request_adapterenumerates each constructed instance's adapters and returns the one that best matches the requester'sRequestAdapterOptions.
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.rsbecomes the active backend.- It calls
navigator.gpuviaweb-sys. - It does not link
wgpu-coreorwgpu-hal.
When you build for wasm with the webgl feature:
wgpu/src/backend/wgpu_core.rsis the active backend.wgpu-coreis linked in, but only the GLESwgpu-halbackend is enabled.- The result runs on WebGL2 via
web-sys'sWebGl2RenderingContext.
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:
- New module under
wgpu-hal/src/. Implementhal::Apiand every trait method. - New cfg gate in
Cargo.toml's feature list and incfg_aliasesinbuild.rs. - Plumb through
wgpu-core/src/instance.rs::Instance::try_add_hal. - Add the backend to
Backends/Backendinwgpu-types/src/backend.rs(this is a public API change). - Wire up shader translation if needed (a new
naga::back::*target, possibly). - 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.