pub fn buffer_no_copy<T: Sized>(device: &metal::DeviceRef, v: &[T]) -> metal::Buffer {
assert!(is_page_aligned(v));
let byte_len = core::mem::size_of_val(v);
device.new_buffer_with_bytes_no_copy(
v.as_ptr() as *mut core::ffi::c_void,
byte_len.try_into().unwrap(),
metal::MTLResourceOptions::StorageModeShared,
None,
)
}
pub fn buffer_mut_no_copy<T: Sized>(device: &metal::DeviceRef, v: &mut [T]) -> metal::Buffer {
assert!(is_page_aligned(v));
let byte_len = core::mem::size_of_val(v);
device.new_buffer_with_bytes_no_copy(
v.as_mut_ptr() as *mut core::ffi::c_void,
byte_len.try_into().unwrap(),
metal::MTLResourceOptions::StorageModeShared,
None,
)
}
pub(crate) fn void_ptr<T>(v: &T) -> *const core::ffi::c_void {
v as *const T as *const core::ffi::c_void
}
#[repr(C, align(16384))]
struct Page([u8; 16384]);
pub fn is_page_aligned<T>(v: &[T]) -> bool {
v.as_ptr().align_offset(core::mem::align_of::<Page>()) == 0
}
#[allow(clippy::uninit_vec)]
pub unsafe fn page_aligned_uninit_vector<T>(length: usize) -> Vec<T> {
#[repr(C, align(16384))]
struct Page([u8; 16384]);
let item_size = core::mem::size_of::<T>();
let page_size = core::mem::size_of::<Page>();
let num_pages = item_size * length / page_size + 1;
let mut aligned: Vec<Page> = Vec::with_capacity(num_pages);
let ptr = aligned.as_mut_ptr();
let capacity = num_pages * page_size / item_size;
core::mem::forget(aligned);
unsafe { Vec::from_raw_parts(ptr as *mut T, length, capacity) }
}