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