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}