diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a1495e081bb..a932721b729 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -181,6 +181,14 @@ jobs: tier: 2 kind: no_std + # 32-bit PowerPC Linux + # Included to test support for `portable-atomic` + - name: Linux ppc32 + os: ubuntu-22.04 + target: powerpc-unknown-linux-gnu + tier: 2 + kind: wgpu-only + name: Clippy ${{ matrix.name }} runs-on: ${{ matrix.os }} diff --git a/Cargo.lock b/Cargo.lock index 1198532882e..e440ef3367d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1305,7 +1305,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2004,7 +2004,7 @@ checksum = "e19b23d53f35ce9f56aebc7d1bb4e6ac1e9c0db7ac85c8d1760c04379edced37" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2134,7 +2134,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -3043,6 +3043,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" +[[package]] +name = "portable-atomic" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" + [[package]] name = "pp-rs" version = "0.2.1" @@ -3336,7 +3342,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4005,7 +4011,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69fff37da548239c3bf9e64a12193d261e8b22b660991c6fd2df057c168f435f" dependencies = [ "cc", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -4507,6 +4513,7 @@ dependencies = [ "log", "naga", "parking_lot", + "portable-atomic", "profiling", "raw-window-handle 0.6.2", "smallvec", @@ -4551,6 +4558,7 @@ dependencies = [ "naga", "once_cell", "parking_lot", + "portable-atomic", "profiling", "raw-window-handle 0.6.2", "ron", @@ -4681,6 +4689,7 @@ dependencies = [ "once_cell", "ordered-float", "parking_lot", + "portable-atomic", "profiling", "range-alloc", "raw-window-handle 0.5.2", @@ -4804,7 +4813,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 38a0b60ce6b..f0608b43cc9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -135,6 +135,7 @@ pico-args = { version = "0.5.0", features = [ ] } png = "0.17.16" pollster = "0.4" +portable-atomic = "1" profiling = { version = "1", default-features = false } raw-window-handle = { version = "0.6", default-features = false } rayon = "1" diff --git a/wgpu-core/Cargo.toml b/wgpu-core/Cargo.toml index 863769913d7..bf8e84eefe9 100644 --- a/wgpu-core/Cargo.toml +++ b/wgpu-core/Cargo.toml @@ -114,6 +114,9 @@ fragile-send-sync-non-atomic-wasm = [ ## Enable using the `mach-dxcompiler-rs` crate to compile DX12 shaders. static-dxc = ["wgpu-hal/static-dxc"] +## Enable portable atomics on platforms that do not support 64bit atomics. +portable-atomic = ["dep:portable-atomic", "wgpu-hal/portable-atomic"] + #! ### Target Conditional Features # -------------------------------------------------------------------- # Look to wgpu-hal's Cargo.toml for explaination how these features and the wgpu-core @@ -179,5 +182,8 @@ serde = { workspace = true, features = ["default", "derive"], optional = true } smallvec.workspace = true thiserror.workspace = true +[target.'cfg(not(target_has_atomic = "64"))'.dependencies] +portable-atomic = { workspace = true, optional = true } + [build-dependencies] cfg_aliases.workspace = true diff --git a/wgpu-core/build.rs b/wgpu-core/build.rs index 55c43fba209..fde109a7fa1 100644 --- a/wgpu-core/build.rs +++ b/wgpu-core/build.rs @@ -18,5 +18,7 @@ fn main() { all(target_vendor = "apple", feature = "vulkan-portability") // Vulkan Portability on Apple ) }, metal: { all(target_vendor = "apple", feature = "metal") }, + + supports_64bit_atomics: { target_has_atomic = "64" } } } diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index 036140e31ba..69a62ab1191 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -9,7 +9,7 @@ use core::{ fmt, mem::{self, ManuallyDrop}, num::NonZeroU32, - sync::atomic::{AtomicBool, AtomicU64, Ordering}, + sync::atomic::{AtomicBool, Ordering}, }; use std::sync::OnceLock; @@ -57,6 +57,11 @@ use super::{ ENTRYPOINT_FAILURE_ERROR, ZERO_BUFFER_SIZE, }; +#[cfg(supports_64bit_atomics)] +use core::sync::atomic::AtomicU64; +#[cfg(not(supports_64bit_atomics))] +use portable_atomic::AtomicU64; + /// Structure describing a logical device. Some members are internally mutable, /// stored behind mutexes. pub struct Device { diff --git a/wgpu-hal/Cargo.toml b/wgpu-hal/Cargo.toml index 9255d507a76..dedf4e1014f 100644 --- a/wgpu-hal/Cargo.toml +++ b/wgpu-hal/Cargo.toml @@ -155,6 +155,7 @@ renderdoc = ["dep:libloading", "dep:renderdoc-sys", "dep:log"] fragile-send-sync-non-atomic-wasm = [ "wgpu-types/fragile-send-sync-non-atomic-wasm", ] +portable-atomic = ["dep:portable-atomic"] ################################### ### Internal Debugging Features ### @@ -300,6 +301,9 @@ khronos-egl = { workspace = true, optional = true, features = [ # Note: it's unused by emscripten, but we keep it to have single code base in egl.rs libloading = { workspace = true, optional = true } +[target.'cfg(not(target_has_atomic = "64"))'.dependencies] +portable-atomic = { workspace = true, optional = true } + [build-dependencies] cfg_aliases.workspace = true diff --git a/wgpu-hal/build.rs b/wgpu-hal/build.rs index 9a648c60eaa..d67321a72d8 100644 --- a/wgpu-hal/build.rs +++ b/wgpu-hal/build.rs @@ -12,6 +12,7 @@ fn main() { metal: { all(target_vendor = "apple", feature = "metal") }, vulkan: { all(not(target_arch = "wasm32"), feature = "vulkan") }, // ⚠️ Keep in sync with target.cfg() definition in Cargo.toml and cfg_alias in `wgpu` crate ⚠️ - static_dxc: { all(target_os = "windows", feature = "static-dxc", not(target_arch = "aarch64")) } + static_dxc: { all(target_os = "windows", feature = "static-dxc", not(target_arch = "aarch64")) }, + supports_64bit_atomics: { target_has_atomic = "64" } } } diff --git a/wgpu-hal/src/lib.rs b/wgpu-hal/src/lib.rs index 3bfc5dab3a7..cd7139b27de 100644 --- a/wgpu-hal/src/lib.rs +++ b/wgpu-hal/src/lib.rs @@ -317,7 +317,10 @@ pub const QUERY_SIZE: wgt::BufferAddress = 8; pub type Label<'a> = Option<&'a str>; pub type MemoryRange = Range; pub type FenceValue = u64; +#[cfg(supports_64bit_atomics)] pub type AtomicFenceValue = core::sync::atomic::AtomicU64; +#[cfg(not(supports_64bit_atomics))] +pub type AtomicFenceValue = portable_atomic::AtomicU64; /// A callback to signal that wgpu is no longer using a resource. #[cfg(any(gles, vulkan))] diff --git a/wgpu-hal/src/noop/mod.rs b/wgpu-hal/src/noop/mod.rs index 2e1f8f665c7..b9ddb242cba 100644 --- a/wgpu-hal/src/noop/mod.rs +++ b/wgpu-hal/src/noop/mod.rs @@ -1,11 +1,12 @@ #![allow(unused_variables)] use alloc::{string::String, vec, vec::Vec}; -use core::{ - ptr, - sync::atomic::{AtomicU64, Ordering}, - time::Duration, -}; +use core::{ptr, sync::atomic::Ordering, time::Duration}; + +#[cfg(supports_64bit_atomics)] +use core::sync::atomic::AtomicU64; +#[cfg(not(supports_64bit_atomics))] +use portable_atomic::AtomicU64; use crate::TlasInstance; diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index aa6f25d05c7..c79f31aeba0 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -179,6 +179,7 @@ wgpu-core = { workspace = true, features = [ "raw-window-handle", "renderdoc", "indirect-validation", + "portable-atomic", ] } wgpu-hal.workspace = true @@ -216,5 +217,8 @@ wgpu-hal.workspace = true smallvec.workspace = true +[target.'cfg(not(target_has_atomic = "64"))'.dependencies] +portable-atomic.workspace = true + [build-dependencies] cfg_aliases.workspace = true diff --git a/wgpu/build.rs b/wgpu/build.rs index d853281dfa4..787e4691fbc 100644 --- a/wgpu/build.rs +++ b/wgpu/build.rs @@ -16,5 +16,6 @@ fn main() { naga: { any(feature = "naga-ir", feature = "spirv", feature = "glsl") }, // ⚠️ Keep in sync with target.cfg() definition in wgpu-hal/Cargo.toml and cfg_alias in `wgpu-hal` crate ⚠️ static_dxc: { all(target_os = "windows", feature = "static-dxc", not(target_arch = "aarch64")) }, + supports_64bit_atomics: { target_has_atomic = "64" } } } diff --git a/wgpu/src/cmp.rs b/wgpu/src/cmp.rs index 64fc73f115a..60829cfde88 100644 --- a/wgpu/src/cmp.rs +++ b/wgpu/src/cmp.rs @@ -4,10 +4,12 @@ //! //! For types (like WebGPU) that don't have such a property, we generate an identifier and use that. -use core::{ - num::NonZeroU64, - sync::atomic::{AtomicU64, Ordering}, -}; +#[cfg(supports_64bit_atomics)] +pub use core::sync::atomic::AtomicU64; +#[cfg(not(supports_64bit_atomics))] +pub use portable_atomic::AtomicU64; + +use core::{num::NonZeroU64, sync::atomic::Ordering}; static NEXT_ID: AtomicU64 = AtomicU64::new(1); diff --git a/xtask/src/check_feature_dependencies.rs b/xtask/src/check_feature_dependencies.rs index 3a1e4c3f0c1..70451df0243 100644 --- a/xtask/src/check_feature_dependencies.rs +++ b/xtask/src/check_feature_dependencies.rs @@ -155,6 +155,22 @@ pub fn check_feature_dependencies(shell: Shell, arguments: Arguments) -> anyhow: default_features: false, search_terms: &[Search::Positive("glow")], }, + Requirement { + human_readable_name: "x86-64 does not depend on portable-atomic", + target: "x86_64-unknown-linux-gnu", + packages: &["wgpu"], + features: &[], + default_features: false, + search_terms: &[Search::Negative("portable-atomic")], + }, + Requirement { + human_readable_name: "ppc32 does depend on portable-atomic", + target: "powerpc-unknown-linux-gnu", + packages: &["wgpu"], + features: &[], + default_features: false, + search_terms: &[Search::Positive("portable-atomic")], + }, ]; let mut any_failures = false;