Skip to main content

mtl_gpu/mtl4/acceleration_structure/
geometry_descriptor.rs

1//! Base descriptor for geometry in an acceleration structure.
2
3use std::ffi::c_void;
4use std::ptr::NonNull;
5
6use mtl_foundation::{Referencing, UInteger};
7use mtl_sys::{msg_send_0, msg_send_1, sel};
8
9use super::BufferRange;
10
11/// Base descriptor for geometry in an acceleration structure.
12///
13/// C++ equivalent: `MTL4::AccelerationStructureGeometryDescriptor`
14#[repr(transparent)]
15pub struct AccelerationStructureGeometryDescriptor(NonNull<c_void>);
16
17impl AccelerationStructureGeometryDescriptor {
18    /// Create an AccelerationStructureGeometryDescriptor from a raw pointer.
19    #[inline]
20    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
21        NonNull::new(ptr).map(Self)
22    }
23
24    /// Get the raw pointer.
25    #[inline]
26    pub fn as_raw(&self) -> *mut c_void {
27        self.0.as_ptr()
28    }
29
30    /// Create a new acceleration structure geometry descriptor.
31    pub fn new() -> Option<Self> {
32        unsafe {
33            let class = mtl_sys::Class::get("MTL4AccelerationStructureGeometryDescriptor")?;
34            let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
35            if ptr.is_null() {
36                return None;
37            }
38            let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
39            Self::from_raw(ptr)
40        }
41    }
42
43    /// Get whether duplicate intersection function invocation is allowed.
44    ///
45    /// C++ equivalent: `bool allowDuplicateIntersectionFunctionInvocation() const`
46    pub fn allow_duplicate_intersection_function_invocation(&self) -> bool {
47        unsafe {
48            msg_send_0(
49                self.as_ptr(),
50                sel!(allowDuplicateIntersectionFunctionInvocation),
51            )
52        }
53    }
54
55    /// Set whether duplicate intersection function invocation is allowed.
56    ///
57    /// C++ equivalent: `void setAllowDuplicateIntersectionFunctionInvocation(bool)`
58    pub fn set_allow_duplicate_intersection_function_invocation(&self, allow: bool) {
59        unsafe {
60            let _: () = msg_send_1(
61                self.as_ptr(),
62                sel!(setAllowDuplicateIntersectionFunctionInvocation:),
63                allow,
64            );
65        }
66    }
67
68    /// Get the intersection function table offset.
69    ///
70    /// C++ equivalent: `NS::UInteger intersectionFunctionTableOffset() const`
71    pub fn intersection_function_table_offset(&self) -> UInteger {
72        unsafe { msg_send_0(self.as_ptr(), sel!(intersectionFunctionTableOffset)) }
73    }
74
75    /// Set the intersection function table offset.
76    ///
77    /// C++ equivalent: `void setIntersectionFunctionTableOffset(NS::UInteger)`
78    pub fn set_intersection_function_table_offset(&self, offset: UInteger) {
79        unsafe {
80            let _: () = msg_send_1(
81                self.as_ptr(),
82                sel!(setIntersectionFunctionTableOffset:),
83                offset,
84            );
85        }
86    }
87
88    /// Get the label.
89    ///
90    /// C++ equivalent: `NS::String* label() const`
91    pub fn label(&self) -> Option<String> {
92        unsafe {
93            let ns_string: *mut c_void = msg_send_0(self.as_ptr(), sel!(label));
94            if ns_string.is_null() {
95                return None;
96            }
97            let c_str: *const i8 = msg_send_0(ns_string, sel!(UTF8String));
98            if c_str.is_null() {
99                return None;
100            }
101            Some(
102                std::ffi::CStr::from_ptr(c_str)
103                    .to_string_lossy()
104                    .into_owned(),
105            )
106        }
107    }
108
109    /// Set the label.
110    ///
111    /// C++ equivalent: `void setLabel(const NS::String*)`
112    pub fn set_label(&self, label: &str) {
113        if let Some(ns_label) = mtl_foundation::String::from_str(label) {
114            unsafe {
115                let _: () = msg_send_1(self.as_ptr(), sel!(setLabel:), ns_label.as_ptr());
116            }
117        }
118    }
119
120    /// Get whether the geometry is opaque.
121    ///
122    /// C++ equivalent: `bool opaque() const`
123    pub fn opaque(&self) -> bool {
124        unsafe { msg_send_0(self.as_ptr(), sel!(opaque)) }
125    }
126
127    /// Set whether the geometry is opaque.
128    ///
129    /// C++ equivalent: `void setOpaque(bool)`
130    pub fn set_opaque(&self, opaque: bool) {
131        unsafe {
132            let _: () = msg_send_1(self.as_ptr(), sel!(setOpaque:), opaque);
133        }
134    }
135
136    /// Get the primitive data buffer.
137    ///
138    /// C++ equivalent: `BufferRange primitiveDataBuffer() const`
139    pub fn primitive_data_buffer(&self) -> BufferRange {
140        unsafe { msg_send_0(self.as_ptr(), sel!(primitiveDataBuffer)) }
141    }
142
143    /// Set the primitive data buffer.
144    ///
145    /// C++ equivalent: `void setPrimitiveDataBuffer(const MTL4::BufferRange)`
146    pub fn set_primitive_data_buffer(&self, buffer: BufferRange) {
147        unsafe {
148            let _: () = msg_send_1(self.as_ptr(), sel!(setPrimitiveDataBuffer:), buffer);
149        }
150    }
151
152    /// Get the primitive data element size.
153    ///
154    /// C++ equivalent: `NS::UInteger primitiveDataElementSize() const`
155    pub fn primitive_data_element_size(&self) -> UInteger {
156        unsafe { msg_send_0(self.as_ptr(), sel!(primitiveDataElementSize)) }
157    }
158
159    /// Set the primitive data element size.
160    ///
161    /// C++ equivalent: `void setPrimitiveDataElementSize(NS::UInteger)`
162    pub fn set_primitive_data_element_size(&self, size: UInteger) {
163        unsafe {
164            let _: () = msg_send_1(self.as_ptr(), sel!(setPrimitiveDataElementSize:), size);
165        }
166    }
167
168    /// Get the primitive data stride.
169    ///
170    /// C++ equivalent: `NS::UInteger primitiveDataStride() const`
171    pub fn primitive_data_stride(&self) -> UInteger {
172        unsafe { msg_send_0(self.as_ptr(), sel!(primitiveDataStride)) }
173    }
174
175    /// Set the primitive data stride.
176    ///
177    /// C++ equivalent: `void setPrimitiveDataStride(NS::UInteger)`
178    pub fn set_primitive_data_stride(&self, stride: UInteger) {
179        unsafe {
180            let _: () = msg_send_1(self.as_ptr(), sel!(setPrimitiveDataStride:), stride);
181        }
182    }
183}
184
185impl Default for AccelerationStructureGeometryDescriptor {
186    fn default() -> Self {
187        Self::new().expect("Failed to create MTL4AccelerationStructureGeometryDescriptor")
188    }
189}
190
191impl Clone for AccelerationStructureGeometryDescriptor {
192    fn clone(&self) -> Self {
193        unsafe {
194            mtl_sys::msg_send_0::<*mut c_void>(self.as_ptr(), mtl_sys::sel!(retain));
195        }
196        Self(self.0)
197    }
198}
199
200impl Drop for AccelerationStructureGeometryDescriptor {
201    fn drop(&mut self) {
202        unsafe {
203            mtl_sys::msg_send_0::<()>(self.as_ptr(), mtl_sys::sel!(release));
204        }
205    }
206}
207
208impl Referencing for AccelerationStructureGeometryDescriptor {
209    #[inline]
210    fn as_ptr(&self) -> *const c_void {
211        self.0.as_ptr()
212    }
213}
214
215unsafe impl Send for AccelerationStructureGeometryDescriptor {}
216unsafe impl Sync for AccelerationStructureGeometryDescriptor {}
217
218impl std::fmt::Debug for AccelerationStructureGeometryDescriptor {
219    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
220        f.debug_struct("AccelerationStructureGeometryDescriptor")
221            .field("label", &self.label())
222            .field("opaque", &self.opaque())
223            .finish()
224    }
225}