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