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