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