1use std::ffi::c_void;
6
7use mtl_foundation::{Referencing, UInteger};
8use mtl_sys::{msg_send_2, msg_send_3, msg_send_4, sel};
9
10use super::Device;
11use crate::buffer::Buffer;
12use crate::enums::ResourceOptions;
13
14impl Device {
15 pub fn new_buffer(&self, length: UInteger, options: ResourceOptions) -> Option<Buffer> {
23 unsafe {
24 let ptr: *mut c_void = msg_send_2(
25 self.as_ptr(),
26 sel!(newBufferWithLength: options:),
27 length,
28 options,
29 );
30 Buffer::from_raw(ptr)
31 }
32 }
33
34 pub fn new_buffer_with_bytes(&self, bytes: &[u8], options: ResourceOptions) -> Option<Buffer> {
38 unsafe {
39 let ptr: *mut c_void = msg_send_3(
40 self.as_ptr(),
41 sel!(newBufferWithBytes: length: options:),
42 bytes.as_ptr() as *const c_void,
43 bytes.len() as UInteger,
44 options,
45 );
46 Buffer::from_raw(ptr)
47 }
48 }
49
50 pub unsafe fn new_buffer_with_bytes_ptr(
58 &self,
59 pointer: *const c_void,
60 length: UInteger,
61 options: ResourceOptions,
62 ) -> Option<Buffer> {
63 unsafe {
64 let ptr: *mut c_void = msg_send_3(
65 self.as_ptr(),
66 sel!(newBufferWithBytes: length: options:),
67 pointer,
68 length,
69 options,
70 );
71 Buffer::from_raw(ptr)
72 }
73 }
74
75 pub unsafe fn new_buffer_with_bytes_no_copy<F>(
86 &self,
87 pointer: *mut c_void,
88 length: UInteger,
89 options: ResourceOptions,
90 deallocator: F,
91 ) -> Option<Buffer>
92 where
93 F: Fn(*mut c_void, usize) + Send + 'static,
94 {
95 let block = mtl_sys::DeallocatorBlock::from_fn(deallocator);
96
97 unsafe {
98 let ptr: *mut c_void = msg_send_4(
99 self.as_ptr(),
100 sel!(newBufferWithBytesNoCopy: length: options: deallocator:),
101 pointer,
102 length,
103 options,
104 block.as_ptr(),
105 );
106 std::mem::forget(block);
108 Buffer::from_raw(ptr)
109 }
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116 use crate::device::system_default;
117
118 #[test]
119 fn test_new_buffer() {
120 let device = system_default().expect("no Metal device");
121 let buffer = device.new_buffer(1024, ResourceOptions::STORAGE_MODE_SHARED);
122 assert!(buffer.is_some());
123
124 let buffer = buffer.unwrap();
125 assert_eq!(buffer.length(), 1024);
126 }
127
128 #[test]
129 fn test_new_buffer_with_bytes() {
130 let device = system_default().expect("no Metal device");
131 let data = [0u8; 256];
132 let buffer = device.new_buffer_with_bytes(&data, ResourceOptions::STORAGE_MODE_SHARED);
133 assert!(buffer.is_some());
134
135 let buffer = buffer.unwrap();
136 assert_eq!(buffer.length(), 256);
137 }
138
139 #[test]
140 fn test_buffer_contents() {
141 let device = system_default().expect("no Metal device");
142 let data = [1u8, 2, 3, 4, 5, 6, 7, 8];
143 let buffer = device
144 .new_buffer_with_bytes(&data, ResourceOptions::STORAGE_MODE_SHARED)
145 .expect("failed to create buffer");
146
147 let contents = buffer.contents();
148 assert!(contents.is_some());
149
150 let ptr = contents.unwrap() as *const u8;
152 unsafe {
153 assert_eq!(*ptr, 1);
154 assert_eq!(*ptr.add(7), 8);
155 }
156 }
157}