Skip to main content

mtl_gpu/
argument_descriptor.rs

1//! Argument descriptor.
2//!
3//! Corresponds to `MTL::ArgumentDescriptor` in `Metal/MTLDevice.hpp`.
4//!
5//! Used to describe arguments for creating argument encoders.
6
7use std::ffi::c_void;
8use std::ptr::NonNull;
9
10use mtl_foundation::{Referencing, UInteger};
11use mtl_sys::{msg_send_0, msg_send_1, sel};
12
13use crate::enums::{BindingAccess, DataType, TextureType};
14
15/// Describes an argument for creating an argument encoder.
16///
17/// C++ equivalent: `MTL::ArgumentDescriptor`
18#[repr(transparent)]
19pub struct ArgumentDescriptor(pub(crate) NonNull<c_void>);
20
21impl ArgumentDescriptor {
22    /// Create a new argument descriptor.
23    ///
24    /// C++ equivalent: `ArgumentDescriptor::argumentDescriptor()`
25    pub fn new() -> Option<Self> {
26        unsafe {
27            let class = mtl_sys::class!(MTLArgumentDescriptor);
28            let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(argumentDescriptor));
29            Self::from_raw(ptr)
30        }
31    }
32
33    /// Create from a raw pointer.
34    #[inline]
35    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
36        NonNull::new(ptr).map(Self)
37    }
38
39    /// Get the raw pointer.
40    #[inline]
41    pub fn as_raw(&self) -> *mut c_void {
42        self.0.as_ptr()
43    }
44
45    /// Get the data type.
46    ///
47    /// C++ equivalent: `DataType dataType() const`
48    #[inline]
49    pub fn data_type(&self) -> DataType {
50        unsafe { msg_send_0(self.as_ptr(), sel!(dataType)) }
51    }
52
53    /// Set the data type.
54    ///
55    /// C++ equivalent: `void setDataType(DataType)`
56    #[inline]
57    pub fn set_data_type(&self, data_type: DataType) {
58        unsafe {
59            msg_send_1::<(), DataType>(self.as_ptr(), sel!(setDataType:), data_type);
60        }
61    }
62
63    /// Get the index.
64    ///
65    /// C++ equivalent: `NS::UInteger index() const`
66    #[inline]
67    pub fn index(&self) -> UInteger {
68        unsafe { msg_send_0(self.as_ptr(), sel!(index)) }
69    }
70
71    /// Set the index.
72    ///
73    /// C++ equivalent: `void setIndex(NS::UInteger)`
74    #[inline]
75    pub fn set_index(&self, index: UInteger) {
76        unsafe {
77            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setIndex:), index);
78        }
79    }
80
81    /// Get the access mode.
82    ///
83    /// C++ equivalent: `BindingAccess access() const`
84    #[inline]
85    pub fn access(&self) -> BindingAccess {
86        unsafe { msg_send_0(self.as_ptr(), sel!(access)) }
87    }
88
89    /// Set the access mode.
90    ///
91    /// C++ equivalent: `void setAccess(BindingAccess)`
92    #[inline]
93    pub fn set_access(&self, access: BindingAccess) {
94        unsafe {
95            msg_send_1::<(), BindingAccess>(self.as_ptr(), sel!(setAccess:), access);
96        }
97    }
98
99    /// Get the array length.
100    ///
101    /// C++ equivalent: `NS::UInteger arrayLength() const`
102    #[inline]
103    pub fn array_length(&self) -> UInteger {
104        unsafe { msg_send_0(self.as_ptr(), sel!(arrayLength)) }
105    }
106
107    /// Set the array length.
108    ///
109    /// C++ equivalent: `void setArrayLength(NS::UInteger)`
110    #[inline]
111    pub fn set_array_length(&self, array_length: UInteger) {
112        unsafe {
113            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setArrayLength:), array_length);
114        }
115    }
116
117    /// Get the texture type.
118    ///
119    /// C++ equivalent: `TextureType textureType() const`
120    #[inline]
121    pub fn texture_type(&self) -> TextureType {
122        unsafe { msg_send_0(self.as_ptr(), sel!(textureType)) }
123    }
124
125    /// Set the texture type.
126    ///
127    /// C++ equivalent: `void setTextureType(TextureType)`
128    #[inline]
129    pub fn set_texture_type(&self, texture_type: TextureType) {
130        unsafe {
131            msg_send_1::<(), TextureType>(self.as_ptr(), sel!(setTextureType:), texture_type);
132        }
133    }
134
135    /// Get the constant block alignment.
136    ///
137    /// C++ equivalent: `NS::UInteger constantBlockAlignment() const`
138    #[inline]
139    pub fn constant_block_alignment(&self) -> UInteger {
140        unsafe { msg_send_0(self.as_ptr(), sel!(constantBlockAlignment)) }
141    }
142
143    /// Set the constant block alignment.
144    ///
145    /// C++ equivalent: `void setConstantBlockAlignment(NS::UInteger)`
146    #[inline]
147    pub fn set_constant_block_alignment(&self, alignment: UInteger) {
148        unsafe {
149            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setConstantBlockAlignment:), alignment);
150        }
151    }
152}
153
154impl Default for ArgumentDescriptor {
155    fn default() -> Self {
156        Self::new().expect("failed to create ArgumentDescriptor")
157    }
158}
159
160impl Clone for ArgumentDescriptor {
161    fn clone(&self) -> Self {
162        unsafe {
163            msg_send_0::<*mut c_void>(self.as_ptr(), sel!(retain));
164        }
165        Self(self.0)
166    }
167}
168
169impl Drop for ArgumentDescriptor {
170    fn drop(&mut self) {
171        unsafe {
172            msg_send_0::<()>(self.as_ptr(), sel!(release));
173        }
174    }
175}
176
177impl Referencing for ArgumentDescriptor {
178    #[inline]
179    fn as_ptr(&self) -> *const c_void {
180        self.0.as_ptr()
181    }
182}
183
184unsafe impl Send for ArgumentDescriptor {}
185unsafe impl Sync for ArgumentDescriptor {}
186
187#[cfg(test)]
188mod tests {
189    use super::*;
190
191    #[test]
192    fn test_type_size() {
193        assert_eq!(
194            std::mem::size_of::<ArgumentDescriptor>(),
195            std::mem::size_of::<*mut c_void>()
196        );
197    }
198}