-
Notifications
You must be signed in to change notification settings - Fork 21
Expand file tree
/
Copy pathbuffer.rs
More file actions
78 lines (67 loc) · 2.31 KB
/
buffer.rs
File metadata and controls
78 lines (67 loc) · 2.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
use crate::error;
use crate::error::FilterChainError;
use objc2::rc::Retained;
use objc2::runtime::ProtocolObject;
use objc2_foundation::{NSRange, NSString};
use objc2_metal::{MTLBuffer, MTLDevice, MTLResource, MTLResourceOptions};
use std::ops::{Deref, DerefMut};
pub struct MetalBuffer {
buffer: Retained<ProtocolObject<dyn MTLBuffer>>,
size: usize,
storage_mode: MTLResourceOptions,
}
impl AsRef<ProtocolObject<dyn MTLBuffer>> for MetalBuffer {
fn as_ref(&self) -> &ProtocolObject<dyn MTLBuffer> {
self.buffer.as_ref()
}
}
impl MetalBuffer {
pub fn new(
device: &ProtocolObject<dyn MTLDevice>,
mut size: usize,
label: &str,
) -> error::Result<Self> {
let storage_mode = if cfg!(all(target_arch = "aarch64", target_vendor = "apple")) {
MTLResourceOptions::StorageModeShared
} else {
MTLResourceOptions::StorageModeManaged
};
// Can't create buffer of size 0.
if size == 0 {
size = 16;
};
let buffer = device
.newBufferWithLength_options(size, storage_mode)
.ok_or(FilterChainError::BufferError)?;
buffer.setLabel(Some(&*NSString::from_str(label)));
Ok(Self {
buffer,
size,
storage_mode,
})
}
pub fn flush(&self) {
// We don't know what was actually written to so...
if self.storage_mode == MTLResourceOptions::StorageModeManaged {
self.buffer.didModifyRange(NSRange {
location: 0,
length: self.size,
})
}
}
}
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) }
}
}