1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//! `static`-friendly synchronization primitives for the GPU module.
//!
//! ## Background
//!
//! On native, `std::sync::Mutex<T>`, `std::sync::OnceLock<T>`, and
//! `once_cell::sync::Lazy<T>` are all `Sync` whenever `T: Send`.
//! Static items must implement `Sync`, which is why we write
//! `static FOO: Mutex<Bar> = Mutex::new(...)` without thinking.
//!
//! On `wasm32-unknown-unknown`, wgpu's WebGPU backend types
//! (`Texture`, `Buffer`, `BindGroup`, …) wrap raw JS handles
//! (`*mut u8` inside `JsValue`) and are `!Send + !Sync` — by design,
//! because a JsValue is bound to the JS thread that created it.
//! That breaks every wgpu-holding `static`. The runtime is also
//! single-threaded under wasm32 (`wasm_bindgen_futures::spawn_local`
//! everywhere) so the bound is purely typechecking — there is no
//! real cross-thread aliasing to police.
//!
//! This module provides drop-in replacements that satisfy the
//! `Sync` requirement on wasm via `unsafe impl Sync` over a
//! `RefCell<>` or an `UnsafeCell<>`, with the same surface as the
//! standard primitive on native.
// ─── GpuMutex ──────────────────────────────────────────────────────────────
/// Mutex-shaped storage for GPU caches.
///
/// Native: `std::sync::Mutex<T>`. Wasm: a `RefCell<T>` with an
/// `unsafe impl Sync` and a `lock()` that mirrors the standard
/// signature so callers compile against either backend with
/// `.lock().unwrap_or_else(|e| e.into_inner())`.
pub type GpuMutex<T> = Mutex;
;
// SAFETY: wasm32-unknown-unknown is single-threaded; there is no
// other thread that could race on this cell. The RefCell's runtime
// borrow check still catches reentrant aliasing on the one thread.
// `Send` is also asserted because some upstream wrappers
// (`once_cell::sync::Lazy<GpuMutex<…>>`) require it for `Sync`.
unsafe
unsafe
// ─── GpuOnceLock ───────────────────────────────────────────────────────────
/// One-shot lazy storage for GPU pipelines and other init-once
/// resources.
///
/// Native: `std::sync::OnceLock<T>`. Wasm: a `OnceCell<T>` based on
/// `UnsafeCell` with `unsafe impl Sync` — same single-thread
/// argument as `GpuMutex`. The wasm variant exposes the same
/// `.get()` and `.get_or_init(f)` shape so call sites compile
/// either way.
pub type GpuOnceLock<T> = OnceLock;
// SAFETY: wasm32 single-thread; no concurrent access possible. The
// only-once invariant is upheld by checking the slot before write.
unsafe
unsafe