wgpu_types/lib.rs
1//! This library describes the API surface of WebGPU that is agnostic of the backend.
2//! This API is used for targeting both Web and Native.
3
4#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
5#![allow(
6 // We don't use syntax sugar where it's not necessary.
7 clippy::match_like_matches_macro,
8)]
9#![warn(clippy::ptr_as_ptr, missing_docs, unsafe_op_in_unsafe_fn)]
10#![no_std]
11
12#[cfg(feature = "std")]
13extern crate std;
14
15extern crate alloc;
16
17use alloc::borrow::Cow;
18use alloc::{string::String, vec, vec::Vec};
19use core::{
20 fmt,
21 hash::{Hash, Hasher},
22 mem,
23 num::NonZeroU32,
24 ops::Range,
25};
26
27use bytemuck::{Pod, Zeroable};
28
29#[cfg(any(feature = "serde", test))]
30use {
31 alloc::format,
32 serde::{Deserialize, Serialize},
33};
34
35pub mod assertions;
36mod cast_utils;
37mod counters;
38mod env;
39pub mod error;
40mod features;
41pub mod instance;
42pub mod math;
43mod transfers;
44
45pub use counters::*;
46pub use features::*;
47pub use instance::*;
48pub use transfers::*;
49
50/// Integral type used for [`Buffer`] offsets and sizes.
51///
52/// [`Buffer`]: ../wgpu/struct.Buffer.html
53pub type BufferAddress = u64;
54
55/// Integral type used for [`BufferSlice`] sizes.
56///
57/// Note that while this type is non-zero, a [`Buffer`] *per se* can have a size of zero,
58/// but no slice or mapping can be created from it.
59///
60/// [`Buffer`]: ../wgpu/struct.Buffer.html
61/// [`BufferSlice`]: ../wgpu/struct.BufferSlice.html
62pub type BufferSize = core::num::NonZeroU64;
63
64/// Integral type used for binding locations in shaders.
65///
66/// Used in [`VertexAttribute`]s and errors.
67///
68/// [`VertexAttribute`]: ../wgpu/struct.VertexAttribute.html
69pub type ShaderLocation = u32;
70
71/// Integral type used for
72/// [dynamic bind group offsets](../wgpu/struct.RenderPass.html#method.set_bind_group).
73pub type DynamicOffset = u32;
74
75/// Buffer-to-texture copies must have [`bytes_per_row`] aligned to this number.
76///
77/// This doesn't apply to [`Queue::write_texture`][Qwt], only to [`copy_buffer_to_texture()`].
78///
79/// [`bytes_per_row`]: TexelCopyBufferLayout::bytes_per_row
80/// [`copy_buffer_to_texture()`]: ../wgpu/struct.Queue.html#method.copy_buffer_to_texture
81/// [Qwt]: ../wgpu/struct.Queue.html#method.write_texture
82pub const COPY_BYTES_PER_ROW_ALIGNMENT: u32 = 256;
83
84/// An [offset into the query resolve buffer] has to be aligned to this.
85///
86/// [offset into the query resolve buffer]: ../wgpu/struct.CommandEncoder.html#method.resolve_query_set
87pub const QUERY_RESOLVE_BUFFER_ALIGNMENT: BufferAddress = 256;
88
89/// Buffer to buffer copy as well as buffer clear offsets and sizes must be aligned to this number.
90pub const COPY_BUFFER_ALIGNMENT: BufferAddress = 4;
91
92/// Minimum alignment of buffer mappings.
93///
94/// The range passed to [`map_async()`] or [`get_mapped_range()`] must be at least this aligned.
95///
96/// [`map_async()`]: ../wgpu/struct.Buffer.html#method.map_async
97/// [`get_mapped_range()`]: ../wgpu/struct.Buffer.html#method.get_mapped_range
98pub const MAP_ALIGNMENT: BufferAddress = 8;
99
100/// [Vertex buffer strides] have to be a multiple of this number.
101///
102/// [Vertex buffer strides]: ../wgpu/struct.VertexBufferLayout.html#structfield.array_stride
103pub const VERTEX_STRIDE_ALIGNMENT: BufferAddress = 4;
104/// Ranges of [writes to push constant storage] must be at least this aligned.
105///
106/// [writes to push constant storage]: ../wgpu/struct.RenderPass.html#method.set_push_constants
107pub const PUSH_CONSTANT_ALIGNMENT: u32 = 4;
108
109/// Maximum queries in a [`QuerySetDescriptor`].
110pub const QUERY_SET_MAX_QUERIES: u32 = 4096;
111
112/// Size in bytes of a single piece of [query] data.
113///
114/// [query]: ../wgpu/struct.QuerySet.html
115pub const QUERY_SIZE: u32 = 8;
116
117/// Backends supported by wgpu.
118///
119/// See also [`Backends`].
120#[repr(u8)]
121#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
122#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
123pub enum Backend {
124 /// Dummy backend, which may be used for testing.
125 ///
126 /// It performs no rendering or computation, but allows creation of stub GPU resource types,
127 /// so that code which manages GPU resources can be tested without an available GPU.
128 /// Specifically, the following operations are implemented:
129 ///
130 /// * Enumerating adapters will always return one noop adapter, which can be used to create
131 /// devices.
132 /// * Buffers may be created, written, mapped, and copied to other buffers.
133 /// * Command encoders may be created, but only buffer operations are useful.
134 ///
135 /// Other resources can be created but are nonfunctional; notably,
136 ///
137 /// * Render passes and compute passes are not executed.
138 /// * Textures may be created, but do not store any texels.
139 /// * There are no compatible surfaces.
140 ///
141 /// An adapter using the noop backend can only be obtained if [`NoopBackendOptions`]
142 /// enables it, in addition to the ordinary requirement of [`Backends::NOOP`] being set.
143 /// This ensures that applications not desiring a non-functional backend will not receive it.
144 Noop = 0,
145 /// Vulkan API (Windows, Linux, Android, MacOS via `vulkan-portability`/MoltenVK)
146 Vulkan = 1,
147 /// Metal API (Apple platforms)
148 Metal = 2,
149 /// Direct3D-12 (Windows)
150 Dx12 = 3,
151 /// OpenGL 3.3+ (Windows), OpenGL ES 3.0+ (Linux, Android, MacOS via Angle), and WebGL2
152 Gl = 4,
153 /// WebGPU in the browser
154 BrowserWebGpu = 5,
155}
156
157impl Backend {
158 /// Array of all [`Backend`] values, corresponding to [`Backends::all()`].
159 pub const ALL: [Backend; Backends::all().bits().count_ones() as usize] = [
160 Self::Noop,
161 Self::Vulkan,
162 Self::Metal,
163 Self::Dx12,
164 Self::Gl,
165 Self::BrowserWebGpu,
166 ];
167
168 /// Returns the string name of the backend.
169 #[must_use]
170 pub const fn to_str(self) -> &'static str {
171 match self {
172 Backend::Noop => "noop",
173 Backend::Vulkan => "vulkan",
174 Backend::Metal => "metal",
175 Backend::Dx12 => "dx12",
176 Backend::Gl => "gl",
177 Backend::BrowserWebGpu => "webgpu",
178 }
179 }
180}
181
182impl core::fmt::Display for Backend {
183 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
184 f.write_str(self.to_str())
185 }
186}
187
188/// Power Preference when choosing a physical adapter.
189///
190/// Corresponds to [WebGPU `GPUPowerPreference`](
191/// https://gpuweb.github.io/gpuweb/#enumdef-gpupowerpreference).
192#[repr(C)]
193#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Default)]
194#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
195#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
196pub enum PowerPreference {
197 #[default]
198 /// Power usage is not considered when choosing an adapter.
199 None = 0,
200 /// Adapter that uses the least possible power. This is often an integrated GPU.
201 LowPower = 1,
202 /// Adapter that has the highest performance. This is often a discrete GPU.
203 HighPerformance = 2,
204}
205
206impl PowerPreference {
207 /// Get a power preference from the environment variable `WGPU_POWER_PREF`.
208 pub fn from_env() -> Option<Self> {
209 let env = crate::env::var("WGPU_POWER_PREF")?;
210 match env.to_lowercase().as_str() {
211 "low" => Some(Self::LowPower),
212 "high" => Some(Self::HighPerformance),
213 "none" => Some(Self::None),
214 _ => None,
215 }
216 }
217}
218
219bitflags::bitflags! {
220 /// Represents the backends that wgpu will use.
221 #[repr(transparent)]
222 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
223 #[cfg_attr(feature = "serde", serde(transparent))]
224 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
225 pub struct Backends: u32 {
226 /// [`Backend::Noop`].
227 const NOOP = 1 << Backend::Noop as u32;
228
229 /// [`Backend::Vulkan`].
230 /// Supported on Windows, Linux/Android, and macOS/iOS via Vulkan Portability (with the Vulkan feature enabled)
231 const VULKAN = 1 << Backend::Vulkan as u32;
232
233 /// [`Backend::Gl`].
234 /// Supported on Linux/Android, the web through webassembly via WebGL, and Windows and
235 /// macOS/iOS via ANGLE
236 const GL = 1 << Backend::Gl as u32;
237
238 /// [`Backend::Metal`].
239 /// Supported on macOS and iOS.
240 const METAL = 1 << Backend::Metal as u32;
241
242 /// [`Backend::Dx12`].
243 /// Supported on Windows 10 and later
244 const DX12 = 1 << Backend::Dx12 as u32;
245
246 /// [`Backend::BrowserWebGpu`].
247 /// Supported when targeting the web through WebAssembly with the `webgpu` feature enabled.
248 ///
249 /// The WebGPU backend is special in several ways:
250 /// It is not not implemented by `wgpu_core` and instead by the higher level `wgpu` crate.
251 /// Whether WebGPU is targeted is decided upon the creation of the `wgpu::Instance`,
252 /// *not* upon adapter creation. See `wgpu::Instance::new`.
253 const BROWSER_WEBGPU = 1 << Backend::BrowserWebGpu as u32;
254
255 /// All the apis that wgpu offers first tier of support for.
256 ///
257 /// * [`Backends::VULKAN`]
258 /// * [`Backends::METAL`]
259 /// * [`Backends::DX12`]
260 /// * [`Backends::BROWSER_WEBGPU`]
261 const PRIMARY = Self::VULKAN.bits()
262 | Self::METAL.bits()
263 | Self::DX12.bits()
264 | Self::BROWSER_WEBGPU.bits();
265
266 /// All the apis that wgpu offers second tier of support for. These may
267 /// be unsupported/still experimental.
268 ///
269 /// * [`Backends::GL`]
270 const SECONDARY = Self::GL.bits();
271 }
272}
273
274impl Default for Backends {
275 fn default() -> Self {
276 Self::all()
277 }
278}
279
280impl From<Backend> for Backends {
281 fn from(backend: Backend) -> Self {
282 Self::from_bits(1 << backend as u32).unwrap()
283 }
284}
285
286impl Backends {
287 /// Gets a set of backends from the environment variable `WGPU_BACKEND`.
288 ///
289 /// See [`Self::from_comma_list()`] for the format of the string.
290 pub fn from_env() -> Option<Self> {
291 let env = crate::env::var("WGPU_BACKEND")?;
292 Some(Self::from_comma_list(&env))
293 }
294
295 /// Takes the given options, modifies them based on the `WGPU_BACKEND` environment variable, and returns the result.
296 pub fn with_env(&self) -> Self {
297 if let Some(env) = Self::from_env() {
298 env
299 } else {
300 *self
301 }
302 }
303
304 /// Generates a set of backends from a comma separated list of case-insensitive backend names.
305 ///
306 /// Whitespace is stripped, so both 'gl, dx12' and 'gl,dx12' are valid.
307 ///
308 /// Always returns WEBGPU on wasm over webgpu.
309 ///
310 /// Names:
311 /// - vulkan = "vulkan" or "vk"
312 /// - dx12 = "dx12" or "d3d12"
313 /// - metal = "metal" or "mtl"
314 /// - gles = "opengl" or "gles" or "gl"
315 /// - webgpu = "webgpu"
316 pub fn from_comma_list(string: &str) -> Self {
317 let mut backends = Self::empty();
318 for backend in string.to_lowercase().split(',') {
319 backends |= match backend.trim() {
320 "vulkan" | "vk" => Self::VULKAN,
321 "dx12" | "d3d12" => Self::DX12,
322 "metal" | "mtl" => Self::METAL,
323 "opengl" | "gles" | "gl" => Self::GL,
324 "webgpu" => Self::BROWSER_WEBGPU,
325 "noop" => Self::NOOP,
326 b => {
327 log::warn!("unknown backend string '{}'", b);
328 continue;
329 }
330 }
331 }
332
333 if backends.is_empty() {
334 log::warn!("no valid backend strings found!");
335 }
336
337 backends
338 }
339}
340
341/// Options for requesting adapter.
342///
343/// Corresponds to [WebGPU `GPURequestAdapterOptions`](
344/// https://gpuweb.github.io/gpuweb/#dictdef-gpurequestadapteroptions).
345#[repr(C)]
346#[derive(Clone, Debug, PartialEq, Eq, Hash)]
347#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
348pub struct RequestAdapterOptions<S> {
349 /// Power preference for the adapter.
350 pub power_preference: PowerPreference,
351 /// Indicates that only a fallback adapter can be returned. This is generally a "software"
352 /// implementation on the system.
353 pub force_fallback_adapter: bool,
354 /// Surface that is required to be presentable with the requested adapter. This does not
355 /// create the surface, only guarantees that the adapter can present to said surface.
356 /// For WebGL, this is strictly required, as an adapter can not be created without a surface.
357 pub compatible_surface: Option<S>,
358}
359
360impl<S> Default for RequestAdapterOptions<S> {
361 fn default() -> Self {
362 Self {
363 power_preference: PowerPreference::default(),
364 force_fallback_adapter: false,
365 compatible_surface: None,
366 }
367 }
368}
369
370/// Error when [`Instance::request_adapter()`] fails.
371///
372/// This type is not part of the WebGPU standard, where `requestAdapter()` would simply return null.
373///
374/// [`Instance::request_adapter()`]: ../wgpu/struct.Instance.html#method.request_adapter
375#[derive(Clone, Debug, PartialEq)]
376#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
377#[non_exhaustive]
378pub enum RequestAdapterError {
379 /// No adapter available via the instance’s backends matched the request’s adapter criteria.
380 NotFound {
381 // These fields must be set by wgpu-core and wgpu, but are not intended to be stable API,
382 // only data for the production of the error message.
383 #[doc(hidden)]
384 active_backends: Backends,
385 #[doc(hidden)]
386 requested_backends: Backends,
387 #[doc(hidden)]
388 supported_backends: Backends,
389 #[doc(hidden)]
390 no_fallback_backends: Backends,
391 #[doc(hidden)]
392 no_adapter_backends: Backends,
393 #[doc(hidden)]
394 incompatible_surface_backends: Backends,
395 },
396
397 /// Attempted to obtain adapter specified by environment variable, but the environment variable
398 /// was not set.
399 EnvNotSet,
400}
401
402impl core::error::Error for RequestAdapterError {}
403impl fmt::Display for RequestAdapterError {
404 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
405 match self {
406 RequestAdapterError::NotFound {
407 active_backends,
408 requested_backends,
409 supported_backends,
410 no_fallback_backends,
411 no_adapter_backends,
412 incompatible_surface_backends,
413 } => {
414 write!(f, "No suitable graphics adapter found; ")?;
415 let mut first = true;
416 for backend in Backend::ALL {
417 let bit = Backends::from(backend);
418 let comma = if mem::take(&mut first) { "" } else { ", " };
419 let explanation = if !requested_backends.contains(bit) {
420 // We prefer reporting this, because it makes the error most stable with
421 // respect to what is directly controllable by the caller, as opposed to
422 // compilation options or the run-time environment.
423 "not requested"
424 } else if !supported_backends.contains(bit) {
425 "support not compiled in"
426 } else if no_adapter_backends.contains(bit) {
427 "found no adapters"
428 } else if incompatible_surface_backends.contains(bit) {
429 "not compatible with provided surface"
430 } else if no_fallback_backends.contains(bit) {
431 "had no fallback adapters"
432 } else if !active_backends.contains(bit) {
433 // Backend requested but not active in this instance
434 if backend == Backend::Noop {
435 "not explicitly enabled"
436 } else {
437 "drivers/libraries could not be loaded"
438 }
439 } else {
440 // This path should be unreachable, but don't crash.
441 "[unknown reason]"
442 };
443 write!(f, "{comma}{backend} {explanation}")?;
444 }
445 }
446 RequestAdapterError::EnvNotSet => f.write_str("WGPU_ADAPTER_NAME not set")?,
447 }
448 Ok(())
449 }
450}
451
452/// Represents the sets of limits an adapter/device supports.
453///
454/// We provide three different defaults.
455/// - [`Limits::downlevel_defaults()`]. This is a set of limits that is guaranteed to work on almost
456/// all backends, including "downlevel" backends such as OpenGL and D3D11, other than WebGL. For
457/// most applications we recommend using these limits, assuming they are high enough for your
458/// application, and you do not intent to support WebGL.
459/// - [`Limits::downlevel_webgl2_defaults()`] This is a set of limits that is lower even than the
460/// [`downlevel_defaults()`], configured to be low enough to support running in the browser using
461/// WebGL2.
462/// - [`Limits::default()`]. This is the set of limits that is guaranteed to work on all modern
463/// backends and is guaranteed to be supported by WebGPU. Applications needing more modern
464/// features can use this as a reasonable set of limits if they are targeting only desktop and
465/// modern mobile devices.
466///
467/// We recommend starting with the most restrictive limits you can and manually increasing the
468/// limits you need boosted. This will let you stay running on all hardware that supports the limits
469/// you need.
470///
471/// Limits "better" than the default must be supported by the adapter and requested when requesting
472/// a device. If limits "better" than the adapter supports are requested, requesting a device will
473/// panic. Once a device is requested, you may only use resources up to the limits requested _even_
474/// if the adapter supports "better" limits.
475///
476/// Requesting limits that are "better" than you need may cause performance to decrease because the
477/// implementation needs to support more than is needed. You should ideally only request exactly
478/// what you need.
479///
480/// Corresponds to [WebGPU `GPUSupportedLimits`](
481/// https://gpuweb.github.io/gpuweb/#gpusupportedlimits).
482///
483/// [`downlevel_defaults()`]: Limits::downlevel_defaults
484#[repr(C)]
485#[derive(Clone, Debug, PartialEq, Eq, Hash)]
486#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
487#[cfg_attr(feature = "serde", serde(rename_all = "camelCase", default))]
488pub struct Limits {
489 /// Maximum allowed value for the `size.width` of a texture created with `TextureDimension::D1`.
490 /// Defaults to 8192. Higher is "better".
491 #[cfg_attr(feature = "serde", serde(rename = "maxTextureDimension1D"))]
492 pub max_texture_dimension_1d: u32,
493 /// Maximum allowed value for the `size.width` and `size.height` of a texture created with `TextureDimension::D2`.
494 /// Defaults to 8192. Higher is "better".
495 #[cfg_attr(feature = "serde", serde(rename = "maxTextureDimension2D"))]
496 pub max_texture_dimension_2d: u32,
497 /// Maximum allowed value for the `size.width`, `size.height`, and `size.depth_or_array_layers`
498 /// of a texture created with `TextureDimension::D3`.
499 /// Defaults to 2048. Higher is "better".
500 #[cfg_attr(feature = "serde", serde(rename = "maxTextureDimension3D"))]
501 pub max_texture_dimension_3d: u32,
502 /// Maximum allowed value for the `size.depth_or_array_layers` of a texture created with `TextureDimension::D2`.
503 /// Defaults to 256. Higher is "better".
504 pub max_texture_array_layers: u32,
505 /// Amount of bind groups that can be attached to a pipeline at the same time. Defaults to 4. Higher is "better".
506 pub max_bind_groups: u32,
507 /// Maximum binding index allowed in `create_bind_group_layout`. Defaults to 1000. Higher is "better".
508 pub max_bindings_per_bind_group: u32,
509 /// Amount of uniform buffer bindings that can be dynamic in a single pipeline. Defaults to 8. Higher is "better".
510 pub max_dynamic_uniform_buffers_per_pipeline_layout: u32,
511 /// Amount of storage buffer bindings that can be dynamic in a single pipeline. Defaults to 4. Higher is "better".
512 pub max_dynamic_storage_buffers_per_pipeline_layout: u32,
513 /// Amount of sampled textures visible in a single shader stage. Defaults to 16. Higher is "better".
514 pub max_sampled_textures_per_shader_stage: u32,
515 /// Amount of samplers visible in a single shader stage. Defaults to 16. Higher is "better".
516 pub max_samplers_per_shader_stage: u32,
517 /// Amount of storage buffers visible in a single shader stage. Defaults to 8. Higher is "better".
518 pub max_storage_buffers_per_shader_stage: u32,
519 /// Amount of storage textures visible in a single shader stage. Defaults to 4. Higher is "better".
520 pub max_storage_textures_per_shader_stage: u32,
521 /// Amount of uniform buffers visible in a single shader stage. Defaults to 12. Higher is "better".
522 pub max_uniform_buffers_per_shader_stage: u32,
523 /// Amount of individual resources within binding arrays that can be accessed in a single shader stage. Applies
524 /// to all types of bindings except samplers.
525 ///
526 /// This "defaults" to 0. However if binding arrays are supported, all devices can support 500,000. Higher is "better".
527 pub max_binding_array_elements_per_shader_stage: u32,
528 /// Amount of individual samplers within binding arrays that can be accessed in a single shader stage.
529 ///
530 /// This "defaults" to 0. However if binding arrays are supported, all devices can support 1,000. Higher is "better".
531 pub max_binding_array_sampler_elements_per_shader_stage: u32,
532 /// Maximum size in bytes of a binding to a uniform buffer. Defaults to 64 KiB. Higher is "better".
533 pub max_uniform_buffer_binding_size: u32,
534 /// Maximum size in bytes of a binding to a storage buffer. Defaults to 128 MiB. Higher is "better".
535 pub max_storage_buffer_binding_size: u32,
536 /// Maximum length of `VertexState::buffers` when creating a `RenderPipeline`.
537 /// Defaults to 8. Higher is "better".
538 pub max_vertex_buffers: u32,
539 /// A limit above which buffer allocations are guaranteed to fail.
540 /// Defaults to 256 MiB. Higher is "better".
541 ///
542 /// Buffer allocations below the maximum buffer size may not succeed depending on available memory,
543 /// fragmentation and other factors.
544 pub max_buffer_size: u64,
545 /// Maximum length of `VertexBufferLayout::attributes`, summed over all `VertexState::buffers`,
546 /// when creating a `RenderPipeline`.
547 /// Defaults to 16. Higher is "better".
548 pub max_vertex_attributes: u32,
549 /// Maximum value for `VertexBufferLayout::array_stride` when creating a `RenderPipeline`.
550 /// Defaults to 2048. Higher is "better".
551 pub max_vertex_buffer_array_stride: u32,
552 /// Required `BufferBindingType::Uniform` alignment for `BufferBinding::offset`
553 /// when creating a `BindGroup`, or for `set_bind_group` `dynamicOffsets`.
554 /// Defaults to 256. Lower is "better".
555 pub min_uniform_buffer_offset_alignment: u32,
556 /// Required `BufferBindingType::Storage` alignment for `BufferBinding::offset`
557 /// when creating a `BindGroup`, or for `set_bind_group` `dynamicOffsets`.
558 /// Defaults to 256. Lower is "better".
559 pub min_storage_buffer_offset_alignment: u32,
560 /// Maximum allowed number of components (scalars) of input or output locations for
561 /// inter-stage communication (vertex outputs to fragment inputs). Defaults to 60.
562 /// Higher is "better".
563 pub max_inter_stage_shader_components: u32,
564 /// The maximum allowed number of color attachments.
565 pub max_color_attachments: u32,
566 /// The maximum number of bytes necessary to hold one sample (pixel or subpixel) of render
567 /// pipeline output data, across all color attachments as described by [`TextureFormat::target_pixel_byte_cost`]
568 /// and [`TextureFormat::target_component_alignment`]. Defaults to 32. Higher is "better".
569 ///
570 /// ⚠️ `Rgba8Unorm`/`Rgba8Snorm`/`Bgra8Unorm`/`Bgra8Snorm` are deceptively 8 bytes per sample. ⚠️
571 pub max_color_attachment_bytes_per_sample: u32,
572 /// Maximum number of bytes used for workgroup memory in a compute entry point. Defaults to
573 /// 16384. Higher is "better".
574 pub max_compute_workgroup_storage_size: u32,
575 /// Maximum value of the product of the `workgroup_size` dimensions for a compute entry-point.
576 /// Defaults to 256. Higher is "better".
577 pub max_compute_invocations_per_workgroup: u32,
578 /// The maximum value of the `workgroup_size` X dimension for a compute stage `ShaderModule` entry-point.
579 /// Defaults to 256. Higher is "better".
580 pub max_compute_workgroup_size_x: u32,
581 /// The maximum value of the `workgroup_size` Y dimension for a compute stage `ShaderModule` entry-point.
582 /// Defaults to 256. Higher is "better".
583 pub max_compute_workgroup_size_y: u32,
584 /// The maximum value of the `workgroup_size` Z dimension for a compute stage `ShaderModule` entry-point.
585 /// Defaults to 64. Higher is "better".
586 pub max_compute_workgroup_size_z: u32,
587 /// The maximum value for each dimension of a `ComputePass::dispatch(x, y, z)` operation.
588 /// Defaults to 65535. Higher is "better".
589 pub max_compute_workgroups_per_dimension: u32,
590
591 /// Minimal number of invocations in a subgroup. Higher is "better".
592 pub min_subgroup_size: u32,
593 /// Maximal number of invocations in a subgroup. Lower is "better".
594 pub max_subgroup_size: u32,
595 /// Amount of storage available for push constants in bytes. Defaults to 0. Higher is "better".
596 /// Requesting more than 0 during device creation requires [`Features::PUSH_CONSTANTS`] to be enabled.
597 ///
598 /// Expect the size to be:
599 /// - Vulkan: 128-256 bytes
600 /// - DX12: 256 bytes
601 /// - Metal: 4096 bytes
602 /// - OpenGL doesn't natively support push constants, and are emulated with uniforms,
603 /// so this number is less useful but likely 256.
604 pub max_push_constant_size: u32,
605 /// Maximum number of live non-sampler bindings.
606 ///
607 /// This limit only affects the d3d12 backend. Using a large number will allow the device
608 /// to create many bind groups at the cost of a large up-front allocation at device creation.
609 pub max_non_sampler_bindings: u32,
610 /// The maximum number of primitive (ex: triangles, aabbs) a BLAS is allowed to have. Requesting
611 /// more than 0 during device creation only makes sense if [`Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE`]
612 /// is enabled.
613 pub max_blas_primitive_count: u32,
614 /// The maximum number of geometry descriptors a BLAS is allowed to have. Requesting
615 /// more than 0 during device creation only makes sense if [`Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE`]
616 /// is enabled.
617 pub max_blas_geometry_count: u32,
618 /// The maximum number of instances a TLAS is allowed to have. Requesting more than 0 during
619 /// device creation only makes sense if [`Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE`]
620 /// is enabled.
621 pub max_tlas_instance_count: u32,
622 /// The maximum number of acceleration structures allowed to be used in a shader stage.
623 /// Requesting more than 0 during device creation only makes sense if [`Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE`]
624 /// is enabled.
625 pub max_acceleration_structures_per_shader_stage: u32,
626}
627
628impl Default for Limits {
629 fn default() -> Self {
630 Self::defaults()
631 }
632}
633
634impl Limits {
635 /// These default limits are guaranteed to to work on all modern
636 /// backends and guaranteed to be supported by WebGPU
637 ///
638 /// Those limits are as follows:
639 /// ```rust
640 /// # use wgpu_types::Limits;
641 /// assert_eq!(Limits::defaults(), Limits {
642 /// max_texture_dimension_1d: 8192,
643 /// max_texture_dimension_2d: 8192,
644 /// max_texture_dimension_3d: 2048,
645 /// max_texture_array_layers: 256,
646 /// max_bind_groups: 4,
647 /// max_bindings_per_bind_group: 1000,
648 /// max_dynamic_uniform_buffers_per_pipeline_layout: 8,
649 /// max_dynamic_storage_buffers_per_pipeline_layout: 4,
650 /// max_sampled_textures_per_shader_stage: 16,
651 /// max_samplers_per_shader_stage: 16,
652 /// max_storage_buffers_per_shader_stage: 8,
653 /// max_storage_textures_per_shader_stage: 4,
654 /// max_uniform_buffers_per_shader_stage: 12,
655 /// max_binding_array_elements_per_shader_stage: 0,
656 /// max_binding_array_sampler_elements_per_shader_stage: 0,
657 /// max_uniform_buffer_binding_size: 64 << 10, // (64 KiB)
658 /// max_storage_buffer_binding_size: 128 << 20, // (128 MiB)
659 /// max_vertex_buffers: 8,
660 /// max_buffer_size: 256 << 20, // (256 MiB)
661 /// max_vertex_attributes: 16,
662 /// max_vertex_buffer_array_stride: 2048,
663 /// min_uniform_buffer_offset_alignment: 256,
664 /// min_storage_buffer_offset_alignment: 256,
665 /// max_inter_stage_shader_components: 60,
666 /// max_color_attachments: 8,
667 /// max_color_attachment_bytes_per_sample: 32,
668 /// max_compute_workgroup_storage_size: 16384,
669 /// max_compute_invocations_per_workgroup: 256,
670 /// max_compute_workgroup_size_x: 256,
671 /// max_compute_workgroup_size_y: 256,
672 /// max_compute_workgroup_size_z: 64,
673 /// max_compute_workgroups_per_dimension: 65535,
674 /// min_subgroup_size: 0,
675 /// max_subgroup_size: 0,
676 /// max_push_constant_size: 0,
677 /// max_non_sampler_bindings: 1_000_000,
678 /// max_blas_primitive_count: 0,
679 /// max_blas_geometry_count: 0,
680 /// max_tlas_instance_count: 0,
681 /// max_acceleration_structures_per_shader_stage: 0,
682 /// });
683 /// ```
684 ///
685 /// Rust doesn't allow const in trait implementations, so we break this out
686 /// to allow reusing these defaults in const contexts
687 #[must_use]
688 pub const fn defaults() -> Self {
689 Self {
690 max_texture_dimension_1d: 8192,
691 max_texture_dimension_2d: 8192,
692 max_texture_dimension_3d: 2048,
693 max_texture_array_layers: 256,
694 max_bind_groups: 4,
695 max_bindings_per_bind_group: 1000,
696 max_dynamic_uniform_buffers_per_pipeline_layout: 8,
697 max_dynamic_storage_buffers_per_pipeline_layout: 4,
698 max_sampled_textures_per_shader_stage: 16,
699 max_samplers_per_shader_stage: 16,
700 max_storage_buffers_per_shader_stage: 8,
701 max_storage_textures_per_shader_stage: 4,
702 max_uniform_buffers_per_shader_stage: 12,
703 max_binding_array_elements_per_shader_stage: 0,
704 max_binding_array_sampler_elements_per_shader_stage: 0,
705 max_uniform_buffer_binding_size: 64 << 10, // (64 KiB)
706 max_storage_buffer_binding_size: 128 << 20, // (128 MiB)
707 max_vertex_buffers: 8,
708 max_buffer_size: 256 << 20, // (256 MiB)
709 max_vertex_attributes: 16,
710 max_vertex_buffer_array_stride: 2048,
711 min_uniform_buffer_offset_alignment: 256,
712 min_storage_buffer_offset_alignment: 256,
713 max_inter_stage_shader_components: 60,
714 max_color_attachments: 8,
715 max_color_attachment_bytes_per_sample: 32,
716 max_compute_workgroup_storage_size: 16384,
717 max_compute_invocations_per_workgroup: 256,
718 max_compute_workgroup_size_x: 256,
719 max_compute_workgroup_size_y: 256,
720 max_compute_workgroup_size_z: 64,
721 max_compute_workgroups_per_dimension: 65535,
722 min_subgroup_size: 0,
723 max_subgroup_size: 0,
724 max_push_constant_size: 0,
725 max_non_sampler_bindings: 1_000_000,
726 max_blas_primitive_count: 0,
727 max_blas_geometry_count: 0,
728 max_tlas_instance_count: 0,
729 max_acceleration_structures_per_shader_stage: 0,
730 }
731 }
732
733 /// These default limits are guaranteed to be compatible with GLES-3.1, and D3D11
734 ///
735 /// Those limits are as follows (different from default are marked with *):
736 /// ```rust
737 /// # use wgpu_types::Limits;
738 /// assert_eq!(Limits::downlevel_defaults(), Limits {
739 /// max_texture_dimension_1d: 2048, // *
740 /// max_texture_dimension_2d: 2048, // *
741 /// max_texture_dimension_3d: 256, // *
742 /// max_texture_array_layers: 256,
743 /// max_bind_groups: 4,
744 /// max_bindings_per_bind_group: 1000,
745 /// max_dynamic_uniform_buffers_per_pipeline_layout: 8,
746 /// max_dynamic_storage_buffers_per_pipeline_layout: 4,
747 /// max_sampled_textures_per_shader_stage: 16,
748 /// max_samplers_per_shader_stage: 16,
749 /// max_storage_buffers_per_shader_stage: 4, // *
750 /// max_storage_textures_per_shader_stage: 4,
751 /// max_uniform_buffers_per_shader_stage: 12,
752 /// max_binding_array_elements_per_shader_stage: 0,
753 /// max_binding_array_sampler_elements_per_shader_stage: 0,
754 /// max_uniform_buffer_binding_size: 16 << 10, // * (16 KiB)
755 /// max_storage_buffer_binding_size: 128 << 20, // (128 MiB)
756 /// max_vertex_buffers: 8,
757 /// max_vertex_attributes: 16,
758 /// max_vertex_buffer_array_stride: 2048,
759 /// min_subgroup_size: 0,
760 /// max_subgroup_size: 0,
761 /// max_push_constant_size: 0,
762 /// min_uniform_buffer_offset_alignment: 256,
763 /// min_storage_buffer_offset_alignment: 256,
764 /// max_inter_stage_shader_components: 60,
765 /// max_color_attachments: 4,
766 /// max_color_attachment_bytes_per_sample: 32,
767 /// max_compute_workgroup_storage_size: 16352, // *
768 /// max_compute_invocations_per_workgroup: 256,
769 /// max_compute_workgroup_size_x: 256,
770 /// max_compute_workgroup_size_y: 256,
771 /// max_compute_workgroup_size_z: 64,
772 /// max_compute_workgroups_per_dimension: 65535,
773 /// max_buffer_size: 256 << 20, // (256 MiB)
774 /// max_non_sampler_bindings: 1_000_000,
775 /// max_blas_primitive_count: 0,
776 /// max_blas_geometry_count: 0,
777 /// max_tlas_instance_count: 0,
778 /// max_acceleration_structures_per_shader_stage: 0,
779 /// });
780 /// ```
781 #[must_use]
782 pub const fn downlevel_defaults() -> Self {
783 Self {
784 max_texture_dimension_1d: 2048,
785 max_texture_dimension_2d: 2048,
786 max_texture_dimension_3d: 256,
787 max_storage_buffers_per_shader_stage: 4,
788 max_uniform_buffer_binding_size: 16 << 10, // (16 KiB)
789 max_color_attachments: 4,
790 // see: https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf#page=7
791 max_compute_workgroup_storage_size: 16352,
792 ..Self::defaults()
793 }
794 }
795
796 /// These default limits are guaranteed to be compatible with GLES-3.0, and D3D11, and WebGL2
797 ///
798 /// Those limits are as follows (different from `downlevel_defaults` are marked with +,
799 /// *'s from `downlevel_defaults` shown as well.):
800 /// ```rust
801 /// # use wgpu_types::Limits;
802 /// assert_eq!(Limits::downlevel_webgl2_defaults(), Limits {
803 /// max_texture_dimension_1d: 2048, // *
804 /// max_texture_dimension_2d: 2048, // *
805 /// max_texture_dimension_3d: 256, // *
806 /// max_texture_array_layers: 256,
807 /// max_bind_groups: 4,
808 /// max_bindings_per_bind_group: 1000,
809 /// max_dynamic_uniform_buffers_per_pipeline_layout: 8,
810 /// max_dynamic_storage_buffers_per_pipeline_layout: 0, // +
811 /// max_sampled_textures_per_shader_stage: 16,
812 /// max_samplers_per_shader_stage: 16,
813 /// max_storage_buffers_per_shader_stage: 0, // * +
814 /// max_storage_textures_per_shader_stage: 0, // +
815 /// max_uniform_buffers_per_shader_stage: 11, // +
816 /// max_binding_array_elements_per_shader_stage: 0,
817 /// max_binding_array_sampler_elements_per_shader_stage: 0,
818 /// max_uniform_buffer_binding_size: 16 << 10, // * (16 KiB)
819 /// max_storage_buffer_binding_size: 0, // * +
820 /// max_vertex_buffers: 8,
821 /// max_vertex_attributes: 16,
822 /// max_vertex_buffer_array_stride: 255, // +
823 /// min_subgroup_size: 0,
824 /// max_subgroup_size: 0,
825 /// max_push_constant_size: 0,
826 /// min_uniform_buffer_offset_alignment: 256,
827 /// min_storage_buffer_offset_alignment: 256,
828 /// max_inter_stage_shader_components: 31,
829 /// max_color_attachments: 4,
830 /// max_color_attachment_bytes_per_sample: 32,
831 /// max_compute_workgroup_storage_size: 0, // +
832 /// max_compute_invocations_per_workgroup: 0, // +
833 /// max_compute_workgroup_size_x: 0, // +
834 /// max_compute_workgroup_size_y: 0, // +
835 /// max_compute_workgroup_size_z: 0, // +
836 /// max_compute_workgroups_per_dimension: 0, // +
837 /// max_buffer_size: 256 << 20, // (256 MiB),
838 /// max_non_sampler_bindings: 1_000_000,
839 /// max_blas_primitive_count: 0,
840 /// max_blas_geometry_count: 0,
841 /// max_tlas_instance_count: 0,
842 /// max_acceleration_structures_per_shader_stage: 0,
843 /// });
844 /// ```
845 #[must_use]
846 pub const fn downlevel_webgl2_defaults() -> Self {
847 Self {
848 max_uniform_buffers_per_shader_stage: 11,
849 max_storage_buffers_per_shader_stage: 0,
850 max_storage_textures_per_shader_stage: 0,
851 max_dynamic_storage_buffers_per_pipeline_layout: 0,
852 max_storage_buffer_binding_size: 0,
853 max_vertex_buffer_array_stride: 255,
854 max_compute_workgroup_storage_size: 0,
855 max_compute_invocations_per_workgroup: 0,
856 max_compute_workgroup_size_x: 0,
857 max_compute_workgroup_size_y: 0,
858 max_compute_workgroup_size_z: 0,
859 max_compute_workgroups_per_dimension: 0,
860 min_subgroup_size: 0,
861 max_subgroup_size: 0,
862
863 // Value supported by Intel Celeron B830 on Windows (OpenGL 3.1)
864 max_inter_stage_shader_components: 31,
865
866 // Most of the values should be the same as the downlevel defaults
867 ..Self::downlevel_defaults()
868 }
869 }
870
871 /// Modify the current limits to use the resolution limits of the other.
872 ///
873 /// This is useful because the swapchain might need to be larger than any other image in the application.
874 ///
875 /// If your application only needs 512x512, you might be running on a 4k display and need extremely high resolution limits.
876 #[must_use]
877 pub const fn using_resolution(self, other: Self) -> Self {
878 Self {
879 max_texture_dimension_1d: other.max_texture_dimension_1d,
880 max_texture_dimension_2d: other.max_texture_dimension_2d,
881 max_texture_dimension_3d: other.max_texture_dimension_3d,
882 ..self
883 }
884 }
885
886 /// Modify the current limits to use the buffer alignment limits of the adapter.
887 ///
888 /// This is useful for when you'd like to dynamically use the "best" supported buffer alignments.
889 #[must_use]
890 pub const fn using_alignment(self, other: Self) -> Self {
891 Self {
892 min_uniform_buffer_offset_alignment: other.min_uniform_buffer_offset_alignment,
893 min_storage_buffer_offset_alignment: other.min_storage_buffer_offset_alignment,
894 ..self
895 }
896 }
897
898 /// The minimum guaranteed limits for acceleration structures if you enable [`Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE`]
899 #[must_use]
900 pub const fn using_minimum_supported_acceleration_structure_values(self) -> Self {
901 Self {
902 max_blas_geometry_count: (1 << 24) - 1, // 2^24 - 1: Vulkan's minimum
903 max_tlas_instance_count: (1 << 24) - 1, // 2^24 - 1: Vulkan's minimum
904 max_blas_primitive_count: 1 << 28, // 2^28: Metal's minimum
905 max_acceleration_structures_per_shader_stage: 16, // Vulkan's minimum
906 ..self
907 }
908 }
909
910 /// Modify the current limits to use the acceleration structure limits of `other` (`other` could
911 /// be the limits of the adapter).
912 #[must_use]
913 pub const fn using_acceleration_structure_values(self, other: Self) -> Self {
914 Self {
915 max_blas_geometry_count: other.max_blas_geometry_count,
916 max_tlas_instance_count: other.max_tlas_instance_count,
917 max_blas_primitive_count: other.max_blas_primitive_count,
918 max_acceleration_structures_per_shader_stage: other
919 .max_acceleration_structures_per_shader_stage,
920 ..self
921 }
922 }
923
924 /// Compares every limits within self is within the limits given in `allowed`.
925 ///
926 /// If you need detailed information on failures, look at [`Limits::check_limits_with_fail_fn`].
927 #[must_use]
928 pub fn check_limits(&self, allowed: &Self) -> bool {
929 let mut within = true;
930 self.check_limits_with_fail_fn(allowed, true, |_, _, _| within = false);
931 within
932 }
933
934 /// Compares every limits within self is within the limits given in `allowed`.
935 /// For an easy to use binary choice, use [`Limits::check_limits`].
936 ///
937 /// If a value is not within the allowed limit, this function calls the `fail_fn`
938 /// with the:
939 /// - limit name
940 /// - self's limit
941 /// - allowed's limit.
942 ///
943 /// If fatal is true, a single failure bails out the comparison after a single failure.
944 pub fn check_limits_with_fail_fn(
945 &self,
946 allowed: &Self,
947 fatal: bool,
948 mut fail_fn: impl FnMut(&'static str, u64, u64),
949 ) {
950 use core::cmp::Ordering;
951
952 macro_rules! compare {
953 ($name:ident, $ordering:ident) => {
954 match self.$name.cmp(&allowed.$name) {
955 Ordering::$ordering | Ordering::Equal => (),
956 _ => {
957 fail_fn(stringify!($name), self.$name as u64, allowed.$name as u64);
958 if fatal {
959 return;
960 }
961 }
962 }
963 };
964 }
965
966 compare!(max_texture_dimension_1d, Less);
967 compare!(max_texture_dimension_2d, Less);
968 compare!(max_texture_dimension_3d, Less);
969 compare!(max_texture_array_layers, Less);
970 compare!(max_bind_groups, Less);
971 compare!(max_bindings_per_bind_group, Less);
972 compare!(max_dynamic_uniform_buffers_per_pipeline_layout, Less);
973 compare!(max_dynamic_storage_buffers_per_pipeline_layout, Less);
974 compare!(max_sampled_textures_per_shader_stage, Less);
975 compare!(max_samplers_per_shader_stage, Less);
976 compare!(max_storage_buffers_per_shader_stage, Less);
977 compare!(max_storage_textures_per_shader_stage, Less);
978 compare!(max_uniform_buffers_per_shader_stage, Less);
979 compare!(max_binding_array_elements_per_shader_stage, Less);
980 compare!(max_uniform_buffer_binding_size, Less);
981 compare!(max_storage_buffer_binding_size, Less);
982 compare!(max_vertex_buffers, Less);
983 compare!(max_buffer_size, Less);
984 compare!(max_vertex_attributes, Less);
985 compare!(max_vertex_buffer_array_stride, Less);
986 compare!(min_uniform_buffer_offset_alignment, Greater);
987 compare!(min_storage_buffer_offset_alignment, Greater);
988 compare!(max_inter_stage_shader_components, Less);
989 compare!(max_color_attachments, Less);
990 compare!(max_color_attachment_bytes_per_sample, Less);
991 compare!(max_compute_workgroup_storage_size, Less);
992 compare!(max_compute_invocations_per_workgroup, Less);
993 compare!(max_compute_workgroup_size_x, Less);
994 compare!(max_compute_workgroup_size_y, Less);
995 compare!(max_compute_workgroup_size_z, Less);
996 compare!(max_compute_workgroups_per_dimension, Less);
997 if self.min_subgroup_size > 0 && self.max_subgroup_size > 0 {
998 compare!(min_subgroup_size, Greater);
999 compare!(max_subgroup_size, Less);
1000 }
1001 compare!(max_push_constant_size, Less);
1002 compare!(max_non_sampler_bindings, Less);
1003 compare!(max_blas_primitive_count, Less);
1004 compare!(max_blas_geometry_count, Less);
1005 compare!(max_tlas_instance_count, Less);
1006 }
1007}
1008
1009/// Represents the sets of additional limits on an adapter,
1010/// which take place when running on downlevel backends.
1011#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1012#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1013pub struct DownlevelLimits {}
1014
1015#[allow(clippy::derivable_impls)]
1016impl Default for DownlevelLimits {
1017 fn default() -> Self {
1018 DownlevelLimits {}
1019 }
1020}
1021
1022/// Lists various ways the underlying platform does not conform to the WebGPU standard.
1023#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1024#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1025pub struct DownlevelCapabilities {
1026 /// Combined boolean flags.
1027 pub flags: DownlevelFlags,
1028 /// Additional limits
1029 pub limits: DownlevelLimits,
1030 /// Which collections of features shaders support. Defined in terms of D3D's shader models.
1031 pub shader_model: ShaderModel,
1032}
1033
1034impl Default for DownlevelCapabilities {
1035 fn default() -> Self {
1036 Self {
1037 flags: DownlevelFlags::all(),
1038 limits: DownlevelLimits::default(),
1039 shader_model: ShaderModel::Sm5,
1040 }
1041 }
1042}
1043
1044impl DownlevelCapabilities {
1045 /// Returns true if the underlying platform offers complete support of the baseline WebGPU standard.
1046 ///
1047 /// If this returns false, some parts of the API will result in validation errors where they would not normally.
1048 /// These parts can be determined by the values in this structure.
1049 #[must_use]
1050 pub fn is_webgpu_compliant(&self) -> bool {
1051 self.flags.contains(DownlevelFlags::compliant())
1052 && self.limits == DownlevelLimits::default()
1053 && self.shader_model >= ShaderModel::Sm5
1054 }
1055}
1056
1057bitflags::bitflags! {
1058 /// Binary flags listing features that may or may not be present on downlevel adapters.
1059 ///
1060 /// A downlevel adapter is a GPU adapter that WGPU supports, but with potentially limited
1061 /// features, due to the lack of hardware feature support.
1062 ///
1063 /// Flags that are **not** present for a downlevel adapter or device usually indicates
1064 /// non-compliance with the WebGPU specification, but not always.
1065 ///
1066 /// You can check whether a set of flags is compliant through the
1067 /// [`DownlevelCapabilities::is_webgpu_compliant()`] function.
1068 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1069 #[cfg_attr(feature = "serde", serde(transparent))]
1070 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1071 pub struct DownlevelFlags: u32 {
1072 /// The device supports compiling and using compute shaders.
1073 ///
1074 /// WebGL2, and GLES3.0 devices do not support compute.
1075 const COMPUTE_SHADERS = 1 << 0;
1076 /// Supports binding storage buffers and textures to fragment shaders.
1077 const FRAGMENT_WRITABLE_STORAGE = 1 << 1;
1078 /// Supports indirect drawing and dispatching.
1079 ///
1080 /// [`Self::COMPUTE_SHADERS`] must be present for this flag.
1081 ///
1082 /// WebGL2, GLES 3.0, and Metal on Apple1/Apple2 GPUs do not support indirect.
1083 const INDIRECT_EXECUTION = 1 << 2;
1084 /// Supports non-zero `base_vertex` parameter to direct indexed draw calls.
1085 ///
1086 /// Indirect calls, if supported, always support non-zero `base_vertex`.
1087 ///
1088 /// Supported by:
1089 /// - Vulkan
1090 /// - DX12
1091 /// - Metal on Apple3+ or Mac1+
1092 /// - OpenGL 3.2+
1093 /// - OpenGL ES 3.2
1094 const BASE_VERTEX = 1 << 3;
1095 /// Supports reading from a depth/stencil texture while using it as a read-only
1096 /// depth/stencil attachment.
1097 ///
1098 /// The WebGL2 and GLES backends do not support RODS.
1099 const READ_ONLY_DEPTH_STENCIL = 1 << 4;
1100 /// Supports textures with mipmaps which have a non power of two size.
1101 const NON_POWER_OF_TWO_MIPMAPPED_TEXTURES = 1 << 5;
1102 /// Supports textures that are cube arrays.
1103 const CUBE_ARRAY_TEXTURES = 1 << 6;
1104 /// Supports comparison samplers.
1105 const COMPARISON_SAMPLERS = 1 << 7;
1106 /// Supports different blend operations per color attachment.
1107 const INDEPENDENT_BLEND = 1 << 8;
1108 /// Supports storage buffers in vertex shaders.
1109 const VERTEX_STORAGE = 1 << 9;
1110
1111 /// Supports samplers with anisotropic filtering. Note this isn't actually required by
1112 /// WebGPU, the implementation is allowed to completely ignore aniso clamp. This flag is
1113 /// here for native backends so they can communicate to the user of aniso is enabled.
1114 ///
1115 /// All backends and all devices support anisotropic filtering.
1116 const ANISOTROPIC_FILTERING = 1 << 10;
1117
1118 /// Supports storage buffers in fragment shaders.
1119 const FRAGMENT_STORAGE = 1 << 11;
1120
1121 /// Supports sample-rate shading.
1122 const MULTISAMPLED_SHADING = 1 << 12;
1123
1124 /// Supports copies between depth textures and buffers.
1125 ///
1126 /// GLES/WebGL don't support this.
1127 const DEPTH_TEXTURE_AND_BUFFER_COPIES = 1 << 13;
1128
1129 /// Supports all the texture usages described in WebGPU. If this isn't supported, you
1130 /// should call `get_texture_format_features` to get how you can use textures of a given format
1131 const WEBGPU_TEXTURE_FORMAT_SUPPORT = 1 << 14;
1132
1133 /// Supports buffer bindings with sizes that aren't a multiple of 16.
1134 ///
1135 /// WebGL doesn't support this.
1136 const BUFFER_BINDINGS_NOT_16_BYTE_ALIGNED = 1 << 15;
1137
1138 /// Supports buffers to combine [`BufferUsages::INDEX`] with usages other than [`BufferUsages::COPY_DST`] and [`BufferUsages::COPY_SRC`].
1139 /// Furthermore, in absence of this feature it is not allowed to copy index buffers from/to buffers with a set of usage flags containing
1140 /// [`BufferUsages::VERTEX`]/[`BufferUsages::UNIFORM`]/[`BufferUsages::STORAGE`] or [`BufferUsages::INDIRECT`].
1141 ///
1142 /// WebGL doesn't support this.
1143 const UNRESTRICTED_INDEX_BUFFER = 1 << 16;
1144
1145 /// Supports full 32-bit range indices (2^32-1 as opposed to 2^24-1 without this flag)
1146 ///
1147 /// Corresponds to Vulkan's `VkPhysicalDeviceFeatures.fullDrawIndexUint32`
1148 const FULL_DRAW_INDEX_UINT32 = 1 << 17;
1149
1150 /// Supports depth bias clamping
1151 ///
1152 /// Corresponds to Vulkan's `VkPhysicalDeviceFeatures.depthBiasClamp`
1153 const DEPTH_BIAS_CLAMP = 1 << 18;
1154
1155 /// Supports specifying which view format values are allowed when create_view() is called on a texture.
1156 ///
1157 /// The WebGL and GLES backends doesn't support this.
1158 const VIEW_FORMATS = 1 << 19;
1159
1160 /// With this feature not present, there are the following restrictions on `Queue::copy_external_image_to_texture`:
1161 /// - The source must not be [`web_sys::OffscreenCanvas`]
1162 /// - [`CopyExternalImageSourceInfo::origin`] must be zero.
1163 /// - [`CopyExternalImageDestInfo::color_space`] must be srgb.
1164 /// - If the source is an [`web_sys::ImageBitmap`]:
1165 /// - [`CopyExternalImageSourceInfo::flip_y`] must be false.
1166 /// - [`CopyExternalImageDestInfo::premultiplied_alpha`] must be false.
1167 ///
1168 /// WebGL doesn't support this. WebGPU does.
1169 const UNRESTRICTED_EXTERNAL_TEXTURE_COPIES = 1 << 20;
1170
1171 /// Supports specifying which view formats are allowed when calling create_view on the texture returned by
1172 /// `Surface::get_current_texture`.
1173 ///
1174 /// The GLES/WebGL and Vulkan on Android doesn't support this.
1175 const SURFACE_VIEW_FORMATS = 1 << 21;
1176
1177 /// If this is true, calls to `CommandEncoder::resolve_query_set` will be performed on the queue timeline.
1178 ///
1179 /// If this is false, calls to `CommandEncoder::resolve_query_set` will be performed on the device (i.e. cpu) timeline
1180 /// and will block that timeline until the query has data. You may work around this limitation by waiting until the submit
1181 /// whose queries you are resolving is fully finished (through use of `queue.on_submitted_work_done`) and only
1182 /// then submitting the resolve_query_set command. The queries will be guaranteed finished, so will not block.
1183 ///
1184 /// Supported by:
1185 /// - Vulkan,
1186 /// - DX12
1187 /// - Metal
1188 /// - OpenGL 4.4+
1189 ///
1190 /// Not Supported by:
1191 /// - GL ES / WebGL
1192 const NONBLOCKING_QUERY_RESOLVE = 1 << 22;
1193 }
1194}
1195
1196impl DownlevelFlags {
1197 /// All flags that indicate if the backend is WebGPU compliant
1198 #[must_use]
1199 pub const fn compliant() -> Self {
1200 // We use manual bit twiddling to make this a const fn as `Sub` and `.remove` aren't const
1201
1202 // WebGPU doesn't actually require aniso
1203 Self::from_bits_truncate(Self::all().bits() & !Self::ANISOTROPIC_FILTERING.bits())
1204 }
1205}
1206
1207/// Collections of shader features a device supports if they support less than WebGPU normally allows.
1208// TODO: Fill out the differences between shader models more completely
1209#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1210#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1211pub enum ShaderModel {
1212 /// Extremely limited shaders, including a total instruction limit.
1213 Sm2,
1214 /// Missing minor features and storage images.
1215 Sm4,
1216 /// WebGPU supports shader module 5.
1217 Sm5,
1218}
1219
1220/// Supported physical device types.
1221#[repr(u8)]
1222#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
1223#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1224pub enum DeviceType {
1225 /// Other or Unknown.
1226 Other,
1227 /// Integrated GPU with shared CPU/GPU memory.
1228 IntegratedGpu,
1229 /// Discrete GPU with separate CPU/GPU memory.
1230 DiscreteGpu,
1231 /// Virtual / Hosted.
1232 VirtualGpu,
1233 /// Cpu / Software Rendering.
1234 Cpu,
1235}
1236
1237//TODO: convert `vendor` and `device` to `u32`
1238
1239/// Information about an adapter.
1240#[derive(Clone, Debug, Eq, PartialEq, Hash)]
1241#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1242pub struct AdapterInfo {
1243 /// Adapter name
1244 pub name: String,
1245 /// [`Backend`]-specific vendor ID of the adapter
1246 ///
1247 /// This generally is a 16-bit PCI vendor ID in the least significant bytes of this field.
1248 /// However, more significant bytes may be non-zero if the backend uses a different
1249 /// representation.
1250 ///
1251 /// * For [`Backend::Vulkan`], the [`VkPhysicalDeviceProperties::vendorID`] is used, which is
1252 /// a superset of PCI IDs.
1253 ///
1254 /// [`VkPhysicalDeviceProperties::vendorID`]: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkPhysicalDeviceProperties.html
1255 pub vendor: u32,
1256 /// [`Backend`]-specific device ID of the adapter
1257 ///
1258 ///
1259 /// This generally is a 16-bit PCI device ID in the least significant bytes of this field.
1260 /// However, more significant bytes may be non-zero if the backend uses a different
1261 /// representation.
1262 ///
1263 /// * For [`Backend::Vulkan`], the [`VkPhysicalDeviceProperties::deviceID`] is used, which is
1264 /// a superset of PCI IDs.
1265 ///
1266 /// [`VkPhysicalDeviceProperties::deviceID`]: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkPhysicalDeviceProperties.html
1267 pub device: u32,
1268 /// Type of device
1269 pub device_type: DeviceType,
1270 /// Driver name
1271 pub driver: String,
1272 /// Driver info
1273 pub driver_info: String,
1274 /// Backend used for device
1275 pub backend: Backend,
1276}
1277
1278/// Hints to the device about the memory allocation strategy.
1279///
1280/// Some backends may ignore these hints.
1281#[derive(Clone, Debug, Default)]
1282#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1283pub enum MemoryHints {
1284 /// Favor performance over memory usage (the default value).
1285 #[default]
1286 Performance,
1287 /// Favor memory usage over performance.
1288 MemoryUsage,
1289 /// Applications that have control over the content that is rendered
1290 /// (typically games) may find an optimal compromise between memory
1291 /// usage and performance by specifying the allocation configuration.
1292 Manual {
1293 /// Defines the range of allowed memory block sizes for sub-allocated
1294 /// resources.
1295 ///
1296 /// The backend may attempt to group multiple resources into fewer
1297 /// device memory blocks (sub-allocation) for performance reasons.
1298 /// The start of the provided range specifies the initial memory
1299 /// block size for sub-allocated resources. After running out of
1300 /// space in existing memory blocks, the backend may chose to
1301 /// progressively increase the block size of subsequent allocations
1302 /// up to a limit specified by the end of the range.
1303 ///
1304 /// This does not limit resource sizes. If a resource does not fit
1305 /// in the specified range, it will typically be placed in a dedicated
1306 /// memory block.
1307 suballocated_device_memory_block_size: Range<u64>,
1308 },
1309}
1310
1311/// Describes a [`Device`](../wgpu/struct.Device.html).
1312///
1313/// Corresponds to [WebGPU `GPUDeviceDescriptor`](
1314/// https://gpuweb.github.io/gpuweb/#gpudevicedescriptor).
1315#[derive(Clone, Debug, Default)]
1316#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1317pub struct DeviceDescriptor<L> {
1318 /// Debug label for the device.
1319 pub label: L,
1320 /// Specifies the features that are required by the device request.
1321 /// The request will fail if the adapter cannot provide these features.
1322 ///
1323 /// Exactly the specified set of features, and no more or less,
1324 /// will be allowed in validation of API calls on the resulting device.
1325 pub required_features: Features,
1326 /// Specifies the limits that are required by the device request.
1327 /// The request will fail if the adapter cannot provide these limits.
1328 ///
1329 /// Exactly the specified limits, and no better or worse,
1330 /// will be allowed in validation of API calls on the resulting device.
1331 pub required_limits: Limits,
1332 /// Hints for memory allocation strategies.
1333 pub memory_hints: MemoryHints,
1334 /// Whether API tracing for debugging is enabled,
1335 /// and where the trace is written if so.
1336 pub trace: Trace,
1337}
1338
1339impl<L> DeviceDescriptor<L> {
1340 /// Takes a closure and maps the label of the device descriptor into another.
1341 #[must_use]
1342 pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> DeviceDescriptor<K> {
1343 DeviceDescriptor {
1344 label: fun(&self.label),
1345 required_features: self.required_features,
1346 required_limits: self.required_limits.clone(),
1347 memory_hints: self.memory_hints.clone(),
1348 trace: self.trace.clone(),
1349 }
1350 }
1351}
1352
1353/// Controls API call tracing and specifies where the trace is written.
1354///
1355/// **Note:** Tracing is currently unavailable.
1356/// See [issue 5974](https://github.com/gfx-rs/wgpu/issues/5974) for updates.
1357#[derive(Clone, Debug, Default)]
1358#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1359// This enum must be non-exhaustive so that enabling the "trace" feature is not a semver break.
1360#[non_exhaustive]
1361pub enum Trace {
1362 /// Tracing disabled.
1363 #[default]
1364 Off,
1365
1366 /// Tracing enabled.
1367 #[cfg(feature = "trace")]
1368 // This must be owned rather than `&'a Path`, because if it were that, then the lifetime
1369 // parameter would be unused when the "trace" feature is disabled, which is prohibited.
1370 Directory(std::path::PathBuf),
1371}
1372
1373bitflags::bitflags! {
1374 /// Describes the shader stages that a binding will be visible from.
1375 ///
1376 /// These can be combined so something that is visible from both vertex and fragment shaders can be defined as:
1377 ///
1378 /// `ShaderStages::VERTEX | ShaderStages::FRAGMENT`
1379 ///
1380 /// Corresponds to [WebGPU `GPUShaderStageFlags`](
1381 /// https://gpuweb.github.io/gpuweb/#typedefdef-gpushaderstageflags).
1382 #[repr(transparent)]
1383 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1384 #[cfg_attr(feature = "serde", serde(transparent))]
1385 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1386 pub struct ShaderStages: u32 {
1387 /// Binding is not visible from any shader stage.
1388 const NONE = 0;
1389 /// Binding is visible from the vertex shader of a render pipeline.
1390 const VERTEX = 1 << 0;
1391 /// Binding is visible from the fragment shader of a render pipeline.
1392 const FRAGMENT = 1 << 1;
1393 /// Binding is visible from the compute shader of a compute pipeline.
1394 const COMPUTE = 1 << 2;
1395 /// Binding is visible from the vertex and fragment shaders of a render pipeline.
1396 const VERTEX_FRAGMENT = Self::VERTEX.bits() | Self::FRAGMENT.bits();
1397 /// Binding is visible from the task shader of a mesh pipeline
1398 const TASK = 1 << 3;
1399 /// Binding is visible from the mesh shader of a mesh pipeline
1400 const MESH = 1 << 4;
1401 }
1402}
1403
1404/// Order in which texture data is laid out in memory.
1405#[derive(Clone, Copy, Default, Debug, PartialEq, Eq, Hash)]
1406pub enum TextureDataOrder {
1407 /// The texture is laid out densely in memory as:
1408 ///
1409 /// ```text
1410 /// Layer0Mip0 Layer0Mip1 Layer0Mip2
1411 /// Layer1Mip0 Layer1Mip1 Layer1Mip2
1412 /// Layer2Mip0 Layer2Mip1 Layer2Mip2
1413 /// ````
1414 ///
1415 /// This is the layout used by dds files.
1416 #[default]
1417 LayerMajor,
1418 /// The texture is laid out densely in memory as:
1419 ///
1420 /// ```text
1421 /// Layer0Mip0 Layer1Mip0 Layer2Mip0
1422 /// Layer0Mip1 Layer1Mip1 Layer2Mip1
1423 /// Layer0Mip2 Layer1Mip2 Layer2Mip2
1424 /// ```
1425 ///
1426 /// This is the layout used by ktx and ktx2 files.
1427 MipMajor,
1428}
1429
1430/// Dimensions of a particular texture view.
1431///
1432/// Corresponds to [WebGPU `GPUTextureViewDimension`](
1433/// https://gpuweb.github.io/gpuweb/#enumdef-gputextureviewdimension).
1434#[repr(C)]
1435#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
1436#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1437pub enum TextureViewDimension {
1438 /// A one dimensional texture. `texture_1d` in WGSL and `texture1D` in GLSL.
1439 #[cfg_attr(feature = "serde", serde(rename = "1d"))]
1440 D1,
1441 /// A two dimensional texture. `texture_2d` in WGSL and `texture2D` in GLSL.
1442 #[cfg_attr(feature = "serde", serde(rename = "2d"))]
1443 #[default]
1444 D2,
1445 /// A two dimensional array texture. `texture_2d_array` in WGSL and `texture2DArray` in GLSL.
1446 #[cfg_attr(feature = "serde", serde(rename = "2d-array"))]
1447 D2Array,
1448 /// A cubemap texture. `texture_cube` in WGSL and `textureCube` in GLSL.
1449 #[cfg_attr(feature = "serde", serde(rename = "cube"))]
1450 Cube,
1451 /// A cubemap array texture. `texture_cube_array` in WGSL and `textureCubeArray` in GLSL.
1452 #[cfg_attr(feature = "serde", serde(rename = "cube-array"))]
1453 CubeArray,
1454 /// A three dimensional texture. `texture_3d` in WGSL and `texture3D` in GLSL.
1455 #[cfg_attr(feature = "serde", serde(rename = "3d"))]
1456 D3,
1457}
1458
1459impl TextureViewDimension {
1460 /// Get the texture dimension required of this texture view dimension.
1461 #[must_use]
1462 pub fn compatible_texture_dimension(self) -> TextureDimension {
1463 match self {
1464 Self::D1 => TextureDimension::D1,
1465 Self::D2 | Self::D2Array | Self::Cube | Self::CubeArray => TextureDimension::D2,
1466 Self::D3 => TextureDimension::D3,
1467 }
1468 }
1469}
1470
1471/// Alpha blend factor.
1472///
1473/// Corresponds to [WebGPU `GPUBlendFactor`](
1474/// https://gpuweb.github.io/gpuweb/#enumdef-gpublendfactor). Values using `Src1`
1475/// require [`Features::DUAL_SOURCE_BLENDING`] and can only be used with the first
1476/// render target.
1477///
1478/// For further details on how the blend factors are applied, see the analogous
1479/// functionality in OpenGL: <https://www.khronos.org/opengl/wiki/Blending#Blending_Parameters>.
1480#[repr(C)]
1481#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
1482#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1483#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
1484pub enum BlendFactor {
1485 /// 0.0
1486 Zero = 0,
1487 /// 1.0
1488 One = 1,
1489 /// S.component
1490 Src = 2,
1491 /// 1.0 - S.component
1492 OneMinusSrc = 3,
1493 /// S.alpha
1494 SrcAlpha = 4,
1495 /// 1.0 - S.alpha
1496 OneMinusSrcAlpha = 5,
1497 /// D.component
1498 Dst = 6,
1499 /// 1.0 - D.component
1500 OneMinusDst = 7,
1501 /// D.alpha
1502 DstAlpha = 8,
1503 /// 1.0 - D.alpha
1504 OneMinusDstAlpha = 9,
1505 /// min(S.alpha, 1.0 - D.alpha)
1506 SrcAlphaSaturated = 10,
1507 /// Constant
1508 Constant = 11,
1509 /// 1.0 - Constant
1510 OneMinusConstant = 12,
1511 /// S1.component
1512 Src1 = 13,
1513 /// 1.0 - S1.component
1514 OneMinusSrc1 = 14,
1515 /// S1.alpha
1516 Src1Alpha = 15,
1517 /// 1.0 - S1.alpha
1518 OneMinusSrc1Alpha = 16,
1519}
1520
1521impl BlendFactor {
1522 /// Returns `true` if the blend factor references the second blend source.
1523 ///
1524 /// Note that the usage of those blend factors require [`Features::DUAL_SOURCE_BLENDING`].
1525 #[must_use]
1526 pub fn ref_second_blend_source(&self) -> bool {
1527 match self {
1528 BlendFactor::Src1
1529 | BlendFactor::OneMinusSrc1
1530 | BlendFactor::Src1Alpha
1531 | BlendFactor::OneMinusSrc1Alpha => true,
1532 _ => false,
1533 }
1534 }
1535}
1536
1537/// Alpha blend operation.
1538///
1539/// Corresponds to [WebGPU `GPUBlendOperation`](
1540/// https://gpuweb.github.io/gpuweb/#enumdef-gpublendoperation).
1541///
1542/// For further details on how the blend operations are applied, see
1543/// the analogous functionality in OpenGL: <https://www.khronos.org/opengl/wiki/Blending#Blend_Equations>.
1544#[repr(C)]
1545#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
1546#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1547#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
1548pub enum BlendOperation {
1549 /// Src + Dst
1550 #[default]
1551 Add = 0,
1552 /// Src - Dst
1553 Subtract = 1,
1554 /// Dst - Src
1555 ReverseSubtract = 2,
1556 /// min(Src, Dst)
1557 Min = 3,
1558 /// max(Src, Dst)
1559 Max = 4,
1560}
1561
1562/// Describes a blend component of a [`BlendState`].
1563///
1564/// Corresponds to [WebGPU `GPUBlendComponent`](
1565/// https://gpuweb.github.io/gpuweb/#dictdef-gpublendcomponent).
1566#[repr(C)]
1567#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1568#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1569#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1570pub struct BlendComponent {
1571 /// Multiplier for the source, which is produced by the fragment shader.
1572 pub src_factor: BlendFactor,
1573 /// Multiplier for the destination, which is stored in the target.
1574 pub dst_factor: BlendFactor,
1575 /// The binary operation applied to the source and destination,
1576 /// multiplied by their respective factors.
1577 pub operation: BlendOperation,
1578}
1579
1580impl BlendComponent {
1581 /// Default blending state that replaces destination with the source.
1582 pub const REPLACE: Self = Self {
1583 src_factor: BlendFactor::One,
1584 dst_factor: BlendFactor::Zero,
1585 operation: BlendOperation::Add,
1586 };
1587
1588 /// Blend state of `(1 * src) + ((1 - src_alpha) * dst)`.
1589 pub const OVER: Self = Self {
1590 src_factor: BlendFactor::One,
1591 dst_factor: BlendFactor::OneMinusSrcAlpha,
1592 operation: BlendOperation::Add,
1593 };
1594
1595 /// Returns true if the state relies on the constant color, which is
1596 /// set independently on a render command encoder.
1597 #[must_use]
1598 pub fn uses_constant(&self) -> bool {
1599 match (self.src_factor, self.dst_factor) {
1600 (BlendFactor::Constant, _)
1601 | (BlendFactor::OneMinusConstant, _)
1602 | (_, BlendFactor::Constant)
1603 | (_, BlendFactor::OneMinusConstant) => true,
1604 (_, _) => false,
1605 }
1606 }
1607}
1608
1609impl Default for BlendComponent {
1610 fn default() -> Self {
1611 Self::REPLACE
1612 }
1613}
1614
1615/// Describe the blend state of a render pipeline,
1616/// within [`ColorTargetState`].
1617///
1618/// Corresponds to [WebGPU `GPUBlendState`](
1619/// https://gpuweb.github.io/gpuweb/#dictdef-gpublendstate).
1620#[repr(C)]
1621#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1622#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1623#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1624pub struct BlendState {
1625 /// Color equation.
1626 pub color: BlendComponent,
1627 /// Alpha equation.
1628 pub alpha: BlendComponent,
1629}
1630
1631impl BlendState {
1632 /// Blend mode that does no color blending, just overwrites the output with the contents of the shader.
1633 pub const REPLACE: Self = Self {
1634 color: BlendComponent::REPLACE,
1635 alpha: BlendComponent::REPLACE,
1636 };
1637
1638 /// Blend mode that does standard alpha blending with non-premultiplied alpha.
1639 pub const ALPHA_BLENDING: Self = Self {
1640 color: BlendComponent {
1641 src_factor: BlendFactor::SrcAlpha,
1642 dst_factor: BlendFactor::OneMinusSrcAlpha,
1643 operation: BlendOperation::Add,
1644 },
1645 alpha: BlendComponent::OVER,
1646 };
1647
1648 /// Blend mode that does standard alpha blending with premultiplied alpha.
1649 pub const PREMULTIPLIED_ALPHA_BLENDING: Self = Self {
1650 color: BlendComponent::OVER,
1651 alpha: BlendComponent::OVER,
1652 };
1653}
1654
1655/// Describes the color state of a render pipeline.
1656///
1657/// Corresponds to [WebGPU `GPUColorTargetState`](
1658/// https://gpuweb.github.io/gpuweb/#dictdef-gpucolortargetstate).
1659#[repr(C)]
1660#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1661#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1662#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1663pub struct ColorTargetState {
1664 /// The [`TextureFormat`] of the image that this pipeline will render to. Must match the format
1665 /// of the corresponding color attachment in [`CommandEncoder::begin_render_pass`][CEbrp]
1666 ///
1667 /// [CEbrp]: ../wgpu/struct.CommandEncoder.html#method.begin_render_pass
1668 pub format: TextureFormat,
1669 /// The blending that is used for this pipeline.
1670 #[cfg_attr(feature = "serde", serde(default))]
1671 pub blend: Option<BlendState>,
1672 /// Mask which enables/disables writes to different color/alpha channel.
1673 #[cfg_attr(feature = "serde", serde(default))]
1674 pub write_mask: ColorWrites,
1675}
1676
1677impl From<TextureFormat> for ColorTargetState {
1678 fn from(format: TextureFormat) -> Self {
1679 Self {
1680 format,
1681 blend: None,
1682 write_mask: ColorWrites::ALL,
1683 }
1684 }
1685}
1686
1687/// Primitive type the input mesh is composed of.
1688///
1689/// Corresponds to [WebGPU `GPUPrimitiveTopology`](
1690/// https://gpuweb.github.io/gpuweb/#enumdef-gpuprimitivetopology).
1691#[repr(C)]
1692#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
1693#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1694#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
1695pub enum PrimitiveTopology {
1696 /// Vertex data is a list of points. Each vertex is a new point.
1697 PointList = 0,
1698 /// Vertex data is a list of lines. Each pair of vertices composes a new line.
1699 ///
1700 /// Vertices `0 1 2 3` create two lines `0 1` and `2 3`
1701 LineList = 1,
1702 /// Vertex data is a strip of lines. Each set of two adjacent vertices form a line.
1703 ///
1704 /// Vertices `0 1 2 3` create three lines `0 1`, `1 2`, and `2 3`.
1705 LineStrip = 2,
1706 /// Vertex data is a list of triangles. Each set of 3 vertices composes a new triangle.
1707 ///
1708 /// Vertices `0 1 2 3 4 5` create two triangles `0 1 2` and `3 4 5`
1709 #[default]
1710 TriangleList = 3,
1711 /// Vertex data is a triangle strip. Each set of three adjacent vertices form a triangle.
1712 ///
1713 /// Vertices `0 1 2 3 4 5` create four triangles `0 1 2`, `2 1 3`, `2 3 4`, and `4 3 5`
1714 TriangleStrip = 4,
1715}
1716
1717impl PrimitiveTopology {
1718 /// Returns true for strip topologies.
1719 #[must_use]
1720 pub fn is_strip(&self) -> bool {
1721 match *self {
1722 Self::PointList | Self::LineList | Self::TriangleList => false,
1723 Self::LineStrip | Self::TriangleStrip => true,
1724 }
1725 }
1726}
1727
1728/// Vertex winding order which classifies the "front" face of a triangle.
1729///
1730/// Corresponds to [WebGPU `GPUFrontFace`](
1731/// https://gpuweb.github.io/gpuweb/#enumdef-gpufrontface).
1732#[repr(C)]
1733#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
1734#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1735#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
1736pub enum FrontFace {
1737 /// Triangles with vertices in counter clockwise order are considered the front face.
1738 ///
1739 /// This is the default with right handed coordinate spaces.
1740 #[default]
1741 Ccw = 0,
1742 /// Triangles with vertices in clockwise order are considered the front face.
1743 ///
1744 /// This is the default with left handed coordinate spaces.
1745 Cw = 1,
1746}
1747
1748/// Face of a vertex.
1749///
1750/// Corresponds to [WebGPU `GPUCullMode`](
1751/// https://gpuweb.github.io/gpuweb/#enumdef-gpucullmode),
1752/// except that the `"none"` value is represented using `Option<Face>` instead.
1753#[repr(C)]
1754#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
1755#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1756#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
1757pub enum Face {
1758 /// Front face
1759 Front = 0,
1760 /// Back face
1761 Back = 1,
1762}
1763
1764/// Type of drawing mode for polygons
1765#[repr(C)]
1766#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
1767#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1768#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
1769pub enum PolygonMode {
1770 /// Polygons are filled
1771 #[default]
1772 Fill = 0,
1773 /// Polygons are drawn as line segments
1774 Line = 1,
1775 /// Polygons are drawn as points
1776 Point = 2,
1777}
1778
1779/// Describes the state of primitive assembly and rasterization in a render pipeline.
1780///
1781/// Corresponds to [WebGPU `GPUPrimitiveState`](
1782/// https://gpuweb.github.io/gpuweb/#dictdef-gpuprimitivestate).
1783#[repr(C)]
1784#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
1785#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1786#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1787pub struct PrimitiveState {
1788 /// The primitive topology used to interpret vertices.
1789 pub topology: PrimitiveTopology,
1790 /// When drawing strip topologies with indices, this is the required format for the index buffer.
1791 /// This has no effect on non-indexed or non-strip draws.
1792 ///
1793 /// Specifying this value enables primitive restart, allowing individual strips to be separated
1794 /// with the index value `0xFFFF` when using `Uint16`, or `0xFFFFFFFF` when using `Uint32`.
1795 #[cfg_attr(feature = "serde", serde(default))]
1796 pub strip_index_format: Option<IndexFormat>,
1797 /// The face to consider the front for the purpose of culling and stencil operations.
1798 #[cfg_attr(feature = "serde", serde(default))]
1799 pub front_face: FrontFace,
1800 /// The face culling mode.
1801 #[cfg_attr(feature = "serde", serde(default))]
1802 pub cull_mode: Option<Face>,
1803 /// If set to true, the polygon depth is not clipped to 0-1 before rasterization.
1804 ///
1805 /// Enabling this requires [`Features::DEPTH_CLIP_CONTROL`] to be enabled.
1806 #[cfg_attr(feature = "serde", serde(default))]
1807 pub unclipped_depth: bool,
1808 /// Controls the way each polygon is rasterized. Can be either `Fill` (default), `Line` or `Point`
1809 ///
1810 /// Setting this to `Line` requires [`Features::POLYGON_MODE_LINE`] to be enabled.
1811 ///
1812 /// Setting this to `Point` requires [`Features::POLYGON_MODE_POINT`] to be enabled.
1813 #[cfg_attr(feature = "serde", serde(default))]
1814 pub polygon_mode: PolygonMode,
1815 /// If set to true, the primitives are rendered with conservative overestimation. I.e. any rastered pixel touched by it is filled.
1816 /// Only valid for `[PolygonMode::Fill`]!
1817 ///
1818 /// Enabling this requires [`Features::CONSERVATIVE_RASTERIZATION`] to be enabled.
1819 pub conservative: bool,
1820}
1821
1822/// Describes the multi-sampling state of a render pipeline.
1823///
1824/// Corresponds to [WebGPU `GPUMultisampleState`](
1825/// https://gpuweb.github.io/gpuweb/#dictdef-gpumultisamplestate).
1826#[repr(C)]
1827#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1828#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1829#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
1830pub struct MultisampleState {
1831 /// The number of samples calculated per pixel (for MSAA). For non-multisampled textures,
1832 /// this should be `1`
1833 pub count: u32,
1834 /// Bitmask that restricts the samples of a pixel modified by this pipeline. All samples
1835 /// can be enabled using the value `!0`
1836 pub mask: u64,
1837 /// When enabled, produces another sample mask per pixel based on the alpha output value, that
1838 /// is ANDed with the sample mask and the primitive coverage to restrict the set of samples
1839 /// affected by a primitive.
1840 ///
1841 /// The implicit mask produced for alpha of zero is guaranteed to be zero, and for alpha of one
1842 /// is guaranteed to be all 1-s.
1843 pub alpha_to_coverage_enabled: bool,
1844}
1845
1846impl Default for MultisampleState {
1847 fn default() -> Self {
1848 MultisampleState {
1849 count: 1,
1850 mask: !0,
1851 alpha_to_coverage_enabled: false,
1852 }
1853 }
1854}
1855
1856bitflags::bitflags! {
1857 /// Feature flags for a texture format.
1858 #[repr(transparent)]
1859 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1860 #[cfg_attr(feature = "serde", serde(transparent))]
1861 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1862 pub struct TextureFormatFeatureFlags: u32 {
1863 /// If not present, the texture can't be sampled with a filtering sampler.
1864 /// This may overwrite TextureSampleType::Float.filterable
1865 const FILTERABLE = 1 << 0;
1866 /// Allows [`TextureDescriptor::sample_count`] to be `2`.
1867 const MULTISAMPLE_X2 = 1 << 1;
1868 /// Allows [`TextureDescriptor::sample_count`] to be `4`.
1869 const MULTISAMPLE_X4 = 1 << 2 ;
1870 /// Allows [`TextureDescriptor::sample_count`] to be `8`.
1871 const MULTISAMPLE_X8 = 1 << 3 ;
1872 /// Allows [`TextureDescriptor::sample_count`] to be `16`.
1873 const MULTISAMPLE_X16 = 1 << 4;
1874 /// Allows a texture of this format to back a view passed as `resolve_target`
1875 /// to a render pass for an automatic driver-implemented resolve.
1876 const MULTISAMPLE_RESOLVE = 1 << 5;
1877 /// When used as a STORAGE texture, then a texture with this format can be bound with
1878 /// [`StorageTextureAccess::ReadOnly`].
1879 const STORAGE_READ_ONLY = 1 << 6;
1880 /// When used as a STORAGE texture, then a texture with this format can be bound with
1881 /// [`StorageTextureAccess::WriteOnly`].
1882 const STORAGE_WRITE_ONLY = 1 << 7;
1883 /// When used as a STORAGE texture, then a texture with this format can be bound with
1884 /// [`StorageTextureAccess::ReadWrite`].
1885 const STORAGE_READ_WRITE = 1 << 8;
1886 /// When used as a STORAGE texture, then a texture with this format can be bound with
1887 /// [`StorageTextureAccess::Atomic`].
1888 const STORAGE_ATOMIC = 1 << 9;
1889 /// If not present, the texture can't be blended into the render target.
1890 const BLENDABLE = 1 << 10;
1891 }
1892}
1893
1894impl TextureFormatFeatureFlags {
1895 /// Sample count supported by a given texture format.
1896 ///
1897 /// returns `true` if `count` is a supported sample count.
1898 #[must_use]
1899 pub fn sample_count_supported(&self, count: u32) -> bool {
1900 use TextureFormatFeatureFlags as tfsc;
1901
1902 match count {
1903 1 => true,
1904 2 => self.contains(tfsc::MULTISAMPLE_X2),
1905 4 => self.contains(tfsc::MULTISAMPLE_X4),
1906 8 => self.contains(tfsc::MULTISAMPLE_X8),
1907 16 => self.contains(tfsc::MULTISAMPLE_X16),
1908 _ => false,
1909 }
1910 }
1911
1912 /// A `Vec` of supported sample counts.
1913 #[must_use]
1914 pub fn supported_sample_counts(&self) -> Vec<u32> {
1915 let all_possible_sample_counts: [u32; 5] = [1, 2, 4, 8, 16];
1916 all_possible_sample_counts
1917 .into_iter()
1918 .filter(|&sc| self.sample_count_supported(sc))
1919 .collect()
1920 }
1921}
1922
1923/// Features supported by a given texture format
1924///
1925/// Features are defined by WebGPU specification unless [`Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES`] is enabled.
1926#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
1927#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1928pub struct TextureFormatFeatures {
1929 /// Valid bits for `TextureDescriptor::Usage` provided for format creation.
1930 pub allowed_usages: TextureUsages,
1931 /// Additional property flags for the format.
1932 pub flags: TextureFormatFeatureFlags,
1933}
1934
1935/// ASTC block dimensions
1936#[repr(C)]
1937#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
1938#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1939pub enum AstcBlock {
1940 /// 4x4 block compressed texture. 16 bytes per block (8 bit/px).
1941 B4x4,
1942 /// 5x4 block compressed texture. 16 bytes per block (6.4 bit/px).
1943 B5x4,
1944 /// 5x5 block compressed texture. 16 bytes per block (5.12 bit/px).
1945 B5x5,
1946 /// 6x5 block compressed texture. 16 bytes per block (4.27 bit/px).
1947 B6x5,
1948 /// 6x6 block compressed texture. 16 bytes per block (3.56 bit/px).
1949 B6x6,
1950 /// 8x5 block compressed texture. 16 bytes per block (3.2 bit/px).
1951 B8x5,
1952 /// 8x6 block compressed texture. 16 bytes per block (2.67 bit/px).
1953 B8x6,
1954 /// 8x8 block compressed texture. 16 bytes per block (2 bit/px).
1955 B8x8,
1956 /// 10x5 block compressed texture. 16 bytes per block (2.56 bit/px).
1957 B10x5,
1958 /// 10x6 block compressed texture. 16 bytes per block (2.13 bit/px).
1959 B10x6,
1960 /// 10x8 block compressed texture. 16 bytes per block (1.6 bit/px).
1961 B10x8,
1962 /// 10x10 block compressed texture. 16 bytes per block (1.28 bit/px).
1963 B10x10,
1964 /// 12x10 block compressed texture. 16 bytes per block (1.07 bit/px).
1965 B12x10,
1966 /// 12x12 block compressed texture. 16 bytes per block (0.89 bit/px).
1967 B12x12,
1968}
1969
1970/// ASTC RGBA channel
1971#[repr(C)]
1972#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
1973#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1974pub enum AstcChannel {
1975 /// 8 bit integer RGBA, [0, 255] converted to/from linear-color float [0, 1] in shader.
1976 ///
1977 /// [`Features::TEXTURE_COMPRESSION_ASTC`] must be enabled to use this channel.
1978 Unorm,
1979 /// 8 bit integer RGBA, Srgb-color [0, 255] converted to/from linear-color float [0, 1] in shader.
1980 ///
1981 /// [`Features::TEXTURE_COMPRESSION_ASTC`] must be enabled to use this channel.
1982 UnormSrgb,
1983 /// floating-point RGBA, linear-color float can be outside of the [0, 1] range.
1984 ///
1985 /// [`Features::TEXTURE_COMPRESSION_ASTC_HDR`] must be enabled to use this channel.
1986 Hdr,
1987}
1988
1989/// Format in which a texture’s texels are stored in GPU memory.
1990///
1991/// Certain formats additionally specify a conversion.
1992/// When these formats are used in a shader, the conversion automatically takes place when loading
1993/// from or storing to the texture.
1994///
1995/// * `Unorm` formats linearly scale the integer range of the storage format to a floating-point
1996/// range of 0 to 1, inclusive.
1997/// * `Snorm` formats linearly scale the integer range of the storage format to a floating-point
1998/// range of −1 to 1, inclusive, except that the most negative value
1999/// (−128 for 8-bit, −32768 for 16-bit) is excluded; on conversion,
2000/// it is treated as identical to the second most negative
2001/// (−127 for 8-bit, −32767 for 16-bit),
2002/// so that the positive and negative ranges are symmetric.
2003/// * `UnormSrgb` formats apply the [sRGB transfer function] so that the storage is sRGB encoded
2004/// while the shader works with linear intensity values.
2005/// * `Uint`, `Sint`, and `Float` formats perform no conversion.
2006///
2007/// Corresponds to [WebGPU `GPUTextureFormat`](
2008/// https://gpuweb.github.io/gpuweb/#enumdef-gputextureformat).
2009///
2010/// [sRGB transfer function]: https://en.wikipedia.org/wiki/SRGB#Transfer_function_(%22gamma%22)
2011#[repr(C)]
2012#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
2013pub enum TextureFormat {
2014 // Normal 8 bit formats
2015 /// Red channel only. 8 bit integer per channel. [0, 255] converted to/from float [0, 1] in shader.
2016 R8Unorm,
2017 /// Red channel only. 8 bit integer per channel. [−127, 127] converted to/from float [−1, 1] in shader.
2018 R8Snorm,
2019 /// Red channel only. 8 bit integer per channel. Unsigned in shader.
2020 R8Uint,
2021 /// Red channel only. 8 bit integer per channel. Signed in shader.
2022 R8Sint,
2023
2024 // Normal 16 bit formats
2025 /// Red channel only. 16 bit integer per channel. Unsigned in shader.
2026 R16Uint,
2027 /// Red channel only. 16 bit integer per channel. Signed in shader.
2028 R16Sint,
2029 /// Red channel only. 16 bit integer per channel. [0, 65535] converted to/from float [0, 1] in shader.
2030 ///
2031 /// [`Features::TEXTURE_FORMAT_16BIT_NORM`] must be enabled to use this texture format.
2032 R16Unorm,
2033 /// Red channel only. 16 bit integer per channel. [−32767, 32767] converted to/from float [−1, 1] in shader.
2034 ///
2035 /// [`Features::TEXTURE_FORMAT_16BIT_NORM`] must be enabled to use this texture format.
2036 R16Snorm,
2037 /// Red channel only. 16 bit float per channel. Float in shader.
2038 R16Float,
2039 /// Red and green channels. 8 bit integer per channel. [0, 255] converted to/from float [0, 1] in shader.
2040 Rg8Unorm,
2041 /// Red and green channels. 8 bit integer per channel. [−127, 127] converted to/from float [−1, 1] in shader.
2042 Rg8Snorm,
2043 /// Red and green channels. 8 bit integer per channel. Unsigned in shader.
2044 Rg8Uint,
2045 /// Red and green channels. 8 bit integer per channel. Signed in shader.
2046 Rg8Sint,
2047
2048 // Normal 32 bit formats
2049 /// Red channel only. 32 bit integer per channel. Unsigned in shader.
2050 R32Uint,
2051 /// Red channel only. 32 bit integer per channel. Signed in shader.
2052 R32Sint,
2053 /// Red channel only. 32 bit float per channel. Float in shader.
2054 R32Float,
2055 /// Red and green channels. 16 bit integer per channel. Unsigned in shader.
2056 Rg16Uint,
2057 /// Red and green channels. 16 bit integer per channel. Signed in shader.
2058 Rg16Sint,
2059 /// Red and green channels. 16 bit integer per channel. [0, 65535] converted to/from float [0, 1] in shader.
2060 ///
2061 /// [`Features::TEXTURE_FORMAT_16BIT_NORM`] must be enabled to use this texture format.
2062 Rg16Unorm,
2063 /// Red and green channels. 16 bit integer per channel. [−32767, 32767] converted to/from float [−1, 1] in shader.
2064 ///
2065 /// [`Features::TEXTURE_FORMAT_16BIT_NORM`] must be enabled to use this texture format.
2066 Rg16Snorm,
2067 /// Red and green channels. 16 bit float per channel. Float in shader.
2068 Rg16Float,
2069 /// Red, green, blue, and alpha channels. 8 bit integer per channel. [0, 255] converted to/from float [0, 1] in shader.
2070 Rgba8Unorm,
2071 /// Red, green, blue, and alpha channels. 8 bit integer per channel. Srgb-color [0, 255] converted to/from linear-color float [0, 1] in shader.
2072 Rgba8UnormSrgb,
2073 /// Red, green, blue, and alpha channels. 8 bit integer per channel. [−127, 127] converted to/from float [−1, 1] in shader.
2074 Rgba8Snorm,
2075 /// Red, green, blue, and alpha channels. 8 bit integer per channel. Unsigned in shader.
2076 Rgba8Uint,
2077 /// Red, green, blue, and alpha channels. 8 bit integer per channel. Signed in shader.
2078 Rgba8Sint,
2079 /// Blue, green, red, and alpha channels. 8 bit integer per channel. [0, 255] converted to/from float [0, 1] in shader.
2080 Bgra8Unorm,
2081 /// Blue, green, red, and alpha channels. 8 bit integer per channel. Srgb-color [0, 255] converted to/from linear-color float [0, 1] in shader.
2082 Bgra8UnormSrgb,
2083
2084 // Packed 32 bit formats
2085 /// Packed unsigned float with 9 bits mantisa for each RGB component, then a common 5 bits exponent
2086 Rgb9e5Ufloat,
2087 /// Red, green, blue, and alpha channels. 10 bit integer for RGB channels, 2 bit integer for alpha channel. Unsigned in shader.
2088 Rgb10a2Uint,
2089 /// Red, green, blue, and alpha channels. 10 bit integer for RGB channels, 2 bit integer for alpha channel. [0, 1023] ([0, 3] for alpha) converted to/from float [0, 1] in shader.
2090 Rgb10a2Unorm,
2091 /// Red, green, and blue channels. 11 bit float with no sign bit for RG channels. 10 bit float with no sign bit for blue channel. Float in shader.
2092 Rg11b10Ufloat,
2093
2094 // Normal 64 bit formats
2095 /// Red channel only. 64 bit integer per channel. Unsigned in shader.
2096 ///
2097 /// [`Features::TEXTURE_INT64_ATOMIC`] must be enabled to use this texture format.
2098 R64Uint,
2099 /// Red and green channels. 32 bit integer per channel. Unsigned in shader.
2100 Rg32Uint,
2101 /// Red and green channels. 32 bit integer per channel. Signed in shader.
2102 Rg32Sint,
2103 /// Red and green channels. 32 bit float per channel. Float in shader.
2104 Rg32Float,
2105 /// Red, green, blue, and alpha channels. 16 bit integer per channel. Unsigned in shader.
2106 Rgba16Uint,
2107 /// Red, green, blue, and alpha channels. 16 bit integer per channel. Signed in shader.
2108 Rgba16Sint,
2109 /// Red, green, blue, and alpha channels. 16 bit integer per channel. [0, 65535] converted to/from float [0, 1] in shader.
2110 ///
2111 /// [`Features::TEXTURE_FORMAT_16BIT_NORM`] must be enabled to use this texture format.
2112 Rgba16Unorm,
2113 /// Red, green, blue, and alpha. 16 bit integer per channel. [−32767, 32767] converted to/from float [−1, 1] in shader.
2114 ///
2115 /// [`Features::TEXTURE_FORMAT_16BIT_NORM`] must be enabled to use this texture format.
2116 Rgba16Snorm,
2117 /// Red, green, blue, and alpha channels. 16 bit float per channel. Float in shader.
2118 Rgba16Float,
2119
2120 // Normal 128 bit formats
2121 /// Red, green, blue, and alpha channels. 32 bit integer per channel. Unsigned in shader.
2122 Rgba32Uint,
2123 /// Red, green, blue, and alpha channels. 32 bit integer per channel. Signed in shader.
2124 Rgba32Sint,
2125 /// Red, green, blue, and alpha channels. 32 bit float per channel. Float in shader.
2126 Rgba32Float,
2127
2128 // Depth and stencil formats
2129 /// Stencil format with 8 bit integer stencil.
2130 Stencil8,
2131 /// Special depth format with 16 bit integer depth.
2132 Depth16Unorm,
2133 /// Special depth format with at least 24 bit integer depth.
2134 Depth24Plus,
2135 /// Special depth/stencil format with at least 24 bit integer depth and 8 bits integer stencil.
2136 Depth24PlusStencil8,
2137 /// Special depth format with 32 bit floating point depth.
2138 Depth32Float,
2139 /// Special depth/stencil format with 32 bit floating point depth and 8 bits integer stencil.
2140 ///
2141 /// [`Features::DEPTH32FLOAT_STENCIL8`] must be enabled to use this texture format.
2142 Depth32FloatStencil8,
2143
2144 /// YUV 4:2:0 chroma subsampled format.
2145 ///
2146 /// Contains two planes:
2147 /// - 0: Single 8 bit channel luminance.
2148 /// - 1: Dual 8 bit channel chrominance at half width and half height.
2149 ///
2150 /// Valid view formats for luminance are [`TextureFormat::R8Unorm`].
2151 ///
2152 /// Valid view formats for chrominance are [`TextureFormat::Rg8Unorm`].
2153 ///
2154 /// Width and height must be even.
2155 ///
2156 /// [`Features::TEXTURE_FORMAT_NV12`] must be enabled to use this texture format.
2157 NV12,
2158
2159 // Compressed textures usable with `TEXTURE_COMPRESSION_BC` feature. `TEXTURE_COMPRESSION_SLICED_3D` is required to use with 3D textures.
2160 /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). 4 color + alpha pallet. 5 bit R + 6 bit G + 5 bit B + 1 bit alpha.
2161 /// [0, 63] ([0, 1] for alpha) converted to/from float [0, 1] in shader.
2162 ///
2163 /// Also known as DXT1.
2164 ///
2165 /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2166 /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2167 Bc1RgbaUnorm,
2168 /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). 4 color + alpha pallet. 5 bit R + 6 bit G + 5 bit B + 1 bit alpha.
2169 /// Srgb-color [0, 63] ([0, 1] for alpha) converted to/from linear-color float [0, 1] in shader.
2170 ///
2171 /// Also known as DXT1.
2172 ///
2173 /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2174 /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2175 Bc1RgbaUnormSrgb,
2176 /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). 4 color pallet. 5 bit R + 6 bit G + 5 bit B + 4 bit alpha.
2177 /// [0, 63] ([0, 15] for alpha) converted to/from float [0, 1] in shader.
2178 ///
2179 /// Also known as DXT3.
2180 ///
2181 /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2182 /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2183 Bc2RgbaUnorm,
2184 /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). 4 color pallet. 5 bit R + 6 bit G + 5 bit B + 4 bit alpha.
2185 /// Srgb-color [0, 63] ([0, 255] for alpha) converted to/from linear-color float [0, 1] in shader.
2186 ///
2187 /// Also known as DXT3.
2188 ///
2189 /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2190 /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2191 Bc2RgbaUnormSrgb,
2192 /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). 4 color pallet + 8 alpha pallet. 5 bit R + 6 bit G + 5 bit B + 8 bit alpha.
2193 /// [0, 63] ([0, 255] for alpha) converted to/from float [0, 1] in shader.
2194 ///
2195 /// Also known as DXT5.
2196 ///
2197 /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2198 /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2199 Bc3RgbaUnorm,
2200 /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). 4 color pallet + 8 alpha pallet. 5 bit R + 6 bit G + 5 bit B + 8 bit alpha.
2201 /// Srgb-color [0, 63] ([0, 255] for alpha) converted to/from linear-color float [0, 1] in shader.
2202 ///
2203 /// Also known as DXT5.
2204 ///
2205 /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2206 /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2207 Bc3RgbaUnormSrgb,
2208 /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). 8 color pallet. 8 bit R.
2209 /// [0, 255] converted to/from float [0, 1] in shader.
2210 ///
2211 /// Also known as RGTC1.
2212 ///
2213 /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2214 /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2215 Bc4RUnorm,
2216 /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). 8 color pallet. 8 bit R.
2217 /// [−127, 127] converted to/from float [−1, 1] in shader.
2218 ///
2219 /// Also known as RGTC1.
2220 ///
2221 /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2222 /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2223 Bc4RSnorm,
2224 /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). 8 color red pallet + 8 color green pallet. 8 bit RG.
2225 /// [0, 255] converted to/from float [0, 1] in shader.
2226 ///
2227 /// Also known as RGTC2.
2228 ///
2229 /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2230 /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2231 Bc5RgUnorm,
2232 /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). 8 color red pallet + 8 color green pallet. 8 bit RG.
2233 /// [−127, 127] converted to/from float [−1, 1] in shader.
2234 ///
2235 /// Also known as RGTC2.
2236 ///
2237 /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2238 /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2239 Bc5RgSnorm,
2240 /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). Variable sized pallet. 16 bit unsigned float RGB. Float in shader.
2241 ///
2242 /// Also known as BPTC (float).
2243 ///
2244 /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2245 /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2246 Bc6hRgbUfloat,
2247 /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). Variable sized pallet. 16 bit signed float RGB. Float in shader.
2248 ///
2249 /// Also known as BPTC (float).
2250 ///
2251 /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2252 /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2253 Bc6hRgbFloat,
2254 /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). Variable sized pallet. 8 bit integer RGBA.
2255 /// [0, 255] converted to/from float [0, 1] in shader.
2256 ///
2257 /// Also known as BPTC (unorm).
2258 ///
2259 /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2260 /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2261 Bc7RgbaUnorm,
2262 /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). Variable sized pallet. 8 bit integer RGBA.
2263 /// Srgb-color [0, 255] converted to/from linear-color float [0, 1] in shader.
2264 ///
2265 /// Also known as BPTC (unorm).
2266 ///
2267 /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2268 /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2269 Bc7RgbaUnormSrgb,
2270 /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). Complex pallet. 8 bit integer RGB.
2271 /// [0, 255] converted to/from float [0, 1] in shader.
2272 ///
2273 /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
2274 Etc2Rgb8Unorm,
2275 /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). Complex pallet. 8 bit integer RGB.
2276 /// Srgb-color [0, 255] converted to/from linear-color float [0, 1] in shader.
2277 ///
2278 /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
2279 Etc2Rgb8UnormSrgb,
2280 /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). Complex pallet. 8 bit integer RGB + 1 bit alpha.
2281 /// [0, 255] ([0, 1] for alpha) converted to/from float [0, 1] in shader.
2282 ///
2283 /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
2284 Etc2Rgb8A1Unorm,
2285 /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). Complex pallet. 8 bit integer RGB + 1 bit alpha.
2286 /// Srgb-color [0, 255] ([0, 1] for alpha) converted to/from linear-color float [0, 1] in shader.
2287 ///
2288 /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
2289 Etc2Rgb8A1UnormSrgb,
2290 /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). Complex pallet. 8 bit integer RGB + 8 bit alpha.
2291 /// [0, 255] converted to/from float [0, 1] in shader.
2292 ///
2293 /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
2294 Etc2Rgba8Unorm,
2295 /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). Complex pallet. 8 bit integer RGB + 8 bit alpha.
2296 /// Srgb-color [0, 255] converted to/from linear-color float [0, 1] in shader.
2297 ///
2298 /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
2299 Etc2Rgba8UnormSrgb,
2300 /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). Complex pallet. 11 bit integer R.
2301 /// [0, 255] converted to/from float [0, 1] in shader.
2302 ///
2303 /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
2304 EacR11Unorm,
2305 /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). Complex pallet. 11 bit integer R.
2306 /// [−127, 127] converted to/from float [−1, 1] in shader.
2307 ///
2308 /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
2309 EacR11Snorm,
2310 /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). Complex pallet. 11 bit integer R + 11 bit integer G.
2311 /// [0, 255] converted to/from float [0, 1] in shader.
2312 ///
2313 /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
2314 EacRg11Unorm,
2315 /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). Complex pallet. 11 bit integer R + 11 bit integer G.
2316 /// [−127, 127] converted to/from float [−1, 1] in shader.
2317 ///
2318 /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
2319 EacRg11Snorm,
2320 /// block compressed texture. 16 bytes per block.
2321 ///
2322 /// Features [`TEXTURE_COMPRESSION_ASTC`] or [`TEXTURE_COMPRESSION_ASTC_HDR`]
2323 /// must be enabled to use this texture format.
2324 ///
2325 /// [`TEXTURE_COMPRESSION_ASTC`]: Features::TEXTURE_COMPRESSION_ASTC
2326 /// [`TEXTURE_COMPRESSION_ASTC_HDR`]: Features::TEXTURE_COMPRESSION_ASTC_HDR
2327 Astc {
2328 /// compressed block dimensions
2329 block: AstcBlock,
2330 /// ASTC RGBA channel
2331 channel: AstcChannel,
2332 },
2333}
2334
2335#[cfg(any(feature = "serde", test))]
2336impl<'de> Deserialize<'de> for TextureFormat {
2337 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2338 where
2339 D: serde::Deserializer<'de>,
2340 {
2341 use serde::de::{self, Error, Unexpected};
2342
2343 struct TextureFormatVisitor;
2344
2345 impl de::Visitor<'_> for TextureFormatVisitor {
2346 type Value = TextureFormat;
2347
2348 fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
2349 formatter.write_str("a valid texture format")
2350 }
2351
2352 fn visit_str<E: Error>(self, s: &str) -> Result<Self::Value, E> {
2353 let format = match s {
2354 "r8unorm" => TextureFormat::R8Unorm,
2355 "r8snorm" => TextureFormat::R8Snorm,
2356 "r8uint" => TextureFormat::R8Uint,
2357 "r8sint" => TextureFormat::R8Sint,
2358 "r16uint" => TextureFormat::R16Uint,
2359 "r16sint" => TextureFormat::R16Sint,
2360 "r16unorm" => TextureFormat::R16Unorm,
2361 "r16snorm" => TextureFormat::R16Snorm,
2362 "r16float" => TextureFormat::R16Float,
2363 "rg8unorm" => TextureFormat::Rg8Unorm,
2364 "rg8snorm" => TextureFormat::Rg8Snorm,
2365 "rg8uint" => TextureFormat::Rg8Uint,
2366 "rg8sint" => TextureFormat::Rg8Sint,
2367 "r32uint" => TextureFormat::R32Uint,
2368 "r32sint" => TextureFormat::R32Sint,
2369 "r32float" => TextureFormat::R32Float,
2370 "rg16uint" => TextureFormat::Rg16Uint,
2371 "rg16sint" => TextureFormat::Rg16Sint,
2372 "rg16unorm" => TextureFormat::Rg16Unorm,
2373 "rg16snorm" => TextureFormat::Rg16Snorm,
2374 "rg16float" => TextureFormat::Rg16Float,
2375 "rgba8unorm" => TextureFormat::Rgba8Unorm,
2376 "rgba8unorm-srgb" => TextureFormat::Rgba8UnormSrgb,
2377 "rgba8snorm" => TextureFormat::Rgba8Snorm,
2378 "rgba8uint" => TextureFormat::Rgba8Uint,
2379 "rgba8sint" => TextureFormat::Rgba8Sint,
2380 "bgra8unorm" => TextureFormat::Bgra8Unorm,
2381 "bgra8unorm-srgb" => TextureFormat::Bgra8UnormSrgb,
2382 "rgb10a2uint" => TextureFormat::Rgb10a2Uint,
2383 "rgb10a2unorm" => TextureFormat::Rgb10a2Unorm,
2384 "rg11b10ufloat" => TextureFormat::Rg11b10Ufloat,
2385 "r64uint" => TextureFormat::R64Uint,
2386 "rg32uint" => TextureFormat::Rg32Uint,
2387 "rg32sint" => TextureFormat::Rg32Sint,
2388 "rg32float" => TextureFormat::Rg32Float,
2389 "rgba16uint" => TextureFormat::Rgba16Uint,
2390 "rgba16sint" => TextureFormat::Rgba16Sint,
2391 "rgba16unorm" => TextureFormat::Rgba16Unorm,
2392 "rgba16snorm" => TextureFormat::Rgba16Snorm,
2393 "rgba16float" => TextureFormat::Rgba16Float,
2394 "rgba32uint" => TextureFormat::Rgba32Uint,
2395 "rgba32sint" => TextureFormat::Rgba32Sint,
2396 "rgba32float" => TextureFormat::Rgba32Float,
2397 "stencil8" => TextureFormat::Stencil8,
2398 "depth32float" => TextureFormat::Depth32Float,
2399 "depth32float-stencil8" => TextureFormat::Depth32FloatStencil8,
2400 "depth16unorm" => TextureFormat::Depth16Unorm,
2401 "depth24plus" => TextureFormat::Depth24Plus,
2402 "depth24plus-stencil8" => TextureFormat::Depth24PlusStencil8,
2403 "nv12" => TextureFormat::NV12,
2404 "rgb9e5ufloat" => TextureFormat::Rgb9e5Ufloat,
2405 "bc1-rgba-unorm" => TextureFormat::Bc1RgbaUnorm,
2406 "bc1-rgba-unorm-srgb" => TextureFormat::Bc1RgbaUnormSrgb,
2407 "bc2-rgba-unorm" => TextureFormat::Bc2RgbaUnorm,
2408 "bc2-rgba-unorm-srgb" => TextureFormat::Bc2RgbaUnormSrgb,
2409 "bc3-rgba-unorm" => TextureFormat::Bc3RgbaUnorm,
2410 "bc3-rgba-unorm-srgb" => TextureFormat::Bc3RgbaUnormSrgb,
2411 "bc4-r-unorm" => TextureFormat::Bc4RUnorm,
2412 "bc4-r-snorm" => TextureFormat::Bc4RSnorm,
2413 "bc5-rg-unorm" => TextureFormat::Bc5RgUnorm,
2414 "bc5-rg-snorm" => TextureFormat::Bc5RgSnorm,
2415 "bc6h-rgb-ufloat" => TextureFormat::Bc6hRgbUfloat,
2416 "bc6h-rgb-float" => TextureFormat::Bc6hRgbFloat,
2417 "bc7-rgba-unorm" => TextureFormat::Bc7RgbaUnorm,
2418 "bc7-rgba-unorm-srgb" => TextureFormat::Bc7RgbaUnormSrgb,
2419 "etc2-rgb8unorm" => TextureFormat::Etc2Rgb8Unorm,
2420 "etc2-rgb8unorm-srgb" => TextureFormat::Etc2Rgb8UnormSrgb,
2421 "etc2-rgb8a1unorm" => TextureFormat::Etc2Rgb8A1Unorm,
2422 "etc2-rgb8a1unorm-srgb" => TextureFormat::Etc2Rgb8A1UnormSrgb,
2423 "etc2-rgba8unorm" => TextureFormat::Etc2Rgba8Unorm,
2424 "etc2-rgba8unorm-srgb" => TextureFormat::Etc2Rgba8UnormSrgb,
2425 "eac-r11unorm" => TextureFormat::EacR11Unorm,
2426 "eac-r11snorm" => TextureFormat::EacR11Snorm,
2427 "eac-rg11unorm" => TextureFormat::EacRg11Unorm,
2428 "eac-rg11snorm" => TextureFormat::EacRg11Snorm,
2429 other => {
2430 if let Some(parts) = other.strip_prefix("astc-") {
2431 let (block, channel) = parts
2432 .split_once('-')
2433 .ok_or_else(|| E::invalid_value(Unexpected::Str(s), &self))?;
2434
2435 let block = match block {
2436 "4x4" => AstcBlock::B4x4,
2437 "5x4" => AstcBlock::B5x4,
2438 "5x5" => AstcBlock::B5x5,
2439 "6x5" => AstcBlock::B6x5,
2440 "6x6" => AstcBlock::B6x6,
2441 "8x5" => AstcBlock::B8x5,
2442 "8x6" => AstcBlock::B8x6,
2443 "8x8" => AstcBlock::B8x8,
2444 "10x5" => AstcBlock::B10x5,
2445 "10x6" => AstcBlock::B10x6,
2446 "10x8" => AstcBlock::B10x8,
2447 "10x10" => AstcBlock::B10x10,
2448 "12x10" => AstcBlock::B12x10,
2449 "12x12" => AstcBlock::B12x12,
2450 _ => return Err(E::invalid_value(Unexpected::Str(s), &self)),
2451 };
2452
2453 let channel = match channel {
2454 "unorm" => AstcChannel::Unorm,
2455 "unorm-srgb" => AstcChannel::UnormSrgb,
2456 "hdr" => AstcChannel::Hdr,
2457 _ => return Err(E::invalid_value(Unexpected::Str(s), &self)),
2458 };
2459
2460 TextureFormat::Astc { block, channel }
2461 } else {
2462 return Err(E::invalid_value(Unexpected::Str(s), &self));
2463 }
2464 }
2465 };
2466
2467 Ok(format)
2468 }
2469 }
2470
2471 deserializer.deserialize_str(TextureFormatVisitor)
2472 }
2473}
2474
2475#[cfg(any(feature = "serde", test))]
2476impl Serialize for TextureFormat {
2477 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
2478 where
2479 S: serde::Serializer,
2480 {
2481 let s: String;
2482 let name = match *self {
2483 TextureFormat::R8Unorm => "r8unorm",
2484 TextureFormat::R8Snorm => "r8snorm",
2485 TextureFormat::R8Uint => "r8uint",
2486 TextureFormat::R8Sint => "r8sint",
2487 TextureFormat::R16Uint => "r16uint",
2488 TextureFormat::R16Sint => "r16sint",
2489 TextureFormat::R16Unorm => "r16unorm",
2490 TextureFormat::R16Snorm => "r16snorm",
2491 TextureFormat::R16Float => "r16float",
2492 TextureFormat::Rg8Unorm => "rg8unorm",
2493 TextureFormat::Rg8Snorm => "rg8snorm",
2494 TextureFormat::Rg8Uint => "rg8uint",
2495 TextureFormat::Rg8Sint => "rg8sint",
2496 TextureFormat::R32Uint => "r32uint",
2497 TextureFormat::R32Sint => "r32sint",
2498 TextureFormat::R32Float => "r32float",
2499 TextureFormat::Rg16Uint => "rg16uint",
2500 TextureFormat::Rg16Sint => "rg16sint",
2501 TextureFormat::Rg16Unorm => "rg16unorm",
2502 TextureFormat::Rg16Snorm => "rg16snorm",
2503 TextureFormat::Rg16Float => "rg16float",
2504 TextureFormat::Rgba8Unorm => "rgba8unorm",
2505 TextureFormat::Rgba8UnormSrgb => "rgba8unorm-srgb",
2506 TextureFormat::Rgba8Snorm => "rgba8snorm",
2507 TextureFormat::Rgba8Uint => "rgba8uint",
2508 TextureFormat::Rgba8Sint => "rgba8sint",
2509 TextureFormat::Bgra8Unorm => "bgra8unorm",
2510 TextureFormat::Bgra8UnormSrgb => "bgra8unorm-srgb",
2511 TextureFormat::Rgb10a2Uint => "rgb10a2uint",
2512 TextureFormat::Rgb10a2Unorm => "rgb10a2unorm",
2513 TextureFormat::Rg11b10Ufloat => "rg11b10ufloat",
2514 TextureFormat::R64Uint => "r64uint",
2515 TextureFormat::Rg32Uint => "rg32uint",
2516 TextureFormat::Rg32Sint => "rg32sint",
2517 TextureFormat::Rg32Float => "rg32float",
2518 TextureFormat::Rgba16Uint => "rgba16uint",
2519 TextureFormat::Rgba16Sint => "rgba16sint",
2520 TextureFormat::Rgba16Unorm => "rgba16unorm",
2521 TextureFormat::Rgba16Snorm => "rgba16snorm",
2522 TextureFormat::Rgba16Float => "rgba16float",
2523 TextureFormat::Rgba32Uint => "rgba32uint",
2524 TextureFormat::Rgba32Sint => "rgba32sint",
2525 TextureFormat::Rgba32Float => "rgba32float",
2526 TextureFormat::Stencil8 => "stencil8",
2527 TextureFormat::Depth32Float => "depth32float",
2528 TextureFormat::Depth16Unorm => "depth16unorm",
2529 TextureFormat::Depth32FloatStencil8 => "depth32float-stencil8",
2530 TextureFormat::Depth24Plus => "depth24plus",
2531 TextureFormat::Depth24PlusStencil8 => "depth24plus-stencil8",
2532 TextureFormat::NV12 => "nv12",
2533 TextureFormat::Rgb9e5Ufloat => "rgb9e5ufloat",
2534 TextureFormat::Bc1RgbaUnorm => "bc1-rgba-unorm",
2535 TextureFormat::Bc1RgbaUnormSrgb => "bc1-rgba-unorm-srgb",
2536 TextureFormat::Bc2RgbaUnorm => "bc2-rgba-unorm",
2537 TextureFormat::Bc2RgbaUnormSrgb => "bc2-rgba-unorm-srgb",
2538 TextureFormat::Bc3RgbaUnorm => "bc3-rgba-unorm",
2539 TextureFormat::Bc3RgbaUnormSrgb => "bc3-rgba-unorm-srgb",
2540 TextureFormat::Bc4RUnorm => "bc4-r-unorm",
2541 TextureFormat::Bc4RSnorm => "bc4-r-snorm",
2542 TextureFormat::Bc5RgUnorm => "bc5-rg-unorm",
2543 TextureFormat::Bc5RgSnorm => "bc5-rg-snorm",
2544 TextureFormat::Bc6hRgbUfloat => "bc6h-rgb-ufloat",
2545 TextureFormat::Bc6hRgbFloat => "bc6h-rgb-float",
2546 TextureFormat::Bc7RgbaUnorm => "bc7-rgba-unorm",
2547 TextureFormat::Bc7RgbaUnormSrgb => "bc7-rgba-unorm-srgb",
2548 TextureFormat::Etc2Rgb8Unorm => "etc2-rgb8unorm",
2549 TextureFormat::Etc2Rgb8UnormSrgb => "etc2-rgb8unorm-srgb",
2550 TextureFormat::Etc2Rgb8A1Unorm => "etc2-rgb8a1unorm",
2551 TextureFormat::Etc2Rgb8A1UnormSrgb => "etc2-rgb8a1unorm-srgb",
2552 TextureFormat::Etc2Rgba8Unorm => "etc2-rgba8unorm",
2553 TextureFormat::Etc2Rgba8UnormSrgb => "etc2-rgba8unorm-srgb",
2554 TextureFormat::EacR11Unorm => "eac-r11unorm",
2555 TextureFormat::EacR11Snorm => "eac-r11snorm",
2556 TextureFormat::EacRg11Unorm => "eac-rg11unorm",
2557 TextureFormat::EacRg11Snorm => "eac-rg11snorm",
2558 TextureFormat::Astc { block, channel } => {
2559 let block = match block {
2560 AstcBlock::B4x4 => "4x4",
2561 AstcBlock::B5x4 => "5x4",
2562 AstcBlock::B5x5 => "5x5",
2563 AstcBlock::B6x5 => "6x5",
2564 AstcBlock::B6x6 => "6x6",
2565 AstcBlock::B8x5 => "8x5",
2566 AstcBlock::B8x6 => "8x6",
2567 AstcBlock::B8x8 => "8x8",
2568 AstcBlock::B10x5 => "10x5",
2569 AstcBlock::B10x6 => "10x6",
2570 AstcBlock::B10x8 => "10x8",
2571 AstcBlock::B10x10 => "10x10",
2572 AstcBlock::B12x10 => "12x10",
2573 AstcBlock::B12x12 => "12x12",
2574 };
2575
2576 let channel = match channel {
2577 AstcChannel::Unorm => "unorm",
2578 AstcChannel::UnormSrgb => "unorm-srgb",
2579 AstcChannel::Hdr => "hdr",
2580 };
2581
2582 s = format!("astc-{block}-{channel}");
2583 &s
2584 }
2585 };
2586 serializer.serialize_str(name)
2587 }
2588}
2589
2590impl TextureAspect {
2591 /// Returns the texture aspect for a given plane.
2592 #[must_use]
2593 pub fn from_plane(plane: u32) -> Option<Self> {
2594 Some(match plane {
2595 0 => Self::Plane0,
2596 1 => Self::Plane1,
2597 2 => Self::Plane2,
2598 _ => return None,
2599 })
2600 }
2601}
2602
2603impl TextureFormat {
2604 /// Returns the aspect-specific format of the original format
2605 ///
2606 /// see <https://gpuweb.github.io/gpuweb/#abstract-opdef-resolving-gputextureaspect>
2607 #[must_use]
2608 pub fn aspect_specific_format(&self, aspect: TextureAspect) -> Option<Self> {
2609 match (*self, aspect) {
2610 (Self::Stencil8, TextureAspect::StencilOnly) => Some(*self),
2611 (
2612 Self::Depth16Unorm | Self::Depth24Plus | Self::Depth32Float,
2613 TextureAspect::DepthOnly,
2614 ) => Some(*self),
2615 (
2616 Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8,
2617 TextureAspect::StencilOnly,
2618 ) => Some(Self::Stencil8),
2619 (Self::Depth24PlusStencil8, TextureAspect::DepthOnly) => Some(Self::Depth24Plus),
2620 (Self::Depth32FloatStencil8, TextureAspect::DepthOnly) => Some(Self::Depth32Float),
2621 (Self::NV12, TextureAspect::Plane0) => Some(Self::R8Unorm),
2622 (Self::NV12, TextureAspect::Plane1) => Some(Self::Rg8Unorm),
2623 // views to multi-planar formats must specify the plane
2624 (format, TextureAspect::All) if !format.is_multi_planar_format() => Some(format),
2625 _ => None,
2626 }
2627 }
2628
2629 /// Returns `true` if `self` is a depth or stencil component of the given
2630 /// combined depth-stencil format
2631 #[must_use]
2632 pub fn is_depth_stencil_component(&self, combined_format: Self) -> bool {
2633 match (combined_format, *self) {
2634 (Self::Depth24PlusStencil8, Self::Depth24Plus | Self::Stencil8)
2635 | (Self::Depth32FloatStencil8, Self::Depth32Float | Self::Stencil8) => true,
2636 _ => false,
2637 }
2638 }
2639
2640 /// Returns `true` if the format is a depth and/or stencil format
2641 ///
2642 /// see <https://gpuweb.github.io/gpuweb/#depth-formats>
2643 #[must_use]
2644 pub fn is_depth_stencil_format(&self) -> bool {
2645 match *self {
2646 Self::Stencil8
2647 | Self::Depth16Unorm
2648 | Self::Depth24Plus
2649 | Self::Depth24PlusStencil8
2650 | Self::Depth32Float
2651 | Self::Depth32FloatStencil8 => true,
2652 _ => false,
2653 }
2654 }
2655
2656 /// Returns `true` if the format is a combined depth-stencil format
2657 ///
2658 /// see <https://gpuweb.github.io/gpuweb/#combined-depth-stencil-format>
2659 #[must_use]
2660 pub fn is_combined_depth_stencil_format(&self) -> bool {
2661 match *self {
2662 Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8 => true,
2663 _ => false,
2664 }
2665 }
2666
2667 /// Returns `true` if the format is a multi-planar format
2668 #[must_use]
2669 pub fn is_multi_planar_format(&self) -> bool {
2670 self.planes().is_some()
2671 }
2672
2673 /// Returns the number of planes a multi-planar format has.
2674 #[must_use]
2675 pub fn planes(&self) -> Option<u32> {
2676 match *self {
2677 Self::NV12 => Some(2),
2678 _ => None,
2679 }
2680 }
2681
2682 /// Returns `true` if the format has a color aspect
2683 #[must_use]
2684 pub fn has_color_aspect(&self) -> bool {
2685 !self.is_depth_stencil_format()
2686 }
2687
2688 /// Returns `true` if the format has a depth aspect
2689 #[must_use]
2690 pub fn has_depth_aspect(&self) -> bool {
2691 match *self {
2692 Self::Depth16Unorm
2693 | Self::Depth24Plus
2694 | Self::Depth24PlusStencil8
2695 | Self::Depth32Float
2696 | Self::Depth32FloatStencil8 => true,
2697 _ => false,
2698 }
2699 }
2700
2701 /// Returns `true` if the format has a stencil aspect
2702 #[must_use]
2703 pub fn has_stencil_aspect(&self) -> bool {
2704 match *self {
2705 Self::Stencil8 | Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8 => true,
2706 _ => false,
2707 }
2708 }
2709
2710 /// Returns the size multiple requirement for a texture using this format.
2711 #[must_use]
2712 pub fn size_multiple_requirement(&self) -> (u32, u32) {
2713 match *self {
2714 Self::NV12 => (2, 2),
2715 _ => self.block_dimensions(),
2716 }
2717 }
2718
2719 /// Returns the dimension of a [block](https://gpuweb.github.io/gpuweb/#texel-block) of texels.
2720 ///
2721 /// Uncompressed formats have a block dimension of `(1, 1)`.
2722 #[must_use]
2723 pub fn block_dimensions(&self) -> (u32, u32) {
2724 match *self {
2725 Self::R8Unorm
2726 | Self::R8Snorm
2727 | Self::R8Uint
2728 | Self::R8Sint
2729 | Self::R16Uint
2730 | Self::R16Sint
2731 | Self::R16Unorm
2732 | Self::R16Snorm
2733 | Self::R16Float
2734 | Self::Rg8Unorm
2735 | Self::Rg8Snorm
2736 | Self::Rg8Uint
2737 | Self::Rg8Sint
2738 | Self::R32Uint
2739 | Self::R32Sint
2740 | Self::R32Float
2741 | Self::Rg16Uint
2742 | Self::Rg16Sint
2743 | Self::Rg16Unorm
2744 | Self::Rg16Snorm
2745 | Self::Rg16Float
2746 | Self::Rgba8Unorm
2747 | Self::Rgba8UnormSrgb
2748 | Self::Rgba8Snorm
2749 | Self::Rgba8Uint
2750 | Self::Rgba8Sint
2751 | Self::Bgra8Unorm
2752 | Self::Bgra8UnormSrgb
2753 | Self::Rgb9e5Ufloat
2754 | Self::Rgb10a2Uint
2755 | Self::Rgb10a2Unorm
2756 | Self::Rg11b10Ufloat
2757 | Self::R64Uint
2758 | Self::Rg32Uint
2759 | Self::Rg32Sint
2760 | Self::Rg32Float
2761 | Self::Rgba16Uint
2762 | Self::Rgba16Sint
2763 | Self::Rgba16Unorm
2764 | Self::Rgba16Snorm
2765 | Self::Rgba16Float
2766 | Self::Rgba32Uint
2767 | Self::Rgba32Sint
2768 | Self::Rgba32Float
2769 | Self::Stencil8
2770 | Self::Depth16Unorm
2771 | Self::Depth24Plus
2772 | Self::Depth24PlusStencil8
2773 | Self::Depth32Float
2774 | Self::Depth32FloatStencil8
2775 | Self::NV12 => (1, 1),
2776
2777 Self::Bc1RgbaUnorm
2778 | Self::Bc1RgbaUnormSrgb
2779 | Self::Bc2RgbaUnorm
2780 | Self::Bc2RgbaUnormSrgb
2781 | Self::Bc3RgbaUnorm
2782 | Self::Bc3RgbaUnormSrgb
2783 | Self::Bc4RUnorm
2784 | Self::Bc4RSnorm
2785 | Self::Bc5RgUnorm
2786 | Self::Bc5RgSnorm
2787 | Self::Bc6hRgbUfloat
2788 | Self::Bc6hRgbFloat
2789 | Self::Bc7RgbaUnorm
2790 | Self::Bc7RgbaUnormSrgb => (4, 4),
2791
2792 Self::Etc2Rgb8Unorm
2793 | Self::Etc2Rgb8UnormSrgb
2794 | Self::Etc2Rgb8A1Unorm
2795 | Self::Etc2Rgb8A1UnormSrgb
2796 | Self::Etc2Rgba8Unorm
2797 | Self::Etc2Rgba8UnormSrgb
2798 | Self::EacR11Unorm
2799 | Self::EacR11Snorm
2800 | Self::EacRg11Unorm
2801 | Self::EacRg11Snorm => (4, 4),
2802
2803 Self::Astc { block, .. } => match block {
2804 AstcBlock::B4x4 => (4, 4),
2805 AstcBlock::B5x4 => (5, 4),
2806 AstcBlock::B5x5 => (5, 5),
2807 AstcBlock::B6x5 => (6, 5),
2808 AstcBlock::B6x6 => (6, 6),
2809 AstcBlock::B8x5 => (8, 5),
2810 AstcBlock::B8x6 => (8, 6),
2811 AstcBlock::B8x8 => (8, 8),
2812 AstcBlock::B10x5 => (10, 5),
2813 AstcBlock::B10x6 => (10, 6),
2814 AstcBlock::B10x8 => (10, 8),
2815 AstcBlock::B10x10 => (10, 10),
2816 AstcBlock::B12x10 => (12, 10),
2817 AstcBlock::B12x12 => (12, 12),
2818 },
2819 }
2820 }
2821
2822 /// Returns `true` for compressed formats.
2823 #[must_use]
2824 pub fn is_compressed(&self) -> bool {
2825 self.block_dimensions() != (1, 1)
2826 }
2827
2828 /// Returns `true` for BCn compressed formats.
2829 #[must_use]
2830 pub fn is_bcn(&self) -> bool {
2831 self.required_features() == Features::TEXTURE_COMPRESSION_BC
2832 }
2833
2834 /// Returns `true` for ASTC compressed formats.
2835 #[must_use]
2836 pub fn is_astc(&self) -> bool {
2837 self.required_features() == Features::TEXTURE_COMPRESSION_ASTC
2838 || self.required_features() == Features::TEXTURE_COMPRESSION_ASTC_HDR
2839 }
2840
2841 /// Returns the required features (if any) in order to use the texture.
2842 #[must_use]
2843 pub fn required_features(&self) -> Features {
2844 match *self {
2845 Self::R8Unorm
2846 | Self::R8Snorm
2847 | Self::R8Uint
2848 | Self::R8Sint
2849 | Self::R16Uint
2850 | Self::R16Sint
2851 | Self::R16Float
2852 | Self::Rg8Unorm
2853 | Self::Rg8Snorm
2854 | Self::Rg8Uint
2855 | Self::Rg8Sint
2856 | Self::R32Uint
2857 | Self::R32Sint
2858 | Self::R32Float
2859 | Self::Rg16Uint
2860 | Self::Rg16Sint
2861 | Self::Rg16Float
2862 | Self::Rgba8Unorm
2863 | Self::Rgba8UnormSrgb
2864 | Self::Rgba8Snorm
2865 | Self::Rgba8Uint
2866 | Self::Rgba8Sint
2867 | Self::Bgra8Unorm
2868 | Self::Bgra8UnormSrgb
2869 | Self::Rgb9e5Ufloat
2870 | Self::Rgb10a2Uint
2871 | Self::Rgb10a2Unorm
2872 | Self::Rg11b10Ufloat
2873 | Self::Rg32Uint
2874 | Self::Rg32Sint
2875 | Self::Rg32Float
2876 | Self::Rgba16Uint
2877 | Self::Rgba16Sint
2878 | Self::Rgba16Float
2879 | Self::Rgba32Uint
2880 | Self::Rgba32Sint
2881 | Self::Rgba32Float
2882 | Self::Stencil8
2883 | Self::Depth16Unorm
2884 | Self::Depth24Plus
2885 | Self::Depth24PlusStencil8
2886 | Self::Depth32Float => Features::empty(),
2887
2888 Self::R64Uint => Features::TEXTURE_INT64_ATOMIC,
2889
2890 Self::Depth32FloatStencil8 => Features::DEPTH32FLOAT_STENCIL8,
2891
2892 Self::NV12 => Features::TEXTURE_FORMAT_NV12,
2893
2894 Self::R16Unorm
2895 | Self::R16Snorm
2896 | Self::Rg16Unorm
2897 | Self::Rg16Snorm
2898 | Self::Rgba16Unorm
2899 | Self::Rgba16Snorm => Features::TEXTURE_FORMAT_16BIT_NORM,
2900
2901 Self::Bc1RgbaUnorm
2902 | Self::Bc1RgbaUnormSrgb
2903 | Self::Bc2RgbaUnorm
2904 | Self::Bc2RgbaUnormSrgb
2905 | Self::Bc3RgbaUnorm
2906 | Self::Bc3RgbaUnormSrgb
2907 | Self::Bc4RUnorm
2908 | Self::Bc4RSnorm
2909 | Self::Bc5RgUnorm
2910 | Self::Bc5RgSnorm
2911 | Self::Bc6hRgbUfloat
2912 | Self::Bc6hRgbFloat
2913 | Self::Bc7RgbaUnorm
2914 | Self::Bc7RgbaUnormSrgb => Features::TEXTURE_COMPRESSION_BC,
2915
2916 Self::Etc2Rgb8Unorm
2917 | Self::Etc2Rgb8UnormSrgb
2918 | Self::Etc2Rgb8A1Unorm
2919 | Self::Etc2Rgb8A1UnormSrgb
2920 | Self::Etc2Rgba8Unorm
2921 | Self::Etc2Rgba8UnormSrgb
2922 | Self::EacR11Unorm
2923 | Self::EacR11Snorm
2924 | Self::EacRg11Unorm
2925 | Self::EacRg11Snorm => Features::TEXTURE_COMPRESSION_ETC2,
2926
2927 Self::Astc { channel, .. } => match channel {
2928 AstcChannel::Hdr => Features::TEXTURE_COMPRESSION_ASTC_HDR,
2929 AstcChannel::Unorm | AstcChannel::UnormSrgb => Features::TEXTURE_COMPRESSION_ASTC,
2930 },
2931 }
2932 }
2933
2934 /// Returns the format features guaranteed by the WebGPU spec.
2935 ///
2936 /// Additional features are available if `Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES` is enabled.
2937 #[must_use]
2938 pub fn guaranteed_format_features(&self, device_features: Features) -> TextureFormatFeatures {
2939 // Multisampling
2940 let none = TextureFormatFeatureFlags::empty();
2941 let msaa = TextureFormatFeatureFlags::MULTISAMPLE_X4;
2942 let msaa_resolve = msaa | TextureFormatFeatureFlags::MULTISAMPLE_RESOLVE;
2943
2944 let s_ro_wo = TextureFormatFeatureFlags::STORAGE_READ_ONLY
2945 | TextureFormatFeatureFlags::STORAGE_WRITE_ONLY;
2946 let s_all = s_ro_wo | TextureFormatFeatureFlags::STORAGE_READ_WRITE;
2947
2948 // Flags
2949 let basic =
2950 TextureUsages::COPY_SRC | TextureUsages::COPY_DST | TextureUsages::TEXTURE_BINDING;
2951 let attachment = basic | TextureUsages::RENDER_ATTACHMENT;
2952 let storage = basic | TextureUsages::STORAGE_BINDING;
2953 let binding = TextureUsages::TEXTURE_BINDING;
2954 let all_flags = attachment | storage | binding;
2955 let atomic_64 = if device_features.contains(Features::TEXTURE_ATOMIC) {
2956 storage | binding | TextureUsages::STORAGE_ATOMIC
2957 } else {
2958 storage | binding
2959 };
2960 let atomic = attachment | atomic_64;
2961 let (rg11b10f_f, rg11b10f_u) =
2962 if device_features.contains(Features::RG11B10UFLOAT_RENDERABLE) {
2963 (msaa_resolve, attachment)
2964 } else {
2965 (msaa, basic)
2966 };
2967 let (bgra8unorm_f, bgra8unorm) = if device_features.contains(Features::BGRA8UNORM_STORAGE) {
2968 (
2969 msaa_resolve | TextureFormatFeatureFlags::STORAGE_WRITE_ONLY,
2970 attachment | TextureUsages::STORAGE_BINDING,
2971 )
2972 } else {
2973 (msaa_resolve, attachment)
2974 };
2975
2976 #[rustfmt::skip] // lets make a nice table
2977 let (
2978 mut flags,
2979 allowed_usages,
2980 ) = match *self {
2981 Self::R8Unorm => (msaa_resolve, attachment),
2982 Self::R8Snorm => ( none, basic),
2983 Self::R8Uint => ( msaa, attachment),
2984 Self::R8Sint => ( msaa, attachment),
2985 Self::R16Uint => ( msaa, attachment),
2986 Self::R16Sint => ( msaa, attachment),
2987 Self::R16Float => (msaa_resolve, attachment),
2988 Self::Rg8Unorm => (msaa_resolve, attachment),
2989 Self::Rg8Snorm => ( none, basic),
2990 Self::Rg8Uint => ( msaa, attachment),
2991 Self::Rg8Sint => ( msaa, attachment),
2992 Self::R32Uint => ( s_all, atomic),
2993 Self::R32Sint => ( s_all, atomic),
2994 Self::R32Float => (msaa | s_all, all_flags),
2995 Self::Rg16Uint => ( msaa, attachment),
2996 Self::Rg16Sint => ( msaa, attachment),
2997 Self::Rg16Float => (msaa_resolve, attachment),
2998 Self::Rgba8Unorm => (msaa_resolve | s_ro_wo, all_flags),
2999 Self::Rgba8UnormSrgb => (msaa_resolve, attachment),
3000 Self::Rgba8Snorm => ( s_ro_wo, storage),
3001 Self::Rgba8Uint => ( msaa | s_ro_wo, all_flags),
3002 Self::Rgba8Sint => ( msaa | s_ro_wo, all_flags),
3003 Self::Bgra8Unorm => (bgra8unorm_f, bgra8unorm),
3004 Self::Bgra8UnormSrgb => (msaa_resolve, attachment),
3005 Self::Rgb10a2Uint => ( msaa, attachment),
3006 Self::Rgb10a2Unorm => (msaa_resolve, attachment),
3007 Self::Rg11b10Ufloat => ( rg11b10f_f, rg11b10f_u),
3008 Self::R64Uint => ( s_ro_wo, atomic_64),
3009 Self::Rg32Uint => ( s_ro_wo, all_flags),
3010 Self::Rg32Sint => ( s_ro_wo, all_flags),
3011 Self::Rg32Float => ( s_ro_wo, all_flags),
3012 Self::Rgba16Uint => ( msaa | s_ro_wo, all_flags),
3013 Self::Rgba16Sint => ( msaa | s_ro_wo, all_flags),
3014 Self::Rgba16Float => (msaa_resolve | s_ro_wo, all_flags),
3015 Self::Rgba32Uint => ( s_ro_wo, all_flags),
3016 Self::Rgba32Sint => ( s_ro_wo, all_flags),
3017 Self::Rgba32Float => ( s_ro_wo, all_flags),
3018
3019 Self::Stencil8 => ( msaa, attachment),
3020 Self::Depth16Unorm => ( msaa, attachment),
3021 Self::Depth24Plus => ( msaa, attachment),
3022 Self::Depth24PlusStencil8 => ( msaa, attachment),
3023 Self::Depth32Float => ( msaa, attachment),
3024 Self::Depth32FloatStencil8 => ( msaa, attachment),
3025
3026 // We only support sampling nv12 textures until we implement transfer plane data.
3027 Self::NV12 => ( none, binding),
3028
3029 Self::R16Unorm => ( msaa | s_ro_wo, storage),
3030 Self::R16Snorm => ( msaa | s_ro_wo, storage),
3031 Self::Rg16Unorm => ( msaa | s_ro_wo, storage),
3032 Self::Rg16Snorm => ( msaa | s_ro_wo, storage),
3033 Self::Rgba16Unorm => ( msaa | s_ro_wo, storage),
3034 Self::Rgba16Snorm => ( msaa | s_ro_wo, storage),
3035
3036 Self::Rgb9e5Ufloat => ( none, basic),
3037
3038 Self::Bc1RgbaUnorm => ( none, basic),
3039 Self::Bc1RgbaUnormSrgb => ( none, basic),
3040 Self::Bc2RgbaUnorm => ( none, basic),
3041 Self::Bc2RgbaUnormSrgb => ( none, basic),
3042 Self::Bc3RgbaUnorm => ( none, basic),
3043 Self::Bc3RgbaUnormSrgb => ( none, basic),
3044 Self::Bc4RUnorm => ( none, basic),
3045 Self::Bc4RSnorm => ( none, basic),
3046 Self::Bc5RgUnorm => ( none, basic),
3047 Self::Bc5RgSnorm => ( none, basic),
3048 Self::Bc6hRgbUfloat => ( none, basic),
3049 Self::Bc6hRgbFloat => ( none, basic),
3050 Self::Bc7RgbaUnorm => ( none, basic),
3051 Self::Bc7RgbaUnormSrgb => ( none, basic),
3052
3053 Self::Etc2Rgb8Unorm => ( none, basic),
3054 Self::Etc2Rgb8UnormSrgb => ( none, basic),
3055 Self::Etc2Rgb8A1Unorm => ( none, basic),
3056 Self::Etc2Rgb8A1UnormSrgb => ( none, basic),
3057 Self::Etc2Rgba8Unorm => ( none, basic),
3058 Self::Etc2Rgba8UnormSrgb => ( none, basic),
3059 Self::EacR11Unorm => ( none, basic),
3060 Self::EacR11Snorm => ( none, basic),
3061 Self::EacRg11Unorm => ( none, basic),
3062 Self::EacRg11Snorm => ( none, basic),
3063
3064 Self::Astc { .. } => ( none, basic),
3065 };
3066
3067 // Get whether the format is filterable, taking features into account
3068 let sample_type1 = self.sample_type(None, Some(device_features));
3069 let is_filterable = sample_type1 == Some(TextureSampleType::Float { filterable: true });
3070
3071 // Features that enable filtering don't affect blendability
3072 let sample_type2 = self.sample_type(None, None);
3073 let is_blendable = sample_type2 == Some(TextureSampleType::Float { filterable: true });
3074
3075 flags.set(TextureFormatFeatureFlags::FILTERABLE, is_filterable);
3076 flags.set(TextureFormatFeatureFlags::BLENDABLE, is_blendable);
3077 flags.set(
3078 TextureFormatFeatureFlags::STORAGE_ATOMIC,
3079 allowed_usages.contains(TextureUsages::STORAGE_ATOMIC),
3080 );
3081
3082 TextureFormatFeatures {
3083 allowed_usages,
3084 flags,
3085 }
3086 }
3087
3088 /// Returns the sample type compatible with this format and aspect.
3089 ///
3090 /// Returns `None` only if this is a combined depth-stencil format or a multi-planar format
3091 /// and `TextureAspect::All` or no `aspect` was provided.
3092 #[must_use]
3093 pub fn sample_type(
3094 &self,
3095 aspect: Option<TextureAspect>,
3096 device_features: Option<Features>,
3097 ) -> Option<TextureSampleType> {
3098 let float = TextureSampleType::Float { filterable: true };
3099 let unfilterable_float = TextureSampleType::Float { filterable: false };
3100 let float32_sample_type = TextureSampleType::Float {
3101 filterable: device_features
3102 .unwrap_or(Features::empty())
3103 .contains(Features::FLOAT32_FILTERABLE),
3104 };
3105 let depth = TextureSampleType::Depth;
3106 let uint = TextureSampleType::Uint;
3107 let sint = TextureSampleType::Sint;
3108
3109 match *self {
3110 Self::R8Unorm
3111 | Self::R8Snorm
3112 | Self::Rg8Unorm
3113 | Self::Rg8Snorm
3114 | Self::Rgba8Unorm
3115 | Self::Rgba8UnormSrgb
3116 | Self::Rgba8Snorm
3117 | Self::Bgra8Unorm
3118 | Self::Bgra8UnormSrgb
3119 | Self::R16Float
3120 | Self::Rg16Float
3121 | Self::Rgba16Float
3122 | Self::Rgb10a2Unorm
3123 | Self::Rg11b10Ufloat => Some(float),
3124
3125 Self::R32Float | Self::Rg32Float | Self::Rgba32Float => Some(float32_sample_type),
3126
3127 Self::R8Uint
3128 | Self::Rg8Uint
3129 | Self::Rgba8Uint
3130 | Self::R16Uint
3131 | Self::Rg16Uint
3132 | Self::Rgba16Uint
3133 | Self::R32Uint
3134 | Self::R64Uint
3135 | Self::Rg32Uint
3136 | Self::Rgba32Uint
3137 | Self::Rgb10a2Uint => Some(uint),
3138
3139 Self::R8Sint
3140 | Self::Rg8Sint
3141 | Self::Rgba8Sint
3142 | Self::R16Sint
3143 | Self::Rg16Sint
3144 | Self::Rgba16Sint
3145 | Self::R32Sint
3146 | Self::Rg32Sint
3147 | Self::Rgba32Sint => Some(sint),
3148
3149 Self::Stencil8 => Some(uint),
3150 Self::Depth16Unorm | Self::Depth24Plus | Self::Depth32Float => Some(depth),
3151 Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8 => match aspect {
3152 Some(TextureAspect::DepthOnly) => Some(depth),
3153 Some(TextureAspect::StencilOnly) => Some(uint),
3154 _ => None,
3155 },
3156
3157 Self::NV12 => match aspect {
3158 Some(TextureAspect::Plane0) | Some(TextureAspect::Plane1) => {
3159 Some(unfilterable_float)
3160 }
3161 _ => None,
3162 },
3163
3164 Self::R16Unorm
3165 | Self::R16Snorm
3166 | Self::Rg16Unorm
3167 | Self::Rg16Snorm
3168 | Self::Rgba16Unorm
3169 | Self::Rgba16Snorm => Some(float),
3170
3171 Self::Rgb9e5Ufloat => Some(float),
3172
3173 Self::Bc1RgbaUnorm
3174 | Self::Bc1RgbaUnormSrgb
3175 | Self::Bc2RgbaUnorm
3176 | Self::Bc2RgbaUnormSrgb
3177 | Self::Bc3RgbaUnorm
3178 | Self::Bc3RgbaUnormSrgb
3179 | Self::Bc4RUnorm
3180 | Self::Bc4RSnorm
3181 | Self::Bc5RgUnorm
3182 | Self::Bc5RgSnorm
3183 | Self::Bc6hRgbUfloat
3184 | Self::Bc6hRgbFloat
3185 | Self::Bc7RgbaUnorm
3186 | Self::Bc7RgbaUnormSrgb => Some(float),
3187
3188 Self::Etc2Rgb8Unorm
3189 | Self::Etc2Rgb8UnormSrgb
3190 | Self::Etc2Rgb8A1Unorm
3191 | Self::Etc2Rgb8A1UnormSrgb
3192 | Self::Etc2Rgba8Unorm
3193 | Self::Etc2Rgba8UnormSrgb
3194 | Self::EacR11Unorm
3195 | Self::EacR11Snorm
3196 | Self::EacRg11Unorm
3197 | Self::EacRg11Snorm => Some(float),
3198
3199 Self::Astc { .. } => Some(float),
3200 }
3201 }
3202
3203 /// The number of bytes one [texel block](https://gpuweb.github.io/gpuweb/#texel-block) occupies during an image copy, if applicable.
3204 ///
3205 /// Known as the [texel block copy footprint](https://gpuweb.github.io/gpuweb/#texel-block-copy-footprint).
3206 ///
3207 /// Note that for uncompressed formats this is the same as the size of a single texel,
3208 /// since uncompressed formats have a block size of 1x1.
3209 ///
3210 /// Returns `None` if any of the following are true:
3211 /// - the format is a combined depth-stencil and no `aspect` was provided
3212 /// - the format is a multi-planar format and no `aspect` was provided
3213 /// - the format is `Depth24Plus`
3214 /// - the format is `Depth24PlusStencil8` and `aspect` is depth.
3215 #[deprecated(since = "0.19.0", note = "Use `block_copy_size` instead.")]
3216 #[must_use]
3217 pub fn block_size(&self, aspect: Option<TextureAspect>) -> Option<u32> {
3218 self.block_copy_size(aspect)
3219 }
3220
3221 /// The number of bytes one [texel block](https://gpuweb.github.io/gpuweb/#texel-block) occupies during an image copy, if applicable.
3222 ///
3223 /// Known as the [texel block copy footprint](https://gpuweb.github.io/gpuweb/#texel-block-copy-footprint).
3224 ///
3225 /// Note that for uncompressed formats this is the same as the size of a single texel,
3226 /// since uncompressed formats have a block size of 1x1.
3227 ///
3228 /// Returns `None` if any of the following are true:
3229 /// - the format is a combined depth-stencil and no `aspect` was provided
3230 /// - the format is a multi-planar format and no `aspect` was provided
3231 /// - the format is `Depth24Plus`
3232 /// - the format is `Depth24PlusStencil8` and `aspect` is depth.
3233 #[must_use]
3234 pub fn block_copy_size(&self, aspect: Option<TextureAspect>) -> Option<u32> {
3235 match *self {
3236 Self::R8Unorm | Self::R8Snorm | Self::R8Uint | Self::R8Sint => Some(1),
3237
3238 Self::Rg8Unorm | Self::Rg8Snorm | Self::Rg8Uint | Self::Rg8Sint => Some(2),
3239 Self::R16Unorm | Self::R16Snorm | Self::R16Uint | Self::R16Sint | Self::R16Float => {
3240 Some(2)
3241 }
3242
3243 Self::Rgba8Unorm
3244 | Self::Rgba8UnormSrgb
3245 | Self::Rgba8Snorm
3246 | Self::Rgba8Uint
3247 | Self::Rgba8Sint
3248 | Self::Bgra8Unorm
3249 | Self::Bgra8UnormSrgb => Some(4),
3250 Self::Rg16Unorm
3251 | Self::Rg16Snorm
3252 | Self::Rg16Uint
3253 | Self::Rg16Sint
3254 | Self::Rg16Float => Some(4),
3255 Self::R32Uint | Self::R32Sint | Self::R32Float => Some(4),
3256 Self::Rgb9e5Ufloat | Self::Rgb10a2Uint | Self::Rgb10a2Unorm | Self::Rg11b10Ufloat => {
3257 Some(4)
3258 }
3259
3260 Self::Rgba16Unorm
3261 | Self::Rgba16Snorm
3262 | Self::Rgba16Uint
3263 | Self::Rgba16Sint
3264 | Self::Rgba16Float => Some(8),
3265 Self::R64Uint | Self::Rg32Uint | Self::Rg32Sint | Self::Rg32Float => Some(8),
3266
3267 Self::Rgba32Uint | Self::Rgba32Sint | Self::Rgba32Float => Some(16),
3268
3269 Self::Stencil8 => Some(1),
3270 Self::Depth16Unorm => Some(2),
3271 Self::Depth32Float => Some(4),
3272 Self::Depth24Plus => None,
3273 Self::Depth24PlusStencil8 => match aspect {
3274 Some(TextureAspect::DepthOnly) => None,
3275 Some(TextureAspect::StencilOnly) => Some(1),
3276 _ => None,
3277 },
3278 Self::Depth32FloatStencil8 => match aspect {
3279 Some(TextureAspect::DepthOnly) => Some(4),
3280 Some(TextureAspect::StencilOnly) => Some(1),
3281 _ => None,
3282 },
3283
3284 Self::NV12 => match aspect {
3285 Some(TextureAspect::Plane0) => Some(1),
3286 Some(TextureAspect::Plane1) => Some(2),
3287 _ => None,
3288 },
3289
3290 Self::Bc1RgbaUnorm | Self::Bc1RgbaUnormSrgb | Self::Bc4RUnorm | Self::Bc4RSnorm => {
3291 Some(8)
3292 }
3293 Self::Bc2RgbaUnorm
3294 | Self::Bc2RgbaUnormSrgb
3295 | Self::Bc3RgbaUnorm
3296 | Self::Bc3RgbaUnormSrgb
3297 | Self::Bc5RgUnorm
3298 | Self::Bc5RgSnorm
3299 | Self::Bc6hRgbUfloat
3300 | Self::Bc6hRgbFloat
3301 | Self::Bc7RgbaUnorm
3302 | Self::Bc7RgbaUnormSrgb => Some(16),
3303
3304 Self::Etc2Rgb8Unorm
3305 | Self::Etc2Rgb8UnormSrgb
3306 | Self::Etc2Rgb8A1Unorm
3307 | Self::Etc2Rgb8A1UnormSrgb
3308 | Self::EacR11Unorm
3309 | Self::EacR11Snorm => Some(8),
3310 Self::Etc2Rgba8Unorm
3311 | Self::Etc2Rgba8UnormSrgb
3312 | Self::EacRg11Unorm
3313 | Self::EacRg11Snorm => Some(16),
3314
3315 Self::Astc { .. } => Some(16),
3316 }
3317 }
3318
3319 /// The largest number that can be returned by [`Self::target_pixel_byte_cost`].
3320 pub const MAX_TARGET_PIXEL_BYTE_COST: u32 = 16;
3321
3322 /// The number of bytes occupied per pixel in a color attachment
3323 /// <https://gpuweb.github.io/gpuweb/#render-target-pixel-byte-cost>
3324 #[must_use]
3325 pub fn target_pixel_byte_cost(&self) -> Option<u32> {
3326 match *self {
3327 Self::R8Unorm | Self::R8Snorm | Self::R8Uint | Self::R8Sint => Some(1),
3328 Self::Rg8Unorm
3329 | Self::Rg8Snorm
3330 | Self::Rg8Uint
3331 | Self::Rg8Sint
3332 | Self::R16Uint
3333 | Self::R16Sint
3334 | Self::R16Unorm
3335 | Self::R16Snorm
3336 | Self::R16Float => Some(2),
3337 Self::Rgba8Uint
3338 | Self::Rgba8Sint
3339 | Self::Rg16Uint
3340 | Self::Rg16Sint
3341 | Self::Rg16Unorm
3342 | Self::Rg16Snorm
3343 | Self::Rg16Float
3344 | Self::R32Uint
3345 | Self::R32Sint
3346 | Self::R32Float => Some(4),
3347 // Despite being 4 bytes per pixel, these are 8 bytes per pixel in the table
3348 Self::Rgba8Unorm
3349 | Self::Rgba8UnormSrgb
3350 | Self::Rgba8Snorm
3351 | Self::Bgra8Unorm
3352 | Self::Bgra8UnormSrgb
3353 // ---
3354 | Self::Rgba16Uint
3355 | Self::Rgba16Sint
3356 | Self::Rgba16Unorm
3357 | Self::Rgba16Snorm
3358 | Self::Rgba16Float
3359 | Self::R64Uint
3360 | Self::Rg32Uint
3361 | Self::Rg32Sint
3362 | Self::Rg32Float
3363 | Self::Rgb10a2Uint
3364 | Self::Rgb10a2Unorm
3365 | Self::Rg11b10Ufloat => Some(8),
3366 Self::Rgba32Uint | Self::Rgba32Sint | Self::Rgba32Float => Some(16),
3367 // ⚠️ If you add formats with larger sizes, make sure you change `MAX_TARGET_PIXEL_BYTE_COST`` ⚠️
3368 Self::Stencil8
3369 | Self::Depth16Unorm
3370 | Self::Depth24Plus
3371 | Self::Depth24PlusStencil8
3372 | Self::Depth32Float
3373 | Self::Depth32FloatStencil8
3374 | Self::NV12
3375 | Self::Rgb9e5Ufloat
3376 | Self::Bc1RgbaUnorm
3377 | Self::Bc1RgbaUnormSrgb
3378 | Self::Bc2RgbaUnorm
3379 | Self::Bc2RgbaUnormSrgb
3380 | Self::Bc3RgbaUnorm
3381 | Self::Bc3RgbaUnormSrgb
3382 | Self::Bc4RUnorm
3383 | Self::Bc4RSnorm
3384 | Self::Bc5RgUnorm
3385 | Self::Bc5RgSnorm
3386 | Self::Bc6hRgbUfloat
3387 | Self::Bc6hRgbFloat
3388 | Self::Bc7RgbaUnorm
3389 | Self::Bc7RgbaUnormSrgb
3390 | Self::Etc2Rgb8Unorm
3391 | Self::Etc2Rgb8UnormSrgb
3392 | Self::Etc2Rgb8A1Unorm
3393 | Self::Etc2Rgb8A1UnormSrgb
3394 | Self::Etc2Rgba8Unorm
3395 | Self::Etc2Rgba8UnormSrgb
3396 | Self::EacR11Unorm
3397 | Self::EacR11Snorm
3398 | Self::EacRg11Unorm
3399 | Self::EacRg11Snorm
3400 | Self::Astc { .. } => None,
3401 }
3402 }
3403
3404 /// See <https://gpuweb.github.io/gpuweb/#render-target-component-alignment>
3405 #[must_use]
3406 pub fn target_component_alignment(&self) -> Option<u32> {
3407 match *self {
3408 Self::R8Unorm
3409 | Self::R8Snorm
3410 | Self::R8Uint
3411 | Self::R8Sint
3412 | Self::Rg8Unorm
3413 | Self::Rg8Snorm
3414 | Self::Rg8Uint
3415 | Self::Rg8Sint
3416 | Self::Rgba8Unorm
3417 | Self::Rgba8UnormSrgb
3418 | Self::Rgba8Snorm
3419 | Self::Rgba8Uint
3420 | Self::Rgba8Sint
3421 | Self::Bgra8Unorm
3422 | Self::Bgra8UnormSrgb => Some(1),
3423 Self::R16Uint
3424 | Self::R16Sint
3425 | Self::R16Unorm
3426 | Self::R16Snorm
3427 | Self::R16Float
3428 | Self::Rg16Uint
3429 | Self::Rg16Sint
3430 | Self::Rg16Unorm
3431 | Self::Rg16Snorm
3432 | Self::Rg16Float
3433 | Self::Rgba16Uint
3434 | Self::Rgba16Sint
3435 | Self::Rgba16Unorm
3436 | Self::Rgba16Snorm
3437 | Self::Rgba16Float => Some(2),
3438 Self::R32Uint
3439 | Self::R32Sint
3440 | Self::R32Float
3441 | Self::R64Uint
3442 | Self::Rg32Uint
3443 | Self::Rg32Sint
3444 | Self::Rg32Float
3445 | Self::Rgba32Uint
3446 | Self::Rgba32Sint
3447 | Self::Rgba32Float
3448 | Self::Rgb10a2Uint
3449 | Self::Rgb10a2Unorm
3450 | Self::Rg11b10Ufloat => Some(4),
3451 Self::Stencil8
3452 | Self::Depth16Unorm
3453 | Self::Depth24Plus
3454 | Self::Depth24PlusStencil8
3455 | Self::Depth32Float
3456 | Self::Depth32FloatStencil8
3457 | Self::NV12
3458 | Self::Rgb9e5Ufloat
3459 | Self::Bc1RgbaUnorm
3460 | Self::Bc1RgbaUnormSrgb
3461 | Self::Bc2RgbaUnorm
3462 | Self::Bc2RgbaUnormSrgb
3463 | Self::Bc3RgbaUnorm
3464 | Self::Bc3RgbaUnormSrgb
3465 | Self::Bc4RUnorm
3466 | Self::Bc4RSnorm
3467 | Self::Bc5RgUnorm
3468 | Self::Bc5RgSnorm
3469 | Self::Bc6hRgbUfloat
3470 | Self::Bc6hRgbFloat
3471 | Self::Bc7RgbaUnorm
3472 | Self::Bc7RgbaUnormSrgb
3473 | Self::Etc2Rgb8Unorm
3474 | Self::Etc2Rgb8UnormSrgb
3475 | Self::Etc2Rgb8A1Unorm
3476 | Self::Etc2Rgb8A1UnormSrgb
3477 | Self::Etc2Rgba8Unorm
3478 | Self::Etc2Rgba8UnormSrgb
3479 | Self::EacR11Unorm
3480 | Self::EacR11Snorm
3481 | Self::EacRg11Unorm
3482 | Self::EacRg11Snorm
3483 | Self::Astc { .. } => None,
3484 }
3485 }
3486
3487 /// Returns the number of components this format has.
3488 #[must_use]
3489 pub fn components(&self) -> u8 {
3490 self.components_with_aspect(TextureAspect::All)
3491 }
3492
3493 /// Returns the number of components this format has taking into account the `aspect`.
3494 ///
3495 /// The `aspect` is only relevant for combined depth-stencil formats and multi-planar formats.
3496 #[must_use]
3497 pub fn components_with_aspect(&self, aspect: TextureAspect) -> u8 {
3498 match *self {
3499 Self::R8Unorm
3500 | Self::R8Snorm
3501 | Self::R8Uint
3502 | Self::R8Sint
3503 | Self::R16Unorm
3504 | Self::R16Snorm
3505 | Self::R16Uint
3506 | Self::R16Sint
3507 | Self::R16Float
3508 | Self::R32Uint
3509 | Self::R32Sint
3510 | Self::R32Float
3511 | Self::R64Uint => 1,
3512
3513 Self::Rg8Unorm
3514 | Self::Rg8Snorm
3515 | Self::Rg8Uint
3516 | Self::Rg8Sint
3517 | Self::Rg16Unorm
3518 | Self::Rg16Snorm
3519 | Self::Rg16Uint
3520 | Self::Rg16Sint
3521 | Self::Rg16Float
3522 | Self::Rg32Uint
3523 | Self::Rg32Sint
3524 | Self::Rg32Float => 2,
3525
3526 Self::Rgba8Unorm
3527 | Self::Rgba8UnormSrgb
3528 | Self::Rgba8Snorm
3529 | Self::Rgba8Uint
3530 | Self::Rgba8Sint
3531 | Self::Bgra8Unorm
3532 | Self::Bgra8UnormSrgb
3533 | Self::Rgba16Unorm
3534 | Self::Rgba16Snorm
3535 | Self::Rgba16Uint
3536 | Self::Rgba16Sint
3537 | Self::Rgba16Float
3538 | Self::Rgba32Uint
3539 | Self::Rgba32Sint
3540 | Self::Rgba32Float => 4,
3541
3542 Self::Rgb9e5Ufloat | Self::Rg11b10Ufloat => 3,
3543 Self::Rgb10a2Uint | Self::Rgb10a2Unorm => 4,
3544
3545 Self::Stencil8 | Self::Depth16Unorm | Self::Depth24Plus | Self::Depth32Float => 1,
3546
3547 Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8 => match aspect {
3548 TextureAspect::DepthOnly | TextureAspect::StencilOnly => 1,
3549 _ => 2,
3550 },
3551
3552 Self::NV12 => match aspect {
3553 TextureAspect::Plane0 => 1,
3554 TextureAspect::Plane1 => 2,
3555 _ => 3,
3556 },
3557
3558 Self::Bc4RUnorm | Self::Bc4RSnorm => 1,
3559 Self::Bc5RgUnorm | Self::Bc5RgSnorm => 2,
3560 Self::Bc6hRgbUfloat | Self::Bc6hRgbFloat => 3,
3561 Self::Bc1RgbaUnorm
3562 | Self::Bc1RgbaUnormSrgb
3563 | Self::Bc2RgbaUnorm
3564 | Self::Bc2RgbaUnormSrgb
3565 | Self::Bc3RgbaUnorm
3566 | Self::Bc3RgbaUnormSrgb
3567 | Self::Bc7RgbaUnorm
3568 | Self::Bc7RgbaUnormSrgb => 4,
3569
3570 Self::EacR11Unorm | Self::EacR11Snorm => 1,
3571 Self::EacRg11Unorm | Self::EacRg11Snorm => 2,
3572 Self::Etc2Rgb8Unorm | Self::Etc2Rgb8UnormSrgb => 3,
3573 Self::Etc2Rgb8A1Unorm
3574 | Self::Etc2Rgb8A1UnormSrgb
3575 | Self::Etc2Rgba8Unorm
3576 | Self::Etc2Rgba8UnormSrgb => 4,
3577
3578 Self::Astc { .. } => 4,
3579 }
3580 }
3581
3582 /// Strips the `Srgb` suffix from the given texture format.
3583 #[must_use]
3584 pub fn remove_srgb_suffix(&self) -> TextureFormat {
3585 match *self {
3586 Self::Rgba8UnormSrgb => Self::Rgba8Unorm,
3587 Self::Bgra8UnormSrgb => Self::Bgra8Unorm,
3588 Self::Bc1RgbaUnormSrgb => Self::Bc1RgbaUnorm,
3589 Self::Bc2RgbaUnormSrgb => Self::Bc2RgbaUnorm,
3590 Self::Bc3RgbaUnormSrgb => Self::Bc3RgbaUnorm,
3591 Self::Bc7RgbaUnormSrgb => Self::Bc7RgbaUnorm,
3592 Self::Etc2Rgb8UnormSrgb => Self::Etc2Rgb8Unorm,
3593 Self::Etc2Rgb8A1UnormSrgb => Self::Etc2Rgb8A1Unorm,
3594 Self::Etc2Rgba8UnormSrgb => Self::Etc2Rgba8Unorm,
3595 Self::Astc {
3596 block,
3597 channel: AstcChannel::UnormSrgb,
3598 } => Self::Astc {
3599 block,
3600 channel: AstcChannel::Unorm,
3601 },
3602 _ => *self,
3603 }
3604 }
3605
3606 /// Adds an `Srgb` suffix to the given texture format, if the format supports it.
3607 #[must_use]
3608 pub fn add_srgb_suffix(&self) -> TextureFormat {
3609 match *self {
3610 Self::Rgba8Unorm => Self::Rgba8UnormSrgb,
3611 Self::Bgra8Unorm => Self::Bgra8UnormSrgb,
3612 Self::Bc1RgbaUnorm => Self::Bc1RgbaUnormSrgb,
3613 Self::Bc2RgbaUnorm => Self::Bc2RgbaUnormSrgb,
3614 Self::Bc3RgbaUnorm => Self::Bc3RgbaUnormSrgb,
3615 Self::Bc7RgbaUnorm => Self::Bc7RgbaUnormSrgb,
3616 Self::Etc2Rgb8Unorm => Self::Etc2Rgb8UnormSrgb,
3617 Self::Etc2Rgb8A1Unorm => Self::Etc2Rgb8A1UnormSrgb,
3618 Self::Etc2Rgba8Unorm => Self::Etc2Rgba8UnormSrgb,
3619 Self::Astc {
3620 block,
3621 channel: AstcChannel::Unorm,
3622 } => Self::Astc {
3623 block,
3624 channel: AstcChannel::UnormSrgb,
3625 },
3626 _ => *self,
3627 }
3628 }
3629
3630 /// Returns `true` for srgb formats.
3631 #[must_use]
3632 pub fn is_srgb(&self) -> bool {
3633 *self != self.remove_srgb_suffix()
3634 }
3635
3636 /// Returns the theoretical memory footprint of a texture with the given format and dimensions.
3637 ///
3638 /// Actual memory usage may greatly exceed this value due to alignment and padding.
3639 #[must_use]
3640 pub fn theoretical_memory_footprint(&self, size: Extent3d) -> u64 {
3641 let (block_width, block_height) = self.block_dimensions();
3642
3643 let block_size = self.block_copy_size(None);
3644
3645 let approximate_block_size = match block_size {
3646 Some(size) => size,
3647 None => match self {
3648 // One f16 per pixel
3649 Self::Depth16Unorm => 2,
3650 // One u24 per pixel, padded to 4 bytes
3651 Self::Depth24Plus => 4,
3652 // One u24 per pixel, plus one u8 per pixel
3653 Self::Depth24PlusStencil8 => 4,
3654 // One f32 per pixel
3655 Self::Depth32Float => 4,
3656 // One f32 per pixel, plus one u8 per pixel, with 3 bytes intermediary padding
3657 Self::Depth32FloatStencil8 => 8,
3658 // One u8 per pixel
3659 Self::Stencil8 => 1,
3660 // Two chroma bytes per block, one luma byte per block
3661 Self::NV12 => 3,
3662 f => {
3663 log::warn!("Memory footprint for format {:?} is not implemented", f);
3664 0
3665 }
3666 },
3667 };
3668
3669 let width_blocks = size.width.div_ceil(block_width) as u64;
3670 let height_blocks = size.height.div_ceil(block_height) as u64;
3671
3672 let total_blocks = width_blocks * height_blocks * size.depth_or_array_layers as u64;
3673
3674 total_blocks * approximate_block_size as u64
3675 }
3676}
3677
3678#[test]
3679fn texture_format_serialize() {
3680 use alloc::string::ToString;
3681
3682 assert_eq!(
3683 serde_json::to_string(&TextureFormat::R8Unorm).unwrap(),
3684 "\"r8unorm\"".to_string()
3685 );
3686 assert_eq!(
3687 serde_json::to_string(&TextureFormat::R8Snorm).unwrap(),
3688 "\"r8snorm\"".to_string()
3689 );
3690 assert_eq!(
3691 serde_json::to_string(&TextureFormat::R8Uint).unwrap(),
3692 "\"r8uint\"".to_string()
3693 );
3694 assert_eq!(
3695 serde_json::to_string(&TextureFormat::R8Sint).unwrap(),
3696 "\"r8sint\"".to_string()
3697 );
3698 assert_eq!(
3699 serde_json::to_string(&TextureFormat::R16Uint).unwrap(),
3700 "\"r16uint\"".to_string()
3701 );
3702 assert_eq!(
3703 serde_json::to_string(&TextureFormat::R16Sint).unwrap(),
3704 "\"r16sint\"".to_string()
3705 );
3706 assert_eq!(
3707 serde_json::to_string(&TextureFormat::R16Unorm).unwrap(),
3708 "\"r16unorm\"".to_string()
3709 );
3710 assert_eq!(
3711 serde_json::to_string(&TextureFormat::R16Snorm).unwrap(),
3712 "\"r16snorm\"".to_string()
3713 );
3714 assert_eq!(
3715 serde_json::to_string(&TextureFormat::R16Float).unwrap(),
3716 "\"r16float\"".to_string()
3717 );
3718 assert_eq!(
3719 serde_json::to_string(&TextureFormat::Rg8Unorm).unwrap(),
3720 "\"rg8unorm\"".to_string()
3721 );
3722 assert_eq!(
3723 serde_json::to_string(&TextureFormat::Rg8Snorm).unwrap(),
3724 "\"rg8snorm\"".to_string()
3725 );
3726 assert_eq!(
3727 serde_json::to_string(&TextureFormat::Rg8Uint).unwrap(),
3728 "\"rg8uint\"".to_string()
3729 );
3730 assert_eq!(
3731 serde_json::to_string(&TextureFormat::Rg8Sint).unwrap(),
3732 "\"rg8sint\"".to_string()
3733 );
3734 assert_eq!(
3735 serde_json::to_string(&TextureFormat::R32Uint).unwrap(),
3736 "\"r32uint\"".to_string()
3737 );
3738 assert_eq!(
3739 serde_json::to_string(&TextureFormat::R32Sint).unwrap(),
3740 "\"r32sint\"".to_string()
3741 );
3742 assert_eq!(
3743 serde_json::to_string(&TextureFormat::R32Float).unwrap(),
3744 "\"r32float\"".to_string()
3745 );
3746 assert_eq!(
3747 serde_json::to_string(&TextureFormat::Rg16Uint).unwrap(),
3748 "\"rg16uint\"".to_string()
3749 );
3750 assert_eq!(
3751 serde_json::to_string(&TextureFormat::Rg16Sint).unwrap(),
3752 "\"rg16sint\"".to_string()
3753 );
3754 assert_eq!(
3755 serde_json::to_string(&TextureFormat::Rg16Unorm).unwrap(),
3756 "\"rg16unorm\"".to_string()
3757 );
3758 assert_eq!(
3759 serde_json::to_string(&TextureFormat::Rg16Snorm).unwrap(),
3760 "\"rg16snorm\"".to_string()
3761 );
3762 assert_eq!(
3763 serde_json::to_string(&TextureFormat::Rg16Float).unwrap(),
3764 "\"rg16float\"".to_string()
3765 );
3766 assert_eq!(
3767 serde_json::to_string(&TextureFormat::Rgba8Unorm).unwrap(),
3768 "\"rgba8unorm\"".to_string()
3769 );
3770 assert_eq!(
3771 serde_json::to_string(&TextureFormat::Rgba8UnormSrgb).unwrap(),
3772 "\"rgba8unorm-srgb\"".to_string()
3773 );
3774 assert_eq!(
3775 serde_json::to_string(&TextureFormat::Rgba8Snorm).unwrap(),
3776 "\"rgba8snorm\"".to_string()
3777 );
3778 assert_eq!(
3779 serde_json::to_string(&TextureFormat::Rgba8Uint).unwrap(),
3780 "\"rgba8uint\"".to_string()
3781 );
3782 assert_eq!(
3783 serde_json::to_string(&TextureFormat::Rgba8Sint).unwrap(),
3784 "\"rgba8sint\"".to_string()
3785 );
3786 assert_eq!(
3787 serde_json::to_string(&TextureFormat::Bgra8Unorm).unwrap(),
3788 "\"bgra8unorm\"".to_string()
3789 );
3790 assert_eq!(
3791 serde_json::to_string(&TextureFormat::Bgra8UnormSrgb).unwrap(),
3792 "\"bgra8unorm-srgb\"".to_string()
3793 );
3794 assert_eq!(
3795 serde_json::to_string(&TextureFormat::Rgb10a2Uint).unwrap(),
3796 "\"rgb10a2uint\"".to_string()
3797 );
3798 assert_eq!(
3799 serde_json::to_string(&TextureFormat::Rgb10a2Unorm).unwrap(),
3800 "\"rgb10a2unorm\"".to_string()
3801 );
3802 assert_eq!(
3803 serde_json::to_string(&TextureFormat::Rg11b10Ufloat).unwrap(),
3804 "\"rg11b10ufloat\"".to_string()
3805 );
3806 assert_eq!(
3807 serde_json::to_string(&TextureFormat::R64Uint).unwrap(),
3808 "\"r64uint\"".to_string()
3809 );
3810 assert_eq!(
3811 serde_json::to_string(&TextureFormat::Rg32Uint).unwrap(),
3812 "\"rg32uint\"".to_string()
3813 );
3814 assert_eq!(
3815 serde_json::to_string(&TextureFormat::Rg32Sint).unwrap(),
3816 "\"rg32sint\"".to_string()
3817 );
3818 assert_eq!(
3819 serde_json::to_string(&TextureFormat::Rg32Float).unwrap(),
3820 "\"rg32float\"".to_string()
3821 );
3822 assert_eq!(
3823 serde_json::to_string(&TextureFormat::Rgba16Uint).unwrap(),
3824 "\"rgba16uint\"".to_string()
3825 );
3826 assert_eq!(
3827 serde_json::to_string(&TextureFormat::Rgba16Sint).unwrap(),
3828 "\"rgba16sint\"".to_string()
3829 );
3830 assert_eq!(
3831 serde_json::to_string(&TextureFormat::Rgba16Unorm).unwrap(),
3832 "\"rgba16unorm\"".to_string()
3833 );
3834 assert_eq!(
3835 serde_json::to_string(&TextureFormat::Rgba16Snorm).unwrap(),
3836 "\"rgba16snorm\"".to_string()
3837 );
3838 assert_eq!(
3839 serde_json::to_string(&TextureFormat::Rgba16Float).unwrap(),
3840 "\"rgba16float\"".to_string()
3841 );
3842 assert_eq!(
3843 serde_json::to_string(&TextureFormat::Rgba32Uint).unwrap(),
3844 "\"rgba32uint\"".to_string()
3845 );
3846 assert_eq!(
3847 serde_json::to_string(&TextureFormat::Rgba32Sint).unwrap(),
3848 "\"rgba32sint\"".to_string()
3849 );
3850 assert_eq!(
3851 serde_json::to_string(&TextureFormat::Rgba32Float).unwrap(),
3852 "\"rgba32float\"".to_string()
3853 );
3854 assert_eq!(
3855 serde_json::to_string(&TextureFormat::Stencil8).unwrap(),
3856 "\"stencil8\"".to_string()
3857 );
3858 assert_eq!(
3859 serde_json::to_string(&TextureFormat::Depth32Float).unwrap(),
3860 "\"depth32float\"".to_string()
3861 );
3862 assert_eq!(
3863 serde_json::to_string(&TextureFormat::Depth16Unorm).unwrap(),
3864 "\"depth16unorm\"".to_string()
3865 );
3866 assert_eq!(
3867 serde_json::to_string(&TextureFormat::Depth32FloatStencil8).unwrap(),
3868 "\"depth32float-stencil8\"".to_string()
3869 );
3870 assert_eq!(
3871 serde_json::to_string(&TextureFormat::Depth24Plus).unwrap(),
3872 "\"depth24plus\"".to_string()
3873 );
3874 assert_eq!(
3875 serde_json::to_string(&TextureFormat::Depth24PlusStencil8).unwrap(),
3876 "\"depth24plus-stencil8\"".to_string()
3877 );
3878 assert_eq!(
3879 serde_json::to_string(&TextureFormat::Rgb9e5Ufloat).unwrap(),
3880 "\"rgb9e5ufloat\"".to_string()
3881 );
3882 assert_eq!(
3883 serde_json::to_string(&TextureFormat::Bc1RgbaUnorm).unwrap(),
3884 "\"bc1-rgba-unorm\"".to_string()
3885 );
3886 assert_eq!(
3887 serde_json::to_string(&TextureFormat::Bc1RgbaUnormSrgb).unwrap(),
3888 "\"bc1-rgba-unorm-srgb\"".to_string()
3889 );
3890 assert_eq!(
3891 serde_json::to_string(&TextureFormat::Bc2RgbaUnorm).unwrap(),
3892 "\"bc2-rgba-unorm\"".to_string()
3893 );
3894 assert_eq!(
3895 serde_json::to_string(&TextureFormat::Bc2RgbaUnormSrgb).unwrap(),
3896 "\"bc2-rgba-unorm-srgb\"".to_string()
3897 );
3898 assert_eq!(
3899 serde_json::to_string(&TextureFormat::Bc3RgbaUnorm).unwrap(),
3900 "\"bc3-rgba-unorm\"".to_string()
3901 );
3902 assert_eq!(
3903 serde_json::to_string(&TextureFormat::Bc3RgbaUnormSrgb).unwrap(),
3904 "\"bc3-rgba-unorm-srgb\"".to_string()
3905 );
3906 assert_eq!(
3907 serde_json::to_string(&TextureFormat::Bc4RUnorm).unwrap(),
3908 "\"bc4-r-unorm\"".to_string()
3909 );
3910 assert_eq!(
3911 serde_json::to_string(&TextureFormat::Bc4RSnorm).unwrap(),
3912 "\"bc4-r-snorm\"".to_string()
3913 );
3914 assert_eq!(
3915 serde_json::to_string(&TextureFormat::Bc5RgUnorm).unwrap(),
3916 "\"bc5-rg-unorm\"".to_string()
3917 );
3918 assert_eq!(
3919 serde_json::to_string(&TextureFormat::Bc5RgSnorm).unwrap(),
3920 "\"bc5-rg-snorm\"".to_string()
3921 );
3922 assert_eq!(
3923 serde_json::to_string(&TextureFormat::Bc6hRgbUfloat).unwrap(),
3924 "\"bc6h-rgb-ufloat\"".to_string()
3925 );
3926 assert_eq!(
3927 serde_json::to_string(&TextureFormat::Bc6hRgbFloat).unwrap(),
3928 "\"bc6h-rgb-float\"".to_string()
3929 );
3930 assert_eq!(
3931 serde_json::to_string(&TextureFormat::Bc7RgbaUnorm).unwrap(),
3932 "\"bc7-rgba-unorm\"".to_string()
3933 );
3934 assert_eq!(
3935 serde_json::to_string(&TextureFormat::Bc7RgbaUnormSrgb).unwrap(),
3936 "\"bc7-rgba-unorm-srgb\"".to_string()
3937 );
3938 assert_eq!(
3939 serde_json::to_string(&TextureFormat::Etc2Rgb8Unorm).unwrap(),
3940 "\"etc2-rgb8unorm\"".to_string()
3941 );
3942 assert_eq!(
3943 serde_json::to_string(&TextureFormat::Etc2Rgb8UnormSrgb).unwrap(),
3944 "\"etc2-rgb8unorm-srgb\"".to_string()
3945 );
3946 assert_eq!(
3947 serde_json::to_string(&TextureFormat::Etc2Rgb8A1Unorm).unwrap(),
3948 "\"etc2-rgb8a1unorm\"".to_string()
3949 );
3950 assert_eq!(
3951 serde_json::to_string(&TextureFormat::Etc2Rgb8A1UnormSrgb).unwrap(),
3952 "\"etc2-rgb8a1unorm-srgb\"".to_string()
3953 );
3954 assert_eq!(
3955 serde_json::to_string(&TextureFormat::Etc2Rgba8Unorm).unwrap(),
3956 "\"etc2-rgba8unorm\"".to_string()
3957 );
3958 assert_eq!(
3959 serde_json::to_string(&TextureFormat::Etc2Rgba8UnormSrgb).unwrap(),
3960 "\"etc2-rgba8unorm-srgb\"".to_string()
3961 );
3962 assert_eq!(
3963 serde_json::to_string(&TextureFormat::EacR11Unorm).unwrap(),
3964 "\"eac-r11unorm\"".to_string()
3965 );
3966 assert_eq!(
3967 serde_json::to_string(&TextureFormat::EacR11Snorm).unwrap(),
3968 "\"eac-r11snorm\"".to_string()
3969 );
3970 assert_eq!(
3971 serde_json::to_string(&TextureFormat::EacRg11Unorm).unwrap(),
3972 "\"eac-rg11unorm\"".to_string()
3973 );
3974 assert_eq!(
3975 serde_json::to_string(&TextureFormat::EacRg11Snorm).unwrap(),
3976 "\"eac-rg11snorm\"".to_string()
3977 );
3978}
3979
3980#[test]
3981fn texture_format_deserialize() {
3982 assert_eq!(
3983 serde_json::from_str::<TextureFormat>("\"r8unorm\"").unwrap(),
3984 TextureFormat::R8Unorm
3985 );
3986 assert_eq!(
3987 serde_json::from_str::<TextureFormat>("\"r8snorm\"").unwrap(),
3988 TextureFormat::R8Snorm
3989 );
3990 assert_eq!(
3991 serde_json::from_str::<TextureFormat>("\"r8uint\"").unwrap(),
3992 TextureFormat::R8Uint
3993 );
3994 assert_eq!(
3995 serde_json::from_str::<TextureFormat>("\"r8sint\"").unwrap(),
3996 TextureFormat::R8Sint
3997 );
3998 assert_eq!(
3999 serde_json::from_str::<TextureFormat>("\"r16uint\"").unwrap(),
4000 TextureFormat::R16Uint
4001 );
4002 assert_eq!(
4003 serde_json::from_str::<TextureFormat>("\"r16sint\"").unwrap(),
4004 TextureFormat::R16Sint
4005 );
4006 assert_eq!(
4007 serde_json::from_str::<TextureFormat>("\"r16unorm\"").unwrap(),
4008 TextureFormat::R16Unorm
4009 );
4010 assert_eq!(
4011 serde_json::from_str::<TextureFormat>("\"r16snorm\"").unwrap(),
4012 TextureFormat::R16Snorm
4013 );
4014 assert_eq!(
4015 serde_json::from_str::<TextureFormat>("\"r16float\"").unwrap(),
4016 TextureFormat::R16Float
4017 );
4018 assert_eq!(
4019 serde_json::from_str::<TextureFormat>("\"rg8unorm\"").unwrap(),
4020 TextureFormat::Rg8Unorm
4021 );
4022 assert_eq!(
4023 serde_json::from_str::<TextureFormat>("\"rg8snorm\"").unwrap(),
4024 TextureFormat::Rg8Snorm
4025 );
4026 assert_eq!(
4027 serde_json::from_str::<TextureFormat>("\"rg8uint\"").unwrap(),
4028 TextureFormat::Rg8Uint
4029 );
4030 assert_eq!(
4031 serde_json::from_str::<TextureFormat>("\"rg8sint\"").unwrap(),
4032 TextureFormat::Rg8Sint
4033 );
4034 assert_eq!(
4035 serde_json::from_str::<TextureFormat>("\"r32uint\"").unwrap(),
4036 TextureFormat::R32Uint
4037 );
4038 assert_eq!(
4039 serde_json::from_str::<TextureFormat>("\"r32sint\"").unwrap(),
4040 TextureFormat::R32Sint
4041 );
4042 assert_eq!(
4043 serde_json::from_str::<TextureFormat>("\"r32float\"").unwrap(),
4044 TextureFormat::R32Float
4045 );
4046 assert_eq!(
4047 serde_json::from_str::<TextureFormat>("\"rg16uint\"").unwrap(),
4048 TextureFormat::Rg16Uint
4049 );
4050 assert_eq!(
4051 serde_json::from_str::<TextureFormat>("\"rg16sint\"").unwrap(),
4052 TextureFormat::Rg16Sint
4053 );
4054 assert_eq!(
4055 serde_json::from_str::<TextureFormat>("\"rg16unorm\"").unwrap(),
4056 TextureFormat::Rg16Unorm
4057 );
4058 assert_eq!(
4059 serde_json::from_str::<TextureFormat>("\"rg16snorm\"").unwrap(),
4060 TextureFormat::Rg16Snorm
4061 );
4062 assert_eq!(
4063 serde_json::from_str::<TextureFormat>("\"rg16float\"").unwrap(),
4064 TextureFormat::Rg16Float
4065 );
4066 assert_eq!(
4067 serde_json::from_str::<TextureFormat>("\"rgba8unorm\"").unwrap(),
4068 TextureFormat::Rgba8Unorm
4069 );
4070 assert_eq!(
4071 serde_json::from_str::<TextureFormat>("\"rgba8unorm-srgb\"").unwrap(),
4072 TextureFormat::Rgba8UnormSrgb
4073 );
4074 assert_eq!(
4075 serde_json::from_str::<TextureFormat>("\"rgba8snorm\"").unwrap(),
4076 TextureFormat::Rgba8Snorm
4077 );
4078 assert_eq!(
4079 serde_json::from_str::<TextureFormat>("\"rgba8uint\"").unwrap(),
4080 TextureFormat::Rgba8Uint
4081 );
4082 assert_eq!(
4083 serde_json::from_str::<TextureFormat>("\"rgba8sint\"").unwrap(),
4084 TextureFormat::Rgba8Sint
4085 );
4086 assert_eq!(
4087 serde_json::from_str::<TextureFormat>("\"bgra8unorm\"").unwrap(),
4088 TextureFormat::Bgra8Unorm
4089 );
4090 assert_eq!(
4091 serde_json::from_str::<TextureFormat>("\"bgra8unorm-srgb\"").unwrap(),
4092 TextureFormat::Bgra8UnormSrgb
4093 );
4094 assert_eq!(
4095 serde_json::from_str::<TextureFormat>("\"rgb10a2uint\"").unwrap(),
4096 TextureFormat::Rgb10a2Uint
4097 );
4098 assert_eq!(
4099 serde_json::from_str::<TextureFormat>("\"rgb10a2unorm\"").unwrap(),
4100 TextureFormat::Rgb10a2Unorm
4101 );
4102 assert_eq!(
4103 serde_json::from_str::<TextureFormat>("\"rg11b10ufloat\"").unwrap(),
4104 TextureFormat::Rg11b10Ufloat
4105 );
4106 assert_eq!(
4107 serde_json::from_str::<TextureFormat>("\"r64uint\"").unwrap(),
4108 TextureFormat::R64Uint
4109 );
4110 assert_eq!(
4111 serde_json::from_str::<TextureFormat>("\"rg32uint\"").unwrap(),
4112 TextureFormat::Rg32Uint
4113 );
4114 assert_eq!(
4115 serde_json::from_str::<TextureFormat>("\"rg32sint\"").unwrap(),
4116 TextureFormat::Rg32Sint
4117 );
4118 assert_eq!(
4119 serde_json::from_str::<TextureFormat>("\"rg32float\"").unwrap(),
4120 TextureFormat::Rg32Float
4121 );
4122 assert_eq!(
4123 serde_json::from_str::<TextureFormat>("\"rgba16uint\"").unwrap(),
4124 TextureFormat::Rgba16Uint
4125 );
4126 assert_eq!(
4127 serde_json::from_str::<TextureFormat>("\"rgba16sint\"").unwrap(),
4128 TextureFormat::Rgba16Sint
4129 );
4130 assert_eq!(
4131 serde_json::from_str::<TextureFormat>("\"rgba16unorm\"").unwrap(),
4132 TextureFormat::Rgba16Unorm
4133 );
4134 assert_eq!(
4135 serde_json::from_str::<TextureFormat>("\"rgba16snorm\"").unwrap(),
4136 TextureFormat::Rgba16Snorm
4137 );
4138 assert_eq!(
4139 serde_json::from_str::<TextureFormat>("\"rgba16float\"").unwrap(),
4140 TextureFormat::Rgba16Float
4141 );
4142 assert_eq!(
4143 serde_json::from_str::<TextureFormat>("\"rgba32uint\"").unwrap(),
4144 TextureFormat::Rgba32Uint
4145 );
4146 assert_eq!(
4147 serde_json::from_str::<TextureFormat>("\"rgba32sint\"").unwrap(),
4148 TextureFormat::Rgba32Sint
4149 );
4150 assert_eq!(
4151 serde_json::from_str::<TextureFormat>("\"rgba32float\"").unwrap(),
4152 TextureFormat::Rgba32Float
4153 );
4154 assert_eq!(
4155 serde_json::from_str::<TextureFormat>("\"stencil8\"").unwrap(),
4156 TextureFormat::Stencil8
4157 );
4158 assert_eq!(
4159 serde_json::from_str::<TextureFormat>("\"depth32float\"").unwrap(),
4160 TextureFormat::Depth32Float
4161 );
4162 assert_eq!(
4163 serde_json::from_str::<TextureFormat>("\"depth16unorm\"").unwrap(),
4164 TextureFormat::Depth16Unorm
4165 );
4166 assert_eq!(
4167 serde_json::from_str::<TextureFormat>("\"depth32float-stencil8\"").unwrap(),
4168 TextureFormat::Depth32FloatStencil8
4169 );
4170 assert_eq!(
4171 serde_json::from_str::<TextureFormat>("\"depth24plus\"").unwrap(),
4172 TextureFormat::Depth24Plus
4173 );
4174 assert_eq!(
4175 serde_json::from_str::<TextureFormat>("\"depth24plus-stencil8\"").unwrap(),
4176 TextureFormat::Depth24PlusStencil8
4177 );
4178 assert_eq!(
4179 serde_json::from_str::<TextureFormat>("\"rgb9e5ufloat\"").unwrap(),
4180 TextureFormat::Rgb9e5Ufloat
4181 );
4182 assert_eq!(
4183 serde_json::from_str::<TextureFormat>("\"bc1-rgba-unorm\"").unwrap(),
4184 TextureFormat::Bc1RgbaUnorm
4185 );
4186 assert_eq!(
4187 serde_json::from_str::<TextureFormat>("\"bc1-rgba-unorm-srgb\"").unwrap(),
4188 TextureFormat::Bc1RgbaUnormSrgb
4189 );
4190 assert_eq!(
4191 serde_json::from_str::<TextureFormat>("\"bc2-rgba-unorm\"").unwrap(),
4192 TextureFormat::Bc2RgbaUnorm
4193 );
4194 assert_eq!(
4195 serde_json::from_str::<TextureFormat>("\"bc2-rgba-unorm-srgb\"").unwrap(),
4196 TextureFormat::Bc2RgbaUnormSrgb
4197 );
4198 assert_eq!(
4199 serde_json::from_str::<TextureFormat>("\"bc3-rgba-unorm\"").unwrap(),
4200 TextureFormat::Bc3RgbaUnorm
4201 );
4202 assert_eq!(
4203 serde_json::from_str::<TextureFormat>("\"bc3-rgba-unorm-srgb\"").unwrap(),
4204 TextureFormat::Bc3RgbaUnormSrgb
4205 );
4206 assert_eq!(
4207 serde_json::from_str::<TextureFormat>("\"bc4-r-unorm\"").unwrap(),
4208 TextureFormat::Bc4RUnorm
4209 );
4210 assert_eq!(
4211 serde_json::from_str::<TextureFormat>("\"bc4-r-snorm\"").unwrap(),
4212 TextureFormat::Bc4RSnorm
4213 );
4214 assert_eq!(
4215 serde_json::from_str::<TextureFormat>("\"bc5-rg-unorm\"").unwrap(),
4216 TextureFormat::Bc5RgUnorm
4217 );
4218 assert_eq!(
4219 serde_json::from_str::<TextureFormat>("\"bc5-rg-snorm\"").unwrap(),
4220 TextureFormat::Bc5RgSnorm
4221 );
4222 assert_eq!(
4223 serde_json::from_str::<TextureFormat>("\"bc6h-rgb-ufloat\"").unwrap(),
4224 TextureFormat::Bc6hRgbUfloat
4225 );
4226 assert_eq!(
4227 serde_json::from_str::<TextureFormat>("\"bc6h-rgb-float\"").unwrap(),
4228 TextureFormat::Bc6hRgbFloat
4229 );
4230 assert_eq!(
4231 serde_json::from_str::<TextureFormat>("\"bc7-rgba-unorm\"").unwrap(),
4232 TextureFormat::Bc7RgbaUnorm
4233 );
4234 assert_eq!(
4235 serde_json::from_str::<TextureFormat>("\"bc7-rgba-unorm-srgb\"").unwrap(),
4236 TextureFormat::Bc7RgbaUnormSrgb
4237 );
4238 assert_eq!(
4239 serde_json::from_str::<TextureFormat>("\"etc2-rgb8unorm\"").unwrap(),
4240 TextureFormat::Etc2Rgb8Unorm
4241 );
4242 assert_eq!(
4243 serde_json::from_str::<TextureFormat>("\"etc2-rgb8unorm-srgb\"").unwrap(),
4244 TextureFormat::Etc2Rgb8UnormSrgb
4245 );
4246 assert_eq!(
4247 serde_json::from_str::<TextureFormat>("\"etc2-rgb8a1unorm\"").unwrap(),
4248 TextureFormat::Etc2Rgb8A1Unorm
4249 );
4250 assert_eq!(
4251 serde_json::from_str::<TextureFormat>("\"etc2-rgb8a1unorm-srgb\"").unwrap(),
4252 TextureFormat::Etc2Rgb8A1UnormSrgb
4253 );
4254 assert_eq!(
4255 serde_json::from_str::<TextureFormat>("\"etc2-rgba8unorm\"").unwrap(),
4256 TextureFormat::Etc2Rgba8Unorm
4257 );
4258 assert_eq!(
4259 serde_json::from_str::<TextureFormat>("\"etc2-rgba8unorm-srgb\"").unwrap(),
4260 TextureFormat::Etc2Rgba8UnormSrgb
4261 );
4262 assert_eq!(
4263 serde_json::from_str::<TextureFormat>("\"eac-r11unorm\"").unwrap(),
4264 TextureFormat::EacR11Unorm
4265 );
4266 assert_eq!(
4267 serde_json::from_str::<TextureFormat>("\"eac-r11snorm\"").unwrap(),
4268 TextureFormat::EacR11Snorm
4269 );
4270 assert_eq!(
4271 serde_json::from_str::<TextureFormat>("\"eac-rg11unorm\"").unwrap(),
4272 TextureFormat::EacRg11Unorm
4273 );
4274 assert_eq!(
4275 serde_json::from_str::<TextureFormat>("\"eac-rg11snorm\"").unwrap(),
4276 TextureFormat::EacRg11Snorm
4277 );
4278}
4279
4280/// Color write mask. Disabled color channels will not be written to.
4281///
4282/// Corresponds to [WebGPU `GPUColorWriteFlags`](
4283/// https://gpuweb.github.io/gpuweb/#typedefdef-gpucolorwriteflags).
4284#[repr(transparent)]
4285#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4286#[cfg_attr(feature = "serde", serde(transparent))]
4287#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
4288pub struct ColorWrites(u32);
4289
4290bitflags::bitflags! {
4291 impl ColorWrites: u32 {
4292 /// Enable red channel writes
4293 const RED = 1 << 0;
4294 /// Enable green channel writes
4295 const GREEN = 1 << 1;
4296 /// Enable blue channel writes
4297 const BLUE = 1 << 2;
4298 /// Enable alpha channel writes
4299 const ALPHA = 1 << 3;
4300 /// Enable red, green, and blue channel writes
4301 const COLOR = Self::RED.bits() | Self::GREEN.bits() | Self::BLUE.bits();
4302 /// Enable writes to all channels.
4303 const ALL = Self::RED.bits() | Self::GREEN.bits() | Self::BLUE.bits() | Self::ALPHA.bits();
4304 }
4305}
4306
4307impl Default for ColorWrites {
4308 fn default() -> Self {
4309 Self::ALL
4310 }
4311}
4312
4313/// Passed to `Device::poll` to control how and if it should block.
4314#[derive(Clone, Debug)]
4315pub enum PollType<T> {
4316 /// On wgpu-core based backends, block until the given submission has
4317 /// completed execution, and any callbacks have been invoked.
4318 ///
4319 /// On WebGPU, this has no effect. Callbacks are invoked from the
4320 /// window event loop.
4321 WaitForSubmissionIndex(T),
4322 /// Same as `WaitForSubmissionIndex` but waits for the most recent submission.
4323 Wait,
4324 /// Check the device for a single time without blocking.
4325 Poll,
4326}
4327
4328impl<T> PollType<T> {
4329 /// Construct a [`Self::Wait`] variant
4330 #[must_use]
4331 pub fn wait() -> Self {
4332 // This function seems a little silly, but it is useful to allow
4333 // <https://github.com/gfx-rs/wgpu/pull/5012> to be split up, as
4334 // it has meaning in that PR.
4335 Self::Wait
4336 }
4337
4338 /// Construct a [`Self::WaitForSubmissionIndex`] variant
4339 #[must_use]
4340 pub fn wait_for(submission_index: T) -> Self {
4341 // This function seems a little silly, but it is useful to allow
4342 // <https://github.com/gfx-rs/wgpu/pull/5012> to be split up, as
4343 // it has meaning in that PR.
4344 Self::WaitForSubmissionIndex(submission_index)
4345 }
4346
4347 /// This `PollType` represents a wait of some kind.
4348 #[must_use]
4349 pub fn is_wait(&self) -> bool {
4350 match *self {
4351 Self::WaitForSubmissionIndex(..) | Self::Wait => true,
4352 Self::Poll => false,
4353 }
4354 }
4355
4356 /// Map on the wait index type.
4357 #[must_use]
4358 pub fn map_index<U, F>(self, func: F) -> PollType<U>
4359 where
4360 F: FnOnce(T) -> U,
4361 {
4362 match self {
4363 Self::WaitForSubmissionIndex(i) => PollType::WaitForSubmissionIndex(func(i)),
4364 Self::Wait => PollType::Wait,
4365 Self::Poll => PollType::Poll,
4366 }
4367 }
4368}
4369
4370/// Error states after a device poll
4371#[derive(Debug)]
4372#[cfg_attr(feature = "std", derive(thiserror::Error))]
4373pub enum PollError {
4374 /// The requested Wait timed out before the submission was completed.
4375 #[cfg_attr(
4376 feature = "std",
4377 error("The requested Wait timed out before the submission was completed.")
4378 )]
4379 Timeout,
4380}
4381
4382/// Status of device poll operation.
4383#[derive(Debug, PartialEq, Eq)]
4384pub enum PollStatus {
4385 /// There are no active submissions in flight as of the beginning of the poll call.
4386 /// Other submissions may have been queued on other threads during the call.
4387 ///
4388 /// This implies that the given Wait was satisfied before the timeout.
4389 QueueEmpty,
4390
4391 /// The requested Wait was satisfied before the timeout.
4392 WaitSucceeded,
4393
4394 /// This was a poll.
4395 Poll,
4396}
4397
4398impl PollStatus {
4399 /// Returns true if the result is [`Self::QueueEmpty`].
4400 #[must_use]
4401 pub fn is_queue_empty(&self) -> bool {
4402 matches!(self, Self::QueueEmpty)
4403 }
4404
4405 /// Returns true if the result is either [`Self::WaitSucceeded`] or [`Self::QueueEmpty`].
4406 #[must_use]
4407 pub fn wait_finished(&self) -> bool {
4408 matches!(self, Self::WaitSucceeded | Self::QueueEmpty)
4409 }
4410}
4411
4412/// State of the stencil operation (fixed-pipeline stage).
4413///
4414/// For use in [`DepthStencilState`].
4415///
4416/// Corresponds to a portion of [WebGPU `GPUDepthStencilState`](
4417/// https://gpuweb.github.io/gpuweb/#dictdef-gpudepthstencilstate).
4418#[repr(C)]
4419#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
4420#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4421pub struct StencilState {
4422 /// Front face mode.
4423 pub front: StencilFaceState,
4424 /// Back face mode.
4425 pub back: StencilFaceState,
4426 /// Stencil values are AND'd with this mask when reading and writing from the stencil buffer. Only low 8 bits are used.
4427 pub read_mask: u32,
4428 /// Stencil values are AND'd with this mask when writing to the stencil buffer. Only low 8 bits are used.
4429 pub write_mask: u32,
4430}
4431
4432impl StencilState {
4433 /// Returns true if the stencil test is enabled.
4434 #[must_use]
4435 pub fn is_enabled(&self) -> bool {
4436 (self.front != StencilFaceState::IGNORE || self.back != StencilFaceState::IGNORE)
4437 && (self.read_mask != 0 || self.write_mask != 0)
4438 }
4439 /// Returns true if the state doesn't mutate the target values.
4440 #[must_use]
4441 pub fn is_read_only(&self, cull_mode: Option<Face>) -> bool {
4442 // The rules are defined in step 7 of the "Device timeline initialization steps"
4443 // subsection of the "Render Pipeline Creation" section of WebGPU
4444 // (link to the section: https://gpuweb.github.io/gpuweb/#render-pipeline-creation)
4445
4446 if self.write_mask == 0 {
4447 return true;
4448 }
4449
4450 let front_ro = cull_mode == Some(Face::Front) || self.front.is_read_only();
4451 let back_ro = cull_mode == Some(Face::Back) || self.back.is_read_only();
4452
4453 front_ro && back_ro
4454 }
4455 /// Returns true if the stencil state uses the reference value for testing.
4456 #[must_use]
4457 pub fn needs_ref_value(&self) -> bool {
4458 self.front.needs_ref_value() || self.back.needs_ref_value()
4459 }
4460}
4461
4462/// Describes the biasing setting for the depth target.
4463///
4464/// For use in [`DepthStencilState`].
4465///
4466/// Corresponds to a portion of [WebGPU `GPUDepthStencilState`](
4467/// https://gpuweb.github.io/gpuweb/#dictdef-gpudepthstencilstate).
4468#[repr(C)]
4469#[derive(Clone, Copy, Debug, Default)]
4470#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4471pub struct DepthBiasState {
4472 /// Constant depth biasing factor, in basic units of the depth format.
4473 pub constant: i32,
4474 /// Slope depth biasing factor.
4475 pub slope_scale: f32,
4476 /// Depth bias clamp value (absolute).
4477 pub clamp: f32,
4478}
4479
4480impl DepthBiasState {
4481 /// Returns true if the depth biasing is enabled.
4482 #[must_use]
4483 pub fn is_enabled(&self) -> bool {
4484 self.constant != 0 || self.slope_scale != 0.0
4485 }
4486}
4487
4488impl Hash for DepthBiasState {
4489 fn hash<H: Hasher>(&self, state: &mut H) {
4490 self.constant.hash(state);
4491 self.slope_scale.to_bits().hash(state);
4492 self.clamp.to_bits().hash(state);
4493 }
4494}
4495
4496impl PartialEq for DepthBiasState {
4497 fn eq(&self, other: &Self) -> bool {
4498 (self.constant == other.constant)
4499 && (self.slope_scale.to_bits() == other.slope_scale.to_bits())
4500 && (self.clamp.to_bits() == other.clamp.to_bits())
4501 }
4502}
4503
4504impl Eq for DepthBiasState {}
4505
4506/// Operation to perform to the output attachment at the start of a render pass.
4507///
4508/// Corresponds to [WebGPU `GPULoadOp`](https://gpuweb.github.io/gpuweb/#enumdef-gpuloadop),
4509/// plus the corresponding clearValue.
4510#[repr(u8)]
4511#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
4512#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4513#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
4514pub enum LoadOp<V> {
4515 /// Loads the specified value for this attachment into the render pass.
4516 ///
4517 /// On some GPU hardware (primarily mobile), "clear" is significantly cheaper
4518 /// because it avoids loading data from main memory into tile-local memory.
4519 ///
4520 /// On other GPU hardware, there isn’t a significant difference.
4521 ///
4522 /// As a result, it is recommended to use "clear" rather than "load" in cases
4523 /// where the initial value doesn’t matter
4524 /// (e.g. the render target will be cleared using a skybox).
4525 Clear(V) = 0,
4526 /// Loads the existing value for this attachment into the render pass.
4527 Load = 1,
4528}
4529
4530impl<V> LoadOp<V> {
4531 /// Returns true if variants are same (ignoring clear value)
4532 pub fn eq_variant<T>(&self, other: LoadOp<T>) -> bool {
4533 matches!(
4534 (self, other),
4535 (LoadOp::Clear(_), LoadOp::Clear(_)) | (LoadOp::Load, LoadOp::Load)
4536 )
4537 }
4538}
4539
4540impl<V: Default> Default for LoadOp<V> {
4541 fn default() -> Self {
4542 Self::Clear(Default::default())
4543 }
4544}
4545
4546/// Operation to perform to the output attachment at the end of a render pass.
4547///
4548/// Corresponds to [WebGPU `GPUStoreOp`](https://gpuweb.github.io/gpuweb/#enumdef-gpustoreop).
4549#[repr(C)]
4550#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Default)]
4551#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4552#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
4553pub enum StoreOp {
4554 /// Stores the resulting value of the render pass for this attachment.
4555 #[default]
4556 Store = 0,
4557 /// Discards the resulting value of the render pass for this attachment.
4558 ///
4559 /// The attachment will be treated as uninitialized afterwards.
4560 /// (If only either Depth or Stencil texture-aspects is set to `Discard`,
4561 /// the respective other texture-aspect will be preserved.)
4562 ///
4563 /// This can be significantly faster on tile-based render hardware.
4564 ///
4565 /// Prefer this if the attachment is not read by subsequent passes.
4566 Discard = 1,
4567}
4568
4569/// Pair of load and store operations for an attachment aspect.
4570///
4571/// This type is unique to the Rust API of `wgpu`. In the WebGPU specification,
4572/// separate `loadOp` and `storeOp` fields are used instead.
4573#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
4574#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4575pub struct Operations<V> {
4576 /// How data should be read through this attachment.
4577 pub load: LoadOp<V>,
4578 /// Whether data will be written to through this attachment.
4579 ///
4580 /// Note that resolve textures (if specified) are always written to,
4581 /// regardless of this setting.
4582 pub store: StoreOp,
4583}
4584
4585impl<V: Default> Default for Operations<V> {
4586 #[inline]
4587 fn default() -> Self {
4588 Self {
4589 load: LoadOp::<V>::default(),
4590 store: StoreOp::default(),
4591 }
4592 }
4593}
4594
4595/// Describes the depth/stencil state in a render pipeline.
4596///
4597/// Corresponds to [WebGPU `GPUDepthStencilState`](
4598/// https://gpuweb.github.io/gpuweb/#dictdef-gpudepthstencilstate).
4599#[repr(C)]
4600#[derive(Clone, Debug, Hash, PartialEq, Eq)]
4601#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4602pub struct DepthStencilState {
4603 /// Format of the depth/stencil buffer, must be special depth format. Must match the format
4604 /// of the depth/stencil attachment in [`CommandEncoder::begin_render_pass`][CEbrp].
4605 ///
4606 /// [CEbrp]: ../wgpu/struct.CommandEncoder.html#method.begin_render_pass
4607 pub format: TextureFormat,
4608 /// If disabled, depth will not be written to.
4609 pub depth_write_enabled: bool,
4610 /// Comparison function used to compare depth values in the depth test.
4611 pub depth_compare: CompareFunction,
4612 /// Stencil state.
4613 #[cfg_attr(feature = "serde", serde(default))]
4614 pub stencil: StencilState,
4615 /// Depth bias state.
4616 #[cfg_attr(feature = "serde", serde(default))]
4617 pub bias: DepthBiasState,
4618}
4619
4620impl DepthStencilState {
4621 /// Returns true if the depth testing is enabled.
4622 #[must_use]
4623 pub fn is_depth_enabled(&self) -> bool {
4624 self.depth_compare != CompareFunction::Always || self.depth_write_enabled
4625 }
4626
4627 /// Returns true if the state doesn't mutate the depth buffer.
4628 #[must_use]
4629 pub fn is_depth_read_only(&self) -> bool {
4630 !self.depth_write_enabled
4631 }
4632
4633 /// Returns true if the state doesn't mutate the stencil.
4634 #[must_use]
4635 pub fn is_stencil_read_only(&self, cull_mode: Option<Face>) -> bool {
4636 self.stencil.is_read_only(cull_mode)
4637 }
4638
4639 /// Returns true if the state doesn't mutate either depth or stencil of the target.
4640 #[must_use]
4641 pub fn is_read_only(&self, cull_mode: Option<Face>) -> bool {
4642 self.is_depth_read_only() && self.is_stencil_read_only(cull_mode)
4643 }
4644}
4645
4646/// Format of indices used with pipeline.
4647///
4648/// Corresponds to [WebGPU `GPUIndexFormat`](
4649/// https://gpuweb.github.io/gpuweb/#enumdef-gpuindexformat).
4650#[repr(C)]
4651#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
4652#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4653#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
4654pub enum IndexFormat {
4655 /// Indices are 16 bit unsigned integers.
4656 Uint16 = 0,
4657 /// Indices are 32 bit unsigned integers.
4658 #[default]
4659 Uint32 = 1,
4660}
4661
4662impl IndexFormat {
4663 /// Returns the size in bytes of the index format
4664 pub fn byte_size(&self) -> usize {
4665 match self {
4666 IndexFormat::Uint16 => 2,
4667 IndexFormat::Uint32 => 4,
4668 }
4669 }
4670}
4671
4672/// Operation to perform on the stencil value.
4673///
4674/// Corresponds to [WebGPU `GPUStencilOperation`](
4675/// https://gpuweb.github.io/gpuweb/#enumdef-gpustenciloperation).
4676#[repr(C)]
4677#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
4678#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4679#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
4680pub enum StencilOperation {
4681 /// Keep stencil value unchanged.
4682 #[default]
4683 Keep = 0,
4684 /// Set stencil value to zero.
4685 Zero = 1,
4686 /// Replace stencil value with value provided in most recent call to
4687 /// [`RenderPass::set_stencil_reference`][RPssr].
4688 ///
4689 /// [RPssr]: ../wgpu/struct.RenderPass.html#method.set_stencil_reference
4690 Replace = 2,
4691 /// Bitwise inverts stencil value.
4692 Invert = 3,
4693 /// Increments stencil value by one, clamping on overflow.
4694 IncrementClamp = 4,
4695 /// Decrements stencil value by one, clamping on underflow.
4696 DecrementClamp = 5,
4697 /// Increments stencil value by one, wrapping on overflow.
4698 IncrementWrap = 6,
4699 /// Decrements stencil value by one, wrapping on underflow.
4700 DecrementWrap = 7,
4701}
4702
4703/// Describes stencil state in a render pipeline.
4704///
4705/// If you are not using stencil state, set this to [`StencilFaceState::IGNORE`].
4706///
4707/// Corresponds to [WebGPU `GPUStencilFaceState`](
4708/// https://gpuweb.github.io/gpuweb/#dictdef-gpustencilfacestate).
4709#[repr(C)]
4710#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4711#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4712#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
4713pub struct StencilFaceState {
4714 /// Comparison function that determines if the fail_op or pass_op is used on the stencil buffer.
4715 pub compare: CompareFunction,
4716 /// Operation that is performed when stencil test fails.
4717 pub fail_op: StencilOperation,
4718 /// Operation that is performed when depth test fails but stencil test succeeds.
4719 pub depth_fail_op: StencilOperation,
4720 /// Operation that is performed when stencil test success.
4721 pub pass_op: StencilOperation,
4722}
4723
4724impl StencilFaceState {
4725 /// Ignore the stencil state for the face.
4726 pub const IGNORE: Self = StencilFaceState {
4727 compare: CompareFunction::Always,
4728 fail_op: StencilOperation::Keep,
4729 depth_fail_op: StencilOperation::Keep,
4730 pass_op: StencilOperation::Keep,
4731 };
4732
4733 /// Returns true if the face state uses the reference value for testing or operation.
4734 #[must_use]
4735 pub fn needs_ref_value(&self) -> bool {
4736 self.compare.needs_ref_value()
4737 || self.fail_op == StencilOperation::Replace
4738 || self.depth_fail_op == StencilOperation::Replace
4739 || self.pass_op == StencilOperation::Replace
4740 }
4741
4742 /// Returns true if the face state doesn't mutate the target values.
4743 #[must_use]
4744 pub fn is_read_only(&self) -> bool {
4745 self.pass_op == StencilOperation::Keep
4746 && self.depth_fail_op == StencilOperation::Keep
4747 && self.fail_op == StencilOperation::Keep
4748 }
4749}
4750
4751impl Default for StencilFaceState {
4752 fn default() -> Self {
4753 Self::IGNORE
4754 }
4755}
4756
4757/// Comparison function used for depth and stencil operations.
4758///
4759/// Corresponds to [WebGPU `GPUCompareFunction`](
4760/// https://gpuweb.github.io/gpuweb/#enumdef-gpucomparefunction).
4761#[repr(C)]
4762#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
4763#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4764#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
4765pub enum CompareFunction {
4766 /// Function never passes
4767 Never = 1,
4768 /// Function passes if new value less than existing value
4769 Less = 2,
4770 /// Function passes if new value is equal to existing value. When using
4771 /// this compare function, make sure to mark your Vertex Shader's `@builtin(position)`
4772 /// output as `@invariant` to prevent artifacting.
4773 Equal = 3,
4774 /// Function passes if new value is less than or equal to existing value
4775 LessEqual = 4,
4776 /// Function passes if new value is greater than existing value
4777 Greater = 5,
4778 /// Function passes if new value is not equal to existing value. When using
4779 /// this compare function, make sure to mark your Vertex Shader's `@builtin(position)`
4780 /// output as `@invariant` to prevent artifacting.
4781 NotEqual = 6,
4782 /// Function passes if new value is greater than or equal to existing value
4783 GreaterEqual = 7,
4784 /// Function always passes
4785 Always = 8,
4786}
4787
4788impl CompareFunction {
4789 /// Returns true if the comparison depends on the reference value.
4790 #[must_use]
4791 pub fn needs_ref_value(self) -> bool {
4792 match self {
4793 Self::Never | Self::Always => false,
4794 _ => true,
4795 }
4796 }
4797}
4798
4799/// Whether a vertex buffer is indexed by vertex or by instance.
4800///
4801/// Consider a call to [`RenderPass::draw`] like this:
4802///
4803/// ```ignore
4804/// render_pass.draw(vertices, instances)
4805/// ```
4806///
4807/// where `vertices` is a `Range<u32>` of vertex indices, and
4808/// `instances` is a `Range<u32>` of instance indices.
4809///
4810/// For this call, `wgpu` invokes the vertex shader entry point once
4811/// for every possible `(v, i)` pair, where `v` is drawn from
4812/// `vertices` and `i` is drawn from `instances`. These invocations
4813/// may happen in any order, and will usually run in parallel.
4814///
4815/// Each vertex buffer has a step mode, established by the
4816/// [`step_mode`] field of its [`VertexBufferLayout`], given when the
4817/// pipeline was created. Buffers whose step mode is [`Vertex`] use
4818/// `v` as the index into their contents, whereas buffers whose step
4819/// mode is [`Instance`] use `i`. The indicated buffer element then
4820/// contributes zero or more attribute values for the `(v, i)` vertex
4821/// shader invocation to use, based on the [`VertexBufferLayout`]'s
4822/// [`attributes`] list.
4823///
4824/// You can visualize the results from all these vertex shader
4825/// invocations as a matrix with a row for each `i` from `instances`,
4826/// and with a column for each `v` from `vertices`. In one sense, `v`
4827/// and `i` are symmetrical: both are used to index vertex buffers and
4828/// provide attribute values. But the key difference between `v` and
4829/// `i` is that line and triangle primitives are built from the values
4830/// of each row, along which `i` is constant and `v` varies, not the
4831/// columns.
4832///
4833/// An indexed draw call works similarly:
4834///
4835/// ```ignore
4836/// render_pass.draw_indexed(indices, base_vertex, instances)
4837/// ```
4838///
4839/// The only difference is that `v` values are drawn from the contents
4840/// of the index buffer—specifically, the subrange of the index
4841/// buffer given by `indices`—instead of simply being sequential
4842/// integers, as they are in a `draw` call.
4843///
4844/// A non-instanced call, where `instances` is `0..1`, is simply a
4845/// matrix with only one row.
4846///
4847/// Corresponds to [WebGPU `GPUVertexStepMode`](
4848/// https://gpuweb.github.io/gpuweb/#enumdef-gpuvertexstepmode).
4849///
4850/// [`RenderPass::draw`]: ../wgpu/struct.RenderPass.html#method.draw
4851/// [`VertexBufferLayout`]: ../wgpu/struct.VertexBufferLayout.html
4852/// [`step_mode`]: ../wgpu/struct.VertexBufferLayout.html#structfield.step_mode
4853/// [`attributes`]: ../wgpu/struct.VertexBufferLayout.html#structfield.attributes
4854/// [`Vertex`]: VertexStepMode::Vertex
4855/// [`Instance`]: VertexStepMode::Instance
4856#[repr(C)]
4857#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
4858#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4859#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
4860pub enum VertexStepMode {
4861 /// Vertex data is advanced every vertex.
4862 #[default]
4863 Vertex = 0,
4864 /// Vertex data is advanced every instance.
4865 Instance = 1,
4866}
4867
4868/// Vertex inputs (attributes) to shaders.
4869///
4870/// These are used to specify the individual attributes within a [`VertexBufferLayout`].
4871/// See its documentation for an example.
4872///
4873/// The [`vertex_attr_array!`] macro can help create these with appropriate offsets.
4874///
4875/// Corresponds to [WebGPU `GPUVertexAttribute`](
4876/// https://gpuweb.github.io/gpuweb/#dictdef-gpuvertexattribute).
4877///
4878/// [`vertex_attr_array!`]: ../wgpu/macro.vertex_attr_array.html
4879/// [`VertexBufferLayout`]: ../wgpu/struct.VertexBufferLayout.html
4880#[repr(C)]
4881#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
4882#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4883#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
4884pub struct VertexAttribute {
4885 /// Format of the input
4886 pub format: VertexFormat,
4887 /// Byte offset of the start of the input
4888 pub offset: BufferAddress,
4889 /// Location for this input. Must match the location in the shader.
4890 pub shader_location: ShaderLocation,
4891}
4892
4893/// Vertex Format for a [`VertexAttribute`] (input).
4894///
4895/// Corresponds to [WebGPU `GPUVertexFormat`](
4896/// https://gpuweb.github.io/gpuweb/#enumdef-gpuvertexformat).
4897#[repr(C)]
4898#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
4899#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4900#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
4901pub enum VertexFormat {
4902 /// One unsigned byte (u8). `u32` in shaders.
4903 Uint8 = 0,
4904 /// Two unsigned bytes (u8). `vec2<u32>` in shaders.
4905 Uint8x2 = 1,
4906 /// Four unsigned bytes (u8). `vec4<u32>` in shaders.
4907 Uint8x4 = 2,
4908 /// One signed byte (i8). `i32` in shaders.
4909 Sint8 = 3,
4910 /// Two signed bytes (i8). `vec2<i32>` in shaders.
4911 Sint8x2 = 4,
4912 /// Four signed bytes (i8). `vec4<i32>` in shaders.
4913 Sint8x4 = 5,
4914 /// One unsigned byte (u8). [0, 255] converted to float [0, 1] `f32` in shaders.
4915 Unorm8 = 6,
4916 /// Two unsigned bytes (u8). [0, 255] converted to float [0, 1] `vec2<f32>` in shaders.
4917 Unorm8x2 = 7,
4918 /// Four unsigned bytes (u8). [0, 255] converted to float [0, 1] `vec4<f32>` in shaders.
4919 Unorm8x4 = 8,
4920 /// One signed byte (i8). [−127, 127] converted to float [−1, 1] `f32` in shaders.
4921 Snorm8 = 9,
4922 /// Two signed bytes (i8). [−127, 127] converted to float [−1, 1] `vec2<f32>` in shaders.
4923 Snorm8x2 = 10,
4924 /// Four signed bytes (i8). [−127, 127] converted to float [−1, 1] `vec4<f32>` in shaders.
4925 Snorm8x4 = 11,
4926 /// One unsigned short (u16). `u32` in shaders.
4927 Uint16 = 12,
4928 /// Two unsigned shorts (u16). `vec2<u32>` in shaders.
4929 Uint16x2 = 13,
4930 /// Four unsigned shorts (u16). `vec4<u32>` in shaders.
4931 Uint16x4 = 14,
4932 /// One signed short (u16). `i32` in shaders.
4933 Sint16 = 15,
4934 /// Two signed shorts (i16). `vec2<i32>` in shaders.
4935 Sint16x2 = 16,
4936 /// Four signed shorts (i16). `vec4<i32>` in shaders.
4937 Sint16x4 = 17,
4938 /// One unsigned short (u16). [0, 65535] converted to float [0, 1] `f32` in shaders.
4939 Unorm16 = 18,
4940 /// Two unsigned shorts (u16). [0, 65535] converted to float [0, 1] `vec2<f32>` in shaders.
4941 Unorm16x2 = 19,
4942 /// Four unsigned shorts (u16). [0, 65535] converted to float [0, 1] `vec4<f32>` in shaders.
4943 Unorm16x4 = 20,
4944 /// One signed short (i16). [−32767, 32767] converted to float [−1, 1] `f32` in shaders.
4945 Snorm16 = 21,
4946 /// Two signed shorts (i16). [−32767, 32767] converted to float [−1, 1] `vec2<f32>` in shaders.
4947 Snorm16x2 = 22,
4948 /// Four signed shorts (i16). [−32767, 32767] converted to float [−1, 1] `vec4<f32>` in shaders.
4949 Snorm16x4 = 23,
4950 /// One half-precision float (no Rust equiv). `f32` in shaders.
4951 Float16 = 24,
4952 /// Two half-precision floats (no Rust equiv). `vec2<f32>` in shaders.
4953 Float16x2 = 25,
4954 /// Four half-precision floats (no Rust equiv). `vec4<f32>` in shaders.
4955 Float16x4 = 26,
4956 /// One single-precision float (f32). `f32` in shaders.
4957 Float32 = 27,
4958 /// Two single-precision floats (f32). `vec2<f32>` in shaders.
4959 Float32x2 = 28,
4960 /// Three single-precision floats (f32). `vec3<f32>` in shaders.
4961 Float32x3 = 29,
4962 /// Four single-precision floats (f32). `vec4<f32>` in shaders.
4963 Float32x4 = 30,
4964 /// One unsigned int (u32). `u32` in shaders.
4965 Uint32 = 31,
4966 /// Two unsigned ints (u32). `vec2<u32>` in shaders.
4967 Uint32x2 = 32,
4968 /// Three unsigned ints (u32). `vec3<u32>` in shaders.
4969 Uint32x3 = 33,
4970 /// Four unsigned ints (u32). `vec4<u32>` in shaders.
4971 Uint32x4 = 34,
4972 /// One signed int (i32). `i32` in shaders.
4973 Sint32 = 35,
4974 /// Two signed ints (i32). `vec2<i32>` in shaders.
4975 Sint32x2 = 36,
4976 /// Three signed ints (i32). `vec3<i32>` in shaders.
4977 Sint32x3 = 37,
4978 /// Four signed ints (i32). `vec4<i32>` in shaders.
4979 Sint32x4 = 38,
4980 /// One double-precision float (f64). `f32` in shaders. Requires [`Features::VERTEX_ATTRIBUTE_64BIT`].
4981 Float64 = 39,
4982 /// Two double-precision floats (f64). `vec2<f32>` in shaders. Requires [`Features::VERTEX_ATTRIBUTE_64BIT`].
4983 Float64x2 = 40,
4984 /// Three double-precision floats (f64). `vec3<f32>` in shaders. Requires [`Features::VERTEX_ATTRIBUTE_64BIT`].
4985 Float64x3 = 41,
4986 /// Four double-precision floats (f64). `vec4<f32>` in shaders. Requires [`Features::VERTEX_ATTRIBUTE_64BIT`].
4987 Float64x4 = 42,
4988 /// Three unsigned 10-bit integers and one 2-bit integer, packed into a 32-bit integer (u32). [0, 1024] converted to float [0, 1] `vec4<f32>` in shaders.
4989 #[cfg_attr(feature = "serde", serde(rename = "unorm10-10-10-2"))]
4990 Unorm10_10_10_2 = 43,
4991 /// Four unsigned 8-bit integers, packed into a 32-bit integer (u32). [0, 255] converted to float [0, 1] `vec4<f32>` in shaders.
4992 #[cfg_attr(feature = "serde", serde(rename = "unorm8x4-bgra"))]
4993 Unorm8x4Bgra = 44,
4994}
4995
4996impl VertexFormat {
4997 /// Returns the byte size of the format.
4998 #[must_use]
4999 pub const fn size(&self) -> u64 {
5000 match self {
5001 Self::Uint8 | Self::Sint8 | Self::Unorm8 | Self::Snorm8 => 1,
5002 Self::Uint8x2
5003 | Self::Sint8x2
5004 | Self::Unorm8x2
5005 | Self::Snorm8x2
5006 | Self::Uint16
5007 | Self::Sint16
5008 | Self::Unorm16
5009 | Self::Snorm16
5010 | Self::Float16 => 2,
5011 Self::Uint8x4
5012 | Self::Sint8x4
5013 | Self::Unorm8x4
5014 | Self::Snorm8x4
5015 | Self::Uint16x2
5016 | Self::Sint16x2
5017 | Self::Unorm16x2
5018 | Self::Snorm16x2
5019 | Self::Float16x2
5020 | Self::Float32
5021 | Self::Uint32
5022 | Self::Sint32
5023 | Self::Unorm10_10_10_2
5024 | Self::Unorm8x4Bgra => 4,
5025 Self::Uint16x4
5026 | Self::Sint16x4
5027 | Self::Unorm16x4
5028 | Self::Snorm16x4
5029 | Self::Float16x4
5030 | Self::Float32x2
5031 | Self::Uint32x2
5032 | Self::Sint32x2
5033 | Self::Float64 => 8,
5034 Self::Float32x3 | Self::Uint32x3 | Self::Sint32x3 => 12,
5035 Self::Float32x4 | Self::Uint32x4 | Self::Sint32x4 | Self::Float64x2 => 16,
5036 Self::Float64x3 => 24,
5037 Self::Float64x4 => 32,
5038 }
5039 }
5040
5041 /// Returns the size read by an acceleration structure build of the vertex format. This is
5042 /// slightly different from [`Self::size`] because the alpha component of 4-component formats
5043 /// are not read in an acceleration structure build, allowing for a smaller stride.
5044 #[must_use]
5045 pub const fn min_acceleration_structure_vertex_stride(&self) -> u64 {
5046 match self {
5047 Self::Float16x2 | Self::Snorm16x2 => 4,
5048 Self::Float32x3 => 12,
5049 Self::Float32x2 => 8,
5050 // This is the minimum value from DirectX
5051 // > A16 component is ignored, other data can be packed there, such as setting vertex stride to 6 bytes
5052 //
5053 // https://microsoft.github.io/DirectX-Specs/d3d/Raytracing.html#d3d12_raytracing_geometry_triangles_desc
5054 //
5055 // Vulkan does not express a minimum stride.
5056 Self::Float16x4 | Self::Snorm16x4 => 6,
5057 _ => unreachable!(),
5058 }
5059 }
5060
5061 /// Returns the alignment required for `wgpu::BlasTriangleGeometry::vertex_stride`
5062 #[must_use]
5063 pub const fn acceleration_structure_stride_alignment(&self) -> u64 {
5064 match self {
5065 Self::Float16x4 | Self::Float16x2 | Self::Snorm16x4 | Self::Snorm16x2 => 2,
5066 Self::Float32x2 | Self::Float32x3 => 4,
5067 _ => unreachable!(),
5068 }
5069 }
5070}
5071
5072bitflags::bitflags! {
5073 /// Different ways that you can use a buffer.
5074 ///
5075 /// The usages determine what kind of memory the buffer is allocated from and what
5076 /// actions the buffer can partake in.
5077 ///
5078 /// Corresponds to [WebGPU `GPUBufferUsageFlags`](
5079 /// https://gpuweb.github.io/gpuweb/#typedefdef-gpubufferusageflags).
5080 #[repr(transparent)]
5081 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5082 #[cfg_attr(feature = "serde", serde(transparent))]
5083 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
5084 pub struct BufferUsages: u32 {
5085 /// Allow a buffer to be mapped for reading using [`Buffer::map_async`] + [`Buffer::get_mapped_range`].
5086 /// This does not include creating a buffer with [`BufferDescriptor::mapped_at_creation`] set.
5087 ///
5088 /// If [`Features::MAPPABLE_PRIMARY_BUFFERS`] isn't enabled, the only other usage a buffer
5089 /// may have is COPY_DST.
5090 const MAP_READ = 1 << 0;
5091 /// Allow a buffer to be mapped for writing using [`Buffer::map_async`] + [`Buffer::get_mapped_range_mut`].
5092 /// This does not include creating a buffer with [`BufferDescriptor::mapped_at_creation`] set.
5093 ///
5094 /// If [`Features::MAPPABLE_PRIMARY_BUFFERS`] feature isn't enabled, the only other usage a buffer
5095 /// may have is COPY_SRC.
5096 const MAP_WRITE = 1 << 1;
5097 /// Allow a buffer to be the source buffer for a [`CommandEncoder::copy_buffer_to_buffer`] or [`CommandEncoder::copy_buffer_to_texture`]
5098 /// operation.
5099 const COPY_SRC = 1 << 2;
5100 /// Allow a buffer to be the destination buffer for a [`CommandEncoder::copy_buffer_to_buffer`], [`CommandEncoder::copy_texture_to_buffer`],
5101 /// [`CommandEncoder::clear_buffer`] or [`Queue::write_buffer`] operation.
5102 const COPY_DST = 1 << 3;
5103 /// Allow a buffer to be the index buffer in a draw operation.
5104 const INDEX = 1 << 4;
5105 /// Allow a buffer to be the vertex buffer in a draw operation.
5106 const VERTEX = 1 << 5;
5107 /// Allow a buffer to be a [`BufferBindingType::Uniform`] inside a bind group.
5108 const UNIFORM = 1 << 6;
5109 /// Allow a buffer to be a [`BufferBindingType::Storage`] inside a bind group.
5110 const STORAGE = 1 << 7;
5111 /// Allow a buffer to be the indirect buffer in an indirect draw call.
5112 const INDIRECT = 1 << 8;
5113 /// Allow a buffer to be the destination buffer for a [`CommandEncoder::resolve_query_set`] operation.
5114 const QUERY_RESOLVE = 1 << 9;
5115 /// Allows a buffer to be used as input for a bottom level acceleration structure build
5116 const BLAS_INPUT = 1 << 10;
5117 /// Allows a buffer to be used as input for a top level acceleration structure build
5118 const TLAS_INPUT = 1 << 11;
5119 }
5120}
5121
5122bitflags::bitflags! {
5123 /// Similar to `BufferUsages`, but used only for `CommandEncoder::transition_resources`.
5124 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
5125 pub struct BufferUses: u16 {
5126 /// The argument to a read-only mapping.
5127 const MAP_READ = 1 << 0;
5128 /// The argument to a write-only mapping.
5129 const MAP_WRITE = 1 << 1;
5130 /// The source of a hardware copy.
5131 /// cbindgen:ignore
5132 const COPY_SRC = 1 << 2;
5133 /// The destination of a hardware copy.
5134 /// cbindgen:ignore
5135 const COPY_DST = 1 << 3;
5136 /// The index buffer used for drawing.
5137 const INDEX = 1 << 4;
5138 /// A vertex buffer used for drawing.
5139 const VERTEX = 1 << 5;
5140 /// A uniform buffer bound in a bind group.
5141 const UNIFORM = 1 << 6;
5142 /// A read-only storage buffer used in a bind group.
5143 /// cbindgen:ignore
5144 const STORAGE_READ_ONLY = 1 << 7;
5145 /// A read-write buffer used in a bind group.
5146 /// cbindgen:ignore
5147 const STORAGE_READ_WRITE = 1 << 8;
5148 /// The indirect or count buffer in a indirect draw or dispatch.
5149 const INDIRECT = 1 << 9;
5150 /// A buffer used to store query results.
5151 const QUERY_RESOLVE = 1 << 10;
5152 /// Buffer used for acceleration structure building.
5153 const ACCELERATION_STRUCTURE_SCRATCH = 1 << 11;
5154 /// Buffer used for bottom level acceleration structure building.
5155 const BOTTOM_LEVEL_ACCELERATION_STRUCTURE_INPUT = 1 << 12;
5156 /// Buffer used for top level acceleration structure building.
5157 const TOP_LEVEL_ACCELERATION_STRUCTURE_INPUT = 1 << 13;
5158 /// A buffer used to store the compacted size of an acceleration structure
5159 const ACCELERATION_STRUCTURE_QUERY = 1 << 14;
5160 /// The combination of states that a buffer may be in _at the same time_.
5161 const INCLUSIVE = Self::MAP_READ.bits() | Self::COPY_SRC.bits() |
5162 Self::INDEX.bits() | Self::VERTEX.bits() | Self::UNIFORM.bits() |
5163 Self::STORAGE_READ_ONLY.bits() | Self::INDIRECT.bits() | Self::BOTTOM_LEVEL_ACCELERATION_STRUCTURE_INPUT.bits() | Self::TOP_LEVEL_ACCELERATION_STRUCTURE_INPUT.bits();
5164 /// The combination of states that a buffer must exclusively be in.
5165 const EXCLUSIVE = Self::MAP_WRITE.bits() | Self::COPY_DST.bits() | Self::STORAGE_READ_WRITE.bits() | Self::ACCELERATION_STRUCTURE_SCRATCH.bits();
5166 /// The combination of all usages that the are guaranteed to be be ordered by the hardware.
5167 /// If a usage is ordered, then if the buffer state doesn't change between draw calls, there
5168 /// are no barriers needed for synchronization.
5169 const ORDERED = Self::INCLUSIVE.bits() | Self::MAP_WRITE.bits();
5170 }
5171}
5172
5173/// A buffer transition for use with `CommandEncoder::transition_resources`.
5174#[derive(Debug)]
5175pub struct BufferTransition<T> {
5176 /// The buffer to transition.
5177 pub buffer: T,
5178 /// The new state to transition to.
5179 pub state: BufferUses,
5180}
5181
5182/// Describes a [`Buffer`](../wgpu/struct.Buffer.html).
5183///
5184/// Corresponds to [WebGPU `GPUBufferDescriptor`](
5185/// https://gpuweb.github.io/gpuweb/#dictdef-gpubufferdescriptor).
5186#[repr(C)]
5187#[derive(Clone, Debug, PartialEq, Eq, Hash)]
5188#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5189pub struct BufferDescriptor<L> {
5190 /// Debug label of a buffer. This will show up in graphics debuggers for easy identification.
5191 pub label: L,
5192 /// Size of a buffer, in bytes.
5193 pub size: BufferAddress,
5194 /// Usages of a buffer. If the buffer is used in any way that isn't specified here, the operation
5195 /// will panic.
5196 pub usage: BufferUsages,
5197 /// Allows a buffer to be mapped immediately after they are made. It does not have to be [`BufferUsages::MAP_READ`] or
5198 /// [`BufferUsages::MAP_WRITE`], all buffers are allowed to be mapped at creation.
5199 ///
5200 /// If this is `true`, [`size`](#structfield.size) must be a multiple of
5201 /// [`COPY_BUFFER_ALIGNMENT`].
5202 pub mapped_at_creation: bool,
5203}
5204
5205impl<L> BufferDescriptor<L> {
5206 /// Takes a closure and maps the label of the buffer descriptor into another.
5207 #[must_use]
5208 pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> BufferDescriptor<K> {
5209 BufferDescriptor {
5210 label: fun(&self.label),
5211 size: self.size,
5212 usage: self.usage,
5213 mapped_at_creation: self.mapped_at_creation,
5214 }
5215 }
5216}
5217
5218/// Describes a [`CommandEncoder`](../wgpu/struct.CommandEncoder.html).
5219///
5220/// Corresponds to [WebGPU `GPUCommandEncoderDescriptor`](
5221/// https://gpuweb.github.io/gpuweb/#dictdef-gpucommandencoderdescriptor).
5222#[repr(C)]
5223#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5224#[derive(Clone, Debug, PartialEq, Eq, Hash)]
5225pub struct CommandEncoderDescriptor<L> {
5226 /// Debug label for the command encoder. This will show up in graphics debuggers for easy identification.
5227 pub label: L,
5228}
5229
5230impl<L> CommandEncoderDescriptor<L> {
5231 /// Takes a closure and maps the label of the command encoder descriptor into another.
5232 #[must_use]
5233 pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> CommandEncoderDescriptor<K> {
5234 CommandEncoderDescriptor {
5235 label: fun(&self.label),
5236 }
5237 }
5238}
5239
5240impl<T> Default for CommandEncoderDescriptor<Option<T>> {
5241 fn default() -> Self {
5242 Self { label: None }
5243 }
5244}
5245
5246/// Timing and queueing with which frames are actually displayed to the user.
5247///
5248/// Use this as part of a [`SurfaceConfiguration`] to control the behavior of
5249/// [`SurfaceTexture::present()`].
5250///
5251/// Some modes are only supported by some backends.
5252/// You can use one of the `Auto*` modes, [`Fifo`](Self::Fifo),
5253/// or choose one of the supported modes from [`SurfaceCapabilities::present_modes`].
5254///
5255/// [presented]: ../wgpu/struct.SurfaceTexture.html#method.present
5256/// [`SurfaceTexture::present()`]: ../wgpu/struct.SurfaceTexture.html#method.present
5257#[repr(C)]
5258#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
5259#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5260pub enum PresentMode {
5261 /// Chooses the first supported mode out of:
5262 ///
5263 /// 1. [`FifoRelaxed`](Self::FifoRelaxed)
5264 /// 2. [`Fifo`](Self::Fifo)
5265 ///
5266 /// Because of the fallback behavior, this is supported everywhere.
5267 AutoVsync = 0,
5268
5269 /// Chooses the first supported mode out of:
5270 ///
5271 /// 1. [`Immediate`](Self::Immediate)
5272 /// 2. [`Mailbox`](Self::Mailbox)
5273 /// 3. [`Fifo`](Self::Fifo)
5274 ///
5275 /// Because of the fallback behavior, this is supported everywhere.
5276 AutoNoVsync = 1,
5277
5278 /// Presentation frames are kept in a First-In-First-Out queue approximately 3 frames
5279 /// long. Every vertical blanking period, the presentation engine will pop a frame
5280 /// off the queue to display. If there is no frame to display, it will present the same
5281 /// frame again until the next vblank.
5282 ///
5283 /// When a present command is executed on the GPU, the presented image is added on the queue.
5284 ///
5285 /// Calls to [`Surface::get_current_texture()`] will block until there is a spot in the queue.
5286 ///
5287 /// * **Tearing:** No tearing will be observed.
5288 /// * **Supported on**: All platforms.
5289 /// * **Also known as**: "Vsync On"
5290 ///
5291 /// This is the [default](Self::default) value for `PresentMode`.
5292 /// If you don't know what mode to choose, choose this mode.
5293 ///
5294 /// [`Surface::get_current_texture()`]: ../wgpu/struct.Surface.html#method.get_current_texture
5295 #[default]
5296 Fifo = 2,
5297
5298 /// Presentation frames are kept in a First-In-First-Out queue approximately 3 frames
5299 /// long. Every vertical blanking period, the presentation engine will pop a frame
5300 /// off the queue to display. If there is no frame to display, it will present the
5301 /// same frame until there is a frame in the queue. The moment there is a frame in the
5302 /// queue, it will immediately pop the frame off the queue.
5303 ///
5304 /// When a present command is executed on the GPU, the presented image is added on the queue.
5305 ///
5306 /// Calls to [`Surface::get_current_texture()`] will block until there is a spot in the queue.
5307 ///
5308 /// * **Tearing**:
5309 /// Tearing will be observed if frames last more than one vblank as the front buffer.
5310 /// * **Supported on**: AMD on Vulkan.
5311 /// * **Also known as**: "Adaptive Vsync"
5312 ///
5313 /// [`Surface::get_current_texture()`]: ../wgpu/struct.Surface.html#method.get_current_texture
5314 FifoRelaxed = 3,
5315
5316 /// Presentation frames are not queued at all. The moment a present command
5317 /// is executed on the GPU, the presented image is swapped onto the front buffer
5318 /// immediately.
5319 ///
5320 /// * **Tearing**: Tearing can be observed.
5321 /// * **Supported on**: Most platforms except older DX12 and Wayland.
5322 /// * **Also known as**: "Vsync Off"
5323 Immediate = 4,
5324
5325 /// Presentation frames are kept in a single-frame queue. Every vertical blanking period,
5326 /// the presentation engine will pop a frame from the queue. If there is no frame to display,
5327 /// it will present the same frame again until the next vblank.
5328 ///
5329 /// When a present command is executed on the GPU, the frame will be put into the queue.
5330 /// If there was already a frame in the queue, the new frame will _replace_ the old frame
5331 /// on the queue.
5332 ///
5333 /// * **Tearing**: No tearing will be observed.
5334 /// * **Supported on**: DX12 on Windows 10, NVidia on Vulkan and Wayland on Vulkan.
5335 /// * **Also known as**: "Fast Vsync"
5336 Mailbox = 5,
5337}
5338
5339/// Specifies how the alpha channel of the textures should be handled during
5340/// compositing.
5341#[repr(C)]
5342#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5343#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5344#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
5345pub enum CompositeAlphaMode {
5346 /// Chooses either `Opaque` or `Inherit` automatically,depending on the
5347 /// `alpha_mode` that the current surface can support.
5348 Auto = 0,
5349 /// The alpha channel, if it exists, of the textures is ignored in the
5350 /// compositing process. Instead, the textures is treated as if it has a
5351 /// constant alpha of 1.0.
5352 Opaque = 1,
5353 /// The alpha channel, if it exists, of the textures is respected in the
5354 /// compositing process. The non-alpha channels of the textures are
5355 /// expected to already be multiplied by the alpha channel by the
5356 /// application.
5357 PreMultiplied = 2,
5358 /// The alpha channel, if it exists, of the textures is respected in the
5359 /// compositing process. The non-alpha channels of the textures are not
5360 /// expected to already be multiplied by the alpha channel by the
5361 /// application; instead, the compositor will multiply the non-alpha
5362 /// channels of the texture by the alpha channel during compositing.
5363 PostMultiplied = 3,
5364 /// The alpha channel, if it exists, of the textures is unknown for processing
5365 /// during compositing. Instead, the application is responsible for setting
5366 /// the composite alpha blending mode using native WSI command. If not set,
5367 /// then a platform-specific default will be used.
5368 Inherit = 4,
5369}
5370
5371impl Default for CompositeAlphaMode {
5372 fn default() -> Self {
5373 Self::Auto
5374 }
5375}
5376
5377bitflags::bitflags! {
5378 /// Different ways that you can use a texture.
5379 ///
5380 /// The usages determine what kind of memory the texture is allocated from and what
5381 /// actions the texture can partake in.
5382 ///
5383 /// Corresponds to [WebGPU `GPUTextureUsageFlags`](
5384 /// https://gpuweb.github.io/gpuweb/#typedefdef-gputextureusageflags).
5385 #[repr(transparent)]
5386 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5387 #[cfg_attr(feature = "serde", serde(transparent))]
5388 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
5389 pub struct TextureUsages: u32 {
5390 //
5391 // ---- Start numbering at 1 << 0 ----
5392 //
5393 // WebGPU features:
5394 //
5395 /// Allows a texture to be the source in a [`CommandEncoder::copy_texture_to_buffer`] or
5396 /// [`CommandEncoder::copy_texture_to_texture`] operation.
5397 const COPY_SRC = 1 << 0;
5398 /// Allows a texture to be the destination in a [`CommandEncoder::copy_buffer_to_texture`],
5399 /// [`CommandEncoder::copy_texture_to_texture`], or [`Queue::write_texture`] operation.
5400 const COPY_DST = 1 << 1;
5401 /// Allows a texture to be a [`BindingType::Texture`] in a bind group.
5402 const TEXTURE_BINDING = 1 << 2;
5403 /// Allows a texture to be a [`BindingType::StorageTexture`] in a bind group.
5404 const STORAGE_BINDING = 1 << 3;
5405 /// Allows a texture to be an output attachment of a render pass.
5406 const RENDER_ATTACHMENT = 1 << 4;
5407
5408 //
5409 // ---- Restart Numbering for Native Features ---
5410 //
5411 // Native Features:
5412 //
5413 /// Allows a texture to be used with image atomics. Requires [`Features::TEXTURE_ATOMIC`].
5414 const STORAGE_ATOMIC = 1 << 16;
5415 }
5416}
5417
5418bitflags::bitflags! {
5419 /// Similar to `TextureUsages`, but used only for `CommandEncoder::transition_resources`.
5420 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
5421 pub struct TextureUses: u16 {
5422 /// The texture is in unknown state.
5423 const UNINITIALIZED = 1 << 0;
5424 /// Ready to present image to the surface.
5425 const PRESENT = 1 << 1;
5426 /// The source of a hardware copy.
5427 /// cbindgen:ignore
5428 const COPY_SRC = 1 << 2;
5429 /// The destination of a hardware copy.
5430 /// cbindgen:ignore
5431 const COPY_DST = 1 << 3;
5432 /// Read-only sampled or fetched resource.
5433 const RESOURCE = 1 << 4;
5434 /// The color target of a renderpass.
5435 const COLOR_TARGET = 1 << 5;
5436 /// Read-only depth stencil usage.
5437 const DEPTH_STENCIL_READ = 1 << 6;
5438 /// Read-write depth stencil usage
5439 const DEPTH_STENCIL_WRITE = 1 << 7;
5440 /// Read-only storage texture usage. Corresponds to a UAV in d3d, so is exclusive, despite being read only.
5441 /// cbindgen:ignore
5442 const STORAGE_READ_ONLY = 1 << 8;
5443 /// Write-only storage texture usage.
5444 /// cbindgen:ignore
5445 const STORAGE_WRITE_ONLY = 1 << 9;
5446 /// Read-write storage texture usage.
5447 /// cbindgen:ignore
5448 const STORAGE_READ_WRITE = 1 << 10;
5449 /// Image atomic enabled storage.
5450 /// cbindgen:ignore
5451 const STORAGE_ATOMIC = 1 << 11;
5452 /// The combination of states that a texture may be in _at the same time_.
5453 /// cbindgen:ignore
5454 const INCLUSIVE = Self::COPY_SRC.bits() | Self::RESOURCE.bits() | Self::DEPTH_STENCIL_READ.bits();
5455 /// The combination of states that a texture must exclusively be in.
5456 /// cbindgen:ignore
5457 const EXCLUSIVE = Self::COPY_DST.bits() | Self::COLOR_TARGET.bits() | Self::DEPTH_STENCIL_WRITE.bits() | Self::STORAGE_READ_ONLY.bits() | Self::STORAGE_WRITE_ONLY.bits() | Self::STORAGE_READ_WRITE.bits() | Self::STORAGE_ATOMIC.bits() | Self::PRESENT.bits();
5458 /// The combination of all usages that the are guaranteed to be be ordered by the hardware.
5459 /// If a usage is ordered, then if the texture state doesn't change between draw calls, there
5460 /// are no barriers needed for synchronization.
5461 /// cbindgen:ignore
5462 const ORDERED = Self::INCLUSIVE.bits() | Self::COLOR_TARGET.bits() | Self::DEPTH_STENCIL_WRITE.bits() | Self::STORAGE_READ_ONLY.bits();
5463
5464 /// Flag used by the wgpu-core texture tracker to say a texture is in different states for every sub-resource
5465 const COMPLEX = 1 << 12;
5466 /// Flag used by the wgpu-core texture tracker to say that the tracker does not know the state of the sub-resource.
5467 /// This is different from UNINITIALIZED as that says the tracker does know, but the texture has not been initialized.
5468 const UNKNOWN = 1 << 13;
5469 }
5470}
5471
5472/// A texture transition for use with `CommandEncoder::transition_resources`.
5473#[derive(Debug)]
5474pub struct TextureTransition<T> {
5475 /// The texture to transition.
5476 pub texture: T,
5477 /// An optional selector to transition only part of the texture.
5478 ///
5479 /// If None, the entire texture will be transitioned.
5480 pub selector: Option<TextureSelector>,
5481 /// The new state to transition to.
5482 pub state: TextureUses,
5483}
5484
5485/// Specifies a particular set of subresources in a texture.
5486#[derive(Clone, Debug, PartialEq, Eq)]
5487pub struct TextureSelector {
5488 /// Range of mips to use.
5489 pub mips: Range<u32>,
5490 /// Range of layers to use.
5491 pub layers: Range<u32>,
5492}
5493
5494/// Defines the capabilities of a given surface and adapter.
5495#[derive(Debug)]
5496pub struct SurfaceCapabilities {
5497 /// List of supported formats to use with the given adapter. The first format in the vector is preferred.
5498 ///
5499 /// Returns an empty vector if the surface is incompatible with the adapter.
5500 pub formats: Vec<TextureFormat>,
5501 /// List of supported presentation modes to use with the given adapter.
5502 ///
5503 /// Returns an empty vector if the surface is incompatible with the adapter.
5504 pub present_modes: Vec<PresentMode>,
5505 /// List of supported alpha modes to use with the given adapter.
5506 ///
5507 /// Will return at least one element, [`CompositeAlphaMode::Opaque`] or [`CompositeAlphaMode::Inherit`].
5508 pub alpha_modes: Vec<CompositeAlphaMode>,
5509 /// Bitflag of supported texture usages for the surface to use with the given adapter.
5510 ///
5511 /// The usage [`TextureUsages::RENDER_ATTACHMENT`] is guaranteed.
5512 pub usages: TextureUsages,
5513}
5514
5515impl Default for SurfaceCapabilities {
5516 fn default() -> Self {
5517 Self {
5518 formats: Vec::new(),
5519 present_modes: Vec::new(),
5520 alpha_modes: vec![CompositeAlphaMode::Opaque],
5521 usages: TextureUsages::RENDER_ATTACHMENT,
5522 }
5523 }
5524}
5525
5526/// Configures a [`Surface`] for presentation.
5527///
5528/// [`Surface`]: ../wgpu/struct.Surface.html
5529#[repr(C)]
5530#[derive(Clone, Debug, PartialEq, Eq, Hash)]
5531#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5532pub struct SurfaceConfiguration<V> {
5533 /// The usage of the swap chain. The only usage guaranteed to be supported is [`TextureUsages::RENDER_ATTACHMENT`].
5534 pub usage: TextureUsages,
5535 /// The texture format of the swap chain. The only formats that are guaranteed are
5536 /// [`TextureFormat::Bgra8Unorm`] and [`TextureFormat::Bgra8UnormSrgb`].
5537 pub format: TextureFormat,
5538 /// Width of the swap chain. Must be the same size as the surface, and nonzero.
5539 ///
5540 /// If this is not the same size as the underlying surface (e.g. if it is
5541 /// set once, and the window is later resized), the behaviour is defined
5542 /// but platform-specific, and may change in the future (currently macOS
5543 /// scales the surface, other platforms may do something else).
5544 pub width: u32,
5545 /// Height of the swap chain. Must be the same size as the surface, and nonzero.
5546 ///
5547 /// If this is not the same size as the underlying surface (e.g. if it is
5548 /// set once, and the window is later resized), the behaviour is defined
5549 /// but platform-specific, and may change in the future (currently macOS
5550 /// scales the surface, other platforms may do something else).
5551 pub height: u32,
5552 /// Presentation mode of the swap chain. Fifo is the only mode guaranteed to be supported.
5553 /// `FifoRelaxed`, `Immediate`, and `Mailbox` will crash if unsupported, while `AutoVsync` and
5554 /// `AutoNoVsync` will gracefully do a designed sets of fallbacks if their primary modes are
5555 /// unsupported.
5556 pub present_mode: PresentMode,
5557 /// Desired maximum number of frames that the presentation engine should queue in advance.
5558 ///
5559 /// This is a hint to the backend implementation and will always be clamped to the supported range.
5560 /// As a consequence, either the maximum frame latency is set directly on the swap chain,
5561 /// or waits on present are scheduled to avoid exceeding the maximum frame latency if supported,
5562 /// or the swap chain size is set to (max-latency + 1).
5563 ///
5564 /// Defaults to 2 when created via `Surface::get_default_config`.
5565 ///
5566 /// Typical values range from 3 to 1, but higher values are possible:
5567 /// * Choose 2 or higher for potentially smoother frame display, as it allows to be at least one frame
5568 /// to be queued up. This typically avoids starving the GPU's work queue.
5569 /// Higher values are useful for achieving a constant flow of frames to the display under varying load.
5570 /// * Choose 1 for low latency from frame recording to frame display.
5571 /// ⚠️ If the backend does not support waiting on present, this will cause the CPU to wait for the GPU
5572 /// to finish all work related to the previous frame when calling `Surface::get_current_texture`,
5573 /// causing CPU-GPU serialization (i.e. when `Surface::get_current_texture` returns, the GPU might be idle).
5574 /// It is currently not possible to query this. See <https://github.com/gfx-rs/wgpu/issues/2869>.
5575 /// * A value of 0 is generally not supported and always clamped to a higher value.
5576 pub desired_maximum_frame_latency: u32,
5577 /// Specifies how the alpha channel of the textures should be handled during compositing.
5578 pub alpha_mode: CompositeAlphaMode,
5579 /// Specifies what view formats will be allowed when calling `Texture::create_view` on the texture returned by `Surface::get_current_texture`.
5580 ///
5581 /// View formats of the same format as the texture are always allowed.
5582 ///
5583 /// Note: currently, only the srgb-ness is allowed to change. (ex: `Rgba8Unorm` texture + `Rgba8UnormSrgb` view)
5584 pub view_formats: V,
5585}
5586
5587impl<V: Clone> SurfaceConfiguration<V> {
5588 /// Map `view_formats` of the texture descriptor into another.
5589 pub fn map_view_formats<M>(&self, fun: impl FnOnce(V) -> M) -> SurfaceConfiguration<M> {
5590 SurfaceConfiguration {
5591 usage: self.usage,
5592 format: self.format,
5593 width: self.width,
5594 height: self.height,
5595 present_mode: self.present_mode,
5596 desired_maximum_frame_latency: self.desired_maximum_frame_latency,
5597 alpha_mode: self.alpha_mode,
5598 view_formats: fun(self.view_formats.clone()),
5599 }
5600 }
5601}
5602
5603/// Status of the received surface image.
5604#[repr(C)]
5605#[derive(Debug)]
5606pub enum SurfaceStatus {
5607 /// No issues.
5608 Good,
5609 /// The swap chain is operational, but it does no longer perfectly
5610 /// match the surface. A re-configuration is needed.
5611 Suboptimal,
5612 /// Unable to get the next frame, timed out.
5613 Timeout,
5614 /// The surface under the swap chain has changed.
5615 Outdated,
5616 /// The surface under the swap chain is lost.
5617 Lost,
5618 /// The surface status is not known since `Surface::get_current_texture` previously failed.
5619 Unknown,
5620}
5621
5622/// Nanosecond timestamp used by the presentation engine.
5623///
5624/// The specific clock depends on the window system integration (WSI) API used.
5625///
5626/// <table>
5627/// <tr>
5628/// <td>WSI</td>
5629/// <td>Clock</td>
5630/// </tr>
5631/// <tr>
5632/// <td>IDXGISwapchain</td>
5633/// <td><a href="https://docs.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter">QueryPerformanceCounter</a></td>
5634/// </tr>
5635/// <tr>
5636/// <td>IPresentationManager</td>
5637/// <td><a href="https://docs.microsoft.com/en-us/windows/win32/api/realtimeapiset/nf-realtimeapiset-queryinterrupttimeprecise">QueryInterruptTimePrecise</a></td>
5638/// </tr>
5639/// <tr>
5640/// <td>CAMetalLayer</td>
5641/// <td><a href="https://developer.apple.com/documentation/kernel/1462446-mach_absolute_time">mach_absolute_time</a></td>
5642/// </tr>
5643/// <tr>
5644/// <td>VK_GOOGLE_display_timing</td>
5645/// <td><a href="https://linux.die.net/man/3/clock_gettime">clock_gettime(CLOCK_MONOTONIC)</a></td>
5646/// </tr>
5647/// </table>
5648#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
5649pub struct PresentationTimestamp(
5650 /// Timestamp in nanoseconds.
5651 pub u128,
5652);
5653
5654impl PresentationTimestamp {
5655 /// A timestamp that is invalid due to the platform not having a timestamp system.
5656 pub const INVALID_TIMESTAMP: Self = Self(u128::MAX);
5657
5658 /// Returns true if this timestamp is the invalid timestamp.
5659 #[must_use]
5660 pub fn is_invalid(self) -> bool {
5661 self == Self::INVALID_TIMESTAMP
5662 }
5663}
5664
5665/// RGBA double precision color.
5666///
5667/// This is not to be used as a generic color type, only for specific wgpu interfaces.
5668#[repr(C)]
5669#[derive(Clone, Copy, Debug, Default, PartialEq)]
5670#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5671#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
5672pub struct Color {
5673 /// Red component of the color
5674 pub r: f64,
5675 /// Green component of the color
5676 pub g: f64,
5677 /// Blue component of the color
5678 pub b: f64,
5679 /// Alpha component of the color
5680 pub a: f64,
5681}
5682
5683#[allow(missing_docs)]
5684impl Color {
5685 pub const TRANSPARENT: Self = Self {
5686 r: 0.0,
5687 g: 0.0,
5688 b: 0.0,
5689 a: 0.0,
5690 };
5691 pub const BLACK: Self = Self {
5692 r: 0.0,
5693 g: 0.0,
5694 b: 0.0,
5695 a: 1.0,
5696 };
5697 pub const WHITE: Self = Self {
5698 r: 1.0,
5699 g: 1.0,
5700 b: 1.0,
5701 a: 1.0,
5702 };
5703 pub const RED: Self = Self {
5704 r: 1.0,
5705 g: 0.0,
5706 b: 0.0,
5707 a: 1.0,
5708 };
5709 pub const GREEN: Self = Self {
5710 r: 0.0,
5711 g: 1.0,
5712 b: 0.0,
5713 a: 1.0,
5714 };
5715 pub const BLUE: Self = Self {
5716 r: 0.0,
5717 g: 0.0,
5718 b: 1.0,
5719 a: 1.0,
5720 };
5721}
5722
5723/// Dimensionality of a texture.
5724///
5725/// Corresponds to [WebGPU `GPUTextureDimension`](
5726/// https://gpuweb.github.io/gpuweb/#enumdef-gputexturedimension).
5727#[repr(C)]
5728#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
5729#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5730pub enum TextureDimension {
5731 /// 1D texture
5732 #[cfg_attr(feature = "serde", serde(rename = "1d"))]
5733 D1,
5734 /// 2D texture
5735 #[cfg_attr(feature = "serde", serde(rename = "2d"))]
5736 D2,
5737 /// 3D texture
5738 #[cfg_attr(feature = "serde", serde(rename = "3d"))]
5739 D3,
5740}
5741
5742/// Origin of a copy from a 2D image.
5743///
5744/// Corresponds to [WebGPU `GPUOrigin2D`](
5745/// https://gpuweb.github.io/gpuweb/#dictdef-gpuorigin2ddict).
5746#[repr(C)]
5747#[derive(Clone, Copy, PartialEq, Eq, Hash)]
5748#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5749#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
5750pub struct Origin2d {
5751 #[allow(missing_docs)]
5752 pub x: u32,
5753 #[allow(missing_docs)]
5754 pub y: u32,
5755}
5756
5757impl Origin2d {
5758 /// Zero origin.
5759 pub const ZERO: Self = Self { x: 0, y: 0 };
5760
5761 /// Adds the third dimension to this origin
5762 #[must_use]
5763 pub fn to_3d(self, z: u32) -> Origin3d {
5764 Origin3d {
5765 x: self.x,
5766 y: self.y,
5767 z,
5768 }
5769 }
5770}
5771
5772impl core::fmt::Debug for Origin2d {
5773 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
5774 (self.x, self.y).fmt(f)
5775 }
5776}
5777
5778/// Origin of a copy to/from a texture.
5779///
5780/// Corresponds to [WebGPU `GPUOrigin3D`](
5781/// https://gpuweb.github.io/gpuweb/#dictdef-gpuorigin3ddict).
5782#[repr(C)]
5783#[derive(Clone, Copy, PartialEq, Eq, Hash)]
5784#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5785#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
5786pub struct Origin3d {
5787 /// X position of the origin
5788 pub x: u32,
5789 /// Y position of the origin
5790 pub y: u32,
5791 /// Z position of the origin
5792 pub z: u32,
5793}
5794
5795impl Origin3d {
5796 /// Zero origin.
5797 pub const ZERO: Self = Self { x: 0, y: 0, z: 0 };
5798
5799 /// Removes the third dimension from this origin
5800 #[must_use]
5801 pub fn to_2d(self) -> Origin2d {
5802 Origin2d {
5803 x: self.x,
5804 y: self.y,
5805 }
5806 }
5807}
5808
5809impl Default for Origin3d {
5810 fn default() -> Self {
5811 Self::ZERO
5812 }
5813}
5814
5815impl core::fmt::Debug for Origin3d {
5816 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
5817 (self.x, self.y, self.z).fmt(f)
5818 }
5819}
5820
5821/// Extent of a texture related operation.
5822///
5823/// Corresponds to [WebGPU `GPUExtent3D`](
5824/// https://gpuweb.github.io/gpuweb/#dictdef-gpuextent3ddict).
5825#[repr(C)]
5826#[derive(Clone, Copy, PartialEq, Eq, Hash)]
5827#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5828#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
5829pub struct Extent3d {
5830 /// Width of the extent
5831 pub width: u32,
5832 /// Height of the extent
5833 pub height: u32,
5834 /// The depth of the extent or the number of array layers
5835 #[cfg_attr(feature = "serde", serde(default = "default_depth"))]
5836 pub depth_or_array_layers: u32,
5837}
5838
5839impl core::fmt::Debug for Extent3d {
5840 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
5841 (self.width, self.height, self.depth_or_array_layers).fmt(f)
5842 }
5843}
5844
5845#[cfg(feature = "serde")]
5846fn default_depth() -> u32 {
5847 1
5848}
5849
5850impl Default for Extent3d {
5851 fn default() -> Self {
5852 Self {
5853 width: 1,
5854 height: 1,
5855 depth_or_array_layers: 1,
5856 }
5857 }
5858}
5859
5860impl Extent3d {
5861 /// Calculates the [physical size] backing a texture of the given
5862 /// format and extent. This includes padding to the block width
5863 /// and height of the format.
5864 ///
5865 /// This is the texture extent that you must upload at when uploading to _mipmaps_ of compressed textures.
5866 ///
5867 /// [physical size]: https://gpuweb.github.io/gpuweb/#physical-miplevel-specific-texture-extent
5868 #[must_use]
5869 pub fn physical_size(&self, format: TextureFormat) -> Self {
5870 let (block_width, block_height) = format.block_dimensions();
5871
5872 let width = self.width.div_ceil(block_width) * block_width;
5873 let height = self.height.div_ceil(block_height) * block_height;
5874
5875 Self {
5876 width,
5877 height,
5878 depth_or_array_layers: self.depth_or_array_layers,
5879 }
5880 }
5881
5882 /// Calculates the maximum possible count of mipmaps.
5883 ///
5884 /// Treats the depth as part of the mipmaps. If calculating
5885 /// for a 2DArray texture, which does not mipmap depth, set depth to 1.
5886 #[must_use]
5887 pub fn max_mips(&self, dim: TextureDimension) -> u32 {
5888 match dim {
5889 TextureDimension::D1 => 1,
5890 TextureDimension::D2 => {
5891 let max_dim = self.width.max(self.height);
5892 32 - max_dim.leading_zeros()
5893 }
5894 TextureDimension::D3 => {
5895 let max_dim = self.width.max(self.height.max(self.depth_or_array_layers));
5896 32 - max_dim.leading_zeros()
5897 }
5898 }
5899 }
5900
5901 /// Calculates the extent at a given mip level.
5902 /// Does *not* account for memory size being a multiple of block size.
5903 ///
5904 /// <https://gpuweb.github.io/gpuweb/#logical-miplevel-specific-texture-extent>
5905 #[must_use]
5906 pub fn mip_level_size(&self, level: u32, dim: TextureDimension) -> Self {
5907 Self {
5908 width: u32::max(1, self.width >> level),
5909 height: match dim {
5910 TextureDimension::D1 => 1,
5911 _ => u32::max(1, self.height >> level),
5912 },
5913 depth_or_array_layers: match dim {
5914 TextureDimension::D1 => 1,
5915 TextureDimension::D2 => self.depth_or_array_layers,
5916 TextureDimension::D3 => u32::max(1, self.depth_or_array_layers >> level),
5917 },
5918 }
5919 }
5920}
5921
5922#[test]
5923fn test_physical_size() {
5924 let format = TextureFormat::Bc1RgbaUnormSrgb; // 4x4 blocks
5925 assert_eq!(
5926 Extent3d {
5927 width: 7,
5928 height: 7,
5929 depth_or_array_layers: 1
5930 }
5931 .physical_size(format),
5932 Extent3d {
5933 width: 8,
5934 height: 8,
5935 depth_or_array_layers: 1
5936 }
5937 );
5938 // Doesn't change, already aligned
5939 assert_eq!(
5940 Extent3d {
5941 width: 8,
5942 height: 8,
5943 depth_or_array_layers: 1
5944 }
5945 .physical_size(format),
5946 Extent3d {
5947 width: 8,
5948 height: 8,
5949 depth_or_array_layers: 1
5950 }
5951 );
5952 let format = TextureFormat::Astc {
5953 block: AstcBlock::B8x5,
5954 channel: AstcChannel::Unorm,
5955 }; // 8x5 blocks
5956 assert_eq!(
5957 Extent3d {
5958 width: 7,
5959 height: 7,
5960 depth_or_array_layers: 1
5961 }
5962 .physical_size(format),
5963 Extent3d {
5964 width: 8,
5965 height: 10,
5966 depth_or_array_layers: 1
5967 }
5968 );
5969}
5970
5971#[test]
5972fn test_max_mips() {
5973 // 1D
5974 assert_eq!(
5975 Extent3d {
5976 width: 240,
5977 height: 1,
5978 depth_or_array_layers: 1
5979 }
5980 .max_mips(TextureDimension::D1),
5981 1
5982 );
5983 // 2D
5984 assert_eq!(
5985 Extent3d {
5986 width: 1,
5987 height: 1,
5988 depth_or_array_layers: 1
5989 }
5990 .max_mips(TextureDimension::D2),
5991 1
5992 );
5993 assert_eq!(
5994 Extent3d {
5995 width: 60,
5996 height: 60,
5997 depth_or_array_layers: 1
5998 }
5999 .max_mips(TextureDimension::D2),
6000 6
6001 );
6002 assert_eq!(
6003 Extent3d {
6004 width: 240,
6005 height: 1,
6006 depth_or_array_layers: 1000
6007 }
6008 .max_mips(TextureDimension::D2),
6009 8
6010 );
6011 // 3D
6012 assert_eq!(
6013 Extent3d {
6014 width: 16,
6015 height: 30,
6016 depth_or_array_layers: 60
6017 }
6018 .max_mips(TextureDimension::D3),
6019 6
6020 );
6021}
6022
6023/// Describes a [`TextureView`].
6024///
6025/// For use with [`Texture::create_view()`].
6026///
6027/// Corresponds to [WebGPU `GPUTextureViewDescriptor`](
6028/// https://gpuweb.github.io/gpuweb/#dictdef-gputextureviewdescriptor).
6029///
6030/// [`TextureView`]: ../wgpu/struct.TextureView.html
6031/// [`Texture::create_view()`]: ../wgpu/struct.Texture.html#method.create_view
6032#[derive(Clone, Debug, Default, Eq, PartialEq)]
6033pub struct TextureViewDescriptor<L> {
6034 /// Debug label of the texture view. This will show up in graphics debuggers for easy identification.
6035 pub label: L,
6036 /// Format of the texture view. Either must be the same as the texture format or in the list
6037 /// of `view_formats` in the texture's descriptor.
6038 pub format: Option<TextureFormat>,
6039 /// The dimension of the texture view. For 1D textures, this must be `D1`. For 2D textures it must be one of
6040 /// `D2`, `D2Array`, `Cube`, and `CubeArray`. For 3D textures it must be `D3`
6041 pub dimension: Option<TextureViewDimension>,
6042 /// The allowed usage(s) for the texture view. Must be a subset of the usage flags of the texture.
6043 /// If not provided, defaults to the full set of usage flags of the texture.
6044 pub usage: Option<TextureUsages>,
6045 /// Aspect of the texture. Color textures must be [`TextureAspect::All`].
6046 pub aspect: TextureAspect,
6047 /// Base mip level.
6048 pub base_mip_level: u32,
6049 /// Mip level count.
6050 /// If `Some(count)`, `base_mip_level + count` must be less or equal to underlying texture mip count.
6051 /// If `None`, considered to include the rest of the mipmap levels, but at least 1 in total.
6052 pub mip_level_count: Option<u32>,
6053 /// Base array layer.
6054 pub base_array_layer: u32,
6055 /// Layer count.
6056 /// If `Some(count)`, `base_array_layer + count` must be less or equal to the underlying array count.
6057 /// If `None`, considered to include the rest of the array layers, but at least 1 in total.
6058 pub array_layer_count: Option<u32>,
6059}
6060
6061/// Describes a [`Texture`](../wgpu/struct.Texture.html).
6062///
6063/// Corresponds to [WebGPU `GPUTextureDescriptor`](
6064/// https://gpuweb.github.io/gpuweb/#dictdef-gputexturedescriptor).
6065#[repr(C)]
6066#[derive(Clone, Debug, PartialEq, Eq, Hash)]
6067#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6068pub struct TextureDescriptor<L, V> {
6069 /// Debug label of the texture. This will show up in graphics debuggers for easy identification.
6070 pub label: L,
6071 /// Size of the texture. All components must be greater than zero. For a
6072 /// regular 1D/2D texture, the unused sizes will be 1. For 2DArray textures,
6073 /// Z is the number of 2D textures in that array.
6074 pub size: Extent3d,
6075 /// Mip count of texture. For a texture with no extra mips, this must be 1.
6076 pub mip_level_count: u32,
6077 /// Sample count of texture. If this is not 1, texture must have [`BindingType::Texture::multisampled`] set to true.
6078 pub sample_count: u32,
6079 /// Dimensions of the texture.
6080 pub dimension: TextureDimension,
6081 /// Format of the texture.
6082 pub format: TextureFormat,
6083 /// Allowed usages of the texture. If used in other ways, the operation will panic.
6084 pub usage: TextureUsages,
6085 /// Specifies what view formats will be allowed when calling `Texture::create_view` on this texture.
6086 ///
6087 /// View formats of the same format as the texture are always allowed.
6088 ///
6089 /// Note: currently, only the srgb-ness is allowed to change. (ex: `Rgba8Unorm` texture + `Rgba8UnormSrgb` view)
6090 pub view_formats: V,
6091}
6092
6093impl<L, V> TextureDescriptor<L, V> {
6094 /// Takes a closure and maps the label of the texture descriptor into another.
6095 #[must_use]
6096 pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> TextureDescriptor<K, V>
6097 where
6098 V: Clone,
6099 {
6100 TextureDescriptor {
6101 label: fun(&self.label),
6102 size: self.size,
6103 mip_level_count: self.mip_level_count,
6104 sample_count: self.sample_count,
6105 dimension: self.dimension,
6106 format: self.format,
6107 usage: self.usage,
6108 view_formats: self.view_formats.clone(),
6109 }
6110 }
6111
6112 /// Maps the label and view formats of the texture descriptor into another.
6113 #[must_use]
6114 pub fn map_label_and_view_formats<K, M>(
6115 &self,
6116 l_fun: impl FnOnce(&L) -> K,
6117 v_fun: impl FnOnce(V) -> M,
6118 ) -> TextureDescriptor<K, M>
6119 where
6120 V: Clone,
6121 {
6122 TextureDescriptor {
6123 label: l_fun(&self.label),
6124 size: self.size,
6125 mip_level_count: self.mip_level_count,
6126 sample_count: self.sample_count,
6127 dimension: self.dimension,
6128 format: self.format,
6129 usage: self.usage,
6130 view_formats: v_fun(self.view_formats.clone()),
6131 }
6132 }
6133
6134 /// Calculates the extent at a given mip level.
6135 ///
6136 /// If the given mip level is larger than possible, returns None.
6137 ///
6138 /// Treats the depth as part of the mipmaps. If calculating
6139 /// for a 2DArray texture, which does not mipmap depth, set depth to 1.
6140 ///
6141 /// ```rust
6142 /// # use wgpu_types as wgpu;
6143 /// # type TextureDescriptor<'a> = wgpu::TextureDescriptor<(), &'a [wgpu::TextureFormat]>;
6144 /// let desc = TextureDescriptor {
6145 /// label: (),
6146 /// size: wgpu::Extent3d { width: 100, height: 60, depth_or_array_layers: 1 },
6147 /// mip_level_count: 7,
6148 /// sample_count: 1,
6149 /// dimension: wgpu::TextureDimension::D3,
6150 /// format: wgpu::TextureFormat::Rgba8Sint,
6151 /// usage: wgpu::TextureUsages::empty(),
6152 /// view_formats: &[],
6153 /// };
6154 ///
6155 /// assert_eq!(desc.mip_level_size(0), Some(wgpu::Extent3d { width: 100, height: 60, depth_or_array_layers: 1 }));
6156 /// assert_eq!(desc.mip_level_size(1), Some(wgpu::Extent3d { width: 50, height: 30, depth_or_array_layers: 1 }));
6157 /// assert_eq!(desc.mip_level_size(2), Some(wgpu::Extent3d { width: 25, height: 15, depth_or_array_layers: 1 }));
6158 /// assert_eq!(desc.mip_level_size(3), Some(wgpu::Extent3d { width: 12, height: 7, depth_or_array_layers: 1 }));
6159 /// assert_eq!(desc.mip_level_size(4), Some(wgpu::Extent3d { width: 6, height: 3, depth_or_array_layers: 1 }));
6160 /// assert_eq!(desc.mip_level_size(5), Some(wgpu::Extent3d { width: 3, height: 1, depth_or_array_layers: 1 }));
6161 /// assert_eq!(desc.mip_level_size(6), Some(wgpu::Extent3d { width: 1, height: 1, depth_or_array_layers: 1 }));
6162 /// assert_eq!(desc.mip_level_size(7), None);
6163 /// ```
6164 #[must_use]
6165 pub fn mip_level_size(&self, level: u32) -> Option<Extent3d> {
6166 if level >= self.mip_level_count {
6167 return None;
6168 }
6169
6170 Some(self.size.mip_level_size(level, self.dimension))
6171 }
6172
6173 /// Computes the render extent of this texture.
6174 ///
6175 /// <https://gpuweb.github.io/gpuweb/#abstract-opdef-compute-render-extent>
6176 #[must_use]
6177 pub fn compute_render_extent(&self, mip_level: u32) -> Extent3d {
6178 Extent3d {
6179 width: u32::max(1, self.size.width >> mip_level),
6180 height: u32::max(1, self.size.height >> mip_level),
6181 depth_or_array_layers: 1,
6182 }
6183 }
6184
6185 /// Returns the number of array layers.
6186 ///
6187 /// <https://gpuweb.github.io/gpuweb/#abstract-opdef-array-layer-count>
6188 #[must_use]
6189 pub fn array_layer_count(&self) -> u32 {
6190 match self.dimension {
6191 TextureDimension::D1 | TextureDimension::D3 => 1,
6192 TextureDimension::D2 => self.size.depth_or_array_layers,
6193 }
6194 }
6195}
6196
6197/// Describes a `Sampler`.
6198///
6199/// For use with `Device::create_sampler`.
6200///
6201/// Corresponds to [WebGPU `GPUSamplerDescriptor`](
6202/// https://gpuweb.github.io/gpuweb/#dictdef-gpusamplerdescriptor).
6203#[derive(Clone, Debug, PartialEq)]
6204#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6205pub struct SamplerDescriptor<L> {
6206 /// Debug label of the sampler. This will show up in graphics debuggers for easy identification.
6207 pub label: L,
6208 /// How to deal with out of bounds accesses in the u (i.e. x) direction
6209 pub address_mode_u: AddressMode,
6210 /// How to deal with out of bounds accesses in the v (i.e. y) direction
6211 pub address_mode_v: AddressMode,
6212 /// How to deal with out of bounds accesses in the w (i.e. z) direction
6213 pub address_mode_w: AddressMode,
6214 /// How to filter the texture when it needs to be magnified (made larger)
6215 pub mag_filter: FilterMode,
6216 /// How to filter the texture when it needs to be minified (made smaller)
6217 pub min_filter: FilterMode,
6218 /// How to filter between mip map levels
6219 pub mipmap_filter: FilterMode,
6220 /// Minimum level of detail (i.e. mip level) to use
6221 pub lod_min_clamp: f32,
6222 /// Maximum level of detail (i.e. mip level) to use
6223 pub lod_max_clamp: f32,
6224 /// If this is enabled, this is a comparison sampler using the given comparison function.
6225 pub compare: Option<CompareFunction>,
6226 /// Must be at least 1. If this is not 1, all filter modes must be linear.
6227 pub anisotropy_clamp: u16,
6228 /// Border color to use when `address_mode` is [`AddressMode::ClampToBorder`]
6229 pub border_color: Option<SamplerBorderColor>,
6230}
6231
6232impl<L: Default> Default for SamplerDescriptor<L> {
6233 fn default() -> Self {
6234 Self {
6235 label: Default::default(),
6236 address_mode_u: Default::default(),
6237 address_mode_v: Default::default(),
6238 address_mode_w: Default::default(),
6239 mag_filter: Default::default(),
6240 min_filter: Default::default(),
6241 mipmap_filter: Default::default(),
6242 lod_min_clamp: 0.0,
6243 lod_max_clamp: 32.0,
6244 compare: None,
6245 anisotropy_clamp: 1,
6246 border_color: None,
6247 }
6248 }
6249}
6250
6251/// Selects a subset of the data a [`Texture`] holds.
6252///
6253/// Used in [texture views](TextureViewDescriptor) and
6254/// [texture copy operations](TexelCopyTextureInfo).
6255///
6256/// Corresponds to [WebGPU `GPUTextureAspect`](
6257/// https://gpuweb.github.io/gpuweb/#enumdef-gputextureaspect).
6258///
6259/// [`Texture`]: ../wgpu/struct.Texture.html
6260#[repr(C)]
6261#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
6262#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6263#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
6264pub enum TextureAspect {
6265 /// Depth, Stencil, and Color.
6266 #[default]
6267 All,
6268 /// Stencil.
6269 StencilOnly,
6270 /// Depth.
6271 DepthOnly,
6272 /// Plane 0.
6273 Plane0,
6274 /// Plane 1.
6275 Plane1,
6276 /// Plane 2.
6277 Plane2,
6278}
6279
6280/// How edges should be handled in texture addressing.
6281///
6282/// Corresponds to [WebGPU `GPUAddressMode`](
6283/// https://gpuweb.github.io/gpuweb/#enumdef-gpuaddressmode).
6284#[repr(C)]
6285#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
6286#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6287#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
6288pub enum AddressMode {
6289 /// Clamp the value to the edge of the texture
6290 ///
6291 /// -0.25 -> 0.0
6292 /// 1.25 -> 1.0
6293 #[default]
6294 ClampToEdge = 0,
6295 /// Repeat the texture in a tiling fashion
6296 ///
6297 /// -0.25 -> 0.75
6298 /// 1.25 -> 0.25
6299 Repeat = 1,
6300 /// Repeat the texture, mirroring it every repeat
6301 ///
6302 /// -0.25 -> 0.25
6303 /// 1.25 -> 0.75
6304 MirrorRepeat = 2,
6305 /// Clamp the value to the border of the texture
6306 /// Requires feature [`Features::ADDRESS_MODE_CLAMP_TO_BORDER`]
6307 ///
6308 /// -0.25 -> border
6309 /// 1.25 -> border
6310 ClampToBorder = 3,
6311}
6312
6313/// Texel mixing mode when sampling between texels.
6314///
6315/// Corresponds to [WebGPU `GPUFilterMode`](
6316/// https://gpuweb.github.io/gpuweb/#enumdef-gpufiltermode).
6317#[repr(C)]
6318#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
6319#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6320#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
6321pub enum FilterMode {
6322 /// Nearest neighbor sampling.
6323 ///
6324 /// This creates a pixelated effect when used as a mag filter
6325 #[default]
6326 Nearest = 0,
6327 /// Linear Interpolation
6328 ///
6329 /// This makes textures smooth but blurry when used as a mag filter.
6330 Linear = 1,
6331}
6332
6333/// A range of push constant memory to pass to a shader stage.
6334#[derive(Clone, Debug, PartialEq, Eq, Hash)]
6335#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6336pub struct PushConstantRange {
6337 /// Stage push constant range is visible from. Each stage can only be served by at most one range.
6338 /// One range can serve multiple stages however.
6339 pub stages: ShaderStages,
6340 /// Range in push constant memory to use for the stage. Must be less than [`Limits::max_push_constant_size`].
6341 /// Start and end must be aligned to the 4s.
6342 pub range: Range<u32>,
6343}
6344
6345/// Describes a [`CommandBuffer`](../wgpu/struct.CommandBuffer.html).
6346///
6347/// Corresponds to [WebGPU `GPUCommandBufferDescriptor`](
6348/// https://gpuweb.github.io/gpuweb/#dictdef-gpucommandbufferdescriptor).
6349#[repr(C)]
6350#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
6351#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6352pub struct CommandBufferDescriptor<L> {
6353 /// Debug label of this command buffer.
6354 pub label: L,
6355}
6356
6357impl<L> CommandBufferDescriptor<L> {
6358 /// Takes a closure and maps the label of the command buffer descriptor into another.
6359 #[must_use]
6360 pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> CommandBufferDescriptor<K> {
6361 CommandBufferDescriptor {
6362 label: fun(&self.label),
6363 }
6364 }
6365}
6366
6367/// Describes the depth/stencil attachment for render bundles.
6368///
6369/// Corresponds to a portion of [WebGPU `GPURenderBundleEncoderDescriptor`](
6370/// https://gpuweb.github.io/gpuweb/#dictdef-gpurenderbundleencoderdescriptor).
6371#[repr(C)]
6372#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
6373#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6374pub struct RenderBundleDepthStencil {
6375 /// Format of the attachment.
6376 pub format: TextureFormat,
6377 /// If the depth aspect of the depth stencil attachment is going to be written to.
6378 ///
6379 /// This must match the [`RenderPassDepthStencilAttachment::depth_ops`] of the renderpass this render bundle is executed in.
6380 /// If `depth_ops` is `Some(..)` this must be false. If it is `None` this must be true.
6381 ///
6382 /// [`RenderPassDepthStencilAttachment::depth_ops`]: ../wgpu/struct.RenderPassDepthStencilAttachment.html#structfield.depth_ops
6383 pub depth_read_only: bool,
6384
6385 /// If the stencil aspect of the depth stencil attachment is going to be written to.
6386 ///
6387 /// This must match the [`RenderPassDepthStencilAttachment::stencil_ops`] of the renderpass this render bundle is executed in.
6388 /// If `depth_ops` is `Some(..)` this must be false. If it is `None` this must be true.
6389 ///
6390 /// [`RenderPassDepthStencilAttachment::stencil_ops`]: ../wgpu/struct.RenderPassDepthStencilAttachment.html#structfield.stencil_ops
6391 pub stencil_read_only: bool,
6392}
6393
6394/// Describes a [`RenderBundle`](../wgpu/struct.RenderBundle.html).
6395///
6396/// Corresponds to [WebGPU `GPURenderBundleDescriptor`](
6397/// https://gpuweb.github.io/gpuweb/#dictdef-gpurenderbundledescriptor).
6398#[repr(C)]
6399#[derive(Clone, Debug, PartialEq, Eq, Hash)]
6400#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6401pub struct RenderBundleDescriptor<L> {
6402 /// Debug label of the render bundle encoder. This will show up in graphics debuggers for easy identification.
6403 pub label: L,
6404}
6405
6406impl<L> RenderBundleDescriptor<L> {
6407 /// Takes a closure and maps the label of the render bundle descriptor into another.
6408 #[must_use]
6409 pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> RenderBundleDescriptor<K> {
6410 RenderBundleDescriptor {
6411 label: fun(&self.label),
6412 }
6413 }
6414}
6415
6416impl<T> Default for RenderBundleDescriptor<Option<T>> {
6417 fn default() -> Self {
6418 Self { label: None }
6419 }
6420}
6421
6422/// Layout of a texture in a buffer's memory.
6423///
6424/// The bytes per row and rows per image can be hard to figure out so here are some examples:
6425///
6426/// | Resolution | Format | Bytes per block | Pixels per block | Bytes per row | Rows per image |
6427/// |------------|--------|-----------------|------------------|----------------------------------------|------------------------------|
6428/// | 256x256 | RGBA8 | 4 | 1 * 1 * 1 | 256 * 4 = Some(1024) | None |
6429/// | 32x16x8 | RGBA8 | 4 | 1 * 1 * 1 | 32 * 4 = 128 padded to 256 = Some(256) | None |
6430/// | 256x256 | BC3 | 16 | 4 * 4 * 1 | 16 * (256 / 4) = 1024 = Some(1024) | None |
6431/// | 64x64x8 | BC3 | 16 | 4 * 4 * 1 | 16 * (64 / 4) = 256 = Some(256) | 64 / 4 = 16 = Some(16) |
6432///
6433/// Corresponds to [WebGPU `GPUTexelCopyBufferLayout`](
6434/// https://gpuweb.github.io/gpuweb/#dictdef-gpuimagedatalayout).
6435#[repr(C)]
6436#[derive(Clone, Copy, Debug, Default)]
6437#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6438pub struct TexelCopyBufferLayout {
6439 /// Offset into the buffer that is the start of the texture. Must be a multiple of texture block size.
6440 /// For non-compressed textures, this is 1.
6441 pub offset: BufferAddress,
6442 /// Bytes per "row" in an image.
6443 ///
6444 /// A row is one row of pixels or of compressed blocks in the x direction.
6445 ///
6446 /// This value is required if there are multiple rows (i.e. height or depth is more than one pixel or pixel block for compressed textures)
6447 ///
6448 /// Must be a multiple of 256 for [`CommandEncoder::copy_buffer_to_texture`][CEcbtt]
6449 /// and [`CommandEncoder::copy_texture_to_buffer`][CEcttb]. You must manually pad the
6450 /// image such that this is a multiple of 256. It will not affect the image data.
6451 ///
6452 /// [`Queue::write_texture`][Qwt] does not have this requirement.
6453 ///
6454 /// Must be a multiple of the texture block size. For non-compressed textures, this is 1.
6455 ///
6456 /// [CEcbtt]: ../wgpu/struct.CommandEncoder.html#method.copy_buffer_to_texture
6457 /// [CEcttb]: ../wgpu/struct.CommandEncoder.html#method.copy_texture_to_buffer
6458 /// [Qwt]: ../wgpu/struct.Queue.html#method.write_texture
6459 pub bytes_per_row: Option<u32>,
6460 /// "Rows" that make up a single "image".
6461 ///
6462 /// A row is one row of pixels or of compressed blocks in the x direction.
6463 ///
6464 /// An image is one layer in the z direction of a 3D image or 2DArray texture.
6465 ///
6466 /// The amount of rows per image may be larger than the actual amount of rows of data.
6467 ///
6468 /// Required if there are multiple images (i.e. the depth is more than one).
6469 pub rows_per_image: Option<u32>,
6470}
6471
6472/// Specific type of a buffer binding.
6473///
6474/// Corresponds to [WebGPU `GPUBufferBindingType`](
6475/// https://gpuweb.github.io/gpuweb/#enumdef-gpubufferbindingtype).
6476#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash)]
6477#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6478pub enum BufferBindingType {
6479 /// A buffer for uniform values.
6480 ///
6481 /// Example WGSL syntax:
6482 /// ```rust,ignore
6483 /// struct Globals {
6484 /// a_uniform: vec2<f32>,
6485 /// another_uniform: vec2<f32>,
6486 /// }
6487 /// @group(0) @binding(0)
6488 /// var<uniform> globals: Globals;
6489 /// ```
6490 ///
6491 /// Example GLSL syntax:
6492 /// ```cpp,ignore
6493 /// layout(std140, binding = 0)
6494 /// uniform Globals {
6495 /// vec2 aUniform;
6496 /// vec2 anotherUniform;
6497 /// };
6498 /// ```
6499 #[default]
6500 Uniform,
6501 /// A storage buffer.
6502 ///
6503 /// Example WGSL syntax:
6504 /// ```rust,ignore
6505 /// @group(0) @binding(0)
6506 /// var<storage, read_write> my_element: array<vec4<f32>>;
6507 /// ```
6508 ///
6509 /// Example GLSL syntax:
6510 /// ```cpp,ignore
6511 /// layout (set=0, binding=0) buffer myStorageBuffer {
6512 /// vec4 myElement[];
6513 /// };
6514 /// ```
6515 Storage {
6516 /// If `true`, the buffer can only be read in the shader,
6517 /// and it:
6518 /// - may or may not be annotated with `read` (WGSL).
6519 /// - must be annotated with `readonly` (GLSL).
6520 ///
6521 /// Example WGSL syntax:
6522 /// ```rust,ignore
6523 /// @group(0) @binding(0)
6524 /// var<storage, read> my_element: array<vec4<f32>>;
6525 /// ```
6526 ///
6527 /// Example GLSL syntax:
6528 /// ```cpp,ignore
6529 /// layout (set=0, binding=0) readonly buffer myStorageBuffer {
6530 /// vec4 myElement[];
6531 /// };
6532 /// ```
6533 read_only: bool,
6534 },
6535}
6536
6537/// Specific type of a sample in a texture binding.
6538///
6539/// Corresponds to [WebGPU `GPUTextureSampleType`](
6540/// https://gpuweb.github.io/gpuweb/#enumdef-gputexturesampletype).
6541#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
6542#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6543pub enum TextureSampleType {
6544 /// Sampling returns floats.
6545 ///
6546 /// Example WGSL syntax:
6547 /// ```rust,ignore
6548 /// @group(0) @binding(0)
6549 /// var t: texture_2d<f32>;
6550 /// ```
6551 ///
6552 /// Example GLSL syntax:
6553 /// ```cpp,ignore
6554 /// layout(binding = 0)
6555 /// uniform texture2D t;
6556 /// ```
6557 Float {
6558 /// If this is `false`, the texture can't be sampled with
6559 /// a filtering sampler.
6560 ///
6561 /// Even if this is `true`, it's possible to sample with
6562 /// a **non-filtering** sampler.
6563 filterable: bool,
6564 },
6565 /// Sampling does the depth reference comparison.
6566 ///
6567 /// This is also compatible with a non-filtering sampler.
6568 ///
6569 /// Example WGSL syntax:
6570 /// ```rust,ignore
6571 /// @group(0) @binding(0)
6572 /// var t: texture_depth_2d;
6573 /// ```
6574 ///
6575 /// Example GLSL syntax:
6576 /// ```cpp,ignore
6577 /// layout(binding = 0)
6578 /// uniform texture2DShadow t;
6579 /// ```
6580 Depth,
6581 /// Sampling returns signed integers.
6582 ///
6583 /// Example WGSL syntax:
6584 /// ```rust,ignore
6585 /// @group(0) @binding(0)
6586 /// var t: texture_2d<i32>;
6587 /// ```
6588 ///
6589 /// Example GLSL syntax:
6590 /// ```cpp,ignore
6591 /// layout(binding = 0)
6592 /// uniform itexture2D t;
6593 /// ```
6594 Sint,
6595 /// Sampling returns unsigned integers.
6596 ///
6597 /// Example WGSL syntax:
6598 /// ```rust,ignore
6599 /// @group(0) @binding(0)
6600 /// var t: texture_2d<u32>;
6601 /// ```
6602 ///
6603 /// Example GLSL syntax:
6604 /// ```cpp,ignore
6605 /// layout(binding = 0)
6606 /// uniform utexture2D t;
6607 /// ```
6608 Uint,
6609}
6610
6611impl Default for TextureSampleType {
6612 fn default() -> Self {
6613 Self::Float { filterable: true }
6614 }
6615}
6616
6617/// Specific type of a sample in a texture binding.
6618///
6619/// For use in [`BindingType::StorageTexture`].
6620///
6621/// Corresponds to [WebGPU `GPUStorageTextureAccess`](
6622/// https://gpuweb.github.io/gpuweb/#enumdef-gpustoragetextureaccess).
6623#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
6624#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6625#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
6626pub enum StorageTextureAccess {
6627 /// The texture can only be written in the shader and it:
6628 /// - may or may not be annotated with `write` (WGSL).
6629 /// - must be annotated with `writeonly` (GLSL).
6630 ///
6631 /// Example WGSL syntax:
6632 /// ```rust,ignore
6633 /// @group(0) @binding(0)
6634 /// var my_storage_image: texture_storage_2d<r32float, write>;
6635 /// ```
6636 ///
6637 /// Example GLSL syntax:
6638 /// ```cpp,ignore
6639 /// layout(set=0, binding=0, r32f) writeonly uniform image2D myStorageImage;
6640 /// ```
6641 WriteOnly,
6642 /// The texture can only be read in the shader and it must be annotated with `read` (WGSL) or
6643 /// `readonly` (GLSL).
6644 ///
6645 /// [`Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES`] must be enabled to use this access
6646 /// mode. This is a native-only extension.
6647 ///
6648 /// Example WGSL syntax:
6649 /// ```rust,ignore
6650 /// @group(0) @binding(0)
6651 /// var my_storage_image: texture_storage_2d<r32float, read>;
6652 /// ```
6653 ///
6654 /// Example GLSL syntax:
6655 /// ```cpp,ignore
6656 /// layout(set=0, binding=0, r32f) readonly uniform image2D myStorageImage;
6657 /// ```
6658 ReadOnly,
6659 /// The texture can be both read and written in the shader and must be annotated with
6660 /// `read_write` in WGSL.
6661 ///
6662 /// [`Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES`] must be enabled to use this access
6663 /// mode. This is a nonstandard, native-only extension.
6664 ///
6665 /// Example WGSL syntax:
6666 /// ```rust,ignore
6667 /// @group(0) @binding(0)
6668 /// var my_storage_image: texture_storage_2d<r32float, read_write>;
6669 /// ```
6670 ///
6671 /// Example GLSL syntax:
6672 /// ```cpp,ignore
6673 /// layout(set=0, binding=0, r32f) uniform image2D myStorageImage;
6674 /// ```
6675 ReadWrite,
6676 /// The texture can be both read and written in the shader via atomics and must be annotated
6677 /// with `read_write` in WGSL.
6678 ///
6679 /// [`Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES`] must be enabled to use this access
6680 /// mode. This is a nonstandard, native-only extension.
6681 ///
6682 /// Example WGSL syntax:
6683 /// ```rust,ignore
6684 /// @group(0) @binding(0)
6685 /// var my_storage_image: texture_storage_2d<r32uint, atomic>;
6686 /// ```
6687 Atomic,
6688}
6689
6690/// Specific type of a sampler binding.
6691///
6692/// For use in [`BindingType::Sampler`].
6693///
6694/// Corresponds to [WebGPU `GPUSamplerBindingType`](
6695/// https://gpuweb.github.io/gpuweb/#enumdef-gpusamplerbindingtype).
6696#[repr(C)]
6697#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
6698#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6699#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
6700pub enum SamplerBindingType {
6701 /// The sampling result is produced based on more than a single color sample from a texture,
6702 /// e.g. when bilinear interpolation is enabled.
6703 Filtering,
6704 /// The sampling result is produced based on a single color sample from a texture.
6705 NonFiltering,
6706 /// Use as a comparison sampler instead of a normal sampler.
6707 /// For more info take a look at the analogous functionality in OpenGL: <https://www.khronos.org/opengl/wiki/Sampler_Object#Comparison_mode>.
6708 Comparison,
6709}
6710
6711/// Type of a binding in a [bind group layout][`BindGroupLayoutEntry`].
6712///
6713/// For each binding in a layout, a [`BindGroup`] must provide a [`BindingResource`] of the
6714/// corresponding type.
6715///
6716/// Corresponds to WebGPU's mutually exclusive fields within [`GPUBindGroupLayoutEntry`](
6717/// https://gpuweb.github.io/gpuweb/#dictdef-gpubindgrouplayoutentry).
6718///
6719/// [`BindingResource`]: ../wgpu/enum.BindingResource.html
6720/// [`BindGroup`]: ../wgpu/struct.BindGroup.html
6721#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
6722#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6723pub enum BindingType {
6724 /// A buffer binding.
6725 ///
6726 /// Corresponds to [WebGPU `GPUBufferBindingLayout`](
6727 /// https://gpuweb.github.io/gpuweb/#dictdef-gpubufferbindinglayout).
6728 Buffer {
6729 /// Sub-type of the buffer binding.
6730 ty: BufferBindingType,
6731
6732 /// Indicates that the binding has a dynamic offset.
6733 ///
6734 /// One offset must be passed to [`RenderPass::set_bind_group`][RPsbg]
6735 /// for each dynamic binding in increasing order of binding number.
6736 ///
6737 /// [RPsbg]: ../wgpu/struct.RenderPass.html#method.set_bind_group
6738 #[cfg_attr(feature = "serde", serde(default))]
6739 has_dynamic_offset: bool,
6740
6741 /// The minimum size for a [`BufferBinding`] matching this entry, in bytes.
6742 ///
6743 /// If this is `Some(size)`:
6744 ///
6745 /// - When calling [`create_bind_group`], the resource at this bind point
6746 /// must be a [`BindingResource::Buffer`] whose effective size is at
6747 /// least `size`.
6748 ///
6749 /// - When calling [`create_render_pipeline`] or [`create_compute_pipeline`],
6750 /// `size` must be at least the [minimum buffer binding size] for the
6751 /// shader module global at this bind point: large enough to hold the
6752 /// global's value, along with one element of a trailing runtime-sized
6753 /// array, if present.
6754 ///
6755 /// If this is `None`:
6756 ///
6757 /// - Each draw or dispatch command checks that the buffer range at this
6758 /// bind point satisfies the [minimum buffer binding size].
6759 ///
6760 /// [`BufferBinding`]: ../wgpu/struct.BufferBinding.html
6761 /// [`create_bind_group`]: ../wgpu/struct.Device.html#method.create_bind_group
6762 /// [`BindingResource::Buffer`]: ../wgpu/enum.BindingResource.html#variant.Buffer
6763 /// [minimum buffer binding size]: https://www.w3.org/TR/webgpu/#minimum-buffer-binding-size
6764 /// [`create_render_pipeline`]: ../wgpu/struct.Device.html#method.create_render_pipeline
6765 /// [`create_compute_pipeline`]: ../wgpu/struct.Device.html#method.create_compute_pipeline
6766 #[cfg_attr(feature = "serde", serde(default))]
6767 min_binding_size: Option<BufferSize>,
6768 },
6769 /// A sampler that can be used to sample a texture.
6770 ///
6771 /// Example WGSL syntax:
6772 /// ```rust,ignore
6773 /// @group(0) @binding(0)
6774 /// var s: sampler;
6775 /// ```
6776 ///
6777 /// Example GLSL syntax:
6778 /// ```cpp,ignore
6779 /// layout(binding = 0)
6780 /// uniform sampler s;
6781 /// ```
6782 ///
6783 /// Corresponds to [WebGPU `GPUSamplerBindingLayout`](
6784 /// https://gpuweb.github.io/gpuweb/#dictdef-gpusamplerbindinglayout).
6785 Sampler(SamplerBindingType),
6786 /// A texture binding.
6787 ///
6788 /// Example WGSL syntax:
6789 /// ```rust,ignore
6790 /// @group(0) @binding(0)
6791 /// var t: texture_2d<f32>;
6792 /// ```
6793 ///
6794 /// Example GLSL syntax:
6795 /// ```cpp,ignore
6796 /// layout(binding = 0)
6797 /// uniform texture2D t;
6798 /// ```
6799 ///
6800 /// Corresponds to [WebGPU `GPUTextureBindingLayout`](
6801 /// https://gpuweb.github.io/gpuweb/#dictdef-gputexturebindinglayout).
6802 Texture {
6803 /// Sample type of the texture binding.
6804 sample_type: TextureSampleType,
6805 /// Dimension of the texture view that is going to be sampled.
6806 view_dimension: TextureViewDimension,
6807 /// True if the texture has a sample count greater than 1. If this is true,
6808 /// the texture must be declared as `texture_multisampled_2d` or
6809 /// `texture_depth_multisampled_2d` in the shader, and read using `textureLoad`.
6810 multisampled: bool,
6811 },
6812 /// A storage texture.
6813 ///
6814 /// Example WGSL syntax:
6815 /// ```rust,ignore
6816 /// @group(0) @binding(0)
6817 /// var my_storage_image: texture_storage_2d<r32float, write>;
6818 /// ```
6819 ///
6820 /// Example GLSL syntax:
6821 /// ```cpp,ignore
6822 /// layout(set=0, binding=0, r32f) writeonly uniform image2D myStorageImage;
6823 /// ```
6824 /// Note that the texture format must be specified in the shader, along with the
6825 /// access mode. For WGSL, the format must be one of the enumerants in the list
6826 /// of [storage texel formats](https://gpuweb.github.io/gpuweb/wgsl/#storage-texel-formats).
6827 ///
6828 /// Corresponds to [WebGPU `GPUStorageTextureBindingLayout`](
6829 /// https://gpuweb.github.io/gpuweb/#dictdef-gpustoragetexturebindinglayout).
6830 StorageTexture {
6831 /// Allowed access to this texture.
6832 access: StorageTextureAccess,
6833 /// Format of the texture.
6834 format: TextureFormat,
6835 /// Dimension of the texture view that is going to be sampled.
6836 view_dimension: TextureViewDimension,
6837 },
6838
6839 /// A ray-tracing acceleration structure binding.
6840 ///
6841 /// Example WGSL syntax:
6842 /// ```rust,ignore
6843 /// @group(0) @binding(0)
6844 /// var as: acceleration_structure;
6845 /// ```
6846 ///
6847 /// or with vertex return enabled
6848 /// ```rust,ignore
6849 /// @group(0) @binding(0)
6850 /// var as: acceleration_structure<vertex_return>;
6851 /// ```
6852 ///
6853 /// Example GLSL syntax:
6854 /// ```cpp,ignore
6855 /// layout(binding = 0)
6856 /// uniform accelerationStructureEXT as;
6857 /// ```
6858 AccelerationStructure {
6859 /// Whether this acceleration structure can be used to
6860 /// create a ray query that has flag vertex return in the shader
6861 ///
6862 /// If enabled requires [`Features::EXPERIMENTAL_RAY_HIT_VERTEX_RETURN`]
6863 vertex_return: bool,
6864 },
6865
6866 /// An external texture binding.
6867 ///
6868 /// Example WGSL syntax:
6869 /// ```rust,ignore
6870 /// @group(0) @binding(0)
6871 /// var t: texture_external;
6872 /// ```
6873 ///
6874 /// Corresponds to [WebGPU `GPUExternalTextureBindingLayout`](
6875 /// https://gpuweb.github.io/gpuweb/#dictdef-gpuexternaltexturebindinglayout).
6876 ///
6877 /// Requires [`Features::EXTERNAL_TEXTURE`]
6878 ExternalTexture,
6879}
6880
6881impl BindingType {
6882 /// Returns true for buffer bindings with dynamic offset enabled.
6883 #[must_use]
6884 pub fn has_dynamic_offset(&self) -> bool {
6885 match *self {
6886 Self::Buffer {
6887 has_dynamic_offset, ..
6888 } => has_dynamic_offset,
6889 _ => false,
6890 }
6891 }
6892}
6893
6894/// Describes a single binding inside a bind group.
6895///
6896/// Corresponds to [WebGPU `GPUBindGroupLayoutEntry`](
6897/// https://gpuweb.github.io/gpuweb/#dictdef-gpubindgrouplayoutentry).
6898#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
6899#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6900pub struct BindGroupLayoutEntry {
6901 /// Binding index. Must match shader index and be unique inside a `BindGroupLayout`. A binding
6902 /// of index 1, would be described as `@group(0) @binding(1)` in shaders.
6903 pub binding: u32,
6904 /// Which shader stages can see this binding.
6905 pub visibility: ShaderStages,
6906 /// The type of the binding
6907 pub ty: BindingType,
6908 /// If the binding is an array of multiple resources. Corresponds to `binding_array<T>` in the shader.
6909 ///
6910 /// When this is `Some` the following validation applies:
6911 /// - Size must be of value 1 or greater.
6912 /// - When `ty == BindingType::Texture`, [`Features::TEXTURE_BINDING_ARRAY`] must be supported.
6913 /// - When `ty == BindingType::Sampler`, [`Features::TEXTURE_BINDING_ARRAY`] must be supported.
6914 /// - When `ty == BindingType::Buffer`, [`Features::BUFFER_BINDING_ARRAY`] must be supported.
6915 /// - When `ty == BindingType::Buffer` and `ty.ty == BufferBindingType::Storage`, [`Features::STORAGE_RESOURCE_BINDING_ARRAY`] must be supported.
6916 /// - When `ty == BindingType::StorageTexture`, [`Features::STORAGE_RESOURCE_BINDING_ARRAY`] must be supported.
6917 /// - When any binding in the group is an array, no `BindingType::Buffer` in the group may have `has_dynamic_offset == true`
6918 /// - When any binding in the group is an array, no `BindingType::Buffer` in the group may have `ty.ty == BufferBindingType::Uniform`.
6919 ///
6920 #[cfg_attr(feature = "serde", serde(default))]
6921 pub count: Option<NonZeroU32>,
6922}
6923
6924/// View of a buffer which can be used to copy to/from a texture.
6925///
6926/// Corresponds to [WebGPU `GPUTexelCopyBufferInfo`](
6927/// https://gpuweb.github.io/gpuweb/#dictdef-gpuimagecopybuffer).
6928#[repr(C)]
6929#[derive(Copy, Clone, Debug)]
6930#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6931pub struct TexelCopyBufferInfo<B> {
6932 /// The buffer to be copied to/from.
6933 pub buffer: B,
6934 /// The layout of the texture data in this buffer.
6935 pub layout: TexelCopyBufferLayout,
6936}
6937
6938/// View of a texture which can be used to copy to/from a buffer/texture.
6939///
6940/// Corresponds to [WebGPU `GPUTexelCopyTextureInfo`](
6941/// https://gpuweb.github.io/gpuweb/#dictdef-gpuimagecopytexture).
6942#[repr(C)]
6943#[derive(Copy, Clone, Debug)]
6944#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6945pub struct TexelCopyTextureInfo<T> {
6946 /// The texture to be copied to/from.
6947 pub texture: T,
6948 /// The target mip level of the texture.
6949 pub mip_level: u32,
6950 /// The base texel of the texture in the selected `mip_level`. Together
6951 /// with the `copy_size` argument to copy functions, defines the
6952 /// sub-region of the texture to copy.
6953 #[cfg_attr(feature = "serde", serde(default))]
6954 pub origin: Origin3d,
6955 /// The copy aspect.
6956 #[cfg_attr(feature = "serde", serde(default))]
6957 pub aspect: TextureAspect,
6958}
6959
6960impl<T> TexelCopyTextureInfo<T> {
6961 /// Adds color space and premultiplied alpha information to make this
6962 /// descriptor tagged.
6963 pub fn to_tagged(
6964 self,
6965 color_space: PredefinedColorSpace,
6966 premultiplied_alpha: bool,
6967 ) -> CopyExternalImageDestInfo<T> {
6968 CopyExternalImageDestInfo {
6969 texture: self.texture,
6970 mip_level: self.mip_level,
6971 origin: self.origin,
6972 aspect: self.aspect,
6973 color_space,
6974 premultiplied_alpha,
6975 }
6976 }
6977}
6978
6979/// View of an external texture that can be used to copy to a texture.
6980///
6981/// Corresponds to [WebGPU `GPUCopyExternalImageSourceInfo`](
6982/// https://gpuweb.github.io/gpuweb/#dictdef-gpuimagecopyexternalimage).
6983#[cfg(all(target_arch = "wasm32", feature = "web"))]
6984#[derive(Clone, Debug)]
6985pub struct CopyExternalImageSourceInfo {
6986 /// The texture to be copied from. The copy source data is captured at the moment
6987 /// the copy is issued.
6988 pub source: ExternalImageSource,
6989 /// The base texel used for copying from the external image. Together
6990 /// with the `copy_size` argument to copy functions, defines the
6991 /// sub-region of the image to copy.
6992 ///
6993 /// Relative to the top left of the image.
6994 ///
6995 /// Must be [`Origin2d::ZERO`] if [`DownlevelFlags::UNRESTRICTED_EXTERNAL_TEXTURE_COPIES`] is not supported.
6996 pub origin: Origin2d,
6997 /// If the Y coordinate of the image should be flipped. Even if this is
6998 /// true, `origin` is still relative to the top left.
6999 pub flip_y: bool,
7000}
7001
7002/// Source of an external texture copy.
7003///
7004/// Corresponds to the [implicit union type on WebGPU `GPUCopyExternalImageSourceInfo.source`](
7005/// https://gpuweb.github.io/gpuweb/#dom-gpuimagecopyexternalimage-source).
7006#[cfg(all(target_arch = "wasm32", feature = "web"))]
7007#[derive(Clone, Debug)]
7008pub enum ExternalImageSource {
7009 /// Copy from a previously-decoded image bitmap.
7010 ImageBitmap(web_sys::ImageBitmap),
7011 /// Copy from an image element.
7012 HTMLImageElement(web_sys::HtmlImageElement),
7013 /// Copy from a current frame of a video element.
7014 HTMLVideoElement(web_sys::HtmlVideoElement),
7015 /// Copy from an image.
7016 ImageData(web_sys::ImageData),
7017 /// Copy from a on-screen canvas.
7018 HTMLCanvasElement(web_sys::HtmlCanvasElement),
7019 /// Copy from a off-screen canvas.
7020 ///
7021 /// Requires [`DownlevelFlags::UNRESTRICTED_EXTERNAL_TEXTURE_COPIES`]
7022 OffscreenCanvas(web_sys::OffscreenCanvas),
7023 /// Copy from a video frame.
7024 #[cfg(web_sys_unstable_apis)]
7025 VideoFrame(web_sys::VideoFrame),
7026}
7027
7028#[cfg(all(target_arch = "wasm32", feature = "web"))]
7029impl ExternalImageSource {
7030 /// Gets the pixel, not css, width of the source.
7031 pub fn width(&self) -> u32 {
7032 match self {
7033 ExternalImageSource::ImageBitmap(b) => b.width(),
7034 ExternalImageSource::HTMLImageElement(i) => i.width(),
7035 ExternalImageSource::HTMLVideoElement(v) => v.video_width(),
7036 ExternalImageSource::ImageData(i) => i.width(),
7037 ExternalImageSource::HTMLCanvasElement(c) => c.width(),
7038 ExternalImageSource::OffscreenCanvas(c) => c.width(),
7039 #[cfg(web_sys_unstable_apis)]
7040 ExternalImageSource::VideoFrame(v) => v.display_width(),
7041 }
7042 }
7043
7044 /// Gets the pixel, not css, height of the source.
7045 pub fn height(&self) -> u32 {
7046 match self {
7047 ExternalImageSource::ImageBitmap(b) => b.height(),
7048 ExternalImageSource::HTMLImageElement(i) => i.height(),
7049 ExternalImageSource::HTMLVideoElement(v) => v.video_height(),
7050 ExternalImageSource::ImageData(i) => i.height(),
7051 ExternalImageSource::HTMLCanvasElement(c) => c.height(),
7052 ExternalImageSource::OffscreenCanvas(c) => c.height(),
7053 #[cfg(web_sys_unstable_apis)]
7054 ExternalImageSource::VideoFrame(v) => v.display_height(),
7055 }
7056 }
7057}
7058
7059#[cfg(all(target_arch = "wasm32", feature = "web"))]
7060impl core::ops::Deref for ExternalImageSource {
7061 type Target = js_sys::Object;
7062
7063 fn deref(&self) -> &Self::Target {
7064 match self {
7065 Self::ImageBitmap(b) => b,
7066 Self::HTMLImageElement(i) => i,
7067 Self::HTMLVideoElement(v) => v,
7068 Self::ImageData(i) => i,
7069 Self::HTMLCanvasElement(c) => c,
7070 Self::OffscreenCanvas(c) => c,
7071 #[cfg(web_sys_unstable_apis)]
7072 Self::VideoFrame(v) => v,
7073 }
7074 }
7075}
7076
7077#[cfg(all(
7078 target_arch = "wasm32",
7079 feature = "web",
7080 feature = "fragile-send-sync-non-atomic-wasm",
7081 not(target_feature = "atomics")
7082))]
7083unsafe impl Send for ExternalImageSource {}
7084#[cfg(all(
7085 target_arch = "wasm32",
7086 feature = "web",
7087 feature = "fragile-send-sync-non-atomic-wasm",
7088 not(target_feature = "atomics")
7089))]
7090unsafe impl Sync for ExternalImageSource {}
7091
7092/// Color spaces supported on the web.
7093///
7094/// Corresponds to [HTML Canvas `PredefinedColorSpace`](
7095/// https://html.spec.whatwg.org/multipage/canvas.html#predefinedcolorspace).
7096#[derive(Copy, Clone, Debug, PartialEq, Eq)]
7097#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7098#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
7099pub enum PredefinedColorSpace {
7100 /// sRGB color space
7101 Srgb,
7102 /// Display-P3 color space
7103 DisplayP3,
7104}
7105
7106/// View of a texture which can be used to copy to a texture, including
7107/// color space and alpha premultiplication information.
7108///
7109/// Corresponds to [WebGPU `GPUCopyExternalImageDestInfo`](
7110/// https://gpuweb.github.io/gpuweb/#dictdef-gpuimagecopytexturetagged).
7111#[derive(Copy, Clone, Debug)]
7112#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7113pub struct CopyExternalImageDestInfo<T> {
7114 /// The texture to be copied to/from.
7115 pub texture: T,
7116 /// The target mip level of the texture.
7117 pub mip_level: u32,
7118 /// The base texel of the texture in the selected `mip_level`.
7119 pub origin: Origin3d,
7120 /// The copy aspect.
7121 pub aspect: TextureAspect,
7122 /// The color space of this texture.
7123 pub color_space: PredefinedColorSpace,
7124 /// The premultiplication of this texture
7125 pub premultiplied_alpha: bool,
7126}
7127
7128impl<T> CopyExternalImageDestInfo<T> {
7129 /// Removes the colorspace information from the type.
7130 pub fn to_untagged(self) -> TexelCopyTextureInfo<T> {
7131 TexelCopyTextureInfo {
7132 texture: self.texture,
7133 mip_level: self.mip_level,
7134 origin: self.origin,
7135 aspect: self.aspect,
7136 }
7137 }
7138}
7139
7140/// Subresource range within an image
7141#[repr(C)]
7142#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
7143#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7144#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
7145pub struct ImageSubresourceRange {
7146 /// Aspect of the texture. Color textures must be [`TextureAspect::All`][TAA].
7147 ///
7148 /// [TAA]: ../wgpu/enum.TextureAspect.html#variant.All
7149 pub aspect: TextureAspect,
7150 /// Base mip level.
7151 pub base_mip_level: u32,
7152 /// Mip level count.
7153 /// If `Some(count)`, `base_mip_level + count` must be less or equal to underlying texture mip count.
7154 /// If `None`, considered to include the rest of the mipmap levels, but at least 1 in total.
7155 pub mip_level_count: Option<u32>,
7156 /// Base array layer.
7157 pub base_array_layer: u32,
7158 /// Layer count.
7159 /// If `Some(count)`, `base_array_layer + count` must be less or equal to the underlying array count.
7160 /// If `None`, considered to include the rest of the array layers, but at least 1 in total.
7161 pub array_layer_count: Option<u32>,
7162}
7163
7164impl ImageSubresourceRange {
7165 /// Returns if the given range represents a full resource, with a texture of the given
7166 /// layer count and mip count.
7167 ///
7168 /// ```rust
7169 /// # use wgpu_types as wgpu;
7170 ///
7171 /// let range_none = wgpu::ImageSubresourceRange {
7172 /// aspect: wgpu::TextureAspect::All,
7173 /// base_mip_level: 0,
7174 /// mip_level_count: None,
7175 /// base_array_layer: 0,
7176 /// array_layer_count: None,
7177 /// };
7178 /// assert_eq!(range_none.is_full_resource(wgpu::TextureFormat::Stencil8, 5, 10), true);
7179 ///
7180 /// let range_some = wgpu::ImageSubresourceRange {
7181 /// aspect: wgpu::TextureAspect::All,
7182 /// base_mip_level: 0,
7183 /// mip_level_count: Some(5),
7184 /// base_array_layer: 0,
7185 /// array_layer_count: Some(10),
7186 /// };
7187 /// assert_eq!(range_some.is_full_resource(wgpu::TextureFormat::Stencil8, 5, 10), true);
7188 ///
7189 /// let range_mixed = wgpu::ImageSubresourceRange {
7190 /// aspect: wgpu::TextureAspect::StencilOnly,
7191 /// base_mip_level: 0,
7192 /// // Only partial resource
7193 /// mip_level_count: Some(3),
7194 /// base_array_layer: 0,
7195 /// array_layer_count: None,
7196 /// };
7197 /// assert_eq!(range_mixed.is_full_resource(wgpu::TextureFormat::Stencil8, 5, 10), false);
7198 /// ```
7199 #[must_use]
7200 pub fn is_full_resource(
7201 &self,
7202 format: TextureFormat,
7203 mip_levels: u32,
7204 array_layers: u32,
7205 ) -> bool {
7206 // Mip level count and array layer count need to deal with both the None and Some(count) case.
7207 let mip_level_count = self.mip_level_count.unwrap_or(mip_levels);
7208 let array_layer_count = self.array_layer_count.unwrap_or(array_layers);
7209
7210 let aspect_eq = Some(format) == format.aspect_specific_format(self.aspect);
7211
7212 let base_mip_level_eq = self.base_mip_level == 0;
7213 let mip_level_count_eq = mip_level_count == mip_levels;
7214
7215 let base_array_layer_eq = self.base_array_layer == 0;
7216 let array_layer_count_eq = array_layer_count == array_layers;
7217
7218 aspect_eq
7219 && base_mip_level_eq
7220 && mip_level_count_eq
7221 && base_array_layer_eq
7222 && array_layer_count_eq
7223 }
7224
7225 /// Returns the mip level range of a subresource range describes for a specific texture.
7226 #[must_use]
7227 pub fn mip_range(&self, mip_level_count: u32) -> Range<u32> {
7228 self.base_mip_level..match self.mip_level_count {
7229 Some(mip_level_count) => self.base_mip_level + mip_level_count,
7230 None => mip_level_count,
7231 }
7232 }
7233
7234 /// Returns the layer range of a subresource range describes for a specific texture.
7235 #[must_use]
7236 pub fn layer_range(&self, array_layer_count: u32) -> Range<u32> {
7237 self.base_array_layer..match self.array_layer_count {
7238 Some(array_layer_count) => self.base_array_layer + array_layer_count,
7239 None => array_layer_count,
7240 }
7241 }
7242}
7243
7244/// Color variation to use when sampler addressing mode is [`AddressMode::ClampToBorder`]
7245#[repr(C)]
7246#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
7247#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7248pub enum SamplerBorderColor {
7249 /// [0, 0, 0, 0]
7250 TransparentBlack,
7251 /// [0, 0, 0, 1]
7252 OpaqueBlack,
7253 /// [1, 1, 1, 1]
7254 OpaqueWhite,
7255
7256 /// On the Metal backend, this is equivalent to `TransparentBlack` for
7257 /// textures that have an alpha component, and equivalent to `OpaqueBlack`
7258 /// for textures that do not have an alpha component. On other backends,
7259 /// this is equivalent to `TransparentBlack`. Requires
7260 /// [`Features::ADDRESS_MODE_CLAMP_TO_ZERO`]. Not supported on the web.
7261 Zero,
7262}
7263
7264/// Describes how to create a `QuerySet`.
7265///
7266/// Corresponds to [WebGPU `GPUQuerySetDescriptor`](
7267/// https://gpuweb.github.io/gpuweb/#dictdef-gpuquerysetdescriptor).
7268#[derive(Clone, Debug)]
7269#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7270pub struct QuerySetDescriptor<L> {
7271 /// Debug label for the query set.
7272 pub label: L,
7273 /// Kind of query that this query set should contain.
7274 pub ty: QueryType,
7275 /// Total count of queries the set contains. Must not be zero.
7276 /// Must not be greater than [`QUERY_SET_MAX_QUERIES`].
7277 pub count: u32,
7278}
7279
7280impl<L> QuerySetDescriptor<L> {
7281 /// Takes a closure and maps the label of the query set descriptor into another.
7282 #[must_use]
7283 pub fn map_label<'a, K>(&'a self, fun: impl FnOnce(&'a L) -> K) -> QuerySetDescriptor<K> {
7284 QuerySetDescriptor {
7285 label: fun(&self.label),
7286 ty: self.ty,
7287 count: self.count,
7288 }
7289 }
7290}
7291
7292/// Type of query contained in a [`QuerySet`].
7293///
7294/// Corresponds to [WebGPU `GPUQueryType`](
7295/// https://gpuweb.github.io/gpuweb/#enumdef-gpuquerytype).
7296///
7297/// [`QuerySet`]: ../wgpu/struct.QuerySet.html
7298#[derive(Copy, Clone, Debug)]
7299#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7300pub enum QueryType {
7301 /// Query returns a single 64-bit number, serving as an occlusion boolean.
7302 Occlusion,
7303 /// Query returns up to 5 64-bit numbers based on the given flags.
7304 ///
7305 /// See [`PipelineStatisticsTypes`]'s documentation for more information
7306 /// on how they get resolved.
7307 ///
7308 /// [`Features::PIPELINE_STATISTICS_QUERY`] must be enabled to use this query type.
7309 PipelineStatistics(PipelineStatisticsTypes),
7310 /// Query returns a 64-bit number indicating the GPU-timestamp
7311 /// where all previous commands have finished executing.
7312 ///
7313 /// Must be multiplied by [`Queue::get_timestamp_period`][Qgtp] to get
7314 /// the value in nanoseconds. Absolute values have no meaning,
7315 /// but timestamps can be subtracted to get the time it takes
7316 /// for a string of operations to complete.
7317 ///
7318 /// [`Features::TIMESTAMP_QUERY`] must be enabled to use this query type.
7319 ///
7320 /// [Qgtp]: ../wgpu/struct.Queue.html#method.get_timestamp_period
7321 Timestamp,
7322}
7323
7324bitflags::bitflags! {
7325 /// Flags for which pipeline data should be recorded in a query.
7326 ///
7327 /// Used in [`QueryType`].
7328 ///
7329 /// The amount of values written when resolved depends
7330 /// on the amount of flags set. For example, if 3 flags are set, 3
7331 /// 64-bit values will be written per query.
7332 ///
7333 /// The order they are written is the order they are declared
7334 /// in these bitflags. For example, if you enabled `CLIPPER_PRIMITIVES_OUT`
7335 /// and `COMPUTE_SHADER_INVOCATIONS`, it would write 16 bytes,
7336 /// the first 8 bytes being the primitive out value, the last 8
7337 /// bytes being the compute shader invocation count.
7338 #[repr(transparent)]
7339 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7340 #[cfg_attr(feature = "serde", serde(transparent))]
7341 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
7342 pub struct PipelineStatisticsTypes : u8 {
7343 /// Amount of times the vertex shader is ran. Accounts for
7344 /// the vertex cache when doing indexed rendering.
7345 const VERTEX_SHADER_INVOCATIONS = 1 << 0;
7346 /// Amount of times the clipper is invoked. This
7347 /// is also the amount of triangles output by the vertex shader.
7348 const CLIPPER_INVOCATIONS = 1 << 1;
7349 /// Amount of primitives that are not culled by the clipper.
7350 /// This is the amount of triangles that are actually on screen
7351 /// and will be rasterized and rendered.
7352 const CLIPPER_PRIMITIVES_OUT = 1 << 2;
7353 /// Amount of times the fragment shader is ran. Accounts for
7354 /// fragment shaders running in 2x2 blocks in order to get
7355 /// derivatives.
7356 const FRAGMENT_SHADER_INVOCATIONS = 1 << 3;
7357 /// Amount of times a compute shader is invoked. This will
7358 /// be equivalent to the dispatch count times the workgroup size.
7359 const COMPUTE_SHADER_INVOCATIONS = 1 << 4;
7360 }
7361}
7362
7363/// Argument buffer layout for `draw_indirect` commands.
7364#[repr(C)]
7365#[derive(Copy, Clone, Debug, Default, Pod, Zeroable)]
7366pub struct DrawIndirectArgs {
7367 /// The number of vertices to draw.
7368 pub vertex_count: u32,
7369 /// The number of instances to draw.
7370 pub instance_count: u32,
7371 /// The Index of the first vertex to draw.
7372 pub first_vertex: u32,
7373 /// The instance ID of the first instance to draw.
7374 ///
7375 /// Has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`](crate::Features::INDIRECT_FIRST_INSTANCE) is enabled.
7376 pub first_instance: u32,
7377}
7378
7379impl DrawIndirectArgs {
7380 /// Returns the bytes representation of the struct, ready to be written in a buffer.
7381 #[must_use]
7382 pub fn as_bytes(&self) -> &[u8] {
7383 bytemuck::bytes_of(self)
7384 }
7385}
7386
7387/// Argument buffer layout for `draw_indexed_indirect` commands.
7388#[repr(C)]
7389#[derive(Copy, Clone, Debug, Default, Pod, Zeroable)]
7390pub struct DrawIndexedIndirectArgs {
7391 /// The number of indices to draw.
7392 pub index_count: u32,
7393 /// The number of instances to draw.
7394 pub instance_count: u32,
7395 /// The first index within the index buffer.
7396 pub first_index: u32,
7397 /// The value added to the vertex index before indexing into the vertex buffer.
7398 pub base_vertex: i32,
7399 /// The instance ID of the first instance to draw.
7400 ///
7401 /// Has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`](crate::Features::INDIRECT_FIRST_INSTANCE) is enabled.
7402 pub first_instance: u32,
7403}
7404
7405impl DrawIndexedIndirectArgs {
7406 /// Returns the bytes representation of the struct, ready to be written in a buffer.
7407 #[must_use]
7408 pub fn as_bytes(&self) -> &[u8] {
7409 bytemuck::bytes_of(self)
7410 }
7411}
7412
7413/// Argument buffer layout for `dispatch_indirect` commands.
7414#[repr(C)]
7415#[derive(Copy, Clone, Debug, Default, Pod, Zeroable)]
7416pub struct DispatchIndirectArgs {
7417 /// The number of work groups in X dimension.
7418 pub x: u32,
7419 /// The number of work groups in Y dimension.
7420 pub y: u32,
7421 /// The number of work groups in Z dimension.
7422 pub z: u32,
7423}
7424
7425impl DispatchIndirectArgs {
7426 /// Returns the bytes representation of the struct, ready to be written into a buffer.
7427 #[must_use]
7428 pub fn as_bytes(&self) -> &[u8] {
7429 bytemuck::bytes_of(self)
7430 }
7431}
7432
7433/// Describes how shader bound checks should be performed.
7434#[derive(Copy, Clone, Debug)]
7435#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7436pub struct ShaderRuntimeChecks {
7437 /// Enforce bounds checks in shaders, even if the underlying driver doesn't
7438 /// support doing so natively.
7439 ///
7440 /// When this is `true`, `wgpu` promises that shaders can only read or
7441 /// write the accessible region of a bindgroup's buffer bindings. If
7442 /// the underlying graphics platform cannot implement these bounds checks
7443 /// itself, `wgpu` will inject bounds checks before presenting the
7444 /// shader to the platform.
7445 ///
7446 /// When this is `false`, `wgpu` only enforces such bounds checks if the
7447 /// underlying platform provides a way to do so itself. `wgpu` does not
7448 /// itself add any bounds checks to generated shader code.
7449 ///
7450 /// Note that `wgpu` users may try to initialize only those portions of
7451 /// buffers that they anticipate might be read from. Passing `false` here
7452 /// may allow shaders to see wider regions of the buffers than expected,
7453 /// making such deferred initialization visible to the application.
7454 pub bounds_checks: bool,
7455 ///
7456 /// If false, the caller MUST ensure that all passed shaders do not contain any infinite loops.
7457 ///
7458 /// If it does, backend compilers MAY treat such a loop as unreachable code and draw
7459 /// conclusions about other safety-critical code paths. This option SHOULD NOT be disabled
7460 /// when running untrusted code.
7461 pub force_loop_bounding: bool,
7462}
7463
7464impl ShaderRuntimeChecks {
7465 /// Creates a new configuration where the shader is fully checked.
7466 #[must_use]
7467 pub fn checked() -> Self {
7468 unsafe { Self::all(true) }
7469 }
7470
7471 /// Creates a new configuration where none of the checks are performed.
7472 ///
7473 /// # Safety
7474 ///
7475 /// See the documentation for the `set_*` methods for the safety requirements
7476 /// of each sub-configuration.
7477 #[must_use]
7478 pub fn unchecked() -> Self {
7479 unsafe { Self::all(false) }
7480 }
7481
7482 /// Creates a new configuration where all checks are enabled or disabled. To safely
7483 /// create a configuration with all checks enabled, use [`ShaderRuntimeChecks::checked`].
7484 ///
7485 /// # Safety
7486 ///
7487 /// See the documentation for the `set_*` methods for the safety requirements
7488 /// of each sub-configuration.
7489 #[must_use]
7490 pub unsafe fn all(all_checks: bool) -> Self {
7491 Self {
7492 bounds_checks: all_checks,
7493 force_loop_bounding: all_checks,
7494 }
7495 }
7496}
7497
7498impl Default for ShaderRuntimeChecks {
7499 fn default() -> Self {
7500 Self::checked()
7501 }
7502}
7503
7504#[derive(Clone, Debug, PartialEq, Eq)]
7505#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7506/// Descriptor for all size defining attributes of a single triangle geometry inside a bottom level acceleration structure.
7507pub struct BlasTriangleGeometrySizeDescriptor {
7508 /// Format of a vertex position, must be [`VertexFormat::Float32x3`]
7509 /// with just [`Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE`]
7510 /// but [`Features::EXTENDED_ACCELERATION_STRUCTURE_VERTEX_FORMATS`] adds more.
7511 pub vertex_format: VertexFormat,
7512 /// Number of vertices.
7513 pub vertex_count: u32,
7514 /// Format of an index. Only needed if an index buffer is used.
7515 /// If `index_format` is provided `index_count` is required.
7516 pub index_format: Option<IndexFormat>,
7517 /// Number of indices. Only needed if an index buffer is used.
7518 /// If `index_count` is provided `index_format` is required.
7519 pub index_count: Option<u32>,
7520 /// Flags for the geometry.
7521 pub flags: AccelerationStructureGeometryFlags,
7522}
7523
7524#[derive(Clone, Debug)]
7525#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7526/// Descriptor for all size defining attributes of all geometries inside a bottom level acceleration structure.
7527pub enum BlasGeometrySizeDescriptors {
7528 /// Triangle geometry version.
7529 Triangles {
7530 /// Descriptor for each triangle geometry.
7531 descriptors: Vec<BlasTriangleGeometrySizeDescriptor>,
7532 },
7533}
7534
7535#[repr(u8)]
7536#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
7537#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7538/// Update mode for acceleration structure builds.
7539pub enum AccelerationStructureUpdateMode {
7540 /// Always perform a full build.
7541 Build,
7542 /// If possible, perform an incremental update.
7543 ///
7544 /// Not advised for major topology changes.
7545 /// (Useful for e.g. skinning)
7546 PreferUpdate,
7547}
7548
7549#[repr(C)]
7550#[derive(Clone, Debug, PartialEq, Eq, Hash)]
7551#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7552/// Descriptor for creating a bottom level acceleration structure.
7553pub struct CreateBlasDescriptor<L> {
7554 /// Label for the bottom level acceleration structure.
7555 pub label: L,
7556 /// Flags for the bottom level acceleration structure.
7557 pub flags: AccelerationStructureFlags,
7558 /// Update mode for the bottom level acceleration structure.
7559 pub update_mode: AccelerationStructureUpdateMode,
7560}
7561
7562impl<L> CreateBlasDescriptor<L> {
7563 /// Takes a closure and maps the label of the blas descriptor into another.
7564 pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> CreateBlasDescriptor<K> {
7565 CreateBlasDescriptor {
7566 label: fun(&self.label),
7567 flags: self.flags,
7568 update_mode: self.update_mode,
7569 }
7570 }
7571}
7572
7573#[repr(C)]
7574#[derive(Clone, Debug, PartialEq, Eq, Hash)]
7575#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7576/// Descriptor for creating a top level acceleration structure.
7577pub struct CreateTlasDescriptor<L> {
7578 /// Label for the top level acceleration structure.
7579 pub label: L,
7580 /// Number of instances that can be stored in the acceleration structure.
7581 pub max_instances: u32,
7582 /// Flags for the bottom level acceleration structure.
7583 pub flags: AccelerationStructureFlags,
7584 /// Update mode for the bottom level acceleration structure.
7585 pub update_mode: AccelerationStructureUpdateMode,
7586}
7587
7588impl<L> CreateTlasDescriptor<L> {
7589 /// Takes a closure and maps the label of the blas descriptor into another.
7590 pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> CreateTlasDescriptor<K> {
7591 CreateTlasDescriptor {
7592 label: fun(&self.label),
7593 flags: self.flags,
7594 update_mode: self.update_mode,
7595 max_instances: self.max_instances,
7596 }
7597 }
7598}
7599
7600bitflags::bitflags!(
7601 /// Flags for acceleration structures
7602 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7603 #[cfg_attr(feature = "serde", serde(transparent))]
7604 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
7605 pub struct AccelerationStructureFlags: u8 {
7606 /// Allow for incremental updates (no change in size), currently this is unimplemented
7607 /// and will build as normal (this is fine, update vs build should be unnoticeable)
7608 const ALLOW_UPDATE = 1 << 0;
7609 /// Allow the acceleration structure to be compacted in a copy operation
7610 /// (`Blas::prepare_for_compaction`, `CommandEncoder::compact_blas`).
7611 const ALLOW_COMPACTION = 1 << 1;
7612 /// Optimize for fast ray tracing performance, recommended if the geometry is unlikely
7613 /// to change (e.g. in a game: non-interactive scene geometry)
7614 const PREFER_FAST_TRACE = 1 << 2;
7615 /// Optimize for fast build time, recommended if geometry is likely to change frequently
7616 /// (e.g. in a game: player model).
7617 const PREFER_FAST_BUILD = 1 << 3;
7618 /// Optimize for low memory footprint (both while building and in the output BLAS).
7619 const LOW_MEMORY = 1 << 4;
7620 /// Use `BlasTriangleGeometry::transform_buffer` when building a BLAS (only allowed in
7621 /// BLAS creation)
7622 const USE_TRANSFORM = 1 << 5;
7623 /// Allow retrieval of the vertices of the triangle hit by a ray.
7624 const ALLOW_RAY_HIT_VERTEX_RETURN = 1 << 6;
7625 }
7626);
7627
7628bitflags::bitflags!(
7629 /// Flags for acceleration structure geometries
7630 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7631 #[cfg_attr(feature = "serde", serde(transparent))]
7632 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
7633 pub struct AccelerationStructureGeometryFlags: u8 {
7634 /// Is OPAQUE (is there no alpha test) recommended as currently in naga there is no
7635 /// candidate intersections yet so currently BLASes without this flag will not have hits.
7636 /// Not enabling this makes the BLAS unable to be interacted with in WGSL.
7637 const OPAQUE = 1 << 0;
7638 /// NO_DUPLICATE_ANY_HIT_INVOCATION, not useful unless using hal with wgpu, ray-tracing
7639 /// pipelines are not supported in wgpu so any-hit shaders do not exist. For when any-hit
7640 /// shaders are implemented (or experienced users who combine this with an underlying library:
7641 /// for any primitive (triangle or AABB) multiple any-hit shaders sometimes may be invoked
7642 /// (especially in AABBs like a sphere), if this flag in present only one hit on a primitive may
7643 /// invoke an any-hit shader.
7644 const NO_DUPLICATE_ANY_HIT_INVOCATION = 1 << 1;
7645 }
7646);
7647
7648#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
7649/// What a copy between acceleration structures should do
7650pub enum AccelerationStructureCopy {
7651 /// Directly duplicate an acceleration structure to another
7652 Clone,
7653 /// Duplicate and compact an acceleration structure
7654 Compact,
7655}
7656
7657#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
7658/// What type the data of an acceleration structure is
7659pub enum AccelerationStructureType {
7660 /// The types of the acceleration structure are triangles
7661 Triangles,
7662 /// The types of the acceleration structure are axis aligned bounding boxes
7663 AABBs,
7664 /// The types of the acceleration structure are instances
7665 Instances,
7666}
7667
7668/// Alignment requirement for transform buffers used in acceleration structure builds
7669pub const TRANSFORM_BUFFER_ALIGNMENT: BufferAddress = 16;
7670
7671/// Alignment requirement for instance buffers used in acceleration structure builds (`build_acceleration_structures_unsafe_tlas`)
7672pub const INSTANCE_BUFFER_ALIGNMENT: BufferAddress = 16;
7673
7674pub use send_sync::*;
7675
7676#[doc(hidden)]
7677mod send_sync {
7678 pub trait WasmNotSendSync: WasmNotSend + WasmNotSync {}
7679 impl<T: WasmNotSend + WasmNotSync> WasmNotSendSync for T {}
7680 #[cfg(any(
7681 not(target_arch = "wasm32"),
7682 all(
7683 feature = "fragile-send-sync-non-atomic-wasm",
7684 not(target_feature = "atomics")
7685 )
7686 ))]
7687 pub trait WasmNotSend: Send {}
7688 #[cfg(any(
7689 not(target_arch = "wasm32"),
7690 all(
7691 feature = "fragile-send-sync-non-atomic-wasm",
7692 not(target_feature = "atomics")
7693 )
7694 ))]
7695 impl<T: Send> WasmNotSend for T {}
7696 #[cfg(not(any(
7697 not(target_arch = "wasm32"),
7698 all(
7699 feature = "fragile-send-sync-non-atomic-wasm",
7700 not(target_feature = "atomics")
7701 )
7702 )))]
7703 pub trait WasmNotSend {}
7704 #[cfg(not(any(
7705 not(target_arch = "wasm32"),
7706 all(
7707 feature = "fragile-send-sync-non-atomic-wasm",
7708 not(target_feature = "atomics")
7709 )
7710 )))]
7711 impl<T> WasmNotSend for T {}
7712
7713 #[cfg(any(
7714 not(target_arch = "wasm32"),
7715 all(
7716 feature = "fragile-send-sync-non-atomic-wasm",
7717 not(target_feature = "atomics")
7718 )
7719 ))]
7720 pub trait WasmNotSync: Sync {}
7721 #[cfg(any(
7722 not(target_arch = "wasm32"),
7723 all(
7724 feature = "fragile-send-sync-non-atomic-wasm",
7725 not(target_feature = "atomics")
7726 )
7727 ))]
7728 impl<T: Sync> WasmNotSync for T {}
7729 #[cfg(not(any(
7730 not(target_arch = "wasm32"),
7731 all(
7732 feature = "fragile-send-sync-non-atomic-wasm",
7733 not(target_feature = "atomics")
7734 )
7735 )))]
7736 pub trait WasmNotSync {}
7737 #[cfg(not(any(
7738 not(target_arch = "wasm32"),
7739 all(
7740 feature = "fragile-send-sync-non-atomic-wasm",
7741 not(target_feature = "atomics")
7742 )
7743 )))]
7744 impl<T> WasmNotSync for T {}
7745}
7746
7747/// Corresponds to a [`GPUDeviceLostReason`].
7748///
7749/// [`GPUDeviceLostReason`]: https://www.w3.org/TR/webgpu/#enumdef-gpudevicelostreason
7750#[repr(u8)]
7751#[derive(Debug, Copy, Clone, Eq, PartialEq)]
7752#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7753pub enum DeviceLostReason {
7754 /// The device was lost for an unspecific reason, including driver errors.
7755 Unknown = 0,
7756 /// The device's `destroy` method was called.
7757 Destroyed = 1,
7758}
7759
7760/// Descriptor for creating a shader module.
7761///
7762/// This type is unique to the Rust API of `wgpu`. In the WebGPU specification,
7763/// only WGSL source code strings are accepted.
7764#[derive(Debug, Clone)]
7765pub enum CreateShaderModuleDescriptorPassthrough<'a, L> {
7766 /// Passthrough for SPIR-V binaries.
7767 SpirV(ShaderModuleDescriptorSpirV<'a, L>),
7768 /// Passthrough for MSL source code.
7769 Msl(ShaderModuleDescriptorMsl<'a, L>),
7770 /// Passthrough for DXIL compiled with DXC
7771 Dxil(ShaderModuleDescriptorDxil<'a, L>),
7772 /// Passthrough for HLSL
7773 Hlsl(ShaderModuleDescriptorHlsl<'a, L>),
7774}
7775
7776impl<'a, L> CreateShaderModuleDescriptorPassthrough<'a, L> {
7777 /// Takes a closure and maps the label of the shader module descriptor into another.
7778 pub fn map_label<K>(
7779 &self,
7780 fun: impl FnOnce(&L) -> K,
7781 ) -> CreateShaderModuleDescriptorPassthrough<'_, K> {
7782 match self {
7783 CreateShaderModuleDescriptorPassthrough::SpirV(inner) => {
7784 CreateShaderModuleDescriptorPassthrough::<'_, K>::SpirV(
7785 ShaderModuleDescriptorSpirV {
7786 label: fun(&inner.label),
7787 source: inner.source.clone(),
7788 },
7789 )
7790 }
7791 CreateShaderModuleDescriptorPassthrough::Msl(inner) => {
7792 CreateShaderModuleDescriptorPassthrough::<'_, K>::Msl(ShaderModuleDescriptorMsl {
7793 entry_point: inner.entry_point.clone(),
7794 label: fun(&inner.label),
7795 num_workgroups: inner.num_workgroups,
7796 source: inner.source.clone(),
7797 })
7798 }
7799 CreateShaderModuleDescriptorPassthrough::Dxil(inner) => {
7800 CreateShaderModuleDescriptorPassthrough::<'_, K>::Dxil(ShaderModuleDescriptorDxil {
7801 entry_point: inner.entry_point.clone(),
7802 label: fun(&inner.label),
7803 num_workgroups: inner.num_workgroups,
7804 source: inner.source,
7805 })
7806 }
7807 CreateShaderModuleDescriptorPassthrough::Hlsl(inner) => {
7808 CreateShaderModuleDescriptorPassthrough::<'_, K>::Hlsl(ShaderModuleDescriptorHlsl {
7809 entry_point: inner.entry_point.clone(),
7810 label: fun(&inner.label),
7811 num_workgroups: inner.num_workgroups,
7812 source: inner.source,
7813 })
7814 }
7815 }
7816 }
7817
7818 /// Returns the label of shader module passthrough descriptor.
7819 pub fn label(&'a self) -> &'a L {
7820 match self {
7821 CreateShaderModuleDescriptorPassthrough::SpirV(inner) => &inner.label,
7822 CreateShaderModuleDescriptorPassthrough::Msl(inner) => &inner.label,
7823 CreateShaderModuleDescriptorPassthrough::Dxil(inner) => &inner.label,
7824 CreateShaderModuleDescriptorPassthrough::Hlsl(inner) => &inner.label,
7825 }
7826 }
7827
7828 #[cfg(feature = "trace")]
7829 /// Returns the source data for tracing purpose.
7830 pub fn trace_data(&self) -> &[u8] {
7831 match self {
7832 CreateShaderModuleDescriptorPassthrough::SpirV(inner) => {
7833 bytemuck::cast_slice(&inner.source)
7834 }
7835 CreateShaderModuleDescriptorPassthrough::Msl(inner) => inner.source.as_bytes(),
7836 CreateShaderModuleDescriptorPassthrough::Dxil(inner) => inner.source,
7837 CreateShaderModuleDescriptorPassthrough::Hlsl(inner) => inner.source.as_bytes(),
7838 }
7839 }
7840
7841 #[cfg(feature = "trace")]
7842 /// Returns the binary file extension for tracing purpose.
7843 pub fn trace_binary_ext(&self) -> &'static str {
7844 match self {
7845 CreateShaderModuleDescriptorPassthrough::SpirV(..) => "spv",
7846 CreateShaderModuleDescriptorPassthrough::Msl(..) => "msl",
7847 CreateShaderModuleDescriptorPassthrough::Dxil(..) => "dxil",
7848 CreateShaderModuleDescriptorPassthrough::Hlsl(..) => "hlsl",
7849 }
7850 }
7851}
7852
7853/// Descriptor for a shader module given by Metal MSL source.
7854///
7855/// This type is unique to the Rust API of `wgpu`. In the WebGPU specification,
7856/// only WGSL source code strings are accepted.
7857#[derive(Debug, Clone)]
7858pub struct ShaderModuleDescriptorMsl<'a, L> {
7859 /// Entrypoint.
7860 pub entry_point: String,
7861 /// Debug label of the shader module. This will show up in graphics debuggers for easy identification.
7862 pub label: L,
7863 /// Number of workgroups in each dimension x, y and z.
7864 pub num_workgroups: (u32, u32, u32),
7865 /// Shader MSL source.
7866 pub source: Cow<'a, str>,
7867}
7868
7869/// Descriptor for a shader module given by DirectX DXIL source.
7870///
7871/// This type is unique to the Rust API of `wgpu`. In the WebGPU specification,
7872/// only WGSL source code strings are accepted.
7873#[derive(Debug, Clone)]
7874pub struct ShaderModuleDescriptorDxil<'a, L> {
7875 /// Entrypoint.
7876 pub entry_point: String,
7877 /// Debug label of the shader module. This will show up in graphics debuggers for easy identification.
7878 pub label: L,
7879 /// Number of workgroups in each dimension x, y and z.
7880 pub num_workgroups: (u32, u32, u32),
7881 /// Shader DXIL source.
7882 pub source: &'a [u8],
7883}
7884
7885/// Descriptor for a shader module given by DirectX HLSL source.
7886///
7887/// This type is unique to the Rust API of `wgpu`. In the WebGPU specification,
7888/// only WGSL source code strings are accepted.
7889#[derive(Debug, Clone)]
7890pub struct ShaderModuleDescriptorHlsl<'a, L> {
7891 /// Entrypoint.
7892 pub entry_point: String,
7893 /// Debug label of the shader module. This will show up in graphics debuggers for easy identification.
7894 pub label: L,
7895 /// Number of workgroups in each dimension x, y and z.
7896 pub num_workgroups: (u32, u32, u32),
7897 /// Shader HLSL source.
7898 pub source: &'a str,
7899}
7900
7901/// Descriptor for a shader module given by SPIR-V binary.
7902///
7903/// This type is unique to the Rust API of `wgpu`. In the WebGPU specification,
7904/// only WGSL source code strings are accepted.
7905#[derive(Debug, Clone)]
7906pub struct ShaderModuleDescriptorSpirV<'a, L> {
7907 /// Debug label of the shader module. This will show up in graphics debuggers for easy identification.
7908 pub label: L,
7909 /// Binary SPIR-V data, in 4-byte words.
7910 pub source: Cow<'a, [u32]>,
7911}