Skip to main content

mtl_gpu/acceleration/geometry/
bounding_box.rs

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