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