1#![doc = document_features::document_features!()]
7#![no_std]
10#![recursion_limit = "256"]
12#![cfg_attr(
14 all(
15 not(all(feature = "vulkan", not(target_arch = "wasm32"))),
16 not(all(feature = "metal", any(target_vendor = "apple"))),
17 not(all(feature = "dx12", windows)),
18 not(feature = "gles"),
19 ),
20 allow(unused, clippy::let_and_return)
21)]
22#![cfg_attr(docsrs, feature(doc_cfg))]
23#![allow(
24 clippy::bool_assert_comparison,
26 clippy::match_like_matches_macro,
28 clippy::redundant_pattern_matching,
30 clippy::needless_lifetimes,
32 clippy::new_without_default,
34 clippy::needless_update,
36 clippy::too_many_arguments,
38 clippy::pattern_type_mismatch,
40 rustdoc::private_intra_doc_links,
42)]
43#![warn(
44 clippy::alloc_instead_of_core,
45 clippy::ptr_as_ptr,
46 clippy::std_instead_of_alloc,
47 clippy::std_instead_of_core,
48 trivial_casts,
49 trivial_numeric_casts,
50 unsafe_op_in_unsafe_fn,
51 unused_extern_crates,
52 unused_qualifications
53)]
54#![cfg_attr(not(send_sync), allow(clippy::arc_with_non_send_sync))]
63
64extern crate alloc;
65#[cfg(feature = "std")]
66extern crate std;
67extern crate wgpu_hal as hal;
68extern crate wgpu_types as wgt;
69
70mod as_hal;
71pub mod binding_model;
72pub mod command;
73mod conv;
74pub mod device;
75pub mod error;
76pub mod global;
77mod hash_utils;
78pub mod hub;
79pub mod id;
80pub mod identity;
81mod indirect_validation;
82mod init_tracker;
83pub mod instance;
84pub mod limits;
85mod lock;
86pub mod pipeline;
87mod pipeline_cache;
88mod pool;
89pub mod present;
90pub mod ray_tracing;
91pub mod registry;
92pub mod resource;
93mod snatch;
94pub mod storage;
95mod timestamp_normalization;
96mod track;
97mod weak_vec;
98mod scratch;
103pub mod validation;
104
105pub use validation::{map_storage_format_from_naga, map_storage_format_to_naga};
106
107pub use hal::{api, MAX_BIND_GROUPS, MAX_COLOR_ATTACHMENTS, MAX_VERTEX_BUFFERS};
108pub use naga;
109
110use alloc::{
111 borrow::{Cow, ToOwned as _},
112 string::String,
113};
114
115pub(crate) use hash_utils::*;
116
117pub type SubmissionIndex = hal::FenceValue;
121
122type Index = u32;
123type Epoch = u32;
124
125pub type RawString = *const core::ffi::c_char;
126pub type Label<'a> = Option<Cow<'a, str>>;
127
128trait LabelHelpers<'a> {
129 fn to_hal(&'a self, flags: wgt::InstanceFlags) -> Option<&'a str>;
130 fn to_string(&self) -> String;
131}
132impl<'a> LabelHelpers<'a> for Label<'a> {
133 fn to_hal(&'a self, flags: wgt::InstanceFlags) -> Option<&'a str> {
134 if flags.contains(wgt::InstanceFlags::DISCARD_HAL_LABELS) {
135 return None;
136 }
137
138 self.as_deref()
139 }
140 fn to_string(&self) -> String {
141 self.as_deref().map(str::to_owned).unwrap_or_default()
142 }
143}
144
145pub fn hal_label<T: AsRef<str>>(opt: Option<T>, flags: wgt::InstanceFlags) -> Option<T> {
146 if flags.contains(wgt::InstanceFlags::DISCARD_HAL_LABELS) {
147 return None;
148 }
149
150 opt
151}
152
153const DOWNLEVEL_WARNING_MESSAGE: &str = concat!(
154 "The underlying API or device in use does not ",
155 "support enough features to be a fully compliant implementation of WebGPU. ",
156 "A subset of the features can still be used. ",
157 "If you are running this program on native and not in a browser and wish to limit ",
158 "the features you use to the supported subset, ",
159 "call Adapter::downlevel_properties or Device::downlevel_properties to get ",
160 "a listing of the features the current ",
161 "platform supports."
162);
163
164const DOWNLEVEL_ERROR_MESSAGE: &str = concat!(
165 "This is not an invalid use of WebGPU: the underlying API or device does not ",
166 "support enough features to be a fully compliant implementation. ",
167 "A subset of the features can still be used. ",
168 "If you are running this program on native and not in a browser ",
169 "and wish to work around this issue, call ",
170 "Adapter::downlevel_properties or Device::downlevel_properties ",
171 "to get a listing of the features the current platform supports."
172);
173
174#[cfg(feature = "api_log_info")]
175macro_rules! api_log {
176 ($($arg:tt)+) => (log::info!($($arg)+))
177}
178#[cfg(not(feature = "api_log_info"))]
179macro_rules! api_log {
180 ($($arg:tt)+) => (log::trace!($($arg)+))
181}
182
183#[cfg(feature = "api_log_info")]
184macro_rules! api_log_debug {
185 ($($arg:tt)+) => (log::info!($($arg)+))
186}
187#[cfg(not(feature = "api_log_info"))]
188macro_rules! api_log_debug {
189 ($($arg:tt)+) => (log::debug!($($arg)+))
190}
191
192pub(crate) use api_log;
193pub(crate) use api_log_debug;
194
195#[cfg(feature = "resource_log_info")]
196macro_rules! resource_log {
197 ($($arg:tt)+) => (log::info!($($arg)+))
198}
199#[cfg(not(feature = "resource_log_info"))]
200macro_rules! resource_log {
201 ($($arg:tt)+) => (log::trace!($($arg)+))
202}
203pub(crate) use resource_log;
204
205#[inline]
206pub(crate) fn get_lowest_common_denom(a: u32, b: u32) -> u32 {
207 let gcd = if a >= b {
208 get_greatest_common_divisor(a, b)
209 } else {
210 get_greatest_common_divisor(b, a)
211 };
212 a * b / gcd
213}
214
215#[inline]
216pub(crate) fn get_greatest_common_divisor(mut a: u32, mut b: u32) -> u32 {
217 assert!(a >= b);
218 loop {
219 let c = a % b;
220 if c == 0 {
221 return b;
222 } else {
223 a = b;
224 b = c;
225 }
226 }
227}
228
229#[cfg(not(feature = "std"))]
230use core::cell::OnceCell as OnceCellOrLock;
231#[cfg(feature = "std")]
232use std::sync::OnceLock as OnceCellOrLock;
233
234#[cfg(test)]
235mod tests {
236 use super::*;
237
238 #[test]
239 fn test_lcd() {
240 assert_eq!(get_lowest_common_denom(2, 2), 2);
241 assert_eq!(get_lowest_common_denom(2, 3), 6);
242 assert_eq!(get_lowest_common_denom(6, 4), 12);
243 }
244
245 #[test]
246 fn test_gcd() {
247 assert_eq!(get_greatest_common_divisor(5, 1), 1);
248 assert_eq!(get_greatest_common_divisor(4, 2), 2);
249 assert_eq!(get_greatest_common_divisor(6, 4), 2);
250 assert_eq!(get_greatest_common_divisor(7, 7), 7);
251 }
252}