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