Skip to main content

apple_mps/
ray.rs

1use crate::ffi;
2use apple_metal::{CommandBuffer, MetalBuffer, MetalDevice};
3use core::ffi::c_void;
4use core::ptr;
5
6/// `MPSPolygonType` constants.
7pub mod polygon_type {
8    pub const TRIANGLE: usize = 0;
9    pub const QUADRILATERAL: usize = 1;
10}
11
12/// `MPSAccelerationStructureUsage` bitflags.
13pub mod acceleration_structure_usage {
14    pub const NONE: usize = 0;
15    pub const REFIT: usize = 1;
16    pub const FREQUENT_REBUILD: usize = 2;
17    pub const PREFER_GPU_BUILD: usize = 4;
18    pub const PREFER_CPU_BUILD: usize = 8;
19}
20
21/// `MPSAccelerationStructureStatus` constants.
22pub mod acceleration_structure_status {
23    pub const UNBUILT: usize = 0;
24    pub const BUILT: usize = 1;
25}
26
27/// `MPSIntersectionType` constants.
28pub mod intersection_type {
29    pub const NEAREST: usize = 0;
30    pub const ANY: usize = 1;
31}
32
33/// `MPSRayDataType` constants.
34pub mod ray_data_type {
35    pub const ORIGIN_DIRECTION: usize = 0;
36    pub const ORIGIN_MIN_DISTANCE_DIRECTION_MAX_DISTANCE: usize = 1;
37    pub const ORIGIN_MASK_DIRECTION_MAX_DISTANCE: usize = 2;
38    pub const PACKED_ORIGIN_DIRECTION: usize = 3;
39}
40
41/// `MPSIntersectionDataType` constants.
42pub mod intersection_data_type {
43    pub const DISTANCE: usize = 0;
44    pub const DISTANCE_PRIMITIVE_INDEX: usize = 1;
45    pub const DISTANCE_PRIMITIVE_INDEX_COORDINATES: usize = 2;
46    pub const DISTANCE_PRIMITIVE_INDEX_INSTANCE_INDEX: usize = 3;
47    pub const DISTANCE_PRIMITIVE_INDEX_INSTANCE_INDEX_COORDINATES: usize = 4;
48    pub const DISTANCE_PRIMITIVE_INDEX_BUFFER_INDEX: usize = 5;
49    pub const DISTANCE_PRIMITIVE_INDEX_BUFFER_INDEX_COORDINATES: usize = 6;
50    pub const DISTANCE_PRIMITIVE_INDEX_BUFFER_INDEX_INSTANCE_INDEX: usize = 7;
51    pub const DISTANCE_PRIMITIVE_INDEX_BUFFER_INDEX_INSTANCE_INDEX_COORDINATES: usize = 8;
52}
53
54/// `MTLCullMode` constants.
55pub mod cull_mode {
56    pub const NONE: usize = 0;
57    pub const FRONT: usize = 1;
58    pub const BACK: usize = 2;
59}
60
61/// `MTLWinding` constants.
62pub mod winding {
63    pub const CLOCKWISE: usize = 0;
64    pub const COUNTER_CLOCKWISE: usize = 1;
65}
66
67macro_rules! opaque_handle {
68    ($name:ident) => {
69        pub struct $name {
70            ptr: *mut c_void,
71        }
72
73        unsafe impl Send for $name {}
74        unsafe impl Sync for $name {}
75
76        impl Drop for $name {
77            fn drop(&mut self) {
78                if !self.ptr.is_null() {
79                    unsafe { ffi::mps_object_release(self.ptr) };
80                    self.ptr = ptr::null_mut();
81                }
82            }
83        }
84
85        impl $name {
86            #[must_use]
87            pub const fn as_ptr(&self) -> *mut c_void {
88                self.ptr
89            }
90        }
91    };
92}
93
94opaque_handle!(PolygonAccelerationStructure);
95impl PolygonAccelerationStructure {
96    #[must_use]
97    pub fn new(device: &MetalDevice) -> Option<Self> {
98        let ptr = unsafe { ffi::mps_polygon_acceleration_structure_new(device.as_ptr()) };
99        if ptr.is_null() {
100            None
101        } else {
102            Some(Self { ptr })
103        }
104    }
105
106    #[must_use]
107    pub fn polygon_type(&self) -> usize {
108        unsafe { ffi::mps_polygon_acceleration_structure_polygon_type(self.ptr) }
109    }
110
111    pub fn set_polygon_type(&self, polygon_type: usize) {
112        unsafe { ffi::mps_polygon_acceleration_structure_set_polygon_type(self.ptr, polygon_type) };
113    }
114
115    #[must_use]
116    pub fn vertex_stride(&self) -> usize {
117        unsafe { ffi::mps_polygon_acceleration_structure_vertex_stride(self.ptr) }
118    }
119
120    pub fn set_vertex_stride(&self, vertex_stride: usize) {
121        unsafe {
122            ffi::mps_polygon_acceleration_structure_set_vertex_stride(self.ptr, vertex_stride);
123        };
124    }
125
126    #[must_use]
127    pub fn index_type(&self) -> u32 {
128        unsafe { ffi::mps_polygon_acceleration_structure_index_type(self.ptr) }
129    }
130
131    pub fn set_index_type(&self, index_type: u32) {
132        unsafe { ffi::mps_polygon_acceleration_structure_set_index_type(self.ptr, index_type) };
133    }
134
135    pub fn set_vertex_buffer(&self, buffer: Option<&MetalBuffer>) {
136        let buffer_ptr = buffer.map_or(ptr::null_mut(), MetalBuffer::as_ptr);
137        unsafe { ffi::mps_polygon_acceleration_structure_set_vertex_buffer(self.ptr, buffer_ptr) };
138    }
139
140    #[must_use]
141    pub fn vertex_buffer_offset(&self) -> usize {
142        unsafe { ffi::mps_polygon_acceleration_structure_vertex_buffer_offset(self.ptr) }
143    }
144
145    pub fn set_vertex_buffer_offset(&self, offset: usize) {
146        unsafe {
147            ffi::mps_polygon_acceleration_structure_set_vertex_buffer_offset(self.ptr, offset);
148        };
149    }
150
151    pub fn set_index_buffer(&self, buffer: Option<&MetalBuffer>) {
152        let buffer_ptr = buffer.map_or(ptr::null_mut(), MetalBuffer::as_ptr);
153        unsafe { ffi::mps_polygon_acceleration_structure_set_index_buffer(self.ptr, buffer_ptr) };
154    }
155
156    #[must_use]
157    pub fn index_buffer_offset(&self) -> usize {
158        unsafe { ffi::mps_polygon_acceleration_structure_index_buffer_offset(self.ptr) }
159    }
160
161    pub fn set_index_buffer_offset(&self, offset: usize) {
162        unsafe {
163            ffi::mps_polygon_acceleration_structure_set_index_buffer_offset(self.ptr, offset);
164        };
165    }
166
167    #[must_use]
168    pub fn polygon_count(&self) -> usize {
169        unsafe { ffi::mps_polygon_acceleration_structure_polygon_count(self.ptr) }
170    }
171
172    pub fn set_polygon_count(&self, count: usize) {
173        unsafe { ffi::mps_polygon_acceleration_structure_set_polygon_count(self.ptr, count) };
174    }
175
176    #[must_use]
177    pub fn usage(&self) -> usize {
178        unsafe { ffi::mps_polygon_acceleration_structure_usage(self.ptr) }
179    }
180
181    pub fn set_usage(&self, usage: usize) {
182        unsafe { ffi::mps_polygon_acceleration_structure_set_usage(self.ptr, usage) };
183    }
184
185    #[must_use]
186    pub fn status(&self) -> usize {
187        unsafe { ffi::mps_polygon_acceleration_structure_status(self.ptr) }
188    }
189
190    pub fn rebuild(&self) {
191        unsafe { ffi::mps_polygon_acceleration_structure_rebuild(self.ptr) };
192    }
193
194    pub fn encode_refit(&self, command_buffer: &CommandBuffer) {
195        unsafe {
196            ffi::mps_polygon_acceleration_structure_encode_refit(self.ptr, command_buffer.as_ptr());
197        };
198    }
199}
200
201opaque_handle!(RayIntersector);
202impl RayIntersector {
203    #[must_use]
204    pub fn new(device: &MetalDevice) -> Option<Self> {
205        let ptr = unsafe { ffi::mps_ray_intersector_new(device.as_ptr()) };
206        if ptr.is_null() {
207            None
208        } else {
209            Some(Self { ptr })
210        }
211    }
212
213    #[must_use]
214    pub fn cull_mode(&self) -> usize {
215        unsafe { ffi::mps_ray_intersector_cull_mode(self.ptr) }
216    }
217
218    pub fn set_cull_mode(&self, cull_mode: usize) {
219        unsafe { ffi::mps_ray_intersector_set_cull_mode(self.ptr, cull_mode) };
220    }
221
222    #[must_use]
223    pub fn front_facing_winding(&self) -> usize {
224        unsafe { ffi::mps_ray_intersector_front_facing_winding(self.ptr) }
225    }
226
227    pub fn set_front_facing_winding(&self, winding: usize) {
228        unsafe { ffi::mps_ray_intersector_set_front_facing_winding(self.ptr, winding) };
229    }
230
231    #[must_use]
232    pub fn ray_stride(&self) -> usize {
233        unsafe { ffi::mps_ray_intersector_ray_stride(self.ptr) }
234    }
235
236    pub fn set_ray_stride(&self, stride: usize) {
237        unsafe { ffi::mps_ray_intersector_set_ray_stride(self.ptr, stride) };
238    }
239
240    #[must_use]
241    pub fn intersection_stride(&self) -> usize {
242        unsafe { ffi::mps_ray_intersector_intersection_stride(self.ptr) }
243    }
244
245    pub fn set_intersection_stride(&self, stride: usize) {
246        unsafe { ffi::mps_ray_intersector_set_intersection_stride(self.ptr, stride) };
247    }
248
249    #[must_use]
250    pub fn ray_data_type(&self) -> usize {
251        unsafe { ffi::mps_ray_intersector_ray_data_type(self.ptr) }
252    }
253
254    pub fn set_ray_data_type(&self, data_type: usize) {
255        unsafe { ffi::mps_ray_intersector_set_ray_data_type(self.ptr, data_type) };
256    }
257
258    #[must_use]
259    pub fn intersection_data_type(&self) -> usize {
260        unsafe { ffi::mps_ray_intersector_intersection_data_type(self.ptr) }
261    }
262
263    pub fn set_intersection_data_type(&self, data_type: usize) {
264        unsafe { ffi::mps_ray_intersector_set_intersection_data_type(self.ptr, data_type) };
265    }
266
267    #[must_use]
268    pub fn recommended_minimum_ray_batch_size(&self, ray_count: usize) -> usize {
269        unsafe { ffi::mps_ray_intersector_recommended_minimum_ray_batch_size(self.ptr, ray_count) }
270    }
271
272    #[allow(clippy::too_many_arguments)]
273    pub fn encode_intersection(
274        &self,
275        command_buffer: &CommandBuffer,
276        intersection_type: usize,
277        ray_buffer: &MetalBuffer,
278        ray_buffer_offset: usize,
279        intersection_buffer: &MetalBuffer,
280        intersection_buffer_offset: usize,
281        ray_count: usize,
282        acceleration_structure: &PolygonAccelerationStructure,
283    ) {
284        unsafe {
285            ffi::mps_ray_intersector_encode_intersection(
286                self.ptr,
287                command_buffer.as_ptr(),
288                intersection_type,
289                ray_buffer.as_ptr(),
290                ray_buffer_offset,
291                intersection_buffer.as_ptr(),
292                intersection_buffer_offset,
293                ray_count,
294                acceleration_structure.as_ptr(),
295            );
296        };
297    }
298}
299
300opaque_handle!(SVGF);
301impl SVGF {
302    #[must_use]
303    pub fn new(device: &MetalDevice) -> Option<Self> {
304        let ptr = unsafe { ffi::mps_svgf_new(device.as_ptr()) };
305        if ptr.is_null() {
306            None
307        } else {
308            Some(Self { ptr })
309        }
310    }
311
312    #[must_use]
313    pub fn depth_weight(&self) -> f32 {
314        unsafe { ffi::mps_svgf_depth_weight(self.ptr) }
315    }
316
317    pub fn set_depth_weight(&self, value: f32) {
318        unsafe { ffi::mps_svgf_set_depth_weight(self.ptr, value) };
319    }
320
321    #[must_use]
322    pub fn normal_weight(&self) -> f32 {
323        unsafe { ffi::mps_svgf_normal_weight(self.ptr) }
324    }
325
326    pub fn set_normal_weight(&self, value: f32) {
327        unsafe { ffi::mps_svgf_set_normal_weight(self.ptr, value) };
328    }
329
330    #[must_use]
331    pub fn luminance_weight(&self) -> f32 {
332        unsafe { ffi::mps_svgf_luminance_weight(self.ptr) }
333    }
334
335    pub fn set_luminance_weight(&self, value: f32) {
336        unsafe { ffi::mps_svgf_set_luminance_weight(self.ptr, value) };
337    }
338
339    #[must_use]
340    pub fn channel_count(&self) -> usize {
341        unsafe { ffi::mps_svgf_channel_count(self.ptr) }
342    }
343
344    pub fn set_channel_count(&self, value: usize) {
345        unsafe { ffi::mps_svgf_set_channel_count(self.ptr, value) };
346    }
347
348    #[must_use]
349    pub fn channel_count2(&self) -> usize {
350        unsafe { ffi::mps_svgf_channel_count2(self.ptr) }
351    }
352
353    pub fn set_channel_count2(&self, value: usize) {
354        unsafe { ffi::mps_svgf_set_channel_count2(self.ptr, value) };
355    }
356}