wgpu/
lib.rs

1//! `wgpu` is a cross-platform, safe, pure-Rust graphics API. It runs natively on
2//! Vulkan, Metal, D3D12, and OpenGL; and on top of WebGL2 and WebGPU on wasm.
3//!
4//! The API is based on the [WebGPU standard][webgpu], but is a fully native Rust library.
5//! It serves as the core of the WebGPU integration in Firefox, Servo, and Deno.
6//!
7//! [webgpu]: https://gpuweb.github.io/gpuweb/
8//!
9//! ## Getting Started
10//!
11//! The main entry point to the API is the [`Instance`] type, from which you can create [`Adapter`], [`Device`], and [`Surface`].
12//!
13//! If you are new to `wgpu` and graphics programming, we recommend starting with [Learn Wgpu].
14//! <!-- Note, "Learn Wgpu" is using the capitalization style in their header, NOT our styling -->
15//!
16//! Additionally, [WebGPU Fundamentals] is a tutorial for WebGPU which is very similar to our API, minus differences between Rust and Javascript.
17//!
18//! We have a [wiki](https://github.com/gfx-rs/wgpu/wiki) which has information on useful architecture patterns, debugging tips, and more getting started information.
19//!
20//! There are examples for this version [available on GitHub](https://github.com/gfx-rs/wgpu/tree/v30/examples#readme).
21//!
22//! The API is refcounted, so all handles are cloneable, and if you create a resource which references another,
23//! it will automatically keep dependent resources alive.
24//!
25//! `wgpu` uses the coordinate systems of D3D and Metal. Depth ranges from [0, 1].
26//!
27//! | Render                | Texture                |
28//! | --------------------- | ---------------------- |
29//! | ![render_coordinates] | ![texture_coordinates] |
30//!
31//! `wgpu`'s MSRV is **1.87**.
32//!
33//! [Learn Wgpu]: https://sotrh.github.io/learn-wgpu/
34//! [WebGPU Fundamentals]: https://webgpufundamentals.org/
35//! [render_coordinates]: https://raw.githubusercontent.com/gfx-rs/wgpu/refs/heads/v30/docs/render_coordinates.png
36//! [texture_coordinates]: https://raw.githubusercontent.com/gfx-rs/wgpu/refs/heads/v30/docs/texture_coordinates.png
37//!
38//! ## Extension Specifications
39//!
40//! While the core of `wgpu` is based on the WebGPU standard, we also support extensions that allow for features that the standard does not have yet.
41//! For high-level documentation on how to use these extensions, see documentation on [`Features`] or the relevant specification:
42//!
43//! 🧪EXPERIMENTAL🧪 APIs are subject to change and may allow undefined behavior if used incorrectly.
44//!
45//! - 🧪EXPERIMENTAL🧪 [Ray Tracing](https://github.com/gfx-rs/wgpu/blob/v30/docs/api-specs/ray_tracing.md).
46//! - 🧪EXPERIMENTAL🧪 [Mesh Shading](https://github.com/gfx-rs/wgpu/blob/v30/docs/api-specs/mesh_shading.md).
47//!
48//! ## Shader Support
49//!
50//! `wgpu` can consume shaders in [WGSL](https://gpuweb.github.io/gpuweb/wgsl/), SPIR-V, and GLSL.
51//! Both [HLSL](https://github.com/Microsoft/DirectXShaderCompiler) and [GLSL](https://github.com/KhronosGroup/glslang)
52//! have compilers to target SPIR-V. All of these shader languages can be used with any backend as we handle all of the conversions. Additionally, support for these shader inputs is not going away.
53//!
54//! While WebGPU does not support any shading language other than WGSL, we will automatically convert your
55//! non-WGSL shaders if you're running on WebGPU.
56//!
57//! WGSL is always supported by default, but GLSL and SPIR-V need features enabled to compile in support.
58//!
59//! To enable WGSL shaders, enable the `wgsl` feature of `wgpu` (enabled by default).
60//! To enable SPIR-V shaders, enable the `spirv` feature of `wgpu`.
61//! To enable GLSL shaders, enable the `glsl` feature of `wgpu`.
62//!
63//! ## Feature flags
64#![doc = document_features::document_features!()]
65//!
66//! ### Feature Aliases
67//!
68//! These features aren't actually features on the crate itself, but a convenient shorthand for
69//! complicated cases.
70//!
71//! - **`wgpu_core`** --- Enabled when there is any non-webgpu backend enabled on the platform.
72//! - **`naga`** --- Enabled when target `glsl` or `spirv` input is enabled, or when `wgpu_core` is enabled.
73//!
74//! ## Surface color spaces and HDR output
75//!
76//! A surface can present in different color spaces to get HDR or wide-gamut
77//! output onto the screen. This is configured through
78//! [`SurfaceConfiguration::color_space`], and the rest of this section is a
79//! concept primer on how it works.
80//!
81//! ### HDR output in a nutshell
82//!
83//! By default a surface is standard dynamic range (SDR) with the sRGB gamut: the
84//! value `1.0` is the brightest white, anything above it clips, and only colors
85//! within sRGB are expressible. Other [`SurfaceColorSpace`]s opt into a **wider
86//! gamut** (for example [`DisplayP3`](SurfaceColorSpace::DisplayP3), still SDR
87//! but with more saturated colors than sRGB), **high dynamic range** (values
88//! above `1.0` drive brighter-than-white output), or both (for example
89//! [`Bt2100Pq`](SurfaceColorSpace::Bt2100Pq), aka HDR10), on platforms that
90//! support it.
91//!
92//! Three ideas carry most of the weight:
93//!
94//! * **Reference white and headroom.** Brightness is measured in *nits*
95//!   (cd/m²). On HDR-capable monitors, SDR reference white (plain white, `(1.0, 1.0, 1.0)` in the
96//!   extended color spaces) sits *below* the display's peak output on purpose, so
97//!   highlights have room above it. That gap is the display's *headroom*.
98//! * **The transfer function is a round-trip.** Your shader applies an
99//!   encoding transfer function (the OETF) to turn the light it computed into a
100//!   stored signal, and the display applies the inverse decoding transfer
101//!   function (the EOTF) to turn it back into light. Choosing a color space
102//!   chooses which transfer functions both ends use.
103//! * **Who applies the encoding transfer function.** wgpu applies it for you
104//!   **only** when you render to an `*Srgb` texture view format, where the GPU
105//!   runs the sRGB OETF when a value is stored to a texture. For every other
106//!   color space (linear extended sRGB, encoded extended sRGB or P3, PQ, HLG)
107//!   **the values your shader writes to the surface texture must already be
108//!   encoded by you**, along with any gamut conversion; in a typical renderer
109//!   this happens in a final tone-mapping or post-processing pass. wgpu hands
110//!   the signal to the compositor unchanged; getting this wrong produces a
111//!   wrong image with no error.
112//!
113//! wgpu does **not** tonemap or gamut-map for you. It gives you the surface
114//! and, through [`DisplayHdrInfo`], the display's advisory capabilities;
115//! *choosing* and *applying* a tone curve is your application's job.
116//!
117//! ### The practical path
118//!
119//! 1. **Query capabilities.** Call `Surface::get_capabilities`. To use HDR or
120//!    wide-gamut output, read [`SurfaceCapabilities::format_capabilities`] (each
121//!    format and the [`SurfaceColorSpaces`] it supports), **not**
122//!    [`SurfaceCapabilities::formats`]: the latter lists only formats usable
123//!    with [`Auto`](SurfaceColorSpace::Auto), which never selects HDR.
124//!    [`SurfaceCapabilities::color_spaces`] is a convenience lookup for one
125//!    format.
126//! 2. **Optionally query the display.** Call `Surface::display_hdr_info` for the
127//!    current [`DisplayHdrInfo`] (peak and SDR-white nits, EDR headroom,
128//!    primaries, and a coarse dynamic-range/gamut bucket). Use it to pick a
129//!    tone-map target ([`DisplayHdrInfo::tone_map_headroom`]); *whether* HDR is
130//!    worthwhile is the capability question from step 1, not this live value.
131//!    Every field is advisory and optional; `None` means "cannot tell here",
132//!    never "SDR".
133//! 3. **Choose a format and color space.** Intersect what you want with what
134//!    step 1 advertises, in your own preference order (for example HDR10, then
135//!    linear extended sRGB, then encoded extended sRGB, then SDR
136//!    [`Srgb`](SurfaceColorSpace::Srgb)). Keep an SDR fallback for when nothing
137//!    HDR is advertised, such as when OS HDR is off.
138//! 4. **Configure the surface.** Set [`SurfaceConfiguration::color_space`] and
139//!    `format`. [`Auto`](SurfaceColorSpace::Auto) (the default) reproduces
140//!    wgpu's historical behavior and never picks HDR; any other value must be in
141//!    that format's advertised set or configuration fails validation.
142//! 5. **Encode what you write to the surface texture.** For an `*Srgb` format,
143//!    output linear and the hardware encodes for you. Otherwise the values your
144//!    shader writes to the surface texture must already carry the encoding the
145//!    chosen color space expects (sRGB, extended sRGB, PQ, or HLG) **and** any
146//!    gamut conversion (for example outputting in the BT.2020 gamut for HDR10);
147//!    in a typical renderer you do this in a final tone-mapping or
148//!    post-processing pass. See the table below.
149//! 6. **Present** as usual. If OS HDR is toggled mid-run, you'll see it on the
150//!    next `Surface::display_hdr_info` poll; re-query `Surface::get_capabilities`
151//!    and re-run the steps above.
152//!
153//! The standalone [HDR surface example] implements every step, including the
154//! encoding transfer function for each color space.
155//!
156//! ### What to output from your fragment shader
157//!
158//! What the values your shader writes to the surface texture must contain for
159//! each color space, and whether wgpu applies the transfer function for you:
160//!
161//! | Color space | Typical format | You write | wgpu encodes? |
162//! | ----------- | -------------- | --------- | ------------- |
163//! | `Srgb`, `*Srgb` format | `{Rgba,Bgra}8UnormSrgb` | linear | **yes** (hardware sRGB OETF on store) |
164//! | `Srgb`, non-srgb format | `{Rgba,Bgra}8Unorm` | sRGB-encoded | no; apply the sRGB OETF yourself or use `*Srgb` instead |
165//! | `ExtendedSrgbLinear` (scRGB) | `Rgba16Float` | linear, `1.0` = SDR white | no, but no encoding is necessary |
166//! | `ExtendedSrgb` | `Rgba16Float` | extended sRGB-encoded | no; apply the extended sRGB OETF yourself |
167//! | `DisplayP3` | `Bgra8Unorm` | sRGB-encoded, P3 primaries | no; apply the sRGB OETF (after gamut-mapping to P3) |
168//! | `ExtendedDisplayP3` | `Rgba16Float` | extended sRGB-encoded, P3 primaries | no; apply the extended sRGB OETF (after gamut-mapping to P3) |
169//! | `Bt2100Pq` (HDR10) | `Rgb10a2Unorm` | PQ-encoded, BT.2020 primaries | no; apply the PQ OETF (after gamut-mapping to BT.2020) |
170//! | `Bt2100Hlg` | `Rgb10a2Unorm` | HLG-encoded, BT.2020 primaries | no; apply the HLG OETF (after gamut-mapping to BT.2020) |
171//!
172//! In short, wgpu applies the transfer function for you only when you render to
173//! an `*Srgb` format. In every other case the values your shader writes to the
174//! surface texture must already carry both the transfer function and any gamut
175//! conversion. The [HDR surface example] implements every encoder in WGSL.
176//!
177//! ### Glossary
178//!
179//! * **Chromaticity** --- a color's hue and saturation independent of its
180//!   brightness, given as an `(x, y)` coordinate on the CIE 1931 diagram.
181//! * **Primaries / gamut** --- the chromaticities of the red, green, and blue a
182//!   color space addresses, and so the range of colors it can express. [BT.709]
183//!   is the sRGB gamut, [Display P3] is wider, and [BT.2020] is wider still.
184//! * **White point** --- the chromaticity of `R = G = B` (what "white" looks
185//!   like). Every color space here uses [D65], standard daylight.
186//! * **Transfer function (OETF / EOTF)** --- how stored values map to light. The
187//!   *OETF* is the encoding transfer function your application applies; the
188//!   *EOTF* is the inverse decoding transfer function the display applies.
189//! * **SDR / HDR** --- standard dynamic range clips at `1.0` (reference white);
190//!   high dynamic range lets values above `1.0` drive brighter-than-white
191//!   output.
192//! * **Nits and reference white** --- a *nit* (cd/m²) is a unit of brightness;
193//!   *reference white* (also called *paper white*, especially on Windows) is the
194//!   brightness of SDR plain white, set below the panel's peak so highlights have
195//!   room above it.
196//! * **Headroom (EDR)** --- how much brighter than current SDR white the display
197//!   can go right now, as a multiplier (`1.0` means none). Dynamic; see
198//!   [`DisplayHdrInfo::tone_map_headroom`].
199//! * **PQ / HLG** --- the two HDR transfer functions: [PQ] (SMPTE ST 2084,
200//!   HDR10) encodes absolute luminance, [HLG] (BT.2100) encodes relative
201//!   luminance.
202//! * **scRGB / extended-range sRGB** --- sRGB extended past 0.0..=1.0 for
203//!   HDR: [scRGB] is *linear*
204//!   ([`ExtendedSrgbLinear`](SurfaceColorSpace::ExtendedSrgbLinear)), while
205//!   [`ExtendedSrgb`](SurfaceColorSpace::ExtendedSrgb) is the same range but
206//!   sRGB-*encoded* (gamma), the web's HDR path.
207//!
208//! [HDR surface example]: https://github.com/gfx-rs/wgpu/tree/v30/examples/standalone/03_hdr_surface
209//! [BT.709]: https://www.itu.int/rec/R-REC-BT.709
210//! [BT.2020]: https://www.itu.int/rec/R-REC-BT.2020
211//! [Display P3]: https://en.wikipedia.org/wiki/DCI-P3#Display_P3
212//! [D65]: https://en.wikipedia.org/wiki/Standard_illuminant#D65_values
213//! [PQ]: https://en.wikipedia.org/wiki/Perceptual_quantizer
214//! [HLG]: https://www.itu.int/rec/R-REC-BT.2100
215//! [scRGB]: https://en.wikipedia.org/wiki/ScRGB
216//!
217
218#![no_std]
219// `-Znext-solver` requires deeper recursion limits (at least for now) to prove Send/Sync
220#![recursion_limit = "256"]
221#![cfg_attr(docsrs, feature(doc_cfg))]
222#![doc(html_logo_url = "https://raw.githubusercontent.com/gfx-rs/wgpu/trunk/logo.png")]
223#![warn(
224    clippy::alloc_instead_of_core,
225    clippy::allow_attributes,
226    clippy::std_instead_of_alloc,
227    clippy::std_instead_of_core,
228    missing_docs,
229    rust_2018_idioms,
230    unsafe_op_in_unsafe_fn
231)]
232#![allow(
233    // We need to investiagate these.
234    clippy::large_enum_variant,
235    // These degrade readability significantly.
236    clippy::bool_assert_comparison,
237    clippy::bool_comparison,
238)]
239// NOTE: Keep this in sync with `wgpu-core`.
240#![cfg_attr(not(send_sync), allow(clippy::arc_with_non_send_sync))]
241#![cfg_attr(not(any(wgpu_core, webgpu)), allow(unused))]
242
243extern crate alloc;
244#[cfg(any(std, test))]
245extern crate std;
246#[cfg(wgpu_core)]
247pub extern crate wgpu_core as wgc;
248#[cfg(wgpu_core)]
249pub extern crate wgpu_hal as hal;
250pub extern crate wgpu_types as wgt;
251
252//
253//
254// Modules
255//
256//
257
258mod api;
259mod backend;
260mod cmp;
261mod dispatch;
262mod macros;
263pub mod util;
264
265//
266//
267// Public re-exports
268//
269//
270
271#[cfg(custom)]
272pub use backend::custom;
273
274pub use api::*;
275pub use wgt::{
276    AdapterInfo, AddressMode, AllocatorReport, AstcBlock, AstcChannel, Backend, BackendOptions,
277    Backends, BindGroupLayoutEntry, BindingType, BlendComponent, BlendFactor, BlendOperation,
278    BlendState, BufferAddress, BufferBindingType, BufferSize, BufferTextureCopyInfo,
279    BufferTransition, BufferUsages, BufferUses, Color, ColorTargetState, ColorWrites,
280    CommandBufferDescriptor, CompareFunction, CompositeAlphaMode, CooperativeMatrixProperties,
281    CooperativeScalarType, CopyExternalImageDestInfo, CoreCounters, DepthBiasState,
282    DepthStencilState, DeviceLostReason, DeviceType, DisplayChromaticity, DisplayCoarseRange,
283    DisplayGamut, DisplayHdrInfo, DisplayHeadroom, DisplayLuminance, DownlevelCapabilities,
284    DownlevelFlags, DownlevelLimits, Dx12BackendOptions, Dx12Compiler, Dx12SwapchainKind,
285    Dx12UseFrameLatencyWaitableObject, DxcShaderModel, DynamicOffset, ExperimentalFeatures,
286    Extent3d, ExternalTextureFormat, ExternalTextureTransferFunction, Face, Features, FeaturesWGPU,
287    FeaturesWebGPU, FilterMode, ForceShaderModelToken, FrontFace, GlBackendOptions, GlDebugFns,
288    GlFenceBehavior, Gles3MinorVersion, HalCounters, ImageSubresourceRange, IndexFormat,
289    InstanceDescriptor, InstanceFlags, InternalCounters, Limits, LoadOpDontCare,
290    MemoryBudgetThresholds, MemoryHints, MipmapFilterMode, MultisampleState, NoopBackendOptions,
291    Origin2d, Origin3d, PassthroughShaderEntryPoint, PipelineStatisticsTypes, PollError,
292    PollStatus, PolygonMode, PowerPreference, PredefinedColorSpace, PresentMode,
293    PresentationTimestamp, PrimitiveState, PrimitiveTopology, QueryType, RenderBundleDepthStencil,
294    RequestAdapterError, SamplerBindingType, SamplerBorderColor, ShaderLocation, ShaderModel,
295    ShaderRuntimeChecks, ShaderStages, StencilFaceState, StencilOperation, StencilState,
296    StorageTextureAccess, SurfaceCapabilities, SurfaceColorSpace, SurfaceColorSpaces,
297    SurfaceFormatCapabilities, SurfaceStatus, TexelCopyBufferLayout, TextureAspect, TextureChannel,
298    TextureDimension, TextureFormat, TextureFormatFeatureFlags, TextureFormatFeatures,
299    TextureSampleType, TextureTransition, TextureUsages, TextureUses, TextureViewDimension, Trace,
300    VertexAttribute, VertexFormat, VertexStepMode, WasmNotSend, WasmNotSendSync, WasmNotSync,
301    WriteOnly, WriteOnlyIter, COPY_BUFFER_ALIGNMENT, COPY_BYTES_PER_ROW_ALIGNMENT,
302    IMMEDIATE_DATA_ALIGNMENT, MAP_ALIGNMENT, MAXIMUM_SUBGROUP_MAX_SIZE, MINIMUM_SUBGROUP_MIN_SIZE,
303    QUERY_RESOLVE_BUFFER_ALIGNMENT, QUERY_SET_MAX_QUERIES, QUERY_SIZE, VERTEX_ALIGNMENT,
304};
305
306#[expect(deprecated)]
307pub use wgt::VERTEX_STRIDE_ALIGNMENT;
308
309// wasm-only types, we try to keep as many types non-platform
310// specific, but these need to depend on web-sys.
311#[cfg(web)]
312pub use wgt::{CopyExternalImageSourceInfo, ExternalImageSource};
313
314/// Re-export of our `naga` dependency.
315///
316#[cfg(wgpu_core)]
317#[cfg_attr(docsrs, doc(cfg(any(wgpu_core, naga))))]
318// We re-export wgpu-core's re-export of naga, as we may not have direct access to it.
319pub use ::wgc::naga;
320/// Re-export of our `naga` dependency.
321///
322#[cfg(all(not(wgpu_core), naga))]
323#[cfg_attr(docsrs, doc(cfg(any(wgpu_core, naga))))]
324// If that's not available, we re-export our own.
325pub use naga;
326
327/// Re-export of our `raw-window-handle` dependency.
328///
329pub use raw_window_handle as rwh;
330
331/// Re-export of our `web-sys` dependency.
332///
333#[cfg(web)]
334pub use web_sys;
335
336/// Vendored WebGPU JS-handle types used by the WebGPU backend.
337///
338/// They are exposed publicly so that interop crates can read the JS handle
339/// behind a [`Texture`] / [`Buffer`] / etc. (via [`Texture::as_webgpu`] and
340/// siblings), and pass a foreign handle in (via
341/// [`Device::create_texture_from_webgpu_handle`]).
342///
343/// A `web_sys::GpuTexture` from a consumer's own `web-sys` dependency wraps
344/// the same JS object as a `wgpu::webgpu::GpuTexture`; convert between them
345/// with [`wasm_bindgen::JsCast::unchecked_into`].
346#[cfg(webgpu)]
347pub mod webgpu {
348    pub use crate::backend::webgpu::webgpu_sys::{
349        GpuBuffer, GpuDevice, GpuQueue, GpuTexture, GpuTextureView,
350    };
351    pub use crate::backend::webgpu::DropCallback;
352}
353
354#[doc(hidden)]
355pub use macros::helpers as __macro_helpers;