Skip to main content

mtl_gpu/argument/
argument.rs

1//! Information about a function argument.
2
3use std::ffi::c_void;
4use std::ptr::NonNull;
5
6use mtl_foundation::{Referencing, UInteger};
7use mtl_sys::{msg_send_0, sel};
8
9use crate::enums::{ArgumentType, BindingAccess, DataType, TextureType};
10
11use super::{PointerType, StructType};
12
13/// Information about a function argument.
14///
15/// C++ equivalent: `MTL::Argument`
16#[repr(transparent)]
17pub struct Argument(pub(crate) NonNull<c_void>);
18
19impl Argument {
20    /// Create from a raw pointer.
21    ///
22    /// # Safety
23    ///
24    /// The pointer must be a valid Metal Argument.
25    #[inline]
26    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
27        NonNull::new(ptr).map(Self)
28    }
29
30    /// Get the raw pointer.
31    #[inline]
32    pub fn as_raw(&self) -> *mut c_void {
33        self.0.as_ptr()
34    }
35
36    /// Get the access mode.
37    ///
38    /// C++ equivalent: `BindingAccess access() const`
39    #[inline]
40    pub fn access(&self) -> BindingAccess {
41        unsafe { msg_send_0(self.as_ptr(), sel!(access)) }
42    }
43
44    /// Get the array length.
45    ///
46    /// C++ equivalent: `NS::UInteger arrayLength() const`
47    #[inline]
48    pub fn array_length(&self) -> UInteger {
49        unsafe { msg_send_0(self.as_ptr(), sel!(arrayLength)) }
50    }
51
52    /// Get the buffer alignment.
53    ///
54    /// C++ equivalent: `NS::UInteger bufferAlignment() const`
55    #[inline]
56    pub fn buffer_alignment(&self) -> UInteger {
57        unsafe { msg_send_0(self.as_ptr(), sel!(bufferAlignment)) }
58    }
59
60    /// Get the buffer data size.
61    ///
62    /// C++ equivalent: `NS::UInteger bufferDataSize() const`
63    #[inline]
64    pub fn buffer_data_size(&self) -> UInteger {
65        unsafe { msg_send_0(self.as_ptr(), sel!(bufferDataSize)) }
66    }
67
68    /// Get the buffer data type.
69    ///
70    /// C++ equivalent: `DataType bufferDataType() const`
71    #[inline]
72    pub fn buffer_data_type(&self) -> DataType {
73        unsafe { msg_send_0(self.as_ptr(), sel!(bufferDataType)) }
74    }
75
76    /// Get the buffer pointer type.
77    ///
78    /// C++ equivalent: `PointerType* bufferPointerType() const`
79    pub fn buffer_pointer_type(&self) -> Option<PointerType> {
80        unsafe {
81            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(bufferPointerType));
82            PointerType::from_raw(ptr)
83        }
84    }
85
86    /// Get the buffer struct type.
87    ///
88    /// C++ equivalent: `StructType* bufferStructType() const`
89    pub fn buffer_struct_type(&self) -> Option<StructType> {
90        unsafe {
91            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(bufferStructType));
92            StructType::from_raw(ptr)
93        }
94    }
95
96    /// Get the index.
97    ///
98    /// C++ equivalent: `NS::UInteger index() const`
99    #[inline]
100    pub fn index(&self) -> UInteger {
101        unsafe { msg_send_0(self.as_ptr(), sel!(index)) }
102    }
103
104    /// Check if the argument is active.
105    ///
106    /// C++ equivalent: `bool isActive() const`
107    #[inline]
108    pub fn is_active(&self) -> bool {
109        unsafe { msg_send_0(self.as_ptr(), sel!(isActive)) }
110    }
111
112    /// Check if this is a depth texture.
113    ///
114    /// C++ equivalent: `bool isDepthTexture() const`
115    #[inline]
116    pub fn is_depth_texture(&self) -> bool {
117        unsafe { msg_send_0(self.as_ptr(), sel!(isDepthTexture)) }
118    }
119
120    /// Get the name.
121    ///
122    /// C++ equivalent: `NS::String* name() const`
123    pub fn name(&self) -> Option<String> {
124        unsafe {
125            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(name));
126            if ptr.is_null() {
127                return None;
128            }
129            let utf8_ptr: *const std::ffi::c_char =
130                mtl_sys::msg_send_0(ptr as *const c_void, sel!(UTF8String));
131            if utf8_ptr.is_null() {
132                return None;
133            }
134            let c_str = std::ffi::CStr::from_ptr(utf8_ptr);
135            Some(c_str.to_string_lossy().into_owned())
136        }
137    }
138
139    /// Get the texture data type.
140    ///
141    /// C++ equivalent: `DataType textureDataType() const`
142    #[inline]
143    pub fn texture_data_type(&self) -> DataType {
144        unsafe { msg_send_0(self.as_ptr(), sel!(textureDataType)) }
145    }
146
147    /// Get the texture type.
148    ///
149    /// C++ equivalent: `TextureType textureType() const`
150    #[inline]
151    pub fn texture_type(&self) -> TextureType {
152        unsafe { msg_send_0(self.as_ptr(), sel!(textureType)) }
153    }
154
155    /// Get the threadgroup memory alignment.
156    ///
157    /// C++ equivalent: `NS::UInteger threadgroupMemoryAlignment() const`
158    #[inline]
159    pub fn threadgroup_memory_alignment(&self) -> UInteger {
160        unsafe { msg_send_0(self.as_ptr(), sel!(threadgroupMemoryAlignment)) }
161    }
162
163    /// Get the threadgroup memory data size.
164    ///
165    /// C++ equivalent: `NS::UInteger threadgroupMemoryDataSize() const`
166    #[inline]
167    pub fn threadgroup_memory_data_size(&self) -> UInteger {
168        unsafe { msg_send_0(self.as_ptr(), sel!(threadgroupMemoryDataSize)) }
169    }
170
171    /// Get the argument type.
172    ///
173    /// C++ equivalent: `ArgumentType type() const`
174    #[inline]
175    pub fn argument_type(&self) -> ArgumentType {
176        unsafe { msg_send_0(self.as_ptr(), sel!(type)) }
177    }
178
179    /// Check if the argument is active (deprecated).
180    ///
181    /// C++ equivalent: `bool active() const`
182    #[deprecated(note = "Use is_active instead")]
183    #[inline]
184    pub fn active(&self) -> bool {
185        unsafe { msg_send_0(self.as_ptr(), sel!(active)) }
186    }
187}
188
189impl Clone for Argument {
190    fn clone(&self) -> Self {
191        unsafe {
192            msg_send_0::<*mut c_void>(self.as_ptr(), sel!(retain));
193        }
194        Self(self.0)
195    }
196}
197
198impl Drop for Argument {
199    fn drop(&mut self) {
200        unsafe {
201            msg_send_0::<()>(self.as_ptr(), sel!(release));
202        }
203    }
204}
205
206impl Referencing for Argument {
207    #[inline]
208    fn as_ptr(&self) -> *const c_void {
209        self.0.as_ptr()
210    }
211}
212
213unsafe impl Send for Argument {}
214unsafe impl Sync for Argument {}