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