use rlx_ir::async_copy::{AsyncCopy, BarrierToken};
use std::sync::atomic::{AtomicU64, Ordering};
use crate::device::metal_device;
pub struct MetalBlitCopy {
counter: AtomicU64,
arena: metal::Buffer,
}
impl MetalBlitCopy {
pub fn new(arena: metal::Buffer) -> Self {
Self {
counter: AtomicU64::new(0),
arena,
}
}
pub fn from_device() -> Option<Self> {
let dev = metal_device()?;
let arena = dev.alloc_shared(1); Some(Self {
counter: AtomicU64::new(0),
arena,
})
}
pub fn issue_intra_arena(&mut self, src: usize, dst: usize, bytes: usize) -> BarrierToken {
let dev = metal_device().expect("Metal device required for MetalBlitCopy");
let cb = dev.queue.new_command_buffer();
let blit = cb.new_blit_command_encoder();
blit.copy_from_buffer(
&self.arena,
src as u64,
&self.arena,
dst as u64,
bytes as u64,
);
blit.end_encoding();
cb.commit();
let id = self.counter.fetch_add(1, Ordering::Relaxed);
cb.wait_until_completed();
BarrierToken(id)
}
}
impl AsyncCopy for MetalBlitCopy {
unsafe fn issue(&mut self, src: *const u8, dst: *mut u8, bytes: usize) -> BarrierToken {
let base = self.arena.contents() as *const u8;
let src_off = unsafe { src.offset_from(base) as usize };
let dst_off = unsafe { (dst as *const u8).offset_from(base) as usize };
self.issue_intra_arena(src_off, dst_off, bytes)
}
fn wait(&mut self, _token: BarrierToken) {
}
}