impl RawId { /// Zip together an identifier and return its raw underlying representation. /// /// # Panics /// /// If both ID components are zero. pubfn zip(index: Index, epoch: Epoch) -> RawId { let v = (index as u64) | ((epoch as u64) << 32); Self(NonZeroU64::new(v).expect("IDs may not be zero"))
}
/// Unzip a raw identifier into its components. pubfn unzip(self) -> (Index, Epoch) {
(self.0.get() as Index, (self.0.get() >> 32) as Epoch)
}
}
/// An identifier for a wgpu object. /// /// An `Id<T>` value identifies a value stored in a [`Global`]'s [`Hub`]. /// /// ## Note on `Id` typing /// /// You might assume that an `Id<T>` can only be used to retrieve a resource of /// type `T`, but that is not quite the case. The id types in `wgpu-core`'s /// public API ([`TextureId`], for example) can refer to resources belonging to /// any backend, but the corresponding resource types ([`Texture<A>`], for /// example) are always parameterized by a specific backend `A`. /// /// So the `T` in `Id<T>` is usually a resource type like `Texture<Noop>`, /// where [`Noop`] is the `wgpu_hal` dummy back end. These empty types are /// never actually used, beyond just making sure you access each `Storage` with /// the right kind of identifier. The members of [`Hub<A>`] pair up each /// `X<Noop>` type with the resource type `X<A>`, for some specific backend /// `A`. /// /// [`Global`]: crate::global::Global /// [`Hub`]: crate::hub::Hub /// [`Hub<A>`]: crate::hub::Hub /// [`Texture<A>`]: crate::resource::Texture /// [`Registry`]: crate::registry::Registry /// [`Noop`]: hal::api::Noop #[repr(transparent)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", serde(transparent))] pubstruct Id<T: Marker>(RawId, PhantomData<T>);
// This type represents Id in a more readable (and editable) way. #[cfg(feature = "serde")] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug)] pubenum SerialId { // The only variant forces RON to not ignore "Id"
Id(Index, Epoch),
}
#[cfg(feature = "serde")] impl fmt::Display for ZeroIdError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "IDs may not be zero")
}
}
#[cfg(feature = "serde")] impl TryFrom<SerialId> for RawId { type Error = ZeroIdError; fn try_from(id: SerialId) -> Result<Self, ZeroIdError> { let SerialId::Id(index, epoch) = id; if index == 0 && epoch == 0 {
Err(ZeroIdError)
} else {
Ok(RawId::zip(index, epoch))
}
}
}
/// Identify an object by the pointer returned by `Arc::as_ptr`. /// /// This is used for tracing. See [IDs and tracing](crate::hub#ids-and-tracing). #[allow(dead_code)] #[cfg(feature = "serde")] #[derive(Debug, serde::Serialize, serde::Deserialize)] pubenum PointerId<T: Marker> { // The only variant forces RON to not ignore "Id"
PointerId(core::num::NonZeroUsize, #[serde(skip)] PhantomData<T>),
}
#[cfg(feature = "serde")] impl<T: Marker> Copy for PointerId<T> {}
#[cfg(feature = "serde")] impl<T: crate::storage::StorageItem> From<&alloc::sync::Arc<T>> for PointerId<T::Marker> { fn from(arc: &alloc::sync::Arc<T>) -> Self { // Since the memory representation of `Arc<T>` is just a pointer to // `ArcInner<T>`, it would be nice to use that pointer as the trace ID, // since many `into_trace` implementations would then be no-ops at // runtime. However, `Arc::as_ptr` returns a pointer to the contained // data, not to the `ArcInner`. The `ArcInner` stores the reference // counts before the data, so the machine code for this conversion has // to add an offset to the pointer.
PointerId::PointerId(
core::num::NonZeroUsize::new(alloc::sync::Arc::as_ptr(arc) as usize).unwrap(),
PhantomData,
)
}
}
impl<T> Id<T> where
T: Marker,
{ /// # Safety /// /// The raw id must be valid for the type. pubunsafefn from_raw(raw: RawId) -> Self { Self(raw, PhantomData)
}
/// Coerce the identifiers into its raw underlying representation. pubfn into_raw(self) -> RawId { self.0
}
impl<T> PartialOrd for Id<T> where
T: Marker,
{ #[inline] fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<T> Ord for Id<T> where
T: Marker,
{ #[inline] fn cmp(&self, other: &Self) -> Ordering { self.0.cmp(&other.0)
}
}
/// Marker trait used to determine which types uniquely identify a resource. /// /// For example, `Device<A>` will have the same type of identifier as /// `Device<B>` because `Device<T>` for any `T` defines the same maker type. pubtrait Marker: 'static + WasmNotSendSync {}
// This allows `()` to be used as a marker type for tests. // // We don't want these in production code, since they essentially remove type // safety, like how identifiers across different types can be compared. #[cfg(test)] impl Marker for () {}
/// Define identifiers for each resource.
macro_rules! ids {
($(
$(#[$($meta:meta)*])* pubtype $name:ident $marker:ident;
)*) => { /// Marker types for each resource. pubmod markers {
$( #[derive(Debug)] pubenum $marker {} implsuper::Marker for $marker {}
)*
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.