Skip to main content

mtl_gpu/library/
function_constant_values.rs

1//! Constant values for specializing a function.
2
3use std::ffi::c_void;
4use std::ptr::NonNull;
5
6use mtl_foundation::{Referencing, UInteger};
7use mtl_sys::{msg_send_0, sel};
8
9/// Constant values for specializing a function.
10///
11/// C++ equivalent: `MTL::FunctionConstantValues`
12///
13/// Function constant values allow you to specialize a function at runtime
14/// by providing values for function constants defined in shader code.
15#[repr(transparent)]
16pub struct FunctionConstantValues(pub(crate) NonNull<c_void>);
17
18impl FunctionConstantValues {
19    /// Allocate a new function constant values object.
20    ///
21    /// C++ equivalent: `static FunctionConstantValues* alloc()`
22    pub fn alloc() -> Option<Self> {
23        unsafe {
24            let cls = mtl_sys::Class::get("MTLFunctionConstantValues")?;
25            let ptr: *mut c_void = msg_send_0(cls.as_ptr(), sel!(alloc));
26            Self::from_raw(ptr)
27        }
28    }
29
30    /// Initialize an allocated function constant values object.
31    ///
32    /// C++ equivalent: `FunctionConstantValues* init()`
33    pub fn init(&self) -> Option<Self> {
34        unsafe {
35            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(init));
36            Self::from_raw(ptr)
37        }
38    }
39
40    /// Create a new function constant values object.
41    pub fn new() -> Option<Self> {
42        Self::alloc()?.init()
43    }
44
45    /// Create from a raw pointer.
46    ///
47    /// # Safety
48    ///
49    /// The pointer must be a valid Metal function constant values object.
50    #[inline]
51    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
52        NonNull::new(ptr).map(Self)
53    }
54
55    /// Get the raw pointer.
56    #[inline]
57    pub fn as_raw(&self) -> *mut c_void {
58        self.0.as_ptr()
59    }
60
61    /// Reset all constant values.
62    ///
63    /// C++ equivalent: `void reset()`
64    #[inline]
65    pub fn reset(&self) {
66        unsafe {
67            msg_send_0::<()>(self.as_ptr(), sel!(reset));
68        }
69    }
70
71    /// Set a constant value by index.
72    ///
73    /// C++ equivalent: `void setConstantValue(const void*, DataType, NS::UInteger)`
74    ///
75    /// # Safety
76    ///
77    /// The value pointer must be valid and point to data of the correct type.
78    pub unsafe fn set_constant_value_at_index(
79        &self,
80        value: *const c_void,
81        data_type: crate::DataType,
82        index: UInteger,
83    ) {
84        unsafe {
85            mtl_sys::msg_send_3::<(), *const c_void, crate::DataType, UInteger>(
86                self.as_ptr(),
87                sel!(setConstantValue: type: atIndex:),
88                value,
89                data_type,
90                index,
91            );
92        }
93    }
94
95    /// Set a constant value by name.
96    ///
97    /// C++ equivalent: `void setConstantValue(const void*, DataType, const NS::String*)`
98    ///
99    /// # Safety
100    ///
101    /// The value pointer must be valid and point to data of the correct type.
102    pub unsafe fn set_constant_value_with_name(
103        &self,
104        value: *const c_void,
105        data_type: crate::DataType,
106        name: &str,
107    ) {
108        if let Some(ns_name) = mtl_foundation::String::from_str(name) {
109            unsafe {
110                mtl_sys::msg_send_3::<(), *const c_void, crate::DataType, *const c_void>(
111                    self.as_ptr(),
112                    sel!(setConstantValue: type: withName:),
113                    value,
114                    data_type,
115                    ns_name.as_ptr(),
116                );
117            }
118        }
119    }
120
121    /// Set multiple constant values in a range.
122    ///
123    /// C++ equivalent: `void setConstantValues(const void*, DataType, NS::Range)`
124    ///
125    /// # Safety
126    ///
127    /// The values pointer must be valid and point to an array of data of the correct type.
128    pub unsafe fn set_constant_values(
129        &self,
130        values: *const c_void,
131        data_type: crate::DataType,
132        location: UInteger,
133        length: UInteger,
134    ) {
135        let range = mtl_foundation::Range::new(location, length);
136        unsafe {
137            mtl_sys::msg_send_3::<(), *const c_void, crate::DataType, mtl_foundation::Range>(
138                self.as_ptr(),
139                sel!(setConstantValues: type: withRange:),
140                values,
141                data_type,
142                range,
143            );
144        }
145    }
146
147    /// Set a boolean constant value by index.
148    pub fn set_bool_at_index(&self, value: bool, index: UInteger) {
149        unsafe {
150            self.set_constant_value_at_index(
151                &value as *const bool as *const c_void,
152                crate::DataType::BOOL,
153                index,
154            );
155        }
156    }
157
158    /// Set an integer constant value by index.
159    pub fn set_int_at_index(&self, value: i32, index: UInteger) {
160        unsafe {
161            self.set_constant_value_at_index(
162                &value as *const i32 as *const c_void,
163                crate::DataType::INT,
164                index,
165            );
166        }
167    }
168
169    /// Set an unsigned integer constant value by index.
170    pub fn set_uint_at_index(&self, value: u32, index: UInteger) {
171        unsafe {
172            self.set_constant_value_at_index(
173                &value as *const u32 as *const c_void,
174                crate::DataType::UINT,
175                index,
176            );
177        }
178    }
179
180    /// Set a float constant value by index.
181    pub fn set_float_at_index(&self, value: f32, index: UInteger) {
182        unsafe {
183            self.set_constant_value_at_index(
184                &value as *const f32 as *const c_void,
185                crate::DataType::FLOAT,
186                index,
187            );
188        }
189    }
190}
191
192impl Default for FunctionConstantValues {
193    fn default() -> Self {
194        Self::new().expect("failed to create FunctionConstantValues")
195    }
196}
197
198impl Clone for FunctionConstantValues {
199    fn clone(&self) -> Self {
200        unsafe {
201            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(copy));
202            Self::from_raw(ptr).expect("failed to copy FunctionConstantValues")
203        }
204    }
205}
206
207impl Drop for FunctionConstantValues {
208    fn drop(&mut self) {
209        unsafe {
210            msg_send_0::<()>(self.as_ptr(), sel!(release));
211        }
212    }
213}
214
215impl Referencing for FunctionConstantValues {
216    #[inline]
217    fn as_ptr(&self) -> *const c_void {
218        self.0.as_ptr()
219    }
220}
221
222unsafe impl Send for FunctionConstantValues {}
223unsafe impl Sync for FunctionConstantValues {}
224
225impl std::fmt::Debug for FunctionConstantValues {
226    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
227        f.debug_struct("FunctionConstantValues").finish()
228    }
229}