Skip to main content

mtl_gpu/acceleration/
curve.rs

1//! Curve geometry descriptors for acceleration structures.
2//!
3//! Contains `AccelerationStructureCurveGeometryDescriptor`.
4
5use std::ffi::c_void;
6use std::ptr::NonNull;
7
8use mtl_foundation::{Referencing, UInteger};
9use mtl_sys::{msg_send_0, msg_send_1, sel};
10
11use crate::Buffer;
12use crate::enums::{AttributeFormat, CurveBasis, CurveEndCaps, CurveType, IndexType};
13
14pub struct AccelerationStructureCurveGeometryDescriptor(pub(crate) NonNull<c_void>);
15
16impl AccelerationStructureCurveGeometryDescriptor {
17    /// Create a new curve geometry descriptor.
18    ///
19    /// C++ equivalent: `static AccelerationStructureCurveGeometryDescriptor* alloc()->init()`
20    pub fn new() -> Option<Self> {
21        unsafe {
22            let class = mtl_sys::Class::get("MTLAccelerationStructureCurveGeometryDescriptor")?;
23            let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
24            if ptr.is_null() {
25                return None;
26            }
27            let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
28            Self::from_raw(ptr)
29        }
30    }
31
32    /// Create from a raw pointer.
33    ///
34    /// # Safety
35    ///
36    /// The pointer must be a valid Metal curve geometry descriptor.
37    #[inline]
38    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
39        NonNull::new(ptr).map(Self)
40    }
41
42    /// Get the raw pointer.
43    #[inline]
44    pub fn as_raw(&self) -> *mut c_void {
45        self.0.as_ptr()
46    }
47
48    // Inherited properties from AccelerationStructureGeometryDescriptor
49
50    /// Get whether duplicate intersection function invocation is allowed.
51    #[inline]
52    pub fn allow_duplicate_intersection_function_invocation(&self) -> bool {
53        unsafe {
54            msg_send_0(
55                self.as_ptr(),
56                sel!(allowDuplicateIntersectionFunctionInvocation),
57            )
58        }
59    }
60
61    /// Set whether duplicate intersection function invocation is allowed.
62    #[inline]
63    pub fn set_allow_duplicate_intersection_function_invocation(&self, allow: bool) {
64        unsafe {
65            msg_send_1::<(), bool>(
66                self.as_ptr(),
67                sel!(setAllowDuplicateIntersectionFunctionInvocation:),
68                allow,
69            );
70        }
71    }
72
73    /// Get the intersection function table offset.
74    #[inline]
75    pub fn intersection_function_table_offset(&self) -> UInteger {
76        unsafe { msg_send_0(self.as_ptr(), sel!(intersectionFunctionTableOffset)) }
77    }
78
79    /// Set the intersection function table offset.
80    #[inline]
81    pub fn set_intersection_function_table_offset(&self, offset: UInteger) {
82        unsafe {
83            msg_send_1::<(), UInteger>(
84                self.as_ptr(),
85                sel!(setIntersectionFunctionTableOffset:),
86                offset,
87            );
88        }
89    }
90
91    /// Get whether geometry is opaque.
92    #[inline]
93    pub fn opaque(&self) -> bool {
94        unsafe { msg_send_0(self.as_ptr(), sel!(opaque)) }
95    }
96
97    /// Set whether geometry is opaque.
98    #[inline]
99    pub fn set_opaque(&self, opaque: bool) {
100        unsafe {
101            msg_send_1::<(), bool>(self.as_ptr(), sel!(setOpaque:), opaque);
102        }
103    }
104
105    /// Get the label.
106    pub fn label(&self) -> Option<String> {
107        unsafe {
108            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(label));
109            if ptr.is_null() {
110                return None;
111            }
112            let utf8_ptr: *const std::ffi::c_char =
113                mtl_sys::msg_send_0(ptr as *const c_void, sel!(UTF8String));
114            if utf8_ptr.is_null() {
115                return None;
116            }
117            let c_str = std::ffi::CStr::from_ptr(utf8_ptr);
118            Some(c_str.to_string_lossy().into_owned())
119        }
120    }
121
122    /// Set the label.
123    pub fn set_label(&self, label: &str) {
124        if let Some(ns_label) = mtl_foundation::String::from_str(label) {
125            unsafe {
126                msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setLabel:), ns_label.as_ptr());
127            }
128        }
129    }
130
131    /// Get the primitive data buffer.
132    pub fn primitive_data_buffer(&self) -> Option<Buffer> {
133        unsafe {
134            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(primitiveDataBuffer));
135            if ptr.is_null() {
136                return None;
137            }
138            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
139            Buffer::from_raw(ptr)
140        }
141    }
142
143    /// Set the primitive data buffer.
144    pub fn set_primitive_data_buffer(&self, buffer: Option<&Buffer>) {
145        unsafe {
146            msg_send_1::<(), *const c_void>(
147                self.as_ptr(),
148                sel!(setPrimitiveDataBuffer:),
149                buffer.map_or(std::ptr::null(), |b| b.as_ptr()),
150            );
151        }
152    }
153
154    /// Get the primitive data buffer offset.
155    #[inline]
156    pub fn primitive_data_buffer_offset(&self) -> UInteger {
157        unsafe { msg_send_0(self.as_ptr(), sel!(primitiveDataBufferOffset)) }
158    }
159
160    /// Set the primitive data buffer offset.
161    #[inline]
162    pub fn set_primitive_data_buffer_offset(&self, offset: UInteger) {
163        unsafe {
164            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setPrimitiveDataBufferOffset:), offset);
165        }
166    }
167
168    /// Get the primitive data element size.
169    #[inline]
170    pub fn primitive_data_element_size(&self) -> UInteger {
171        unsafe { msg_send_0(self.as_ptr(), sel!(primitiveDataElementSize)) }
172    }
173
174    /// Set the primitive data element size.
175    #[inline]
176    pub fn set_primitive_data_element_size(&self, size: UInteger) {
177        unsafe {
178            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setPrimitiveDataElementSize:), size);
179        }
180    }
181
182    /// Get the primitive data stride.
183    #[inline]
184    pub fn primitive_data_stride(&self) -> UInteger {
185        unsafe { msg_send_0(self.as_ptr(), sel!(primitiveDataStride)) }
186    }
187
188    /// Set the primitive data stride.
189    #[inline]
190    pub fn set_primitive_data_stride(&self, stride: UInteger) {
191        unsafe {
192            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setPrimitiveDataStride:), stride);
193        }
194    }
195
196    // Curve-specific properties
197
198    /// Get the control point buffer.
199    ///
200    /// C++ equivalent: `Buffer* controlPointBuffer() const`
201    pub fn control_point_buffer(&self) -> Option<Buffer> {
202        unsafe {
203            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(controlPointBuffer));
204            if ptr.is_null() {
205                return None;
206            }
207            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
208            Buffer::from_raw(ptr)
209        }
210    }
211
212    /// Set the control point buffer.
213    ///
214    /// C++ equivalent: `void setControlPointBuffer(Buffer*)`
215    pub fn set_control_point_buffer(&self, buffer: Option<&Buffer>) {
216        unsafe {
217            msg_send_1::<(), *const c_void>(
218                self.as_ptr(),
219                sel!(setControlPointBuffer:),
220                buffer.map_or(std::ptr::null(), |b| b.as_ptr()),
221            );
222        }
223    }
224
225    /// Get the control point buffer offset.
226    ///
227    /// C++ equivalent: `NS::UInteger controlPointBufferOffset() const`
228    #[inline]
229    pub fn control_point_buffer_offset(&self) -> UInteger {
230        unsafe { msg_send_0(self.as_ptr(), sel!(controlPointBufferOffset)) }
231    }
232
233    /// Set the control point buffer offset.
234    ///
235    /// C++ equivalent: `void setControlPointBufferOffset(NS::UInteger)`
236    #[inline]
237    pub fn set_control_point_buffer_offset(&self, offset: UInteger) {
238        unsafe {
239            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setControlPointBufferOffset:), offset);
240        }
241    }
242
243    /// Get the control point count.
244    ///
245    /// C++ equivalent: `NS::UInteger controlPointCount() const`
246    #[inline]
247    pub fn control_point_count(&self) -> UInteger {
248        unsafe { msg_send_0(self.as_ptr(), sel!(controlPointCount)) }
249    }
250
251    /// Set the control point count.
252    ///
253    /// C++ equivalent: `void setControlPointCount(NS::UInteger)`
254    #[inline]
255    pub fn set_control_point_count(&self, count: UInteger) {
256        unsafe {
257            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setControlPointCount:), count);
258        }
259    }
260
261    /// Get the control point format.
262    ///
263    /// C++ equivalent: `AttributeFormat controlPointFormat() const`
264    #[inline]
265    pub fn control_point_format(&self) -> AttributeFormat {
266        unsafe { msg_send_0(self.as_ptr(), sel!(controlPointFormat)) }
267    }
268
269    /// Set the control point format.
270    ///
271    /// C++ equivalent: `void setControlPointFormat(AttributeFormat)`
272    #[inline]
273    pub fn set_control_point_format(&self, format: AttributeFormat) {
274        unsafe {
275            msg_send_1::<(), AttributeFormat>(self.as_ptr(), sel!(setControlPointFormat:), format);
276        }
277    }
278
279    /// Get the control point stride.
280    ///
281    /// C++ equivalent: `NS::UInteger controlPointStride() const`
282    #[inline]
283    pub fn control_point_stride(&self) -> UInteger {
284        unsafe { msg_send_0(self.as_ptr(), sel!(controlPointStride)) }
285    }
286
287    /// Set the control point stride.
288    ///
289    /// C++ equivalent: `void setControlPointStride(NS::UInteger)`
290    #[inline]
291    pub fn set_control_point_stride(&self, stride: UInteger) {
292        unsafe {
293            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setControlPointStride:), stride);
294        }
295    }
296
297    /// Get the curve basis.
298    ///
299    /// C++ equivalent: `CurveBasis curveBasis() const`
300    #[inline]
301    pub fn curve_basis(&self) -> CurveBasis {
302        unsafe { msg_send_0(self.as_ptr(), sel!(curveBasis)) }
303    }
304
305    /// Set the curve basis.
306    ///
307    /// C++ equivalent: `void setCurveBasis(CurveBasis)`
308    #[inline]
309    pub fn set_curve_basis(&self, basis: CurveBasis) {
310        unsafe {
311            msg_send_1::<(), CurveBasis>(self.as_ptr(), sel!(setCurveBasis:), basis);
312        }
313    }
314
315    /// Get the curve end caps.
316    ///
317    /// C++ equivalent: `CurveEndCaps curveEndCaps() const`
318    #[inline]
319    pub fn curve_end_caps(&self) -> CurveEndCaps {
320        unsafe { msg_send_0(self.as_ptr(), sel!(curveEndCaps)) }
321    }
322
323    /// Set the curve end caps.
324    ///
325    /// C++ equivalent: `void setCurveEndCaps(CurveEndCaps)`
326    #[inline]
327    pub fn set_curve_end_caps(&self, end_caps: CurveEndCaps) {
328        unsafe {
329            msg_send_1::<(), CurveEndCaps>(self.as_ptr(), sel!(setCurveEndCaps:), end_caps);
330        }
331    }
332
333    /// Get the curve type.
334    ///
335    /// C++ equivalent: `CurveType curveType() const`
336    #[inline]
337    pub fn curve_type(&self) -> CurveType {
338        unsafe { msg_send_0(self.as_ptr(), sel!(curveType)) }
339    }
340
341    /// Set the curve type.
342    ///
343    /// C++ equivalent: `void setCurveType(CurveType)`
344    #[inline]
345    pub fn set_curve_type(&self, curve_type: CurveType) {
346        unsafe {
347            msg_send_1::<(), CurveType>(self.as_ptr(), sel!(setCurveType:), curve_type);
348        }
349    }
350
351    /// Get the index buffer.
352    ///
353    /// C++ equivalent: `Buffer* indexBuffer() const`
354    pub fn index_buffer(&self) -> Option<Buffer> {
355        unsafe {
356            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(indexBuffer));
357            if ptr.is_null() {
358                return None;
359            }
360            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
361            Buffer::from_raw(ptr)
362        }
363    }
364
365    /// Set the index buffer.
366    ///
367    /// C++ equivalent: `void setIndexBuffer(Buffer*)`
368    pub fn set_index_buffer(&self, buffer: Option<&Buffer>) {
369        unsafe {
370            msg_send_1::<(), *const c_void>(
371                self.as_ptr(),
372                sel!(setIndexBuffer:),
373                buffer.map_or(std::ptr::null(), |b| b.as_ptr()),
374            );
375        }
376    }
377
378    /// Get the index buffer offset.
379    ///
380    /// C++ equivalent: `NS::UInteger indexBufferOffset() const`
381    #[inline]
382    pub fn index_buffer_offset(&self) -> UInteger {
383        unsafe { msg_send_0(self.as_ptr(), sel!(indexBufferOffset)) }
384    }
385
386    /// Set the index buffer offset.
387    ///
388    /// C++ equivalent: `void setIndexBufferOffset(NS::UInteger)`
389    #[inline]
390    pub fn set_index_buffer_offset(&self, offset: UInteger) {
391        unsafe {
392            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setIndexBufferOffset:), offset);
393        }
394    }
395
396    /// Get the index type.
397    ///
398    /// C++ equivalent: `IndexType indexType() const`
399    #[inline]
400    pub fn index_type(&self) -> IndexType {
401        unsafe { msg_send_0(self.as_ptr(), sel!(indexType)) }
402    }
403
404    /// Set the index type.
405    ///
406    /// C++ equivalent: `void setIndexType(IndexType)`
407    #[inline]
408    pub fn set_index_type(&self, index_type: IndexType) {
409        unsafe {
410            msg_send_1::<(), IndexType>(self.as_ptr(), sel!(setIndexType:), index_type);
411        }
412    }
413
414    /// Get the radius buffer.
415    ///
416    /// C++ equivalent: `Buffer* radiusBuffer() const`
417    pub fn radius_buffer(&self) -> Option<Buffer> {
418        unsafe {
419            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(radiusBuffer));
420            if ptr.is_null() {
421                return None;
422            }
423            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
424            Buffer::from_raw(ptr)
425        }
426    }
427
428    /// Set the radius buffer.
429    ///
430    /// C++ equivalent: `void setRadiusBuffer(Buffer*)`
431    pub fn set_radius_buffer(&self, buffer: Option<&Buffer>) {
432        unsafe {
433            msg_send_1::<(), *const c_void>(
434                self.as_ptr(),
435                sel!(setRadiusBuffer:),
436                buffer.map_or(std::ptr::null(), |b| b.as_ptr()),
437            );
438        }
439    }
440
441    /// Get the radius buffer offset.
442    ///
443    /// C++ equivalent: `NS::UInteger radiusBufferOffset() const`
444    #[inline]
445    pub fn radius_buffer_offset(&self) -> UInteger {
446        unsafe { msg_send_0(self.as_ptr(), sel!(radiusBufferOffset)) }
447    }
448
449    /// Set the radius buffer offset.
450    ///
451    /// C++ equivalent: `void setRadiusBufferOffset(NS::UInteger)`
452    #[inline]
453    pub fn set_radius_buffer_offset(&self, offset: UInteger) {
454        unsafe {
455            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setRadiusBufferOffset:), offset);
456        }
457    }
458
459    /// Get the radius format.
460    ///
461    /// C++ equivalent: `AttributeFormat radiusFormat() const`
462    #[inline]
463    pub fn radius_format(&self) -> AttributeFormat {
464        unsafe { msg_send_0(self.as_ptr(), sel!(radiusFormat)) }
465    }
466
467    /// Set the radius format.
468    ///
469    /// C++ equivalent: `void setRadiusFormat(AttributeFormat)`
470    #[inline]
471    pub fn set_radius_format(&self, format: AttributeFormat) {
472        unsafe {
473            msg_send_1::<(), AttributeFormat>(self.as_ptr(), sel!(setRadiusFormat:), format);
474        }
475    }
476
477    /// Get the radius stride.
478    ///
479    /// C++ equivalent: `NS::UInteger radiusStride() const`
480    #[inline]
481    pub fn radius_stride(&self) -> UInteger {
482        unsafe { msg_send_0(self.as_ptr(), sel!(radiusStride)) }
483    }
484
485    /// Set the radius stride.
486    ///
487    /// C++ equivalent: `void setRadiusStride(NS::UInteger)`
488    #[inline]
489    pub fn set_radius_stride(&self, stride: UInteger) {
490        unsafe {
491            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setRadiusStride:), stride);
492        }
493    }
494
495    /// Get the segment control point count.
496    ///
497    /// C++ equivalent: `NS::UInteger segmentControlPointCount() const`
498    #[inline]
499    pub fn segment_control_point_count(&self) -> UInteger {
500        unsafe { msg_send_0(self.as_ptr(), sel!(segmentControlPointCount)) }
501    }
502
503    /// Set the segment control point count.
504    ///
505    /// C++ equivalent: `void setSegmentControlPointCount(NS::UInteger)`
506    #[inline]
507    pub fn set_segment_control_point_count(&self, count: UInteger) {
508        unsafe {
509            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setSegmentControlPointCount:), count);
510        }
511    }
512
513    /// Get the segment count.
514    ///
515    /// C++ equivalent: `NS::UInteger segmentCount() const`
516    #[inline]
517    pub fn segment_count(&self) -> UInteger {
518        unsafe { msg_send_0(self.as_ptr(), sel!(segmentCount)) }
519    }
520
521    /// Set the segment count.
522    ///
523    /// C++ equivalent: `void setSegmentCount(NS::UInteger)`
524    #[inline]
525    pub fn set_segment_count(&self, count: UInteger) {
526        unsafe {
527            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setSegmentCount:), count);
528        }
529    }
530}
531
532impl Default for AccelerationStructureCurveGeometryDescriptor {
533    fn default() -> Self {
534        Self::new().expect("failed to create curve geometry descriptor")
535    }
536}
537
538impl Clone for AccelerationStructureCurveGeometryDescriptor {
539    fn clone(&self) -> Self {
540        unsafe {
541            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(copy));
542            Self::from_raw(ptr).expect("failed to copy curve geometry descriptor")
543        }
544    }
545}
546
547impl Drop for AccelerationStructureCurveGeometryDescriptor {
548    fn drop(&mut self) {
549        unsafe {
550            msg_send_0::<()>(self.as_ptr(), sel!(release));
551        }
552    }
553}
554
555impl Referencing for AccelerationStructureCurveGeometryDescriptor {
556    #[inline]
557    fn as_ptr(&self) -> *const c_void {
558        self.0.as_ptr()
559    }
560}
561
562unsafe impl Send for AccelerationStructureCurveGeometryDescriptor {}
563unsafe impl Sync for AccelerationStructureCurveGeometryDescriptor {}