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