Skip to main content

mtl_gpu/library/
intersection_function_descriptor.rs

1//! Descriptor for creating intersection functions.
2
3use std::ffi::c_void;
4use std::ptr::NonNull;
5
6use mtl_foundation::Referencing;
7use mtl_sys::{msg_send_0, msg_send_1, sel};
8
9use crate::enums::FunctionOptions;
10
11use super::FunctionConstantValues;
12
13/// Descriptor for creating intersection functions.
14///
15/// C++ equivalent: `MTL::IntersectionFunctionDescriptor`
16///
17/// Used to create intersection functions from a library. Inherits from FunctionDescriptor.
18#[repr(transparent)]
19pub struct IntersectionFunctionDescriptor(pub(crate) NonNull<c_void>);
20
21impl IntersectionFunctionDescriptor {
22    /// Allocate a new intersection function descriptor.
23    ///
24    /// C++ equivalent: `static IntersectionFunctionDescriptor* alloc()`
25    pub fn alloc() -> Option<Self> {
26        unsafe {
27            let cls = mtl_sys::Class::get("MTLIntersectionFunctionDescriptor")?;
28            let ptr: *mut c_void = msg_send_0(cls.as_ptr(), sel!(alloc));
29            Self::from_raw(ptr)
30        }
31    }
32
33    /// Initialize an allocated intersection function descriptor.
34    ///
35    /// C++ equivalent: `IntersectionFunctionDescriptor* init()`
36    pub fn init(&self) -> Option<Self> {
37        unsafe {
38            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(init));
39            Self::from_raw(ptr)
40        }
41    }
42
43    /// Create a new intersection function descriptor.
44    pub fn new() -> Option<Self> {
45        Self::alloc()?.init()
46    }
47
48    /// Create from a raw pointer.
49    ///
50    /// # Safety
51    ///
52    /// The pointer must be a valid Metal intersection function descriptor object.
53    #[inline]
54    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
55        NonNull::new(ptr).map(Self)
56    }
57
58    /// Get the raw pointer.
59    #[inline]
60    pub fn as_raw(&self) -> *mut c_void {
61        self.0.as_ptr()
62    }
63
64    // =========================================================================
65    // Inherited from FunctionDescriptor
66    // =========================================================================
67
68    /// Get the function name.
69    ///
70    /// C++ equivalent: `NS::String* name() const`
71    pub fn name(&self) -> Option<String> {
72        unsafe {
73            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(name));
74            if ptr.is_null() {
75                return None;
76            }
77            let utf8_ptr: *const std::ffi::c_char =
78                mtl_sys::msg_send_0(ptr as *const c_void, sel!(UTF8String));
79            if utf8_ptr.is_null() {
80                return None;
81            }
82            let c_str = std::ffi::CStr::from_ptr(utf8_ptr);
83            Some(c_str.to_string_lossy().into_owned())
84        }
85    }
86
87    /// Set the function name.
88    ///
89    /// C++ equivalent: `void setName(const NS::String*)`
90    pub fn set_name(&self, name: &str) {
91        if let Some(ns_name) = mtl_foundation::String::from_str(name) {
92            unsafe {
93                msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setName:), ns_name.as_ptr());
94            }
95        }
96    }
97
98    /// Get the specialized name.
99    ///
100    /// C++ equivalent: `NS::String* specializedName() const`
101    pub fn specialized_name(&self) -> Option<String> {
102        unsafe {
103            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(specializedName));
104            if ptr.is_null() {
105                return None;
106            }
107            let utf8_ptr: *const std::ffi::c_char =
108                mtl_sys::msg_send_0(ptr as *const c_void, sel!(UTF8String));
109            if utf8_ptr.is_null() {
110                return None;
111            }
112            let c_str = std::ffi::CStr::from_ptr(utf8_ptr);
113            Some(c_str.to_string_lossy().into_owned())
114        }
115    }
116
117    /// Set the specialized name.
118    ///
119    /// C++ equivalent: `void setSpecializedName(const NS::String*)`
120    pub fn set_specialized_name(&self, name: &str) {
121        if let Some(ns_name) = mtl_foundation::String::from_str(name) {
122            unsafe {
123                msg_send_1::<(), *const c_void>(
124                    self.as_ptr(),
125                    sel!(setSpecializedName:),
126                    ns_name.as_ptr(),
127                );
128            }
129        }
130    }
131
132    /// Get the function constant values.
133    ///
134    /// C++ equivalent: `FunctionConstantValues* constantValues() const`
135    pub fn constant_values(&self) -> Option<FunctionConstantValues> {
136        unsafe {
137            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(constantValues));
138            if ptr.is_null() {
139                return None;
140            }
141            msg_send_0::<*mut c_void>(ptr as *const c_void, sel!(retain));
142            FunctionConstantValues::from_raw(ptr)
143        }
144    }
145
146    /// Set the function constant values.
147    ///
148    /// C++ equivalent: `void setConstantValues(const FunctionConstantValues*)`
149    pub fn set_constant_values(&self, values: Option<&FunctionConstantValues>) {
150        let ptr = values.map(|v| v.as_ptr()).unwrap_or(std::ptr::null());
151        unsafe {
152            msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setConstantValues:), ptr);
153        }
154    }
155
156    /// Get the function options.
157    ///
158    /// C++ equivalent: `FunctionOptions options() const`
159    #[inline]
160    pub fn options(&self) -> FunctionOptions {
161        unsafe { msg_send_0(self.as_ptr(), sel!(options)) }
162    }
163
164    /// Set the function options.
165    ///
166    /// C++ equivalent: `void setOptions(FunctionOptions)`
167    #[inline]
168    pub fn set_options(&self, options: FunctionOptions) {
169        unsafe {
170            msg_send_1::<(), FunctionOptions>(self.as_ptr(), sel!(setOptions:), options);
171        }
172    }
173
174    /// Get the binary archives (raw NSArray pointer).
175    ///
176    /// C++ equivalent: `NS::Array* binaryArchives() const`
177    pub fn binary_archives_raw(&self) -> *mut c_void {
178        unsafe { msg_send_0(self.as_ptr(), sel!(binaryArchives)) }
179    }
180
181    /// Set the binary archives.
182    ///
183    /// C++ equivalent: `void setBinaryArchives(const NS::Array*)`
184    ///
185    /// # Safety
186    ///
187    /// The archives pointer must be a valid NSArray of BinaryArchive objects or null.
188    pub unsafe fn set_binary_archives_raw(&self, archives: *const c_void) {
189        unsafe {
190            msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setBinaryArchives:), archives);
191        }
192    }
193}
194
195impl Default for IntersectionFunctionDescriptor {
196    fn default() -> Self {
197        Self::new().expect("failed to create IntersectionFunctionDescriptor")
198    }
199}
200
201impl Clone for IntersectionFunctionDescriptor {
202    fn clone(&self) -> Self {
203        unsafe {
204            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(copy));
205            Self::from_raw(ptr).expect("failed to copy IntersectionFunctionDescriptor")
206        }
207    }
208}
209
210impl Drop for IntersectionFunctionDescriptor {
211    fn drop(&mut self) {
212        unsafe {
213            msg_send_0::<()>(self.as_ptr(), sel!(release));
214        }
215    }
216}
217
218impl Referencing for IntersectionFunctionDescriptor {
219    #[inline]
220    fn as_ptr(&self) -> *const c_void {
221        self.0.as_ptr()
222    }
223}
224
225unsafe impl Send for IntersectionFunctionDescriptor {}
226unsafe impl Sync for IntersectionFunctionDescriptor {}
227
228impl std::fmt::Debug for IntersectionFunctionDescriptor {
229    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
230        f.debug_struct("IntersectionFunctionDescriptor")
231            .field("name", &self.name())
232            .field("specialized_name", &self.specialized_name())
233            .field("options", &self.options())
234            .finish()
235    }
236}