wgpu_core/
lib.rs

1//! This library safely implements WebGPU on native platforms.
2//! It is designed for integration into browsers, as well as wrapping
3//! into other language-specific user-friendly libraries.
4//!
5//! ## Feature flags
6#![doc = document_features::document_features!()]
7//!
8
9// When we have no backends, we end up with a lot of dead or otherwise unreachable code.
10#![cfg_attr(
11    all(
12        not(all(feature = "vulkan", not(target_arch = "wasm32"))),
13        not(all(feature = "metal", any(target_vendor = "apple"))),
14        not(all(feature = "dx12", windows)),
15        not(feature = "gles"),
16    ),
17    allow(unused, clippy::let_and_return)
18)]
19#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
20#![allow(
21    // It is much clearer to assert negative conditions with eq! false
22    clippy::bool_assert_comparison,
23    // We don't use syntax sugar where it's not necessary.
24    clippy::match_like_matches_macro,
25    // Redundant matching is more explicit.
26    clippy::redundant_pattern_matching,
27    // Explicit lifetimes are often easier to reason about.
28    clippy::needless_lifetimes,
29    // No need for defaults in the internal types.
30    clippy::new_without_default,
31    // Needless updates are more scalable, easier to play with features.
32    clippy::needless_update,
33    // Need many arguments for some core functions to be able to re-use code in many situations.
34    clippy::too_many_arguments,
35    // For some reason `rustc` can warn about these in const generics even
36    // though they are required.
37    unused_braces,
38    // It gets in the way a lot and does not prevent bugs in practice.
39    clippy::pattern_type_mismatch,
40    // `wgpu-core` isn't entirely user-facing, so it's useful to document internal items.
41    rustdoc::private_intra_doc_links
42)]
43#![warn(
44    clippy::ptr_as_ptr,
45    trivial_casts,
46    trivial_numeric_casts,
47    unsafe_op_in_unsafe_fn,
48    unused_extern_crates,
49    unused_qualifications
50)]
51// We use `Arc` in wgpu-core, but on wasm (unless opted out via `fragile-send-sync-non-atomic-wasm`)
52// wgpu-hal resources are not Send/Sync, causing a clippy warning for unnecessary `Arc`s.
53// We could use `Rc`s in this case as recommended, but unless atomics are enabled
54// this doesn't make a difference.
55// Therefore, this is only really a concern for users targeting WebGL
56// (the only reason to use wgpu-core on the web in the first place) that have atomics enabled.
57#![cfg_attr(not(send_sync), allow(clippy::arc_with_non_send_sync))]
58
59pub mod binding_model;
60pub mod command;
61mod conv;
62pub mod device;
63pub mod error;
64pub mod global;
65pub mod hal_api;
66mod hash_utils;
67pub mod hub;
68pub mod id;
69pub mod identity;
70#[cfg(feature = "indirect-validation")]
71mod indirect_validation;
72mod init_tracker;
73pub mod instance;
74mod lock;
75pub mod pipeline;
76mod pipeline_cache;
77mod pool;
78pub mod present;
79pub mod ray_tracing;
80pub mod registry;
81pub mod resource;
82mod snatch;
83pub mod storage;
84mod track;
85mod weak_vec;
86// This is public for users who pre-compile shaders while still wanting to
87// preserve all run-time checks that `wgpu-core` does.
88// See <https://github.com/gfx-rs/wgpu/issues/3103>, after which this can be
89// made private again.
90mod scratch;
91pub mod validation;
92
93pub use validation::{map_storage_format_from_naga, map_storage_format_to_naga};
94
95pub use hal::{api, MAX_BIND_GROUPS, MAX_COLOR_ATTACHMENTS, MAX_VERTEX_BUFFERS};
96pub use naga;
97
98use std::{borrow::Cow, os::raw::c_char};
99
100pub(crate) use hash_utils::*;
101
102/// The index of a queue submission.
103///
104/// These are the values stored in `Device::fence`.
105pub type SubmissionIndex = hal::FenceValue;
106
107type Index = u32;
108type Epoch = u32;
109
110pub type RawString = *const c_char;
111pub type Label<'a> = Option<Cow<'a, str>>;
112
113trait LabelHelpers<'a> {
114    fn to_hal(&'a self, flags: wgt::InstanceFlags) -> Option<&'a str>;
115    fn to_string(&self) -> String;
116}
117impl<'a> LabelHelpers<'a> for Label<'a> {
118    fn to_hal(&'a self, flags: wgt::InstanceFlags) -> Option<&'a str> {
119        if flags.contains(wgt::InstanceFlags::DISCARD_HAL_LABELS) {
120            return None;
121        }
122
123        self.as_ref().map(|cow| cow.as_ref())
124    }
125    fn to_string(&self) -> String {
126        self.as_ref().map(|cow| cow.to_string()).unwrap_or_default()
127    }
128}
129
130pub fn hal_label(opt: Option<&str>, flags: wgt::InstanceFlags) -> Option<&str> {
131    if flags.contains(wgt::InstanceFlags::DISCARD_HAL_LABELS) {
132        return None;
133    }
134
135    opt
136}
137
138const DOWNLEVEL_WARNING_MESSAGE: &str = concat!(
139    "The underlying API or device in use does not ",
140    "support enough features to be a fully compliant implementation of WebGPU. ",
141    "A subset of the features can still be used. ",
142    "If you are running this program on native and not in a browser and wish to limit ",
143    "the features you use to the supported subset, ",
144    "call Adapter::downlevel_properties or Device::downlevel_properties to get ",
145    "a listing of the features the current ",
146    "platform supports."
147);
148
149const DOWNLEVEL_ERROR_MESSAGE: &str = concat!(
150    "This is not an invalid use of WebGPU: the underlying API or device does not ",
151    "support enough features to be a fully compliant implementation. ",
152    "A subset of the features can still be used. ",
153    "If you are running this program on native and not in a browser ",
154    "and wish to work around this issue, call ",
155    "Adapter::downlevel_properties or Device::downlevel_properties ",
156    "to get a listing of the features the current platform supports."
157);
158
159#[cfg(feature = "api_log_info")]
160macro_rules! api_log {
161    ($($arg:tt)+) => (log::info!($($arg)+))
162}
163#[cfg(not(feature = "api_log_info"))]
164macro_rules! api_log {
165    ($($arg:tt)+) => (log::trace!($($arg)+))
166}
167
168#[cfg(feature = "api_log_info")]
169macro_rules! api_log_debug {
170    ($($arg:tt)+) => (log::info!($($arg)+))
171}
172#[cfg(not(feature = "api_log_info"))]
173macro_rules! api_log_debug {
174    ($($arg:tt)+) => (log::debug!($($arg)+))
175}
176
177pub(crate) use api_log;
178pub(crate) use api_log_debug;
179
180#[cfg(feature = "resource_log_info")]
181macro_rules! resource_log {
182    ($($arg:tt)+) => (log::info!($($arg)+))
183}
184#[cfg(not(feature = "resource_log_info"))]
185macro_rules! resource_log {
186    ($($arg:tt)+) => (log::trace!($($arg)+))
187}
188pub(crate) use resource_log;
189
190#[inline]
191pub(crate) fn get_lowest_common_denom(a: u32, b: u32) -> u32 {
192    let gcd = if a >= b {
193        get_greatest_common_divisor(a, b)
194    } else {
195        get_greatest_common_divisor(b, a)
196    };
197    a * b / gcd
198}
199
200#[inline]
201pub(crate) fn get_greatest_common_divisor(mut a: u32, mut b: u32) -> u32 {
202    assert!(a >= b);
203    loop {
204        let c = a % b;
205        if c == 0 {
206            return b;
207        } else {
208            a = b;
209            b = c;
210        }
211    }
212}
213
214#[test]
215fn test_lcd() {
216    assert_eq!(get_lowest_common_denom(2, 2), 2);
217    assert_eq!(get_lowest_common_denom(2, 3), 6);
218    assert_eq!(get_lowest_common_denom(6, 4), 12);
219}
220
221#[test]
222fn test_gcd() {
223    assert_eq!(get_greatest_common_divisor(5, 1), 1);
224    assert_eq!(get_greatest_common_divisor(4, 2), 2);
225    assert_eq!(get_greatest_common_divisor(6, 4), 2);
226    assert_eq!(get_greatest_common_divisor(7, 7), 7);
227}