Expand description
A cross-platform unsafe graphics abstraction.
This crate defines a set of traits abstracting over modern graphics APIs, with implementations (“backends”) for Vulkan, Metal, Direct3D, and GL.
wgpu-hal
is a spiritual successor to
gfx-hal, but with reduced scope, and
oriented towards WebGPU implementation goals. It has no overhead for
validation or tracking, and the API translation overhead is kept to the bare
minimum by the design of WebGPU. This API can be used for resource-demanding
applications and engines.
The wgpu-hal
crate’s main design choices:
-
Our traits are meant to be portable: proper use should get equivalent results regardless of the backend.
-
Our traits’ contracts are unsafe: implementations perform minimal validation, if any, and incorrect use will often cause undefined behavior. This allows us to minimize the overhead we impose over the underlying graphics system. If you need safety, the
wgpu-core
crate provides a safe API for drivingwgpu-hal
, implementing all necessary validation, resource state tracking, and so on. (Note thatwgpu-core
is designed for use via FFI; thewgpu
crate provides more idiomatic Rust bindings forwgpu-core
.) Or, you can do your own validation. -
In the same vein, returned errors only cover cases the user can’t anticipate, like running out of memory or losing the device. Any errors that the user could reasonably anticipate are their responsibility to avoid. For example,
wgpu-hal
returns no error for mapping a buffer that’s not mappable: as the buffer creator, the user should already know if they can map it. -
We use static dispatch. The traits are not generally object-safe. You must select a specific backend type like
vulkan::Api
ormetal::Api
, and then use that according to the main traits, or call backend-specific methods. -
We use idiomatic Rust parameter passing, taking objects by reference, returning them by value, and so on, unlike
wgpu-core
, which refers to objects by ID. -
We map buffer contents persistently. This means that the buffer can remain mapped on the CPU while the GPU reads or writes to it. You must explicitly indicate when data might need to be transferred between CPU and GPU, if
wgpu-hal
indicates that the mapping is not coherent (that is, automatically synchronized between the two devices). -
You must record explicit barriers between different usages of a resource. For example, if a buffer is written to by a compute shader, and then used as and index buffer to a draw call, you must use
CommandEncoder::transition_buffers
between those two operations. -
Pipeline layouts are explicitly specified when setting bind group. Incompatible layouts disturb groups bound at higher indices.
-
The API accepts collections as iterators, to avoid forcing the user to store data in particular containers. The implementation doesn’t guarantee that any of the iterators are drained, unless stated otherwise by the function documentation. For this reason, we recommend that iterators don’t do any mutating work.
Unfortunately, wgpu-hal
‘s safety requirements are not fully documented.
Ideally, all trait methods would have doc comments setting out the
requirements users must meet to ensure correct and portable behavior. If you
are aware of a specific requirement that a backend imposes that is not
ensured by the traits’ documented rules, please file an issue. Or, if you are
a capable technical writer, please file a pull request!
§Primary backends
The wgpu-hal
crate has full-featured backends implemented on the following
platform graphics APIs:
-
Vulkan, available on Linux, Android, and Windows, using the
ash
crate’s Vulkan bindings. It’s also available on macOS, if you install MoltenVK. -
Metal on macOS, using the
metal
crate’s bindings. -
Direct3D 12 on Windows, using the
d3d12
crate’s bindings.
§Secondary backends
The wgpu-hal
crate has a partial implementation based on the following
platform graphics API:
- The GL backend is available anywhere OpenGL, OpenGL ES, or WebGL are
available. See the
gles
module documentation for details.
You can see what capabilities an adapter is missing by checking the
DownlevelCapabilities
in ExposedAdapter::capabilities
, available
from Instance::enumerate_adapters
.
The API is generally designed to fit the primary backends better than the secondary backends, so the latter may impose more overhead.
§Traits
The wgpu-hal
crate defines a handful of traits that together
represent a cross-platform abstraction for modern GPU APIs.
-
The
Api
trait represents awgpu-hal
backend. It has no methods of its own, only a collection of associated types. -
Api::Instance
implements theInstance
trait.Instance::init
creates an instance value, which you can use to enumerate the adapters available on the system. For example,vulkan::Api::Instance::init
returns an instance that can enumerate the Vulkan physical devices on your system. -
Api::Adapter
implements theAdapter
trait, representing a particular device from a particular backend. For example, a Vulkan instance might have a Lavapipe software adapter and a GPU-based adapter. -
Api::Device
implements theDevice
trait, representing an active link to a device. You get a device value by callingAdapter::open
, and then use it to create buffers, textures, shader modules, and so on. -
Api::Queue
implements theQueue
trait, which you use to submit command buffers to a given device. -
Api::CommandEncoder
implements theCommandEncoder
trait, which you use to build buffers of commands to submit to a queue. This has all the methods for drawing and running compute shaders, which is presumably what you’re here for. -
Api::Surface
implements theSurface
trait, which represents a swapchain for presenting images on the screen, via interaction with the system’s window manager.
The Api
trait has various other associated types like Api::Buffer
and
Api::Texture
that represent resources the rest of the interface can
operate on, but these generally do not have their own traits.
§Validation is the calling code’s responsibility, not wgpu-hal
’s
As much as possible, wgpu-hal
traits place the burden of validation,
resource tracking, and state tracking on the caller, not on the trait
implementations themselves. Anything which can reasonably be handled in
backend-independent code should be. A wgpu_hal
backend’s sole obligation is
to provide portable behavior, and report conditions that the calling code
can’t reasonably anticipate, like device loss or running out of memory.
The wgpu
crate collection is intended for use in security-sensitive
applications, like web browsers, where the API is available to untrusted
code. This means that wgpu-core
’s validation is not simply a service to
developers, to be provided opportunistically when the performance costs are
acceptable and the necessary data is ready at hand. Rather, wgpu-core
’s
validation must be exhaustive, to ensure that even malicious content cannot
provoke and exploit undefined behavior in the platform’s graphics API.
Because graphics APIs’ requirements are complex, the only practical way for
wgpu
to provide exhaustive validation is to comprehensively track the
lifetime and state of all the resources in the system. Implementing this
separately for each backend is infeasible; effort would be better spent
making the cross-platform validation in wgpu-core
legible and trustworthy.
Fortunately, the requirements are largely similar across the various
platforms, so cross-platform validation is practical.
Some backends have specific requirements that aren’t practical to foist off
on the wgpu-hal
user. For example, properly managing macOS Objective-C or
Microsoft COM reference counts is best handled by using appropriate pointer
types within the backend.
A desire for “defense in depth” may suggest performing additional validation
in wgpu-hal
when the opportunity arises, but this must be done with
caution. Even experienced contributors infer the expectations their changes
must meet by considering not just requirements made explicit in types, tests,
assertions, and comments, but also those implicit in the surrounding code.
When one sees validation or state-tracking code in wgpu-hal
, it is tempting
to conclude, “Oh, wgpu-hal
checks for this, so wgpu-core
needn’t worry
about it - that would be redundant!” The responsibility for exhaustive
validation always rests with wgpu-core
, regardless of what may or may not
be checked in wgpu-hal
.
To this end, any “defense in depth” validation that does appear in wgpu-hal
for requirements that wgpu-core
should have enforced should report failure
via the unreachable!
macro, because problems detected at this stage always
indicate a bug in wgpu-core
.
§Debugging
Most of the information on the wiki Debugging wgpu Applications
page still applies to this API, with the exception of API tracing/replay
functionality, which is only available in wgpu-core
.
Modules§
- A dummy API implementation.
- GLES API internals.
- Vulkan API internals.
Structs§
offset
- offset in bytes- Flags for acceleration structures
- Information of the required size for a corresponding entries struct (+ flags)
- Flags for acceleration structure geometries
offset
- offset in bytesoffset
- offset in bytesoffset
- offset in bytesfirst_vertex
- offset in the vertex buffer (as number of vertices)indices
- optional index buffer with attributestransform
- optional transform- BindGroup descriptor.
- BindGroupLayout descriptor.
- Pipeline layout creation flags.
- Similar to
wgt::BufferUsages
but for internal use. - Updates use source_acceleration_structure if present, else the update will be performed in place. For updates, only the data is allowed to change (not the meta data or sizes).
- Describes a compute pipeline.
- Texture format capability flags.
- All buffers, buffer addresses and offsets will be ignored.The build mode will be ignored.Reducing the amount of Instances, Triangle groups or AABB groups (or the number of Triangles/AABBs in corresponding groups), may result in reduced size requirements.Any other change may result in a bigger or smaller size requirement.
- Error occurring while trying to create an instance, or create a surface from an instance; typically relating to the state of the underlying graphics API or hardware.
- Naga shader module.
- Pipeline layout creation flags.
- Describes a programmable pipeline stage.
- Describes a render (graphics) pipeline.
- Describes information about what a
Surface
’s presentation capabilities are. Fetch this with Adapter::surface_capabilities. - Texture format capability flags.
- Similar to
wgt::TextureUsages
but for internal use. - TextureView descriptor.
- Flag for internal testing.
- Describes how the vertex buffer is interpreted.
Enums§
- Entries for a single descriptor
- Shader input.
Constants§
- Size of a single occlusion/timestamp query, when copied into a buffer, in bytes.
Statics§
- Stores the text of any validation errors that have occurred since the last call to
get_and_reset
.
Traits§
- Encoder and allocation pool for
CommandBuffer
s.
Type Aliases§
- Drop guard to signal wgpu-hal is no longer using an externally created object.