wgpu_core/id.rs
1pub use wgt::markers::*;
2
3/// Identify an object by the pointer returned by `Arc::as_ptr`.
4///
5/// This is used for tracing.
6///
7/// As of `wgpu` v27, commands are encoded all at once when
8/// `CommandEncoder::finish` is called, not when the encoding methods are
9/// called for each command. This implies storing a representation of the
10/// commands in memory until `finish` is called. The
11/// serialized trace identifies resources by the integer value of
12/// `Arc::as_ptr`. These IDs have the type [`crate::id::PointerId`]. The
13/// trace player uses hash maps to go from `PointerId`s to `Arc`s
14/// when replaying a trace.
15#[allow(dead_code)]
16#[cfg(feature = "serde")]
17#[derive(Debug, serde::Serialize, serde::Deserialize)]
18pub enum PointerId<T: Marker> {
19 // The only variant forces RON to not ignore "Id"
20 PointerId(
21 core::num::NonZeroUsize,
22 #[serde(skip)] core::marker::PhantomData<T>,
23 ),
24}
25
26#[cfg(feature = "serde")]
27impl<T: Marker> Copy for PointerId<T> {}
28
29#[cfg(feature = "serde")]
30impl<T: Marker> Clone for PointerId<T> {
31 fn clone(&self) -> Self {
32 *self
33 }
34}
35
36#[cfg(feature = "serde")]
37impl<T: Marker> PartialEq for PointerId<T> {
38 fn eq(&self, other: &Self) -> bool {
39 let PointerId::PointerId(this, _) = self;
40 let PointerId::PointerId(other, _) = other;
41 this == other
42 }
43}
44
45#[cfg(feature = "serde")]
46impl<T: Marker> Eq for PointerId<T> {}
47
48#[cfg(feature = "serde")]
49impl<T: Marker> core::hash::Hash for PointerId<T> {
50 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
51 let PointerId::PointerId(this, _) = self;
52 this.hash(state);
53 }
54}
55
56#[cfg(feature = "serde")]
57impl<T: crate::storage::StorageItem> From<&alloc::sync::Arc<T>> for PointerId<T::Marker> {
58 fn from(arc: &alloc::sync::Arc<T>) -> Self {
59 // Since the memory representation of `Arc<T>` is just a pointer to
60 // `ArcInner<T>`, it would be nice to use that pointer as the trace ID,
61 // since many `into_trace` implementations would then be no-ops at
62 // runtime. However, `Arc::as_ptr` returns a pointer to the contained
63 // data, not to the `ArcInner`. The `ArcInner` stores the reference
64 // counts before the data, so the machine code for this conversion has
65 // to add an offset to the pointer.
66 PointerId::PointerId(
67 core::num::NonZeroUsize::new(alloc::sync::Arc::as_ptr(arc) as usize).unwrap(),
68 core::marker::PhantomData,
69 )
70 }
71}