gfx-rs/wgpu
wgpu-core
Active contributors: Andy Leiserson, Erich Gubler, Connor Fitzgerald, teoxoy, Inner Daemons
wgpu-core (wgpu-core/) is the portable, FFI-friendly implementation of WebGPU. It implements the WebGPU specification's semantics: validation, resource state tracking, command translation, submission, lifetime management. It is what Firefox and Deno actually link against; the wgpu crate is a friendlier Rust facade over it.
Purpose
- Implement WebGPU spec semantics on top of the unsafe
wgpu-haltraits. - Validate every descriptor and every command before it reaches the driver.
- Track resource usage states across pass boundaries to insert pipeline barriers correctly.
- Provide an ID-based public API suitable for FFI (Firefox uses C bindings; Deno uses Rust + Deno's own FFI).
- Offer optional API tracing and replay (
Traceinfrastructure) for crash repros and regression testing.
Directory layout
wgpu-core/
├── Cargo.toml
├── README.md
├── build.rs
├── platform-deps/ per-target glue (apple, wasm, emscripten, win/linux/android)
└── src/
├── lib.rs crate root
├── as_hal.rs "convert this id to a hal handle" trait
├── binding_model.rs BindGroup, BindGroupLayout, PipelineLayout (51 KB)
├── command/ CommandEncoder + pass implementations
│ ├── mod.rs ~76 KB main implementation
│ ├── render.rs render-pass implementation (~140 KB)
│ ├── compute.rs compute-pass (~50 KB)
│ ├── bundle.rs render bundles (~63 KB)
│ ├── ray_tracing.rs BLAS/TLAS commands (~52 KB)
│ ├── transfer.rs copy commands (~57 KB)
│ ├── clear.rs clear commands
│ └── ...
├── conv.rs type conversions to hal types
├── device/ Device + Queue + lifetime
│ ├── mod.rs
│ ├── resource.rs Device implementation (~210 KB)
│ ├── queue.rs Queue (~78 KB)
│ ├── global.rs Global FFI surface (~76 KB)
│ ├── life.rs lifetime tracker
│ ├── trace.rs / trace/ API trace recording
│ └── ...
├── error.rs top-level error types
├── global.rs Global type wrapping the Hub
├── hub.rs per-device resource hub
├── id.rs Id, Marker
├── identity.rs identity management
├── indirect_validation/ indirect-draw validation pipeline
├── init_tracker/ track which buffer ranges are initialized
├── instance.rs Instance, Adapter
├── limits.rs limit checking
├── lock/ ranked lock helpers
├── pipeline.rs shader/pipeline types
├── pipeline_cache.rs persistent pipeline cache
├── pool.rs generic dedup cache
├── present.rs surface acquire/present
├── ray_tracing.rs core ray-tracing types
├── registry.rs typed resource registry
├── resource.rs Buffer, Texture, Sampler, ... (~91 KB)
├── snatch.rs "snatch" cell
├── storage.rs slot-based storage
├── timestamp_normalization/ normalize HW timestamps
├── track/ state-tracking machinery
├── validation.rs shader binding validation (~85 KB)
├── validation/ helpers
└── weak_vec.rswgpu-core/src/device/resource.rs (210 KB, the largest file in wgpu-core) is the canonical place to look when you want to know "what does device.create_X do?". wgpu-core/src/device/global.rs (76 KB) is the FFI surface — every public function on Global.
Key abstractions
| Type / module | File | Purpose |
|---|---|---|
Global |
wgpu-core/src/global.rs |
Top-level container. Every FFI entry point is a method on it. |
Hub |
wgpu-core/src/hub.rs |
Set of registries: buffers, textures, bind groups, pipelines, queries, ... |
Registry<T> |
wgpu-core/src/registry.rs |
Typed accessor over a Storage<T, M>. |
Storage<T, M> |
wgpu-core/src/storage.rs |
Slot-based store keyed by Id<M>. Recycles indices. |
Id<M> |
wgpu-core/src/id.rs |
64-bit handle: index + epoch + backend bits. |
Device |
wgpu-core/src/device/resource.rs |
Logical GPU; owner of every resource it created. |
Queue |
wgpu-core/src/device/queue.rs |
Submission and pending-write management. |
LifetimeTracker |
wgpu-core/src/device/life.rs |
Per-submission resource cleanup. |
Buffer, Texture, etc. |
wgpu-core/src/resource.rs |
Tracked resource structs. |
BindGroup, BindGroupLayout, PipelineLayout |
wgpu-core/src/binding_model.rs |
Bind group machinery. |
RenderPipeline, ComputePipeline, ShaderModule |
wgpu-core/src/pipeline.rs |
Pipeline objects. |
| Trackers | wgpu-core/src/track/ |
BufferTracker, TextureTracker, usage scopes. |
Trace |
wgpu-core/src/device/trace.rs |
API recording. |
How it works
sequenceDiagram
participant User as User (wgpu or FFI)
participant Global as Global / Hub
participant Device
participant Tracker as track/*
participant Hal as wgpu-hal
User->>Global: queue_submit(queue_id, command_buffers)
Global->>Device: queue.submit(...)
Device->>Tracker: merge command-buffer trackers
Tracker->>Tracker: compute usage transitions
Device->>Hal: encode barriers via cmd_buf
Device->>Hal: queue.submit(cmd_bufs, fence)
Hal-->>Device: submission index
Device->>Device: register resources with LifetimeTrackerThe flow above is the most important one to understand. Every command-buffer recording produces per-buffer-buffer trackers; submission merges them into the device's tracker, computes the necessary barriers, encodes them, and submits the resulting hal-level command buffers. LifetimeTracker then records that the resources used by the submission can be dropped once the GPU finishes.
Validation
Validation is woven through the implementation rather than living in a separate "validator" module. Each method on Global (in wgpu-core/src/device/global.rs) calls into Device::create_buffer, Device::create_render_pipeline, etc. (in device/resource.rs), which performs descriptor checks before constructing the underlying HAL resource.
Cross-cutting validators that do live in named modules:
- Shader binding validation (
wgpu-core/src/validation.rs, ~85 KB) — checks that a pipeline's bind group layouts match its shader's interface. - Limit checking (
wgpu-core/src/limits.rs) — sanity-checksLimitsagainst the adapter's capabilities. - Indirect-draw validation (
wgpu-core/src/indirect_validation/) — a compute shader runs at submission time to validatemulti_draw_indirect_*parameters before the GPU consumes them. This is the only place where wgpu-core itself runs a GPU pipeline. - Init tracker (
wgpu-core/src/init_tracker/) — clears uninitialized buffer/texture regions on first use to avoid leaking previous contents. - Timestamp normalization (
wgpu-core/src/timestamp_normalization/) — another compute shader that maps HAL timestamp counters into nanoseconds, smoothing over driver differences.
Locking
wgpu-core uses fine-grained, ranked locks (wgpu-core/src/lock/). Every Mutex/RwLock is created with a static rank; the lock helpers panic in debug builds if locks are taken out of order. Recent commits show this is actively maintained:
fix(core): Order BUFFER_MAP_STATE lock after QUEUE_PENDING_WRITESfix(core): Don't overlap QUEUE_PENDING_WRITES and QUEUE_LIFE_TRACKER locks
When you add a new lock, pick or add a rank in wgpu-core/src/lock/rank.rs. Run cargo nextest run -p wgpu-core — the lock helpers will surface ordering violations.
Public API surface
wgpu-core is consumed in two ways:
- Through the
wgpucrate — every method onGlobalis wrapped bywgpu/src/backend/wgpu_core.rs. - Directly, via Firefox / Deno — Firefox's
gfx/wgpu_bindings/and Deno'sdeno_webgpu/(in this repo!) callGlobal::queue_submit,Global::device_create_buffer, etc. The shape of every method makes the parameters trivially convertible across an FFI boundary: take anId, return aResult<Id, Error>orResult<(), Error>.
This is why wgpu-core is extern crate wgpu_hal as hal; extern crate wgpu_types as wgt; and not use wgpu_hal::*; — the layout of its public types must be predictable.
Integration points
- Above:
wgpu(wgpu/src/backend/wgpu_core.rs),deno_webgpu(deno_webgpu/), Firefox'swgpu_bindings. - Below:
wgpu-halfor everything that touches the GPU;wgpu-naga-bridgefor shader translation;wgpu-typesfor plain data. - Optional: enables
Tracerecording (wgpu-core/src/device/trace.rs) consumed byplayer.
Entry points for modification
- A new WebGPU method — add a method to
Globalinwgpu-core/src/device/global.rs, calling into the matchingDevicemethod indevice/resource.rs. Validate the descriptor; obtain the HAL handle; allocate anId; insert into the registry; return theId. - A new validation rule — add the check inside the relevant
Device::create_Xmethod, returning a typed error from the module's error enum. Add a test intests/tests/wgpu-validation/so it's covered without a real GPU. - A new state-tracking case — modify the appropriate
track/*module. The trackers operate onIds and produce HAL-level transitions. - A new lock — see patterns-and-conventions. Always use
wgpu-core/src/lock/'s helpers, never rawparking_lot.
For deep dives on individual subsystems (the tracker, the lifetime manager, the trace format), wgpu-core/src/track/, wgpu-core/src/device/life.rs, and wgpu-core/src/device/trace.rs are the canonical reads.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.