Crate wgpu_hal

Source
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 driving wgpu-hal, implementing all necessary validation, resource state tracking, and so on. (Note that wgpu-core is designed for use via FFI; the wgpu crate provides more idiomatic Rust bindings for wgpu-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 or metal::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 Device::map_buffer indicates that this is necessary.

  • 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 groups. 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 windows 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 a wgpu-hal backend. It has no methods of its own, only a collection of associated types.

  • Api::Instance implements the Instance 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 the Adapter 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 the Device trait, representing an active link to a device. You get a device value by calling Adapter::open, and then use it to create buffers, textures, shader modules, and so on.

  • Api::Queue implements the Queue trait, which you use to submit command buffers to a given device.

  • Api::CommandEncoder implements the CommandEncoder 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 the Surface 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§

api
auxil
empty
A dummy API implementation.
glesgles
GLES API internals.
vulkanvulkan
Vulkan API internals.

Structs§

AccelerationStructureAABBs
offset - offset in bytes
AccelerationStructureBarrier
AccelerationStructureBuildFlags
Flags for acceleration structures
AccelerationStructureBuildSizes
Information of the required size for a corresponding entries struct (+ flags)
AccelerationStructureDescriptor
AccelerationStructureGeometryFlags
Flags for acceleration structure geometries
AccelerationStructureInstances
offset - offset in bytes
AccelerationStructureTriangleIndices
offset - offset in bytes
AccelerationStructureTriangleTransform
offset - offset in bytes
AccelerationStructureTriangles
first_vertex - offset in the vertex buffer (as number of vertices)indices - optional index buffer with attributestransform - optional transform
AccelerationStructureUses
AcquiredSurfaceTexture
Alignments
Attachment
AttachmentOps
BindGroupDescriptor
BindGroup descriptor.
BindGroupEntry
BindGroupLayoutDescriptor
BindGroupLayout descriptor.
BindGroupLayoutFlags
Pipeline layout creation flags.
BufferBarrier
BufferBinding
A region of a buffer made visible to shaders via a BindGroup.
BufferCopy
BufferDescriptor
BufferMapping
BufferTextureCopy
BufferUses
Similar to wgt::BufferUsages but for internal use.
BuildAccelerationStructureDescriptor
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).
Capabilities
ColorAttachment
CommandEncoderDescriptor
ComputePassDescriptor
ComputePipelineDescriptor
Describes a compute pipeline.
CopyExtent
DebugSource
DepthStencilAttachment
DropGuardgles or vulkan
DynAcquiredSurfaceTexture
DynExposedAdapter
DynOpenDevice
ExposedAdapter
FormatAspects
Texture format capability flags.
GetAccelerationStructureBuildSizesDescriptor
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.
InstanceDescriptor
InstanceError
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.
MemoryFlags
NagaShader
Naga shader module.
OpenDevice
PassTimestampWrites
PipelineCacheDescriptor
PipelineLayoutDescriptor
PipelineLayoutFlags
Pipeline layout creation flags.
ProgrammableStage
Describes a programmable pipeline stage.
Rect
RenderPassDescriptor
RenderPipelineDescriptor
Describes a render (graphics) pipeline.
SamplerDescriptor
ShaderModuleDescriptor
StateTransition
SurfaceCapabilities
Describes information about what a Surface’s presentation capabilities are. Fetch this with Adapter::surface_capabilities.
SurfaceConfiguration
TextureBarrier
TextureBinding
TextureCopy
TextureCopyBase
TextureDescriptor
TextureFormatCapabilities
Texture format capability flags.
TextureUses
Similar to wgt::TextureUsages but for internal use.
TextureViewDescriptor
TextureView descriptor.
TlasInstance
ValidationCanary
Flag for internal testing.
VertexBufferLayout
Describes how the vertex buffer is interpreted.

Enums§

AccelerationStructureBuildMode
AccelerationStructureEntries
Entries for a single descriptor
AccelerationStructureFormat
DeviceError
PipelineCacheError
PipelineError
ShaderError
ShaderInput
Shader input.
SurfaceError

Constants§

MAX_ANISOTROPY
MAX_BIND_GROUPS
MAX_COLOR_ATTACHMENTS
MAX_CONCURRENT_SHADER_STAGES
MAX_MIP_LEVELS
MAX_VERTEX_BUFFERS
QUERY_SIZE
Size of a single occlusion/timestamp query, when copied into a buffer, in bytes.

Statics§

VALIDATION_CANARY
Stores the text of any validation errors that have occurred since the last call to get_and_reset.

Traits§

Adapter
Api
CommandEncoder
Encoder and allocation pool for CommandBuffers.
Device
A connection to a GPU and a pool of resources to use with it.
DynAccelerationStructure
DynAdapter
DynBindGroup
DynBindGroupLayout
DynBuffer
DynCommandBuffer
DynCommandEncoder
DynComputePipeline
DynDevice
DynFence
DynInstance
DynPipelineCache
DynPipelineLayout
DynQuerySet
DynQueue
DynRenderPipeline
DynResource
Base trait for all resources, allows downcasting via Any.
DynSampler
DynShaderModule
DynSurface
DynSurfaceTexture
DynTexture
DynTextureView
Instance
Queue
Surface

Type Aliases§

AtomicFenceValue
DropCallbackgles or vulkan
A callback to signal that wgpu is no longer using a resource.
FenceValue
Label
MemoryRange