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-corecrate provides a safe API for drivingwgpu-hal, implementing all necessary validation, resource state tracking, and so on. (Note thatwgpu-coreis designed for use via FFI; thewgpucrate 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-halreturns 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::Apiormetal::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-halindicates 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_buffersbetween 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
ashcrate’s Vulkan bindings. It’s also available on macOS, if you install MoltenVK. -
Metal on macOS, using the
metalcrate’s bindings. -
Direct3D 12 on Windows, using the
d3d12crate’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
glesmodule 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
Apitrait represents awgpu-halbackend. It has no methods of its own, only a collection of associated types. -
Api::Instanceimplements theInstancetrait.Instance::initcreates an instance value, which you can use to enumerate the adapters available on the system. For example,vulkan::Api::Instance::initreturns an instance that can enumerate the Vulkan physical devices on your system. -
Api::Adapterimplements theAdaptertrait, 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::Deviceimplements theDevicetrait, 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::Queueimplements theQueuetrait, which you use to submit command buffers to a given device. -
Api::CommandEncoderimplements theCommandEncodertrait, 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::Surfaceimplements theSurfacetrait, 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::BufferUsagesbut 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::TextureUsagesbut 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
CommandBuffers.
Type Aliases§
- Drop guard to signal wgpu-hal is no longer using an externally created object.