Skip to main content

mtl_gpu/acceleration/
pass.rs

1//! Acceleration structure pass descriptors.
2//!
3//! Contains pass-related types for acceleration structure operations.
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, msg_send_2, sel};
10
11pub struct AccelerationStructurePassDescriptor(pub(crate) NonNull<c_void>);
12
13impl AccelerationStructurePassDescriptor {
14    /// Create a new acceleration structure pass descriptor.
15    ///
16    /// C++ equivalent: `static AccelerationStructurePassDescriptor* alloc()->init()`
17    pub fn new() -> Option<Self> {
18        unsafe {
19            let class = mtl_sys::Class::get("MTLAccelerationStructurePassDescriptor")?;
20            let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
21            if ptr.is_null() {
22                return None;
23            }
24            let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
25            Self::from_raw(ptr)
26        }
27    }
28
29    /// Create a new acceleration structure pass descriptor using the class method.
30    ///
31    /// C++ equivalent: `static AccelerationStructurePassDescriptor* accelerationStructurePassDescriptor()`
32    pub fn descriptor() -> Option<Self> {
33        unsafe {
34            let class = mtl_sys::Class::get("MTLAccelerationStructurePassDescriptor")?;
35            let ptr: *mut c_void =
36                msg_send_0(class.as_ptr(), sel!(accelerationStructurePassDescriptor));
37            if ptr.is_null() {
38                return None;
39            }
40            // This returns an autoreleased object, so retain it
41            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
42            Self::from_raw(ptr)
43        }
44    }
45
46    /// Create from a raw pointer.
47    ///
48    /// # Safety
49    ///
50    /// The pointer must be a valid Metal acceleration structure pass descriptor.
51    #[inline]
52    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
53        NonNull::new(ptr).map(Self)
54    }
55
56    /// Get the raw pointer.
57    #[inline]
58    pub fn as_raw(&self) -> *mut c_void {
59        self.0.as_ptr()
60    }
61
62    /// Get the sample buffer attachments array.
63    ///
64    /// C++ equivalent: `AccelerationStructurePassSampleBufferAttachmentDescriptorArray* sampleBufferAttachments() const`
65    pub fn sample_buffer_attachments(
66        &self,
67    ) -> Option<AccelerationStructurePassSampleBufferAttachmentDescriptorArray> {
68        unsafe {
69            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(sampleBufferAttachments));
70            if ptr.is_null() {
71                return None;
72            }
73            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
74            AccelerationStructurePassSampleBufferAttachmentDescriptorArray::from_raw(ptr)
75        }
76    }
77}
78
79impl Default for AccelerationStructurePassDescriptor {
80    fn default() -> Self {
81        Self::new().expect("failed to create acceleration structure pass descriptor")
82    }
83}
84
85impl Clone for AccelerationStructurePassDescriptor {
86    fn clone(&self) -> Self {
87        unsafe {
88            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(copy));
89            Self::from_raw(ptr).expect("failed to copy acceleration structure pass descriptor")
90        }
91    }
92}
93
94impl Drop for AccelerationStructurePassDescriptor {
95    fn drop(&mut self) {
96        unsafe {
97            msg_send_0::<()>(self.as_ptr(), sel!(release));
98        }
99    }
100}
101
102impl Referencing for AccelerationStructurePassDescriptor {
103    #[inline]
104    fn as_ptr(&self) -> *const c_void {
105        self.0.as_ptr()
106    }
107}
108
109unsafe impl Send for AccelerationStructurePassDescriptor {}
110unsafe impl Sync for AccelerationStructurePassDescriptor {}
111
112// ============================================================================
113// AccelerationStructurePassSampleBufferAttachmentDescriptor
114// ============================================================================
115
116/// Descriptor for sample buffer attachments in an acceleration structure pass.
117///
118/// C++ equivalent: `MTL::AccelerationStructurePassSampleBufferAttachmentDescriptor`
119#[repr(transparent)]
120pub struct AccelerationStructurePassSampleBufferAttachmentDescriptor(pub(crate) NonNull<c_void>);
121
122impl AccelerationStructurePassSampleBufferAttachmentDescriptor {
123    /// Create a new sample buffer attachment descriptor.
124    ///
125    /// C++ equivalent: `static AccelerationStructurePassSampleBufferAttachmentDescriptor* alloc()->init()`
126    pub fn new() -> Option<Self> {
127        unsafe {
128            let class = mtl_sys::Class::get(
129                "MTLAccelerationStructurePassSampleBufferAttachmentDescriptor",
130            )?;
131            let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
132            if ptr.is_null() {
133                return None;
134            }
135            let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
136            Self::from_raw(ptr)
137        }
138    }
139
140    /// Create from a raw pointer.
141    ///
142    /// # Safety
143    ///
144    /// The pointer must be a valid Metal sample buffer attachment descriptor.
145    #[inline]
146    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
147        NonNull::new(ptr).map(Self)
148    }
149
150    /// Get the raw pointer.
151    #[inline]
152    pub fn as_raw(&self) -> *mut c_void {
153        self.0.as_ptr()
154    }
155
156    /// Get the sample buffer.
157    ///
158    /// # Safety
159    ///
160    /// Returns raw pointer to CounterSampleBuffer.
161    ///
162    /// C++ equivalent: `CounterSampleBuffer* sampleBuffer() const`
163    pub fn sample_buffer_ptr(&self) -> *mut c_void {
164        unsafe { msg_send_0(self.as_ptr(), sel!(sampleBuffer)) }
165    }
166
167    /// Set the sample buffer.
168    ///
169    /// # Safety
170    ///
171    /// The sample_buffer pointer must be valid or null.
172    ///
173    /// C++ equivalent: `void setSampleBuffer(CounterSampleBuffer*)`
174    pub unsafe fn set_sample_buffer_ptr(&self, sample_buffer: *const c_void) {
175        unsafe {
176            msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setSampleBuffer:), sample_buffer);
177        }
178    }
179
180    /// Get the start of encoder sample index.
181    ///
182    /// C++ equivalent: `NS::UInteger startOfEncoderSampleIndex() const`
183    #[inline]
184    pub fn start_of_encoder_sample_index(&self) -> UInteger {
185        unsafe { msg_send_0(self.as_ptr(), sel!(startOfEncoderSampleIndex)) }
186    }
187
188    /// Set the start of encoder sample index.
189    ///
190    /// C++ equivalent: `void setStartOfEncoderSampleIndex(NS::UInteger)`
191    #[inline]
192    pub fn set_start_of_encoder_sample_index(&self, index: UInteger) {
193        unsafe {
194            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setStartOfEncoderSampleIndex:), index);
195        }
196    }
197
198    /// Get the end of encoder sample index.
199    ///
200    /// C++ equivalent: `NS::UInteger endOfEncoderSampleIndex() const`
201    #[inline]
202    pub fn end_of_encoder_sample_index(&self) -> UInteger {
203        unsafe { msg_send_0(self.as_ptr(), sel!(endOfEncoderSampleIndex)) }
204    }
205
206    /// Set the end of encoder sample index.
207    ///
208    /// C++ equivalent: `void setEndOfEncoderSampleIndex(NS::UInteger)`
209    #[inline]
210    pub fn set_end_of_encoder_sample_index(&self, index: UInteger) {
211        unsafe {
212            msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setEndOfEncoderSampleIndex:), index);
213        }
214    }
215}
216
217impl Default for AccelerationStructurePassSampleBufferAttachmentDescriptor {
218    fn default() -> Self {
219        Self::new().expect("failed to create sample buffer attachment descriptor")
220    }
221}
222
223impl Clone for AccelerationStructurePassSampleBufferAttachmentDescriptor {
224    fn clone(&self) -> Self {
225        unsafe {
226            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(copy));
227            Self::from_raw(ptr).expect("failed to copy sample buffer attachment descriptor")
228        }
229    }
230}
231
232impl Drop for AccelerationStructurePassSampleBufferAttachmentDescriptor {
233    fn drop(&mut self) {
234        unsafe {
235            msg_send_0::<()>(self.as_ptr(), sel!(release));
236        }
237    }
238}
239
240impl Referencing for AccelerationStructurePassSampleBufferAttachmentDescriptor {
241    #[inline]
242    fn as_ptr(&self) -> *const c_void {
243        self.0.as_ptr()
244    }
245}
246
247unsafe impl Send for AccelerationStructurePassSampleBufferAttachmentDescriptor {}
248unsafe impl Sync for AccelerationStructurePassSampleBufferAttachmentDescriptor {}
249
250// ============================================================================
251// AccelerationStructurePassSampleBufferAttachmentDescriptorArray
252// ============================================================================
253
254/// Array of sample buffer attachment descriptors for an acceleration structure pass.
255///
256/// C++ equivalent: `MTL::AccelerationStructurePassSampleBufferAttachmentDescriptorArray`
257#[repr(transparent)]
258pub struct AccelerationStructurePassSampleBufferAttachmentDescriptorArray(
259    pub(crate) NonNull<c_void>,
260);
261
262impl AccelerationStructurePassSampleBufferAttachmentDescriptorArray {
263    /// Create a new sample buffer attachment descriptor array.
264    ///
265    /// C++ equivalent: `static AccelerationStructurePassSampleBufferAttachmentDescriptorArray* alloc()->init()`
266    pub fn new() -> Option<Self> {
267        unsafe {
268            let class = mtl_sys::Class::get(
269                "MTLAccelerationStructurePassSampleBufferAttachmentDescriptorArray",
270            )?;
271            let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
272            if ptr.is_null() {
273                return None;
274            }
275            let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
276            Self::from_raw(ptr)
277        }
278    }
279
280    /// Create from a raw pointer.
281    ///
282    /// # Safety
283    ///
284    /// The pointer must be a valid Metal sample buffer attachment descriptor array.
285    #[inline]
286    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
287        NonNull::new(ptr).map(Self)
288    }
289
290    /// Get the raw pointer.
291    #[inline]
292    pub fn as_raw(&self) -> *mut c_void {
293        self.0.as_ptr()
294    }
295
296    /// Get the attachment at the specified index.
297    ///
298    /// C++ equivalent: `AccelerationStructurePassSampleBufferAttachmentDescriptor* object(NS::UInteger)`
299    pub fn object(
300        &self,
301        index: UInteger,
302    ) -> Option<AccelerationStructurePassSampleBufferAttachmentDescriptor> {
303        unsafe {
304            let ptr: *mut c_void =
305                msg_send_1(self.as_ptr(), sel!(objectAtIndexedSubscript:), index);
306            if ptr.is_null() {
307                return None;
308            }
309            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
310            AccelerationStructurePassSampleBufferAttachmentDescriptor::from_raw(ptr)
311        }
312    }
313
314    /// Set the attachment at the specified index.
315    ///
316    /// C++ equivalent: `void setObject(AccelerationStructurePassSampleBufferAttachmentDescriptor*, NS::UInteger)`
317    pub fn set_object(
318        &self,
319        attachment: Option<&AccelerationStructurePassSampleBufferAttachmentDescriptor>,
320        index: UInteger,
321    ) {
322        unsafe {
323            msg_send_2::<(), *const c_void, UInteger>(
324                self.as_ptr(),
325                sel!(setObject:atIndexedSubscript:),
326                attachment.map_or(std::ptr::null(), |a| a.as_ptr()),
327                index,
328            );
329        }
330    }
331}
332
333impl Default for AccelerationStructurePassSampleBufferAttachmentDescriptorArray {
334    fn default() -> Self {
335        Self::new().expect("failed to create sample buffer attachment descriptor array")
336    }
337}
338
339impl Clone for AccelerationStructurePassSampleBufferAttachmentDescriptorArray {
340    fn clone(&self) -> Self {
341        unsafe {
342            msg_send_0::<*mut c_void>(self.as_ptr(), sel!(retain));
343        }
344        Self(self.0)
345    }
346}
347
348impl Drop for AccelerationStructurePassSampleBufferAttachmentDescriptorArray {
349    fn drop(&mut self) {
350        unsafe {
351            msg_send_0::<()>(self.as_ptr(), sel!(release));
352        }
353    }
354}
355
356impl Referencing for AccelerationStructurePassSampleBufferAttachmentDescriptorArray {
357    #[inline]
358    fn as_ptr(&self) -> *const c_void {
359        self.0.as_ptr()
360    }
361}
362
363unsafe impl Send for AccelerationStructurePassSampleBufferAttachmentDescriptorArray {}
364unsafe impl Sync for AccelerationStructurePassSampleBufferAttachmentDescriptorArray {}
365
366#[cfg(test)]
367mod tests {
368    use super::*;
369
370    #[test]
371    fn test_acceleration_structure_pass_descriptor_creation() {
372        let desc = AccelerationStructurePassDescriptor::new();
373        assert!(desc.is_some());
374    }
375
376    #[test]
377    fn test_acceleration_structure_pass_descriptor_class_method() {
378        let desc = AccelerationStructurePassDescriptor::descriptor();
379        assert!(desc.is_some());
380    }
381
382    #[test]
383    fn test_sample_buffer_attachment_descriptor() {
384        let desc = AccelerationStructurePassSampleBufferAttachmentDescriptor::new();
385        assert!(desc.is_some());
386    }
387
388    #[test]
389    fn test_sample_buffer_attachment_descriptor_array() {
390        let arr = AccelerationStructurePassSampleBufferAttachmentDescriptorArray::new();
391        assert!(arr.is_some());
392    }
393}