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