Skip to main content

wgpu_core/lock/
rank.rs

1//! Ranks for `wgpu-core` locks, restricting acquisition order.
2//!
3//! See [`LockRank`].
4
5/// The rank of a lock.
6///
7/// Each [`Mutex`], [`RwLock`], and [`SnatchLock`] in `wgpu-core` has been
8/// assigned a *rank*: a node in the DAG defined at the bottom of
9/// `wgpu-core/src/lock/rank.rs`. The rank of the most recently
10/// acquired lock you are still holding determines which locks you may
11/// attempt to acquire next.
12///
13/// When you create a lock in `wgpu-core`, you must specify its rank
14/// by passing in a [`LockRank`] value. This module declares a
15/// pre-defined set of ranks to cover everything in `wgpu-core`, named
16/// after the type in which they occur, and the name of the type's
17/// field that is a lock. For example, [`CommandBuffer::data`] is a
18/// `Mutex`, and its rank here is the constant
19/// [`COMMAND_BUFFER_DATA`].
20///
21/// Building with `RUSTFLAGS="--cfg wgpu_validate_locks"`, replaces the
22/// lock implementation in `lock::vanilla` with in `lock::ranked`, which
23/// checks that the observed sequences of lock acquisition respect the
24/// ordering defined here.
25///
26/// TODO(<https://github.com/gfx-rs/wgpu/issues/5572>): Resolve invalid
27/// acquisitions of DEVICE_COMMAND_INDICES followed by COMMAND_BUFFER_DATA.
28///
29/// [`Mutex`]: wgpu_sync::Mutex
30/// [`RwLock`]: wgpu_sync::RwLock
31/// [`SnatchLock`]: crate::snatch::SnatchLock
32/// [`CommandBuffer::data`]: crate::command::CommandBuffer::data
33#[derive(Debug, Copy, Clone)]
34pub struct LockRank {
35    /// The bit representing this lock.
36    ///
37    /// There should only be a single bit set in this value.
38    pub(super) bit: LockRankSet,
39
40    /// A bitmask of permitted successor ranks.
41    ///
42    /// If `rank` is the rank of the most recently acquired lock we
43    /// are still holding, then `rank.followers` is the mask of
44    /// locks we are allowed to acquire next.
45    ///
46    /// The `define_lock_ranks!` macro ensures that there are no
47    /// cycles in the graph of lock ranks and their followers.
48    pub(super) followers: LockRankSet,
49}
50
51/// Define a set of lock ranks, and each rank's permitted successors.
52macro_rules! define_lock_ranks {
53    {
54        $(
55            $( #[ $attr:meta ] )*
56            rank $name:ident $member:literal followed by { $( $follower:ident ),* $(,)? }
57        )*
58    } => {
59        // An enum that assigns a unique number to each rank.
60        #[allow(non_camel_case_types, clippy::upper_case_acronyms)]
61        enum LockRankNumber { $( $name, )* }
62
63        bitflags::bitflags! {
64            #[derive(Debug, Copy, Clone, Eq, PartialEq)]
65            /// A bitflags type representing a set of lock ranks.
66            pub struct LockRankSet: u64 {
67                $(
68                    const $name = 1 << (LockRankNumber:: $name as u64);
69                )*
70            }
71        }
72
73        impl LockRankSet {
74            pub fn member_name(self) -> &'static str {
75                match self {
76                    $(
77                        LockRankSet:: $name => $member,
78                    )*
79                    _ => "<unrecognized LockRankSet bit>",
80                }
81            }
82
83            #[cfg_attr(not(feature = "observe_locks"), allow(dead_code))]
84            pub fn const_name(self) -> &'static str {
85                match self {
86                    $(
87                        LockRankSet:: $name => stringify!($name),
88                    )*
89                    _ => "<unrecognized LockRankSet bit>",
90                }
91            }
92        }
93
94        $(
95            // If there is any cycle in the ranking, the initializers
96            // for `followers` will be cyclic, and rustc will give us
97            // an error message explaining the cycle.
98            $( #[ $attr ] )*
99            pub const $name: LockRank = LockRank {
100                bit: LockRankSet:: $name,
101                followers: LockRankSet::empty() $( .union($follower.bit) )*,
102            };
103        )*
104    }
105}
106
107define_lock_ranks! {
108    // Non-leaf ranks, in topological order.
109    rank INSTANCE_DEVICES "InstanceDevices" followed by {
110        DEVICE_SNATCHABLE_LOCK,
111        QUEUE_PENDING_WRITES,
112        DEVICE_TRACKERS,
113        QUEUE_LIFE_TRACKER,
114        BUFFER_BIND_GROUPS,
115        DEVICE_TRACE,
116        TEXTURE_BIND_GROUPS,
117        TEXTURE_CLEAR_MODE,
118        TEXTURE_VIEWS,
119        DEVICE_DEFERRED_DESTROY,
120        DEVICE_LOST_CLOSURE,
121    }
122    // Includes stuff from INSTANCE_DEVICES to cover Device::maintain
123    // and SHARED_TRACKER_INDEX_ALLOCATOR_INNER to cover Texture::new.
124    // We do not expect all of these to be exercised in CI.
125    rank SURFACE_PRESENTATION "Surface::presentation" followed by {
126        DEVICE_SNATCHABLE_LOCK,
127        QUEUE_PENDING_WRITES,
128        DEVICE_TRACKERS,
129        QUEUE_LIFE_TRACKER,
130        BUFFER_BIND_GROUPS,
131        DEVICE_TRACE,
132        TEXTURE_BIND_GROUPS,
133        TEXTURE_CLEAR_MODE,
134        TEXTURE_VIEWS,
135        DEVICE_DEFERRED_DESTROY,
136        DEVICE_LOST_CLOSURE,
137        SHARED_TRACKER_INDEX_ALLOCATOR_INNER,
138    }
139    rank DEVICE_SNATCHABLE_LOCK "Device::snatchable_lock" followed by {
140        BUFFER_MAP_STATE,
141        COMMAND_BUFFER_DATA,
142        DEVICE_COMMAND_INDICES,
143        QUEUE_PENDING_WRITES,
144        DEVICE_TRACKERS,
145        QUEUE_LIFE_TRACKER,
146        BLAS_COMPACTION_STATE,
147        COMMAND_ALLOCATOR_FREE_ENCODERS,
148        BUFFER_BIND_GROUPS,
149        BUFFER_INITIALIZATION_STATUS,
150        BUFFER_POOL,
151        DEVICE_LOST_CLOSURE,
152        DEVICE_TRACE,
153        DEVICE_USAGE_SCOPES,
154        QUERY_SET_INITIALIZED_SLOTS,
155        SHARED_TRACKER_INDEX_ALLOCATOR_INNER,
156        TEXTURE_BIND_GROUPS,
157        TEXTURE_CLEAR_MODE,
158        TEXTURE_INITIALIZATION_STATUS,
159        TEXTURE_VIEWS,
160    }
161    rank DEVICE_COMMAND_INDICES "Device::command_indices" followed by {
162        COMMAND_BUFFER_DATA,
163        BUFFER_MAP_STATE,
164        BUFFER_POOL,
165        DEVICE_TRACKERS,
166        QUEUE_PENDING_WRITES,
167        QUEUE_LIFE_TRACKER,
168        BLAS_COMPACTION_STATE,
169        BLAS_BUILT_INDEX,
170        COMMAND_ALLOCATOR_FREE_ENCODERS,
171        DEVICE_DEFERRED_DESTROY,
172        DEVICE_TRACE,
173        QUERY_SET_INITIALIZED_SLOTS,
174        RESOURCE_POOL_INNER,
175        SHARED_TRACKER_INDEX_ALLOCATOR_INNER,
176        TEXTURE_CLEAR_MODE,
177        TEXTURE_INITIALIZATION_STATUS,
178        TLAS_BUILT_INDEX,
179        TLAS_DEPENDENCIES,
180    }
181    rank COMMAND_BUFFER_DATA "CommandBuffer::data" followed by {
182        BUFFER_MAP_STATE,
183        COMMAND_ALLOCATOR_FREE_ENCODERS,
184        BLAS_COMPACTION_STATE,
185        BUFFER_POOL,
186        DEVICE_TRACE,
187        DEVICE_USAGE_SCOPES,
188        SHARED_TRACKER_INDEX_ALLOCATOR_INNER,
189    }
190    rank QUEUE_PENDING_WRITES "Queue::pending_writes" followed by {
191        BUFFER_MAP_STATE,
192        DEVICE_TRACKERS,
193        COMMAND_ALLOCATOR_FREE_ENCODERS,
194        BUFFER_INITIALIZATION_STATUS,
195        TEXTURE_INITIALIZATION_STATUS,
196        SHARED_TRACKER_INDEX_ALLOCATOR_INNER,
197    }
198    rank DEVICE_TRACKERS "Device::trackers" followed by {
199        BUFFER_BIND_GROUPS,
200        BUFFER_INITIALIZATION_STATUS,
201        DEVICE_DEFERRED_DESTROY,
202        TEXTURE_BIND_GROUPS,
203        TEXTURE_CLEAR_MODE,
204        TEXTURE_INITIALIZATION_STATUS,
205        TEXTURE_VIEWS,
206    }
207    rank QUEUE_LIFE_TRACKER "Queue::life_tracker" followed by {
208        BLAS_COMPACTION_STATE,
209        BUFFER_MAP_STATE,
210        COMMAND_ALLOCATOR_FREE_ENCODERS,
211        BUFFER_INITIALIZATION_STATUS,
212        BUFFER_POOL,
213        DEVICE_DEFERRED_DESTROY,
214        DEVICE_TRACE,
215        RESOURCE_POOL_INNER,
216        SHARED_TRACKER_INDEX_ALLOCATOR_INNER,
217        TEXTURE_CLEAR_MODE,
218    }
219    rank BLAS_COMPACTION_STATE "Blas::compaction_state" followed by {
220        BLAS_BUILT_INDEX,
221    }
222    rank BUFFER_MAP_STATE "Buffer::map_state" followed by {
223        BUFFER_INITIALIZATION_STATUS,
224        DEVICE_TRACE,
225        SHARED_TRACKER_INDEX_ALLOCATOR_INNER,
226    }
227    rank COMMAND_ALLOCATOR_FREE_ENCODERS "CommandAllocator::free_encoders" followed by {
228        SHARED_TRACKER_INDEX_ALLOCATOR_INNER,
229    }
230    rank TLAS_BUILT_INDEX "Tlas::built_index" followed by {
231        TLAS_DEPENDENCIES,
232    }
233    rank TLAS_DEPENDENCIES "Tlas::dependencies" followed by {
234        BLAS_BUILT_INDEX,
235    }
236
237    // Leaf ranks reachable from the graph above, alphabetical.
238    rank BLAS_BUILT_INDEX "Blas::built_index" followed by { }
239    rank BUFFER_BIND_GROUPS "Buffer::bind_groups" followed by { }
240    rank BUFFER_INITIALIZATION_STATUS "Buffer::initialization_status" followed by { }
241    rank BUFFER_POOL "BufferPool::buffers" followed by { }
242    rank DEVICE_DEFERRED_DESTROY "Device::deferred_destroy" followed by { }
243    rank DEVICE_LOST_CLOSURE "Device::device_lost_closure" followed by { }
244    rank DEVICE_TRACE "Device::trace" followed by { }
245    rank DEVICE_USAGE_SCOPES "Device::usage_scopes" followed by { }
246    rank QUERY_SET_INITIALIZED_SLOTS "QuerySet::initialized_slots" followed by { }
247    rank RESOURCE_POOL_INNER "ResourcePool::inner" followed by { }
248    rank SHARED_TRACKER_INDEX_ALLOCATOR_INNER "SharedTrackerIndexAllocator::inner" followed by { }
249    rank TEXTURE_BIND_GROUPS "Texture::bind_groups" followed by { }
250    rank TEXTURE_CLEAR_MODE "Texture::clear_mode" followed by { }
251    rank TEXTURE_INITIALIZATION_STATUS "Texture::initialization_status" followed by { }
252    rank TEXTURE_VIEWS "Texture::views" followed by { }
253
254    #[cfg(test)]
255    rank PAWN "pawn" followed by { ROOK, BISHOP }
256    #[cfg(test)]
257    rank ROOK "rook" followed by { KNIGHT }
258    #[cfg(test)]
259    rank KNIGHT "knight" followed by { }
260    #[cfg(test)]
261    rank BISHOP "bishop" followed by { }
262}