use crate::data::graph::Edge;
use crate::dynamics::solver::solver_contact_graph::ContactRef;
use crate::geometry::{ContactManifold, ContactPair};
#[derive(Copy, Clone)]
pub(crate) struct ManifoldStoreParts {
edges_ptr: usize,
num_edges: usize,
}
impl ManifoldStoreParts {
pub(crate) fn new(edges: *mut Edge<ContactPair>, num_edges: usize) -> Self {
Self {
edges_ptr: edges as usize,
num_edges,
}
}
}
pub(crate) struct ManifoldStore<'a> {
edges: *mut Edge<ContactPair>,
num_edges: usize,
_phantom: core::marker::PhantomData<&'a mut ContactPair>,
}
unsafe impl Send for ManifoldStore<'_> {}
unsafe impl Sync for ManifoldStore<'_> {}
impl<'a> ManifoldStore<'a> {
pub(crate) unsafe fn from_parts(parts: ManifoldStoreParts) -> Self {
Self {
edges: parts.edges_ptr as *mut Edge<ContactPair>,
num_edges: parts.num_edges,
_phantom: core::marker::PhantomData,
}
}
#[inline]
fn pair_ptr(&self, edge: u32) -> *mut ContactPair {
assert!(
(edge as usize) < self.num_edges,
"stale ContactRef edge index"
);
unsafe { &raw mut (*self.edges.add(edge as usize)).weight }
}
#[inline]
fn manifold_ptr(&self, r: ContactRef) -> *mut ContactManifold {
debug_assert!(!r.is_padding());
let pair = self.pair_ptr(r.edge);
unsafe {
let clusters: *mut _ = &raw mut (*pair).solver_clusters;
let vec = if (*clusters).is_empty() {
&raw mut (*pair).manifolds
} else {
clusters
};
assert!(
(r.manifold as usize) < (*vec).len(),
"stale ContactRef manifold ordinal"
);
(*vec).as_mut_ptr().add(r.manifold as usize)
}
}
#[inline]
pub(crate) fn get(&self, r: ContactRef) -> &ContactManifold {
unsafe { &*self.manifold_ptr(r) }
}
#[inline]
pub(crate) fn prefetch_pair(&self, r: ContactRef) {
if r.is_padding() || r.edge as usize >= self.num_edges {
return;
}
let pair = unsafe { &raw const (*self.edges.add(r.edge as usize)).weight };
crate::utils::prefetch_read::<0, _>(pair);
}
#[inline]
pub(crate) fn prefetch_manifold(&self, r: ContactRef) {
if r.is_padding() || r.edge as usize >= self.num_edges {
return;
}
let pair = self.pair_ptr(r.edge);
unsafe {
let clusters = &raw mut (*pair).solver_clusters;
let vec = if (*clusters).is_empty() {
&raw mut (*pair).manifolds
} else {
clusters
};
if (r.manifold as usize) >= (*vec).len() {
return;
}
let m = (*vec).as_ptr().add(r.manifold as usize);
crate::utils::prefetch_read::<4, _>(m);
}
}
#[inline]
#[allow(clippy::mut_from_ref)]
pub(crate) unsafe fn get_mut(&self, r: ContactRef) -> &mut ContactManifold {
unsafe { &mut *self.manifold_ptr(r) }
}
}