2024-02-12 12:38:55 +11:00
|
|
|
use crate::error;
|
2024-02-12 09:54:13 +11:00
|
|
|
use crate::error::FilterChainError;
|
2024-02-13 15:41:18 +11:00
|
|
|
use icrate::Foundation::NSString;
|
2024-02-12 09:54:13 +11:00
|
|
|
use icrate::Metal::{
|
2024-02-13 11:43:28 +11:00
|
|
|
MTLBuffer, MTLDevice, MTLResource, MTLResourceStorageModeManaged, MTLResourceStorageModeShared,
|
2024-02-12 09:54:13 +11:00
|
|
|
};
|
|
|
|
use objc2::rc::Id;
|
|
|
|
use objc2::runtime::ProtocolObject;
|
|
|
|
use std::ops::{Deref, DerefMut};
|
|
|
|
|
|
|
|
pub struct MetalBuffer {
|
|
|
|
buffer: Id<ProtocolObject<dyn MTLBuffer>>,
|
|
|
|
size: usize,
|
|
|
|
}
|
|
|
|
|
2024-02-12 12:38:55 +11:00
|
|
|
impl AsRef<ProtocolObject<dyn MTLBuffer>> for MetalBuffer {
|
|
|
|
fn as_ref(&self) -> &ProtocolObject<dyn MTLBuffer> {
|
|
|
|
self.buffer.as_ref()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-12 09:54:13 +11:00
|
|
|
impl MetalBuffer {
|
2024-02-13 11:43:28 +11:00
|
|
|
pub fn new(
|
|
|
|
device: &ProtocolObject<dyn MTLDevice>,
|
|
|
|
size: usize,
|
|
|
|
label: &str,
|
|
|
|
) -> error::Result<Self> {
|
2024-02-12 09:54:13 +11:00
|
|
|
let resource_mode = if cfg!(target_os = "ios") {
|
|
|
|
MTLResourceStorageModeShared
|
|
|
|
} else {
|
2024-02-13 15:41:18 +11:00
|
|
|
MTLResourceStorageModeManaged
|
2024-02-12 09:54:13 +11:00
|
|
|
};
|
|
|
|
|
|
|
|
let buffer = device
|
|
|
|
.newBufferWithLength_options(size, resource_mode)
|
|
|
|
.ok_or(FilterChainError::BufferError)?;
|
2024-02-13 11:43:28 +11:00
|
|
|
|
|
|
|
buffer.setLabel(Some(&*NSString::from_str(label)));
|
|
|
|
|
2024-02-12 09:54:13 +11:00
|
|
|
Ok(Self { buffer, size })
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn flush(&self) {
|
|
|
|
// We don't know what was actually written to so...
|
2024-02-12 16:43:51 +11:00
|
|
|
// self.buffer.didModifyRange(NSRange {
|
|
|
|
// location: 0,
|
|
|
|
// length: self.size,
|
|
|
|
// })
|
2024-02-12 09:54:13 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Deref for MetalBuffer {
|
|
|
|
type Target = [u8];
|
|
|
|
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
// SAFETY: the lifetime of this reference must be longer than of the MetalBuffer.
|
|
|
|
// Additionally, `MetalBuffer.buffer` is never lent out directly
|
|
|
|
unsafe { std::slice::from_raw_parts(self.buffer.contents().as_ptr().cast(), self.size) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DerefMut for MetalBuffer {
|
|
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
|
|
// SAFETY: the lifetime of this reference must be longer than of the MetalBuffer.
|
|
|
|
// Additionally, `MetalBuffer.buffer` is never lent out directly
|
|
|
|
unsafe { std::slice::from_raw_parts_mut(self.buffer.contents().as_ptr().cast(), self.size) }
|
|
|
|
}
|
|
|
|
}
|