1 // Copyright 2020 GFX developers
3 // Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4 // http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5 // http://opensource.org/licenses/MIT>, at your option. This file may not be
6 // copied, modified, or distributed except according to those terms.
10 use objc::runtime::{BOOL, YES};
12 #[cfg_attr(feature = "link", link(name = "MetalPerformanceShaders", kind = "framework"))]
14 fn MPSSupportsMTLDevice(device: *const std::ffi::c_void) -> BOOL;
17 pub fn mps_supports_device(device: &DeviceRef) -> bool {
18 let b: BOOL = unsafe {
19 let ptr: *const DeviceRef = device;
20 MPSSupportsMTLDevice(ptr as _)
25 /// See <https://developer.apple.com/documentation/metalperformanceshaders/mpskernel>
29 type CType = MPSKernel;
33 /// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsraydatatype>
34 pub enum MPSRayDataType {
36 OriginMinDistanceDirectionMaxDistance = 1,
37 OriginMaskDirectionMaxDistance = 2,
41 /// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsraymaskoptions>
42 #[allow(non_upper_case_globals)]
43 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
44 pub struct MPSRayMaskOptions: NSUInteger {
45 /// Enable primitive masks
47 /// Enable instance masks
52 /// Options that determine the data contained in an intersection result.
54 /// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsintersectiondatatype>
55 pub enum MPSIntersectionDataType {
57 DistancePrimitiveIndex = 1,
58 DistancePrimitiveIndexCoordinates = 2,
59 DistancePrimitiveIndexInstanceIndex = 3,
60 DistancePrimitiveIndexInstanceIndexCoordinates = 4,
63 /// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsintersectiontype>
64 pub enum MPSIntersectionType {
65 /// Find the closest intersection to the ray's origin along the ray direction.
66 /// This is potentially slower than `Any` but is well suited to primary visibility rays.
68 /// Find any intersection along the ray direction. This is potentially faster than `Nearest` and
69 /// is well suited to shadow and occlusion rays.
73 /// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsraymaskoperator>
74 pub enum MPSRayMaskOperator {
75 /// Accept the intersection if `(primitive mask & ray mask) != 0`.
77 /// Accept the intersection if `~(primitive mask & ray mask) != 0`.
79 /// Accept the intersection if `(primitive mask | ray mask) != 0`.
81 /// Accept the intersection if `~(primitive mask | ray mask) != 0`.
83 /// Accept the intersection if `(primitive mask ^ ray mask) != 0`.
84 /// Note that this is equivalent to the "!=" operator.
86 /// Accept the intersection if `~(primitive mask ^ ray mask) != 0`.
87 /// Note that this is equivalent to the "==" operator.
89 /// Accept the intersection if `(primitive mask < ray mask) != 0`.
91 /// Accept the intersection if `(primitive mask <= ray mask) != 0`.
92 LessThanOrEqualTo = 7,
93 /// Accept the intersection if `(primitive mask > ray mask) != 0`.
95 /// Accept the intersection if `(primitive mask >= ray mask) != 0`.
96 GreaterThanOrEqualTo = 9,
99 /// See <https://developer.apple.com/documentation/metalperformanceshaders/mpstriangleintersectiontesttype>
100 pub enum MPSTriangleIntersectionTestType {
101 /// Use the default ray/triangle intersection test
103 /// Use a watertight ray/triangle intersection test which avoids gaps along shared triangle edges.
104 /// Shared vertices may still have gaps.
105 /// This intersection test may be slower than `Default`.
109 /// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsaccelerationstructurestatus>
110 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
111 pub enum MPSAccelerationStructureStatus {
117 /// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsaccelerationstructureusage>
118 #[allow(non_upper_case_globals)]
119 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
120 pub struct MPSAccelerationStructureUsage: NSUInteger {
121 /// No usage options specified
123 /// Option that enables support for refitting the acceleration structure after it has been built.
125 /// Option indicating that the acceleration structure will be rebuilt frequently.
126 const FrequentRebuild = 2;
127 const PreferGPUBuild = 4;
128 const PreferCPUBuild = 8;
132 /// A common bit for all floating point data types.
133 const MPSDataTypeFloatBit: isize = 0x10000000;
134 const MPSDataTypeSignedBit: isize = 0x20000000;
135 const MPSDataTypeNormalizedBit: isize = 0x40000000;
137 /// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsdatatype>
138 pub enum MPSDataType {
141 Float32 = MPSDataTypeFloatBit | 32,
142 Float16 = MPSDataTypeFloatBit | 16,
145 Int8 = MPSDataTypeSignedBit | 8,
146 Int16 = MPSDataTypeSignedBit | 16,
147 Int32 = MPSDataTypeSignedBit | 32,
149 // Unsigned integers. Range: [0, UTYPE_MAX]
154 // Unsigned normalized. Range: [0, 1.0]
155 Unorm1 = MPSDataTypeNormalizedBit | 1,
156 Unorm8 = MPSDataTypeNormalizedBit | 8,
159 /// A kernel that performs intersection tests between rays and geometry.
161 /// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsrayintersector>
162 pub enum MPSRayIntersector {}
165 type CType = MPSRayIntersector;
166 pub struct RayIntersector;
167 type ParentType = Kernel;
170 impl RayIntersector {
171 pub fn from_device(device: &DeviceRef) -> Option<Self> {
173 let intersector: RayIntersector = msg_send![class!(MPSRayIntersector), alloc];
174 let ptr: *mut Object = msg_send![intersector.as_ref(), initWithDevice: device];
184 impl RayIntersectorRef {
185 pub fn set_cull_mode(&self, mode: MTLCullMode) {
186 unsafe { msg_send![self, setCullMode: mode] }
189 pub fn set_front_facing_winding(&self, winding: MTLWinding) {
190 unsafe { msg_send![self, setFrontFacingWinding: winding] }
193 pub fn set_intersection_data_type(&self, options: MPSIntersectionDataType) {
194 unsafe { msg_send![self, setIntersectionDataType: options] }
197 pub fn set_intersection_stride(&self, stride: NSUInteger) {
198 unsafe { msg_send![self, setIntersectionStride: stride] }
201 pub fn set_ray_data_type(&self, ty: MPSRayDataType) {
202 unsafe { msg_send![self, setRayDataType: ty] }
205 pub fn set_ray_index_data_type(&self, ty: MPSDataType) {
206 unsafe { msg_send![self, setRayIndexDataType: ty] }
209 pub fn set_ray_mask(&self, ray_mask: u32) {
210 unsafe { msg_send![self, setRayMask: ray_mask] }
213 pub fn set_ray_mask_operator(&self, operator: MPSRayMaskOperator) {
214 unsafe { msg_send![self, setRayMaskOperator: operator] }
217 pub fn set_ray_mask_options(&self, options: MPSRayMaskOptions) {
218 unsafe { msg_send![self, setRayMaskOptions: options] }
221 pub fn set_ray_stride(&self, stride: NSUInteger) {
222 unsafe { msg_send![self, setRayStride: stride] }
225 pub fn set_triangle_intersection_test_type(&self, test_type: MPSTriangleIntersectionTestType) {
226 unsafe { msg_send![self, setTriangleIntersectionTestType: test_type] }
229 pub fn encode_intersection_to_command_buffer(
231 command_buffer: &CommandBufferRef,
232 intersection_type: MPSIntersectionType,
233 ray_buffer: &BufferRef,
234 ray_buffer_offset: NSUInteger,
235 intersection_buffer: &BufferRef,
236 intersection_buffer_offset: NSUInteger,
237 ray_count: NSUInteger,
238 acceleration_structure: &AccelerationStructureRef,
243 encodeIntersectionToCommandBuffer: command_buffer
244 intersectionType: intersection_type
245 rayBuffer: ray_buffer
246 rayBufferOffset: ray_buffer_offset
247 intersectionBuffer: intersection_buffer
248 intersectionBufferOffset: intersection_buffer_offset
250 accelerationStructure: acceleration_structure
255 pub fn recommended_minimum_ray_batch_size_for_ray_count(
257 ray_count: NSUInteger,
259 unsafe { msg_send![self, recommendedMinimumRayBatchSizeForRayCount: ray_count] }
263 /// A group of acceleration structures which may be used together in an instance acceleration structure.
265 /// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsaccelerationstructuregroup>
266 pub enum MPSAccelerationStructureGroup {}
269 type CType = MPSAccelerationStructureGroup;
270 pub struct AccelerationStructureGroup;
273 impl AccelerationStructureGroup {
274 pub fn new_with_device(device: &DeviceRef) -> Option<Self> {
276 let group: AccelerationStructureGroup =
277 msg_send![class!(MPSAccelerationStructureGroup), alloc];
278 let ptr: *mut Object = msg_send![group.as_ref(), initWithDevice: device];
288 impl AccelerationStructureGroupRef {
289 pub fn device(&self) -> &DeviceRef {
290 unsafe { msg_send![self, device] }
294 /// The base class for data structures that are built over geometry and used to accelerate ray tracing.
296 /// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsaccelerationstructure>
297 pub enum MPSAccelerationStructure {}
300 type CType = MPSAccelerationStructure;
301 pub struct AccelerationStructure;
304 impl AccelerationStructureRef {
305 pub fn status(&self) -> MPSAccelerationStructureStatus {
306 unsafe { msg_send![self, status] }
309 pub fn usage(&self) -> MPSAccelerationStructureUsage {
310 unsafe { msg_send![self, usage] }
313 pub fn set_usage(&self, usage: MPSAccelerationStructureUsage) {
314 unsafe { msg_send![self, setUsage: usage] }
317 pub fn group(&self) -> &AccelerationStructureGroupRef {
318 unsafe { msg_send![self, group] }
321 pub fn encode_refit_to_command_buffer(&self, buffer: &CommandBufferRef) {
322 unsafe { msg_send![self, encodeRefitToCommandBuffer: buffer] }
325 pub fn rebuild(&self) {
326 unsafe { msg_send![self, rebuild] }
330 /// See <https://developer.apple.com/documentation/metalperformanceshaders/mpspolygonaccelerationstructure>
331 pub enum MPSPolygonAccelerationStructure {}
334 type CType = MPSPolygonAccelerationStructure;
335 pub struct PolygonAccelerationStructure;
336 type ParentType = AccelerationStructure;
339 impl PolygonAccelerationStructureRef {
340 pub fn set_index_buffer(&self, buffer: Option<&BufferRef>) {
341 unsafe { msg_send![self, setIndexBuffer: buffer] }
344 pub fn set_index_buffer_offset(&self, offset: NSUInteger) {
345 unsafe { msg_send![self, setIndexBufferOffset: offset] }
348 pub fn set_index_type(&self, data_type: MPSDataType) {
349 unsafe { msg_send![self, setIndexType: data_type] }
352 pub fn set_mask_buffer(&self, buffer: Option<&BufferRef>) {
353 unsafe { msg_send![self, setMaskBuffer: buffer] }
356 pub fn set_mask_buffer_offset(&self, offset: NSUInteger) {
357 unsafe { msg_send![self, setMaskBufferOffset: offset] }
360 pub fn set_vertex_buffer(&self, buffer: Option<&BufferRef>) {
361 unsafe { msg_send![self, setVertexBuffer: buffer] }
364 pub fn set_vertex_buffer_offset(&self, offset: NSUInteger) {
365 unsafe { msg_send![self, setVertexBufferOffset: offset] }
368 pub fn set_vertex_stride(&self, stride: NSUInteger) {
369 unsafe { msg_send![self, setVertexStride: stride] }
373 /// An acceleration structure built over triangles.
375 /// See <https://developer.apple.com/documentation/metalperformanceshaders/mpstriangleaccelerationstructure>
376 pub enum MPSTriangleAccelerationStructure {}
379 type CType = MPSTriangleAccelerationStructure;
380 pub struct TriangleAccelerationStructure;
381 type ParentType = PolygonAccelerationStructure;
384 impl TriangleAccelerationStructure {
385 pub fn from_device(device: &DeviceRef) -> Option<Self> {
387 let structure: TriangleAccelerationStructure =
388 msg_send![class!(MPSTriangleAccelerationStructure), alloc];
389 let ptr: *mut Object = msg_send![structure.as_ref(), initWithDevice: device];
399 impl TriangleAccelerationStructureRef {
400 pub fn triangle_count(&self) -> NSUInteger {
401 unsafe { msg_send![self, triangleCount] }
404 pub fn set_triangle_count(&self, count: NSUInteger) {
405 unsafe { msg_send![self, setTriangleCount: count] }
409 /// See <https://developer.apple.com/documentation/metalperformanceshaders/mpstransformtype>
411 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
412 pub enum MPSTransformType {
417 /// An acceleration structure built over instances of other acceleration structures
419 /// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsinstanceaccelerationstructure>
420 pub enum MPSInstanceAccelerationStructure {}
423 type CType = MPSInstanceAccelerationStructure;
424 pub struct InstanceAccelerationStructure;
425 type ParentType = AccelerationStructure;
428 impl InstanceAccelerationStructure {
429 pub fn init_with_group(group: &AccelerationStructureGroupRef) -> Option<Self> {
431 let structure: InstanceAccelerationStructure =
432 msg_send![class!(MPSInstanceAccelerationStructure), alloc];
433 let ptr: *mut Object = msg_send![structure.as_ref(), initWithGroup: group];
443 impl InstanceAccelerationStructureRef {
444 /// Marshal to Rust Vec
445 pub fn acceleration_structures(&self) -> Vec<PolygonAccelerationStructure> {
447 let acs: *mut Object = msg_send![self, accelerationStructures];
448 let count: NSUInteger = msg_send![acs, count];
451 let ac = msg_send![acs, objectAtIndex: i];
452 PolygonAccelerationStructure::from_ptr(ac)
459 /// Marshal from Rust slice
460 pub fn set_acceleration_structures(&self, acs: &[&PolygonAccelerationStructureRef]) {
461 let ns_array = Array::<PolygonAccelerationStructure>::from_slice(acs);
462 unsafe { msg_send![self, setAccelerationStructures: ns_array] }
465 pub fn instance_buffer(&self) -> &BufferRef {
466 unsafe { msg_send![self, instanceBuffer] }
469 pub fn set_instance_buffer(&self, buffer: &BufferRef) {
470 unsafe { msg_send![self, setInstanceBuffer: buffer] }
473 pub fn instance_buffer_offset(&self) -> NSUInteger {
474 unsafe { msg_send![self, instanceBufferOffset] }
477 pub fn set_instance_buffer_offset(&self, offset: NSUInteger) {
478 unsafe { msg_send![self, setInstanceBufferOffset: offset] }
481 pub fn transform_buffer(&self) -> &BufferRef {
482 unsafe { msg_send![self, transformBuffer] }
485 pub fn set_transform_buffer(&self, buffer: &BufferRef) {
486 unsafe { msg_send![self, setTransformBuffer: buffer] }
489 pub fn transform_buffer_offset(&self) -> NSUInteger {
490 unsafe { msg_send![self, transformBufferOffset] }
493 pub fn set_transform_buffer_offset(&self, offset: NSUInteger) {
494 unsafe { msg_send![self, setTransformBufferOffset: offset] }
497 pub fn transform_type(&self) -> MPSTransformType {
498 unsafe { msg_send![self, transformType] }
501 pub fn set_transform_type(&self, transform_type: MPSTransformType) {
502 unsafe { msg_send![self, setTransformType: transform_type] }
505 pub fn mask_buffer(&self) -> &BufferRef {
506 unsafe { msg_send![self, maskBuffer] }
509 pub fn set_mask_buffer(&self, buffer: &BufferRef) {
510 unsafe { msg_send![self, setMaskBuffer: buffer] }
513 pub fn mask_buffer_offset(&self) -> NSUInteger {
514 unsafe { msg_send![self, maskBufferOffset] }
517 pub fn set_mask_buffer_offset(&self, offset: NSUInteger) {
518 unsafe { msg_send![self, setMaskBufferOffset: offset] }
521 pub fn instance_count(&self) -> NSUInteger {
522 unsafe { msg_send![self, instanceCount] }
525 pub fn set_instance_count(&self, count: NSUInteger) {
526 unsafe { msg_send![self, setInstanceCount: count] }
531 pub struct MPSPackedFloat3 {
532 pub elements: [f32; 3],
535 /// Represents a 3D ray with an origin, a direction, and an intersection distance range from the origin.
537 /// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsrayoriginmindistancedirectionmaxdistance>
539 pub struct MPSRayOriginMinDistanceDirectionMaxDistance {
540 /// Ray origin. The intersection test will be skipped if the origin contains NaNs or infinities.
541 pub origin: MPSPackedFloat3,
542 /// Minimum intersection distance from the origin along the ray direction.
543 /// The intersection test will be skipped if the minimum distance is equal to positive infinity or NaN.
544 pub min_distance: f32,
545 /// Ray direction. Does not need to be normalized. The intersection test will be skipped if
546 /// the direction has length zero or contains NaNs or infinities.
547 pub direction: MPSPackedFloat3,
548 /// Maximum intersection distance from the origin along the ray direction. May be infinite.
549 /// The intersection test will be skipped if the maximum distance is less than zero, NaN, or
550 /// less than the minimum intersection distance.
551 pub max_distance: f32,
554 /// Intersection result which contains the distance from the ray origin to the intersection point,
555 /// the index of the intersected primitive, and the first two barycentric coordinates of the intersection point.
557 /// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsintersectiondistanceprimitiveindexcoordinates>
559 pub struct MPSIntersectionDistancePrimitiveIndexCoordinates {
560 /// Distance from the ray origin to the intersection point along the ray direction vector such
561 /// that `intersection = ray.origin + ray.direction * distance`.
562 /// Is negative if there is no intersection. If the intersection type is `MPSIntersectionTypeAny`,
563 /// is a positive value for a hit or a negative value for a miss.
565 /// Index of the intersected primitive. Undefined if the ray does not intersect a primitive or
566 /// if the intersection type is `MPSIntersectionTypeAny`.
567 pub primitive_index: u32,
568 /// The first two barycentric coordinates `U` and `V` of the intersection point.
569 /// The third coordinate `W = 1 - U - V`. Undefined if the ray does not intersect a primitive or
570 /// if the intersection type is `MPSIntersectionTypeAny`.
571 pub coordinates: [f32; 2],