use std::ops::Range;
use crate::metal::Buffer;
use super::{
AccelerationStructureBoundingBoxGeometryDescriptor,
AccelerationStructureCurveGeometryDescriptor, AccelerationStructureGeometryDescriptor,
AccelerationStructureMotionBoundingBoxGeometryDescriptor,
AccelerationStructureMotionCurveGeometryDescriptor,
AccelerationStructureMotionTriangleGeometryDescriptor,
AccelerationStructureTriangleGeometryDescriptor,
IndirectInstanceAccelerationStructureDescriptor, InstanceAccelerationStructureDescriptor,
PrimitiveAccelerationStructureDescriptor,
};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct AccelerationStructureBufferRange {
inner: metal_rust_ffi::AccelerationStructureBufferRange,
}
impl AccelerationStructureBufferRange {
fn from_ffi(inner: metal_rust_ffi::AccelerationStructureBufferRange) -> Self {
Self { inner }
}
pub const fn len(self) -> u64 {
self.inner.len()
}
pub const fn is_empty(self) -> bool {
self.inner.is_empty()
}
}
#[derive(Clone, Copy)]
pub enum AccelerationStructureGeometry<'a> {
Triangle(&'a AccelerationStructureTriangleGeometryDescriptor),
BoundingBox(&'a AccelerationStructureBoundingBoxGeometryDescriptor),
MotionTriangle(&'a AccelerationStructureMotionTriangleGeometryDescriptor),
MotionBoundingBox(&'a AccelerationStructureMotionBoundingBoxGeometryDescriptor),
Curve(&'a AccelerationStructureCurveGeometryDescriptor),
MotionCurve(&'a AccelerationStructureMotionCurveGeometryDescriptor),
}
macro_rules! range_property {
($type:ty, $get:ident, $set:ident) => {
impl $type {
#[doc = concat!("Returns an opaque snapshot from `", stringify!($get), "`.")]
pub fn $get(&self) -> Result<AccelerationStructureBufferRange, crate::Error> {
self.inner
.$get()
.map(AccelerationStructureBufferRange::from_ffi)
.map_err(crate::Error::from_ffi)
}
#[doc = concat!("Updates `", stringify!($set), "` from a checked live buffer region, or clears it.")]
pub fn $set(
&self,
value: Option<(&Buffer, Range<usize>)>,
) -> Result<(), crate::Error> {
self.inner
.$set(value.map(|(buffer, range)| (&buffer.inner, range)))
.map_err(crate::Error::from_ffi)
}
}
};
}
range_property!(
AccelerationStructureGeometryDescriptor,
primitive_data_buffer,
set_primitive_data_buffer
);
range_property!(
AccelerationStructureTriangleGeometryDescriptor,
index_buffer,
set_index_buffer
);
range_property!(
AccelerationStructureTriangleGeometryDescriptor,
transformation_matrix_buffer,
set_transformation_matrix_buffer
);
range_property!(
AccelerationStructureTriangleGeometryDescriptor,
vertex_buffer,
set_vertex_buffer
);
range_property!(
AccelerationStructureBoundingBoxGeometryDescriptor,
bounding_box_buffer,
set_bounding_box_buffer
);
range_property!(
AccelerationStructureMotionTriangleGeometryDescriptor,
index_buffer,
set_index_buffer
);
range_property!(
AccelerationStructureMotionTriangleGeometryDescriptor,
transformation_matrix_buffer,
set_transformation_matrix_buffer
);
range_property!(
AccelerationStructureMotionTriangleGeometryDescriptor,
vertex_buffers,
set_vertex_buffers
);
range_property!(
AccelerationStructureMotionBoundingBoxGeometryDescriptor,
bounding_box_buffers,
set_bounding_box_buffers
);
range_property!(
AccelerationStructureCurveGeometryDescriptor,
control_point_buffer,
set_control_point_buffer
);
range_property!(
AccelerationStructureCurveGeometryDescriptor,
index_buffer,
set_index_buffer
);
range_property!(
AccelerationStructureCurveGeometryDescriptor,
radius_buffer,
set_radius_buffer
);
range_property!(
AccelerationStructureMotionCurveGeometryDescriptor,
control_point_buffers,
set_control_point_buffers
);
range_property!(
AccelerationStructureMotionCurveGeometryDescriptor,
index_buffer,
set_index_buffer
);
range_property!(
AccelerationStructureMotionCurveGeometryDescriptor,
radius_buffers,
set_radius_buffers
);
range_property!(
InstanceAccelerationStructureDescriptor,
instance_descriptor_buffer,
set_instance_descriptor_buffer
);
range_property!(
InstanceAccelerationStructureDescriptor,
motion_transform_buffer,
set_motion_transform_buffer
);
range_property!(
IndirectInstanceAccelerationStructureDescriptor,
instance_count_buffer,
set_instance_count_buffer
);
range_property!(
IndirectInstanceAccelerationStructureDescriptor,
instance_descriptor_buffer,
set_instance_descriptor_buffer
);
range_property!(
IndirectInstanceAccelerationStructureDescriptor,
motion_transform_buffer,
set_motion_transform_buffer
);
range_property!(
IndirectInstanceAccelerationStructureDescriptor,
motion_transform_count_buffer,
set_motion_transform_count_buffer
);
impl PrimitiveAccelerationStructureDescriptor {
pub fn set_geometry_descriptor_slice(
&self,
descriptors: &[AccelerationStructureGeometry<'_>],
) -> Result<(), crate::Error> {
let descriptors: Vec<_> = descriptors
.iter()
.map(|descriptor| match descriptor {
AccelerationStructureGeometry::Triangle(value) => {
metal_rust_ffi::Metal4AccelerationStructureGeometry::Triangle(&value.inner)
}
AccelerationStructureGeometry::BoundingBox(value) => {
metal_rust_ffi::Metal4AccelerationStructureGeometry::BoundingBox(&value.inner)
}
AccelerationStructureGeometry::MotionTriangle(value) => {
metal_rust_ffi::Metal4AccelerationStructureGeometry::MotionTriangle(
&value.inner,
)
}
AccelerationStructureGeometry::MotionBoundingBox(value) => {
metal_rust_ffi::Metal4AccelerationStructureGeometry::MotionBoundingBox(
&value.inner,
)
}
AccelerationStructureGeometry::Curve(value) => {
metal_rust_ffi::Metal4AccelerationStructureGeometry::Curve(&value.inner)
}
AccelerationStructureGeometry::MotionCurve(value) => {
metal_rust_ffi::Metal4AccelerationStructureGeometry::MotionCurve(&value.inner)
}
})
.collect();
self.inner
.set_geometry_descriptor_slice(&descriptors)
.map_err(crate::Error::from_ffi)
}
pub fn geometry_descriptor_vec(
&self,
) -> Result<Vec<AccelerationStructureGeometryDescriptor>, crate::Error> {
self.inner
.geometry_descriptor_vec()
.map(|values| {
values
.into_iter()
.map(AccelerationStructureGeometryDescriptor::from_ffi)
.collect()
})
.map_err(crate::Error::from_ffi)
}
}