Skip to main content

mtl_gpu/acceleration/geometry/
base.rs

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