1use crate::ffi;
2use apple_metal::{CommandBuffer, MetalBuffer, MetalDevice};
3use core::ffi::c_void;
4use core::ptr;
5
6pub mod polygon_type {
8 pub const TRIANGLE: usize = 0;
10 pub const QUADRILATERAL: usize = 1;
12}
13
14pub mod acceleration_structure_usage {
16 pub const NONE: usize = 0;
18 pub const REFIT: usize = 1;
20 pub const FREQUENT_REBUILD: usize = 2;
22 pub const PREFER_GPU_BUILD: usize = 4;
24 pub const PREFER_CPU_BUILD: usize = 8;
26}
27
28pub mod acceleration_structure_status {
30 pub const UNBUILT: usize = 0;
32 pub const BUILT: usize = 1;
34}
35
36pub mod intersection_type {
38 pub const NEAREST: usize = 0;
40 pub const ANY: usize = 1;
42}
43
44pub mod ray_data_type {
46 pub const ORIGIN_DIRECTION: usize = 0;
48 pub const ORIGIN_MIN_DISTANCE_DIRECTION_MAX_DISTANCE: usize = 1;
50 pub const ORIGIN_MASK_DIRECTION_MAX_DISTANCE: usize = 2;
52 pub const PACKED_ORIGIN_DIRECTION: usize = 3;
54}
55
56pub mod intersection_data_type {
58 pub const DISTANCE: usize = 0;
60 pub const DISTANCE_PRIMITIVE_INDEX: usize = 1;
62 pub const DISTANCE_PRIMITIVE_INDEX_COORDINATES: usize = 2;
64 pub const DISTANCE_PRIMITIVE_INDEX_INSTANCE_INDEX: usize = 3;
66 pub const DISTANCE_PRIMITIVE_INDEX_INSTANCE_INDEX_COORDINATES: usize = 4;
68 pub const DISTANCE_PRIMITIVE_INDEX_BUFFER_INDEX: usize = 5;
70 pub const DISTANCE_PRIMITIVE_INDEX_BUFFER_INDEX_COORDINATES: usize = 6;
72 pub const DISTANCE_PRIMITIVE_INDEX_BUFFER_INDEX_INSTANCE_INDEX: usize = 7;
74 pub const DISTANCE_PRIMITIVE_INDEX_BUFFER_INDEX_INSTANCE_INDEX_COORDINATES: usize = 8;
76}
77
78pub mod cull_mode {
80 pub const NONE: usize = 0;
82 pub const FRONT: usize = 1;
84 pub const BACK: usize = 2;
86}
87
88pub mod winding {
90 pub const CLOCKWISE: usize = 0;
92 pub const COUNTER_CLOCKWISE: usize = 1;
94}
95
96#[doc(hidden)]
97pub use crate::generated::ray::*;
98
99macro_rules! opaque_handle {
100 ($name:ident, $doc:expr) => {
101 #[doc = $doc]
102 pub struct $name {
103 ptr: *mut c_void,
104 }
105
106 unsafe impl Send for $name {}
108 unsafe impl Sync for $name {}
110
111 impl Drop for $name {
112 fn drop(&mut self) {
113 if !self.ptr.is_null() {
114 unsafe { ffi::mps_object_release(self.ptr) };
116 self.ptr = ptr::null_mut();
117 }
118 }
119 }
120
121 impl $name {
122 #[must_use]
124 pub const fn as_ptr(&self) -> *mut c_void {
125 self.ptr
126 }
127 }
128 };
129}
130
131opaque_handle!(PolygonAccelerationStructure, "Wraps `MPSPolygonAccelerationStructure`.");
132impl PolygonAccelerationStructure {
133 #[must_use]
135 pub fn new(device: &MetalDevice) -> Option<Self> {
136 let ptr = unsafe { ffi::mps_polygon_acceleration_structure_new(device.as_ptr()) };
137 if ptr.is_null() {
138 None
139 } else {
140 Some(Self { ptr })
141 }
142 }
143
144 #[must_use]
146 pub fn polygon_type(&self) -> usize {
147 unsafe { ffi::mps_polygon_acceleration_structure_polygon_type(self.ptr) }
148 }
149
150 pub fn set_polygon_type(&self, polygon_type: usize) {
152 unsafe { ffi::mps_polygon_acceleration_structure_set_polygon_type(self.ptr, polygon_type) };
153 }
154
155 #[must_use]
157 pub fn vertex_stride(&self) -> usize {
158 unsafe { ffi::mps_polygon_acceleration_structure_vertex_stride(self.ptr) }
159 }
160
161 pub fn set_vertex_stride(&self, vertex_stride: usize) {
163 unsafe {
164 ffi::mps_polygon_acceleration_structure_set_vertex_stride(self.ptr, vertex_stride);
165 };
166 }
167
168 #[must_use]
170 pub fn index_type(&self) -> u32 {
171 unsafe { ffi::mps_polygon_acceleration_structure_index_type(self.ptr) }
172 }
173
174 pub fn set_index_type(&self, index_type: u32) {
176 unsafe { ffi::mps_polygon_acceleration_structure_set_index_type(self.ptr, index_type) };
177 }
178
179 pub fn set_vertex_buffer(&self, buffer: Option<&MetalBuffer>) {
181 let buffer_ptr = buffer.map_or(ptr::null_mut(), MetalBuffer::as_ptr);
182 unsafe { ffi::mps_polygon_acceleration_structure_set_vertex_buffer(self.ptr, buffer_ptr) };
183 }
184
185 #[must_use]
187 pub fn vertex_buffer_offset(&self) -> usize {
188 unsafe { ffi::mps_polygon_acceleration_structure_vertex_buffer_offset(self.ptr) }
189 }
190
191 pub fn set_vertex_buffer_offset(&self, offset: usize) {
193 unsafe {
194 ffi::mps_polygon_acceleration_structure_set_vertex_buffer_offset(self.ptr, offset);
195 };
196 }
197
198 pub fn set_index_buffer(&self, buffer: Option<&MetalBuffer>) {
200 let buffer_ptr = buffer.map_or(ptr::null_mut(), MetalBuffer::as_ptr);
201 unsafe { ffi::mps_polygon_acceleration_structure_set_index_buffer(self.ptr, buffer_ptr) };
202 }
203
204 #[must_use]
206 pub fn index_buffer_offset(&self) -> usize {
207 unsafe { ffi::mps_polygon_acceleration_structure_index_buffer_offset(self.ptr) }
208 }
209
210 pub fn set_index_buffer_offset(&self, offset: usize) {
212 unsafe {
213 ffi::mps_polygon_acceleration_structure_set_index_buffer_offset(self.ptr, offset);
214 };
215 }
216
217 #[must_use]
219 pub fn polygon_count(&self) -> usize {
220 unsafe { ffi::mps_polygon_acceleration_structure_polygon_count(self.ptr) }
221 }
222
223 pub fn set_polygon_count(&self, count: usize) {
225 unsafe { ffi::mps_polygon_acceleration_structure_set_polygon_count(self.ptr, count) };
226 }
227
228 #[must_use]
230 pub fn usage(&self) -> usize {
231 unsafe { ffi::mps_polygon_acceleration_structure_usage(self.ptr) }
232 }
233
234 pub fn set_usage(&self, usage: usize) {
236 unsafe { ffi::mps_polygon_acceleration_structure_set_usage(self.ptr, usage) };
237 }
238
239 #[must_use]
241 pub fn status(&self) -> usize {
242 unsafe { ffi::mps_polygon_acceleration_structure_status(self.ptr) }
243 }
244
245 pub fn rebuild(&self) {
247 unsafe { ffi::mps_polygon_acceleration_structure_rebuild(self.ptr) };
248 }
249
250 pub fn encode_refit(&self, command_buffer: &CommandBuffer) {
252 unsafe {
253 ffi::mps_polygon_acceleration_structure_encode_refit(self.ptr, command_buffer.as_ptr());
254 };
255 }
256}
257
258opaque_handle!(RayIntersector, "Wraps `MPSRayIntersector`.");
259impl RayIntersector {
260 #[must_use]
262 pub fn new(device: &MetalDevice) -> Option<Self> {
263 let ptr = unsafe { ffi::mps_ray_intersector_new(device.as_ptr()) };
264 if ptr.is_null() {
265 None
266 } else {
267 Some(Self { ptr })
268 }
269 }
270
271 #[must_use]
273 pub fn cull_mode(&self) -> usize {
274 unsafe { ffi::mps_ray_intersector_cull_mode(self.ptr) }
275 }
276
277 pub fn set_cull_mode(&self, cull_mode: usize) {
279 unsafe { ffi::mps_ray_intersector_set_cull_mode(self.ptr, cull_mode) };
280 }
281
282 #[must_use]
284 pub fn front_facing_winding(&self) -> usize {
285 unsafe { ffi::mps_ray_intersector_front_facing_winding(self.ptr) }
286 }
287
288 pub fn set_front_facing_winding(&self, winding: usize) {
290 unsafe { ffi::mps_ray_intersector_set_front_facing_winding(self.ptr, winding) };
291 }
292
293 #[must_use]
295 pub fn ray_stride(&self) -> usize {
296 unsafe { ffi::mps_ray_intersector_ray_stride(self.ptr) }
297 }
298
299 pub fn set_ray_stride(&self, stride: usize) {
301 unsafe { ffi::mps_ray_intersector_set_ray_stride(self.ptr, stride) };
302 }
303
304 #[must_use]
306 pub fn intersection_stride(&self) -> usize {
307 unsafe { ffi::mps_ray_intersector_intersection_stride(self.ptr) }
308 }
309
310 pub fn set_intersection_stride(&self, stride: usize) {
312 unsafe { ffi::mps_ray_intersector_set_intersection_stride(self.ptr, stride) };
313 }
314
315 #[must_use]
317 pub fn ray_data_type(&self) -> usize {
318 unsafe { ffi::mps_ray_intersector_ray_data_type(self.ptr) }
319 }
320
321 pub fn set_ray_data_type(&self, data_type: usize) {
323 unsafe { ffi::mps_ray_intersector_set_ray_data_type(self.ptr, data_type) };
324 }
325
326 #[must_use]
328 pub fn intersection_data_type(&self) -> usize {
329 unsafe { ffi::mps_ray_intersector_intersection_data_type(self.ptr) }
330 }
331
332 pub fn set_intersection_data_type(&self, data_type: usize) {
334 unsafe { ffi::mps_ray_intersector_set_intersection_data_type(self.ptr, data_type) };
335 }
336
337 #[must_use]
339 pub fn recommended_minimum_ray_batch_size(&self, ray_count: usize) -> usize {
340 unsafe { ffi::mps_ray_intersector_recommended_minimum_ray_batch_size(self.ptr, ray_count) }
341 }
342
343 #[allow(clippy::too_many_arguments)]
345 pub fn encode_intersection(
346 &self,
347 command_buffer: &CommandBuffer,
348 intersection_type: usize,
349 ray_buffer: &MetalBuffer,
350 ray_buffer_offset: usize,
351 intersection_buffer: &MetalBuffer,
352 intersection_buffer_offset: usize,
353 ray_count: usize,
354 acceleration_structure: &PolygonAccelerationStructure,
355 ) {
356 unsafe {
357 ffi::mps_ray_intersector_encode_intersection(
358 self.ptr,
359 command_buffer.as_ptr(),
360 intersection_type,
361 ray_buffer.as_ptr(),
362 ray_buffer_offset,
363 intersection_buffer.as_ptr(),
364 intersection_buffer_offset,
365 ray_count,
366 acceleration_structure.as_ptr(),
367 );
368 };
369 }
370}
371
372opaque_handle!(SVGF, "Wraps `MPSSVGF`.");
373impl SVGF {
374 #[must_use]
376 pub fn new(device: &MetalDevice) -> Option<Self> {
377 let ptr = unsafe { ffi::mps_svgf_new(device.as_ptr()) };
378 if ptr.is_null() {
379 None
380 } else {
381 Some(Self { ptr })
382 }
383 }
384
385 #[must_use]
387 pub fn depth_weight(&self) -> f32 {
388 unsafe { ffi::mps_svgf_depth_weight(self.ptr) }
389 }
390
391 pub fn set_depth_weight(&self, value: f32) {
393 unsafe { ffi::mps_svgf_set_depth_weight(self.ptr, value) };
394 }
395
396 #[must_use]
398 pub fn normal_weight(&self) -> f32 {
399 unsafe { ffi::mps_svgf_normal_weight(self.ptr) }
400 }
401
402 pub fn set_normal_weight(&self, value: f32) {
404 unsafe { ffi::mps_svgf_set_normal_weight(self.ptr, value) };
405 }
406
407 #[must_use]
409 pub fn luminance_weight(&self) -> f32 {
410 unsafe { ffi::mps_svgf_luminance_weight(self.ptr) }
411 }
412
413 pub fn set_luminance_weight(&self, value: f32) {
415 unsafe { ffi::mps_svgf_set_luminance_weight(self.ptr, value) };
416 }
417
418 #[must_use]
420 pub fn channel_count(&self) -> usize {
421 unsafe { ffi::mps_svgf_channel_count(self.ptr) }
422 }
423
424 pub fn set_channel_count(&self, value: usize) {
426 unsafe { ffi::mps_svgf_set_channel_count(self.ptr, value) };
427 }
428
429 #[must_use]
431 pub fn channel_count2(&self) -> usize {
432 unsafe { ffi::mps_svgf_channel_count2(self.ptr) }
433 }
434
435 pub fn set_channel_count2(&self, value: usize) {
437 unsafe { ffi::mps_svgf_set_channel_count2(self.ptr, value) };
438 }
439}