use crate::data::graph::Edge;
use crate::dynamics::solver::solver_contact_graph::ContactRef;
use crate::geometry::{ContactManifold, ContactPair, PairContacts, RigidPairContacts};
#[derive(Copy, Clone)]
pub(crate) struct ManifoldStoreParts {
edges_ptr: usize,
num_edges: usize,
}
fn rigid_contacts_offset() -> usize {
use core::sync::atomic::{AtomicUsize, Ordering};
static OFFSET: AtomicUsize = AtomicUsize::new(usize::MAX);
let cached = OFFSET.load(Ordering::Relaxed);
if cached != usize::MAX {
return cached;
}
let probe = ContactPair::default();
let base = &raw const probe.contacts as usize;
let PairContacts::Rigid(rigid) = &probe.contacts else {
unreachable!("a fresh pair holds rigid contacts");
};
let offset = &raw const *rigid as usize - base;
OFFSET.store(offset, Ordering::Relaxed);
offset
}
#[inline]
unsafe fn rigid_contacts_ptr(pair: *mut ContactPair) -> *mut RigidPairContacts {
unsafe {
let contacts = &raw mut (*pair).contacts;
(contacts as *mut u8).add(rigid_contacts_offset()) as *mut RigidPairContacts
}
}
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 rigid = rigid_contacts_ptr(pair);
let clusters: *mut _ = &raw mut (*rigid).solver_clusters;
let vec = if (*clusters).is_empty() {
&raw mut (*rigid).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 rigid = rigid_contacts_ptr(pair);
let clusters = &raw mut (*rigid).solver_clusters;
let vec = if (*clusters).is_empty() {
&raw mut (*rigid).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) }
}
}