use glam_det::nums::{f32x4, Num};
use glam_det::{UnitQuatx4, Vec3x4};
use test::Bencher;
use crate::collision_tasks::tests::common::{ConvexHullInput, TestInput};
use crate::convex_contact_manifold::Convex4ContactManifoldWide;
use crate::traits::{BaseShapeWide, ContactManifoldWide, CreateShapeWide};
use crate::{ConvexContactManifold, ConvexHull, ConvexHullId, ShapeContainer};
macro_rules! impl_bench {
($Type:ident,$TypeA:ident,$TypeB:ident,$ManifoldType:ident,$N:expr) => {
impl BenchShapePairTest for $Type {
type ShapeAWide = $TypeA;
type ShapeBWide = $TypeB;
const N: usize = $N;
#[inline]
fn test_wide(
shape_a: &Self::ShapeAWide,
shape_b: &Self::ShapeBWide,
speculative_margin: f32x4,
offset_b: Vec3x4,
orientation_a: UnitQuatx4,
orientation_b: UnitQuatx4,
container: Option<&ShapeContainer>,
manifold: &mut Convex4ContactManifoldWide,
) {
let contact_context = crate::traits::ContactContext {
orientation_a: &orientation_a,
orientation_b: &orientation_b,
offset_b: &offset_b,
speculative_margin,
pair_count: 4,
complex_shape_container: container,
};
ShapeWideTester::test(shape_a, shape_b, &contact_context, manifold)
}
}
};
}
macro_rules! bench {
($InputType:ident,$Type:ident,$path_root:tt,$( <$id:tt,$name:tt>),*) => {
bench!($InputType,$InputType, $Type,$path_root,$( <$id,$name>),*);
};
($InputType:ident,$BenchType:ident, $Type:ident,$path_root:tt,$( <$id:tt,$name:tt>),*) => {
$(
paste!{
#[bench]
pub fn [<id_ $id _ $name _with_transfer_wide_info>](b: &mut Bencher) {
let input_with_container:WithContainer<$BenchType> = {
let slice = include_bytes!(concat!("../tests/resource/",$path_root,stringify!($name),".json"));
let input: $InputType = serde_json::from_slice(slice).expect("file should be proper JSON");
input.into()
};
$Type::bench_shape_pair_with_transfer_wide_test(b,&input_with_container.0,&input_with_container.1);
}
#[bench]
pub fn [<id_ $id _ $name>](b: &mut Bencher) {
let input_with_container:WithContainer<$BenchType> = {
let slice = include_bytes!(concat!("../tests/resource/",$path_root,stringify!($name),".json"));
let input: $InputType = serde_json::from_slice(slice).expect("file should be proper JSON");
input.into()
};
$Type::bench_shape_pair_test(b,&input_with_container.0,&input_with_container.1);
}
}
)*
};
}
pub(super) struct WithContainer<T>(pub T, pub Option<ShapeContainer>);
impl<ShapeA, ShapeB> From<TestInput<ShapeA, ShapeB>> for WithContainer<TestInput<ShapeA, ShapeB>> {
fn from(input: TestInput<ShapeA, ShapeB>) -> Self {
Self(input, None)
}
}
impl<ShapeA> From<TestInput<ShapeA, ConvexHullInput>>
for WithContainer<TestInput<ShapeA, ConvexHullId>>
{
fn from(input: TestInput<ShapeA, ConvexHullInput>) -> Self {
let mut container = ShapeContainer::default();
let convex_hull = ConvexHull::new_unchecked(&input.b.vertices);
let convex_hull_id = container.add(convex_hull);
assert!(container.get::<ConvexHull>(convex_hull_id).is_some());
Self(
TestInput {
a: input.a,
b: convex_hull_id,
speculative_margin: input.speculative_margin,
offset_b: input.offset_b,
orientation_a: input.orientation_a,
orientation_b: input.orientation_b,
},
Some(container),
)
}
}
impl<ShapeB> From<TestInput<ConvexHullInput, ShapeB>>
for WithContainer<TestInput<ConvexHullId, ShapeB>>
{
fn from(input: TestInput<ConvexHullInput, ShapeB>) -> Self {
let mut container = ShapeContainer::default();
let convex_hull = ConvexHull::new_unchecked(&input.a.vertices);
let convex_hull_id = container.add(convex_hull);
assert!(container.get::<ConvexHull>(convex_hull_id).is_some());
Self(
TestInput {
a: convex_hull_id,
b: input.b,
speculative_margin: input.speculative_margin,
offset_b: input.offset_b,
orientation_a: input.orientation_a,
orientation_b: input.orientation_b,
},
Some(container),
)
}
}
impl From<TestInput<ConvexHullInput, ConvexHullInput>>
for WithContainer<TestInput<ConvexHullId, ConvexHullId>>
{
fn from(input: TestInput<ConvexHullInput, ConvexHullInput>) -> Self {
let mut container = ShapeContainer::default();
let a = {
let convex_hull = ConvexHull::new_unchecked(&input.a.vertices);
container.add(convex_hull)
};
let b = {
let convex_hull = ConvexHull::new_unchecked(&input.b.vertices);
container.add(convex_hull)
};
assert!(container.get::<ConvexHull>(a).is_some());
assert!(container.get::<ConvexHull>(b).is_some());
Self(
TestInput {
a,
b,
speculative_margin: input.speculative_margin,
offset_b: input.offset_b,
orientation_a: input.orientation_a,
orientation_b: input.orientation_b,
},
Some(container),
)
}
}
pub(super) trait BenchShapePairTest {
type ShapeAWide: BaseShapeWide + Default;
type ShapeBWide: BaseShapeWide + Default;
const N: usize;
fn bench_shape_pair_with_transfer_wide_test(
b: &mut Bencher,
data: &TestInput<
<Self::ShapeAWide as BaseShapeWide>::TShape,
<Self::ShapeBWide as BaseShapeWide>::TShape,
>,
container: &Option<ShapeContainer>,
) where
<Self as BenchShapePairTest>::ShapeAWide: CreateShapeWide<4>,
<Self as BenchShapePairTest>::ShapeBWide: CreateShapeWide<4>,
{
let pair_count = 4_usize;
b.iter(
#[inline]
|| {
let a = <Self::ShapeAWide as CreateShapeWide<4>>::create([data.a; 4].iter());
let b = <Self::ShapeBWide as CreateShapeWide<4>>::create([data.b; 4].iter());
let speculative_margin = f32x4::splat(data.speculative_margin);
let offset_b = Vec3x4::splat_soa(data.offset_b);
let orientation_a = UnitQuatx4::splat_soa(data.orientation_a);
let orientation_b = UnitQuatx4::splat_soa(data.orientation_b);
let mut manifold = Convex4ContactManifoldWide::default();
Self::test_wide(
&a,
&b,
speculative_margin,
offset_b,
orientation_a,
orientation_b,
container.as_ref(),
&mut manifold,
);
let mut result = ConvexContactManifold::default();
for i in 0..pair_count {
manifold.get_manifold(i, Self::N, &offset_b, &mut result);
test::black_box(&mut result);
}
test::black_box(result);
},
);
}
fn bench_shape_pair_test(
bencher: &mut Bencher,
data: &TestInput<
<Self::ShapeAWide as BaseShapeWide>::TShape,
<Self::ShapeBWide as BaseShapeWide>::TShape,
>,
container: &Option<ShapeContainer>,
) where
<Self as BenchShapePairTest>::ShapeAWide: CreateShapeWide<4>,
<Self as BenchShapePairTest>::ShapeBWide: CreateShapeWide<4>,
{
let a = <Self::ShapeAWide as CreateShapeWide<4>>::create([data.a; 4].iter());
let b = <Self::ShapeBWide as CreateShapeWide<4>>::create([data.b; 4].iter());
let speculative_margin = f32x4::splat(data.speculative_margin);
let offset_b = Vec3x4::splat_soa(data.offset_b);
let orientation_a = UnitQuatx4::splat_soa(data.orientation_a);
let orientation_b = UnitQuatx4::splat_soa(data.orientation_b);
let mut result = Convex4ContactManifoldWide::default();
bencher.iter(
#[inline]
|| {
Self::test_wide(
&a,
&b,
speculative_margin,
offset_b,
orientation_a,
orientation_b,
container.as_ref(),
&mut result,
);
},
);
test::black_box(result);
}
#[allow(clippy::too_many_arguments)]
fn test_wide(
shape_a: &Self::ShapeAWide,
shape_b: &Self::ShapeBWide,
speculative_margin: f32x4,
offset_b: Vec3x4,
orientation_a: UnitQuatx4,
orientation_b: UnitQuatx4,
container: Option<&ShapeContainer>,
manifold: &mut Convex4ContactManifoldWide,
);
}