gfx-rs/wgpu
wgpu-hal
Active contributors: Inner Daemons, teoxoy, Connor Fitzgerald, Andy Leiserson, Erich Gubler
wgpu-hal (wgpu-hal/) is the unsafe hardware abstraction layer. It defines a set of traits modeled on a "WebGPU shaped" command buffer + resource API, and ships one backend per platform graphics API.
Purpose
- Provide a portable trait surface (
Instance,Adapter,Device,Queue,CommandEncoder,Buffer,Texture, ...) that's a thin shim over real graphics APIs. - Move the cost of validation and state tracking to the layer above (
wgpu-core). HAL backends do as little as possible. - Use static dispatch by default (each backend has its own marker type implementing the
Apitrait); offer dynamic dispatch wrappers forwgpu-coreto use. - Map buffer contents persistently. Require explicit barriers between resource usages.
The wgpu-hal/README.md enumerates the design choices in detail and is required reading before modifying this crate.
Sub-pages by backend
- Vulkan — the primary backend. Linux, Android, Windows; macOS via MoltenVK.
- Metal — macOS, iOS, tvOS.
- DX12 — Windows.
- GLES — OpenGL ES, OpenGL, WebGL2, EGL/WGL/web.
- Noop — does nothing; used by validation tests.
Directory layout
wgpu-hal/
├── Cargo.toml
├── README.md
├── build.rs
├── examples/
└── src/
├── lib.rs trait surface (~108 KB)
├── auxil/ shared helpers (DXC compiler, format conversions, renderdoc)
├── dx12/ D3D12 backend
├── dynamic/ trait-object wrappers
├── gles/ GL/GLES/WebGL2 backend
├── metal/ Metal backend
├── noop/ no-op backend
├── validation_canary.rs shared canary file for validation-layer warnings
└── vulkan/ Vulkan backendThe trait surface is one of the largest files in the workspace (wgpu-hal/src/lib.rs, ~108 KB). It defines the Api associated-types trait and every type alias that backends implement.
Key abstractions
| Trait / type | File | Purpose |
|---|---|---|
Api |
wgpu-hal/src/lib.rs |
Marker trait whose associated types name every other HAL type. One impl per backend. |
Instance, Adapter, Device, Queue, CommandEncoder |
wgpu-hal/src/lib.rs |
The main lifecycle traits. |
Buffer, Texture, TextureView, Sampler, BindGroup, BindGroupLayout, PipelineLayout, RenderPipeline, ComputePipeline, ShaderModule |
wgpu-hal/src/lib.rs |
Resource types (the per-backend impls are concrete types). |
DynInstance, DynDevice, etc. |
wgpu-hal/src/dynamic/ |
Object-safe trait-object wrappers used by wgpu-core. |
auxil::dxc_shader_compiler |
wgpu-hal/src/auxil/dxc_shader_compiler.rs |
DXC integration shared by DX12 (and indirectly tests). |
auxil::renderdoc |
wgpu-hal/src/auxil/renderdoc.rs |
RenderDoc capture API integration. |
Backend selection
Backends are enabled at compile time via cfg flags (build.rs defines vulkan, metal, dx12, gles, noop). At runtime, wgpu-core constructs the Instance for each enabled backend that succeeds — see wgpu-core/src/instance.rs::Instance::try_add_hal. The WGPU_BACKEND environment variable filters which ones are tried.
Static vs dynamic dispatch
wgpu-hal is static-dispatch first. Each backend exposes a marker type:
// in wgpu-hal/src/vulkan/mod.rs
pub struct Api;
impl crate::Api for Api {
type Instance = vulkan::Instance;
type Device = vulkan::Device;
type Queue = vulkan::Queue;
// ...
}wgpu-core would otherwise have to be parameterized over A: hal::Api, which complicates its public surface. Instead, wgpu-hal/src/dynamic/ provides object-safe DynInstance/DynDevice/DynBuffer/... traits and blanket impls that let wgpu-core carry a Vec<(Backend, Box<dyn DynInstance>)>.
Safety contract
The wgpu-hal traits are unsafe. From the README:
- Implementations perform minimal validation. Incorrect use causes undefined behavior.
- Returned errors only cover cases the user can't anticipate (OOM, lost device).
- Pipeline layouts are explicitly specified when binding bind groups; a mismatched layout silently corrupts higher-indexed bindings.
- Barriers are explicit. The caller must call
transition_buffers/transition_texturesbetween conflicting usages. - Buffer maps are persistent. Coherency between CPU and GPU is the caller's responsibility unless the implementation reports the mapping as coherent.
- Iterators passed to HAL methods aren't guaranteed to be drained, so they shouldn't have side effects.
These rules are why wgpu-core exists: layering safety on top of wgpu-hal is a substantial amount of work, done once.
Integration points
- Above:
wgpu-coreis the only intended consumer. Thewgpu-halcrate is published independently for the rare downstream that wants to skipwgpu-coreand roll its own validation, but that path is not actively supported. - Below: each backend wraps a specific external crate or system API. See the per-backend pages.
- Sideways: shared helpers in
wgpu-hal/src/auxil/(DXC compiler glue, format helpers, renderdoc,validation_canary).
Entry points for modification
- Adding a HAL method — add it to the trait in
wgpu-hal/src/lib.rs, then implement it in every backend (vulkan/,metal/,dx12/,gles/,noop/). Add the matchingDynFoomethod inwgpu-hal/src/dynamic/. Then call it fromwgpu-core. - Adding a backend-specific extension — see the backend's page; some are exposed via
Adapter-level capability bits and a method that's only available when the bit is set. - Improving a backend — most work happens in the per-backend
mod.rs,device.rs,command.rs, andadapter.rsfiles. Hot paths in command encoding live incommand.rsfor each backend.
For each backend's specifics, follow the sub-page links above.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.