mtl_gpu/mtl4/
command_allocator.rs1use std::ffi::c_void;
6use std::ptr::NonNull;
7
8use mtl_foundation::Referencing;
9use mtl_sys::{msg_send_0, msg_send_1, sel};
10
11use crate::Device;
12
13#[repr(transparent)]
21pub struct CommandAllocatorDescriptor(NonNull<c_void>);
22
23impl CommandAllocatorDescriptor {
24 #[inline]
26 pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
27 NonNull::new(ptr).map(Self)
28 }
29
30 #[inline]
32 pub fn as_raw(&self) -> *mut c_void {
33 self.0.as_ptr()
34 }
35
36 pub fn new() -> Option<Self> {
38 unsafe {
39 let class = mtl_sys::Class::get("MTL4CommandAllocatorDescriptor")?;
40 let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
41 if ptr.is_null() {
42 return None;
43 }
44 let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
45 Self::from_raw(ptr)
46 }
47 }
48
49 pub fn label(&self) -> Option<String> {
51 unsafe {
52 let ns_string: *mut c_void = msg_send_0(self.as_ptr(), sel!(label));
53 if ns_string.is_null() {
54 return None;
55 }
56 let c_str: *const i8 = msg_send_0(ns_string, sel!(UTF8String));
57 if c_str.is_null() {
58 return None;
59 }
60 Some(
61 std::ffi::CStr::from_ptr(c_str)
62 .to_string_lossy()
63 .into_owned(),
64 )
65 }
66 }
67
68 pub fn set_label(&self, label: &str) {
70 if let Some(ns_label) = mtl_foundation::String::from_str(label) {
71 unsafe {
72 let _: () = msg_send_1(self.as_ptr(), sel!(setLabel:), ns_label.as_ptr());
73 }
74 }
75 }
76}
77
78impl Clone for CommandAllocatorDescriptor {
79 fn clone(&self) -> Self {
80 unsafe {
81 mtl_sys::msg_send_0::<*mut c_void>(self.as_ptr(), mtl_sys::sel!(retain));
82 }
83 Self(self.0)
84 }
85}
86
87impl Drop for CommandAllocatorDescriptor {
88 fn drop(&mut self) {
89 unsafe {
90 mtl_sys::msg_send_0::<()>(self.as_ptr(), mtl_sys::sel!(release));
91 }
92 }
93}
94
95impl Referencing for CommandAllocatorDescriptor {
96 #[inline]
97 fn as_ptr(&self) -> *const c_void {
98 self.0.as_ptr()
99 }
100}
101
102unsafe impl Send for CommandAllocatorDescriptor {}
103unsafe impl Sync for CommandAllocatorDescriptor {}
104
105#[repr(transparent)]
116pub struct CommandAllocator(NonNull<c_void>);
117
118impl CommandAllocator {
119 #[inline]
121 pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
122 NonNull::new(ptr).map(Self)
123 }
124
125 #[inline]
127 pub fn as_raw(&self) -> *mut c_void {
128 self.0.as_ptr()
129 }
130
131 pub fn device(&self) -> Option<Device> {
135 unsafe {
136 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(device));
137 Device::from_raw(ptr)
138 }
139 }
140
141 pub fn label(&self) -> Option<String> {
145 unsafe {
146 let ns_string: *mut c_void = msg_send_0(self.as_ptr(), sel!(label));
147 if ns_string.is_null() {
148 return None;
149 }
150 let c_str: *const i8 = msg_send_0(ns_string, sel!(UTF8String));
151 if c_str.is_null() {
152 return None;
153 }
154 Some(
155 std::ffi::CStr::from_ptr(c_str)
156 .to_string_lossy()
157 .into_owned(),
158 )
159 }
160 }
161
162 pub fn allocated_size(&self) -> u64 {
166 unsafe { msg_send_0(self.as_ptr(), sel!(allocatedSize)) }
167 }
168
169 pub fn reset(&self) {
173 unsafe {
174 let _: () = msg_send_0(self.as_ptr(), sel!(reset));
175 }
176 }
177}
178
179impl Clone for CommandAllocator {
180 fn clone(&self) -> Self {
181 unsafe {
182 mtl_sys::msg_send_0::<*mut c_void>(self.as_ptr(), mtl_sys::sel!(retain));
183 }
184 Self(self.0)
185 }
186}
187
188impl Drop for CommandAllocator {
189 fn drop(&mut self) {
190 unsafe {
191 mtl_sys::msg_send_0::<()>(self.as_ptr(), mtl_sys::sel!(release));
192 }
193 }
194}
195
196impl Referencing for CommandAllocator {
197 #[inline]
198 fn as_ptr(&self) -> *const c_void {
199 self.0.as_ptr()
200 }
201}
202
203unsafe impl Send for CommandAllocator {}
204unsafe impl Sync for CommandAllocator {}
205
206impl std::fmt::Debug for CommandAllocator {
207 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
208 f.debug_struct("CommandAllocator")
209 .field("allocated_size", &self.allocated_size())
210 .finish()
211 }
212}
213
214#[cfg(test)]
215mod tests {
216 use super::*;
217
218 #[test]
219 fn test_command_allocator_descriptor_size() {
220 assert_eq!(
221 std::mem::size_of::<CommandAllocatorDescriptor>(),
222 std::mem::size_of::<*mut c_void>()
223 );
224 }
225
226 #[test]
227 fn test_command_allocator_size() {
228 assert_eq!(
229 std::mem::size_of::<CommandAllocator>(),
230 std::mem::size_of::<*mut c_void>()
231 );
232 }
233
234 #[test]
235 fn test_command_allocator_descriptor_creation() {
236 if let Some(desc) = CommandAllocatorDescriptor::new() {
238 drop(desc);
240 }
241 }
242}