Skip to main content

mtl_gpu/acceleration/geometry/
triangle.rs

1//! Triangle 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;
10use crate::enums::{AttributeFormat, IndexType, MatrixLayout};
11
12/// Descriptor for triangle geometry in acceleration structures.
13///
14/// C++ equivalent: `MTL::AccelerationStructureTriangleGeometryDescriptor`
15#[repr(transparent)]
16pub struct AccelerationStructureTriangleGeometryDescriptor(pub(crate) NonNull<c_void>);
17
18impl AccelerationStructureTriangleGeometryDescriptor {
19    /// Create a new triangle geometry descriptor.
20    ///
21    /// C++ equivalent: `static AccelerationStructureTriangleGeometryDescriptor* alloc()->init()`
22    pub fn new() -> Option<Self> {
23        unsafe {
24            let class =
25                mtl_sys::Class::get("MTLAccelerationStructureTriangleGeometryDescriptor")?;
26            let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
27            if ptr.is_null() {
28                return None;
29            }
30            let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
31            Self::from_raw(ptr)
32        }
33    }
34
35    /// Create from a raw pointer.
36    ///
37    /// # Safety
38    ///
39    /// The pointer must be a valid Metal triangle geometry descriptor.
40    #[inline]
41    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
42        NonNull::new(ptr).map(Self)
43    }
44
45    /// Get the raw pointer.
46    #[inline]
47    pub fn as_raw(&self) -> *mut c_void {
48        self.0.as_ptr()
49    }
50
51    // Inherited properties from AccelerationStructureGeometryDescriptor
52
53    /// Get whether duplicate intersection function invocation is allowed.
54    #[inline]
55    pub fn allow_duplicate_intersection_function_invocation(&self) -> bool {
56        unsafe {
57            msg_send_0(
58                self.as_ptr(),
59                sel!(allowDuplicateIntersectionFunctionInvocation),
60            )
61        }
62    }
63
64    /// Set whether duplicate intersection function invocation is allowed.
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    #[inline]
78    pub fn intersection_function_table_offset(&self) -> UInteger {
79        unsafe { msg_send_0(self.as_ptr(), sel!(intersectionFunctionTableOffset)) }
80    }
81
82    /// Set the intersection function table offset.
83    #[inline]
84    pub fn set_intersection_function_table_offset(&self, offset: UInteger) {
85        unsafe {
86            msg_send_1::<(), UInteger>(
87                self.as_ptr(),
88                sel!(setIntersectionFunctionTableOffset:),
89                offset,
90            );
91        }
92    }
93
94    /// Get whether geometry is opaque.
95    #[inline]
96    pub fn opaque(&self) -> bool {
97        unsafe { msg_send_0(self.as_ptr(), sel!(opaque)) }
98    }
99
100    /// Set whether geometry is opaque.
101    #[inline]
102    pub fn set_opaque(&self, opaque: bool) {
103        unsafe {
104            msg_send_1::<(), bool>(self.as_ptr(), sel!(setOpaque:), opaque);
105        }
106    }
107
108    /// Get the label.
109    pub fn label(&self) -> Option<String> {
110        unsafe {
111            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(label));
112            if ptr.is_null() {
113                return None;
114            }
115            let utf8_ptr: *const std::ffi::c_char =
116                mtl_sys::msg_send_0(ptr as *const c_void, sel!(UTF8String));
117            if utf8_ptr.is_null() {
118                return None;
119            }
120            let c_str = std::ffi::CStr::from_ptr(utf8_ptr);
121            Some(c_str.to_string_lossy().into_owned())
122        }
123    }
124
125    /// Set the label.
126    pub fn set_label(&self, label: &str) {
127        if let Some(ns_label) = mtl_foundation::String::from_str(label) {
128            unsafe {
129                msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setLabel:), ns_label.as_ptr());
130            }
131        }
132    }
133
134    /// Get the primitive data buffer.
135    pub fn primitive_data_buffer(&self) -> Option<Buffer> {
136        unsafe {
137            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(primitiveDataBuffer));
138            if ptr.is_null() {
139                return None;
140            }
141            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
142            Buffer::from_raw(ptr)
143        }
144    }
145
146    /// Set the primitive data buffer.
147    pub fn set_primitive_data_buffer(&self, buffer: Option<&Buffer>) {
148        unsafe {
149            msg_send_1::<(), *const c_void>(
150                self.as_ptr(),
151                sel!(setPrimitiveDataBuffer:),
152                buffer.map_or(std::ptr::null(), |b| b.as_ptr()),
153            );
154        }
155    }
156
157    /// Get the primitive data buffer offset.
158    #[inline]
159    pub fn primitive_data_buffer_offset(&self) -> UInteger {
160        unsafe { msg_send_0(self.as_ptr(), sel!(primitiveDataBufferOffset)) }
161    }
162
163    /// Set the primitive data buffer offset.
164    #[inline]
165    pub fn set_primitive_data_buffer_offset(&self, offset: UInteger) {
166        unsafe {
167            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setPrimitiveDataBufferOffset:), offset);
168        }
169    }
170
171    /// Get the primitive data element size.
172    #[inline]
173    pub fn primitive_data_element_size(&self) -> UInteger {
174        unsafe { msg_send_0(self.as_ptr(), sel!(primitiveDataElementSize)) }
175    }
176
177    /// Set the primitive data element size.
178    #[inline]
179    pub fn set_primitive_data_element_size(&self, size: UInteger) {
180        unsafe {
181            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setPrimitiveDataElementSize:), size);
182        }
183    }
184
185    /// Get the primitive data stride.
186    #[inline]
187    pub fn primitive_data_stride(&self) -> UInteger {
188        unsafe { msg_send_0(self.as_ptr(), sel!(primitiveDataStride)) }
189    }
190
191    /// Set the primitive data stride.
192    #[inline]
193    pub fn set_primitive_data_stride(&self, stride: UInteger) {
194        unsafe {
195            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setPrimitiveDataStride:), stride);
196        }
197    }
198
199    // Triangle-specific properties
200
201    /// Get the index buffer.
202    ///
203    /// C++ equivalent: `Buffer* indexBuffer() const`
204    pub fn index_buffer(&self) -> Option<Buffer> {
205        unsafe {
206            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(indexBuffer));
207            if ptr.is_null() {
208                return None;
209            }
210            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
211            Buffer::from_raw(ptr)
212        }
213    }
214
215    /// Set the index buffer.
216    ///
217    /// C++ equivalent: `void setIndexBuffer(Buffer*)`
218    pub fn set_index_buffer(&self, buffer: Option<&Buffer>) {
219        unsafe {
220            msg_send_1::<(), *const c_void>(
221                self.as_ptr(),
222                sel!(setIndexBuffer:),
223                buffer.map_or(std::ptr::null(), |b| b.as_ptr()),
224            );
225        }
226    }
227
228    /// Get the index buffer offset.
229    ///
230    /// C++ equivalent: `NS::UInteger indexBufferOffset() const`
231    #[inline]
232    pub fn index_buffer_offset(&self) -> UInteger {
233        unsafe { msg_send_0(self.as_ptr(), sel!(indexBufferOffset)) }
234    }
235
236    /// Set the index buffer offset.
237    ///
238    /// C++ equivalent: `void setIndexBufferOffset(NS::UInteger)`
239    #[inline]
240    pub fn set_index_buffer_offset(&self, offset: UInteger) {
241        unsafe {
242            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setIndexBufferOffset:), offset);
243        }
244    }
245
246    /// Get the index type.
247    ///
248    /// C++ equivalent: `IndexType indexType() const`
249    #[inline]
250    pub fn index_type(&self) -> IndexType {
251        unsafe { msg_send_0(self.as_ptr(), sel!(indexType)) }
252    }
253
254    /// Set the index type.
255    ///
256    /// C++ equivalent: `void setIndexType(IndexType)`
257    #[inline]
258    pub fn set_index_type(&self, index_type: IndexType) {
259        unsafe {
260            msg_send_1::<(), IndexType>(self.as_ptr(), sel!(setIndexType:), index_type);
261        }
262    }
263
264    /// Get the vertex buffer.
265    ///
266    /// C++ equivalent: `Buffer* vertexBuffer() const`
267    pub fn vertex_buffer(&self) -> Option<Buffer> {
268        unsafe {
269            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(vertexBuffer));
270            if ptr.is_null() {
271                return None;
272            }
273            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
274            Buffer::from_raw(ptr)
275        }
276    }
277
278    /// Set the vertex buffer.
279    ///
280    /// C++ equivalent: `void setVertexBuffer(Buffer*)`
281    pub fn set_vertex_buffer(&self, buffer: Option<&Buffer>) {
282        unsafe {
283            msg_send_1::<(), *const c_void>(
284                self.as_ptr(),
285                sel!(setVertexBuffer:),
286                buffer.map_or(std::ptr::null(), |b| b.as_ptr()),
287            );
288        }
289    }
290
291    /// Get the vertex buffer offset.
292    ///
293    /// C++ equivalent: `NS::UInteger vertexBufferOffset() const`
294    #[inline]
295    pub fn vertex_buffer_offset(&self) -> UInteger {
296        unsafe { msg_send_0(self.as_ptr(), sel!(vertexBufferOffset)) }
297    }
298
299    /// Set the vertex buffer offset.
300    ///
301    /// C++ equivalent: `void setVertexBufferOffset(NS::UInteger)`
302    #[inline]
303    pub fn set_vertex_buffer_offset(&self, offset: UInteger) {
304        unsafe {
305            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setVertexBufferOffset:), offset);
306        }
307    }
308
309    /// Get the vertex format.
310    ///
311    /// C++ equivalent: `AttributeFormat vertexFormat() const`
312    #[inline]
313    pub fn vertex_format(&self) -> AttributeFormat {
314        unsafe { msg_send_0(self.as_ptr(), sel!(vertexFormat)) }
315    }
316
317    /// Set the vertex format.
318    ///
319    /// C++ equivalent: `void setVertexFormat(AttributeFormat)`
320    #[inline]
321    pub fn set_vertex_format(&self, format: AttributeFormat) {
322        unsafe {
323            msg_send_1::<(), AttributeFormat>(self.as_ptr(), sel!(setVertexFormat:), format);
324        }
325    }
326
327    /// Get the vertex stride.
328    ///
329    /// C++ equivalent: `NS::UInteger vertexStride() const`
330    #[inline]
331    pub fn vertex_stride(&self) -> UInteger {
332        unsafe { msg_send_0(self.as_ptr(), sel!(vertexStride)) }
333    }
334
335    /// Set the vertex stride.
336    ///
337    /// C++ equivalent: `void setVertexStride(NS::UInteger)`
338    #[inline]
339    pub fn set_vertex_stride(&self, stride: UInteger) {
340        unsafe {
341            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setVertexStride:), stride);
342        }
343    }
344
345    /// Get the triangle count.
346    ///
347    /// C++ equivalent: `NS::UInteger triangleCount() const`
348    #[inline]
349    pub fn triangle_count(&self) -> UInteger {
350        unsafe { msg_send_0(self.as_ptr(), sel!(triangleCount)) }
351    }
352
353    /// Set the triangle count.
354    ///
355    /// C++ equivalent: `void setTriangleCount(NS::UInteger)`
356    #[inline]
357    pub fn set_triangle_count(&self, count: UInteger) {
358        unsafe {
359            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setTriangleCount:), count);
360        }
361    }
362
363    /// Get the transformation matrix buffer.
364    ///
365    /// C++ equivalent: `Buffer* transformationMatrixBuffer() const`
366    pub fn transformation_matrix_buffer(&self) -> Option<Buffer> {
367        unsafe {
368            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(transformationMatrixBuffer));
369            if ptr.is_null() {
370                return None;
371            }
372            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
373            Buffer::from_raw(ptr)
374        }
375    }
376
377    /// Set the transformation matrix buffer.
378    ///
379    /// C++ equivalent: `void setTransformationMatrixBuffer(Buffer*)`
380    pub fn set_transformation_matrix_buffer(&self, buffer: Option<&Buffer>) {
381        unsafe {
382            msg_send_1::<(), *const c_void>(
383                self.as_ptr(),
384                sel!(setTransformationMatrixBuffer:),
385                buffer.map_or(std::ptr::null(), |b| b.as_ptr()),
386            );
387        }
388    }
389
390    /// Get the transformation matrix buffer offset.
391    ///
392    /// C++ equivalent: `NS::UInteger transformationMatrixBufferOffset() const`
393    #[inline]
394    pub fn transformation_matrix_buffer_offset(&self) -> UInteger {
395        unsafe { msg_send_0(self.as_ptr(), sel!(transformationMatrixBufferOffset)) }
396    }
397
398    /// Set the transformation matrix buffer offset.
399    ///
400    /// C++ equivalent: `void setTransformationMatrixBufferOffset(NS::UInteger)`
401    #[inline]
402    pub fn set_transformation_matrix_buffer_offset(&self, offset: UInteger) {
403        unsafe {
404            msg_send_1::<(), UInteger>(
405                self.as_ptr(),
406                sel!(setTransformationMatrixBufferOffset:),
407                offset,
408            );
409        }
410    }
411
412    /// Get the transformation matrix layout.
413    ///
414    /// C++ equivalent: `MatrixLayout transformationMatrixLayout() const`
415    #[inline]
416    pub fn transformation_matrix_layout(&self) -> MatrixLayout {
417        unsafe { msg_send_0(self.as_ptr(), sel!(transformationMatrixLayout)) }
418    }
419
420    /// Set the transformation matrix layout.
421    ///
422    /// C++ equivalent: `void setTransformationMatrixLayout(MatrixLayout)`
423    #[inline]
424    pub fn set_transformation_matrix_layout(&self, layout: MatrixLayout) {
425        unsafe {
426            msg_send_1::<(), MatrixLayout>(
427                self.as_ptr(),
428                sel!(setTransformationMatrixLayout:),
429                layout,
430            );
431        }
432    }
433}
434
435impl Default for AccelerationStructureTriangleGeometryDescriptor {
436    fn default() -> Self {
437        Self::new().expect("failed to create triangle geometry descriptor")
438    }
439}
440
441impl Clone for AccelerationStructureTriangleGeometryDescriptor {
442    fn clone(&self) -> Self {
443        unsafe {
444            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(copy));
445            Self::from_raw(ptr).expect("failed to copy triangle geometry descriptor")
446        }
447    }
448}
449
450impl Drop for AccelerationStructureTriangleGeometryDescriptor {
451    fn drop(&mut self) {
452        unsafe {
453            msg_send_0::<()>(self.as_ptr(), sel!(release));
454        }
455    }
456}
457
458impl Referencing for AccelerationStructureTriangleGeometryDescriptor {
459    #[inline]
460    fn as_ptr(&self) -> *const c_void {
461        self.0.as_ptr()
462    }
463}
464
465unsafe impl Send for AccelerationStructureTriangleGeometryDescriptor {}
466unsafe impl Sync for AccelerationStructureTriangleGeometryDescriptor {}