Skip to main content

apple_mps/
core.rs

1use crate::ffi;
2use apple_metal::{
3    CommandBuffer as MetalCommandBuffer, CommandQueue, ManuallyDropDevice, MetalBuffer, MetalDevice,
4};
5use core::ffi::c_void;
6use core::ptr;
7
8pub mod device_options {
9    pub const DEFAULT: usize = 0;
10    pub const LOW_POWER: usize = 1;
11    pub const SKIP_REMOVABLE: usize = 2;
12}
13
14macro_rules! opaque_handle {
15    ($name:ident) => {
16        pub struct $name {
17            ptr: *mut c_void,
18        }
19
20        unsafe impl Send for $name {}
21        unsafe impl Sync for $name {}
22
23        impl Drop for $name {
24            fn drop(&mut self) {
25                if !self.ptr.is_null() {
26                    unsafe { ffi::mps_object_release(self.ptr) };
27                    self.ptr = ptr::null_mut();
28                }
29            }
30        }
31
32        impl $name {
33            #[must_use]
34            pub const fn as_ptr(&self) -> *mut c_void {
35                self.ptr
36            }
37        }
38    };
39}
40
41pub fn supports_mtl_device(device: &MetalDevice) -> bool {
42    unsafe { ffi::mps_supports_mtl_device(device.as_ptr()) }
43}
44
45opaque_handle!(PreferredDevice);
46impl PreferredDevice {
47    #[must_use]
48    pub fn as_borrowed_device(&self) -> ManuallyDropDevice {
49        unsafe { MetalDevice::from_raw_borrowed(self.ptr) }
50    }
51}
52
53#[must_use]
54pub fn preferred_device(options: usize) -> Option<PreferredDevice> {
55    let ptr = unsafe { ffi::mps_get_preferred_device(options) };
56    if ptr.is_null() {
57        None
58    } else {
59        Some(PreferredDevice { ptr })
60    }
61}
62
63pub fn hint_temporary_memory_high_water_mark(command_buffer: &MetalCommandBuffer, bytes: usize) {
64    unsafe { ffi::mps_hint_temporary_memory_high_water_mark(command_buffer.as_ptr(), bytes) };
65}
66
67pub fn set_heap_cache_duration(command_buffer: &MetalCommandBuffer, seconds: f64) {
68    unsafe { ffi::mps_set_heap_cache_duration(command_buffer.as_ptr(), seconds) };
69}
70
71opaque_handle!(Predicate);
72impl Predicate {
73    #[must_use]
74    pub fn new_with_buffer(buffer: &MetalBuffer, offset: usize) -> Option<Self> {
75        let ptr = unsafe { ffi::mps_predicate_new_with_buffer(buffer.as_ptr(), offset) };
76        if ptr.is_null() {
77            None
78        } else {
79            Some(Self { ptr })
80        }
81    }
82
83    #[must_use]
84    pub fn new_with_device(device: &MetalDevice) -> Option<Self> {
85        let ptr = unsafe { ffi::mps_predicate_new_with_device(device.as_ptr()) };
86        if ptr.is_null() {
87            None
88        } else {
89            Some(Self { ptr })
90        }
91    }
92
93    #[must_use]
94    pub fn predicate_offset(&self) -> usize {
95        unsafe { ffi::mps_predicate_offset(self.ptr) }
96    }
97}
98
99opaque_handle!(CommandBuffer);
100impl CommandBuffer {
101    #[must_use]
102    pub fn new_with_command_buffer(command_buffer: &MetalCommandBuffer) -> Option<Self> {
103        let ptr =
104            unsafe { ffi::mps_command_buffer_new_with_command_buffer(command_buffer.as_ptr()) };
105        if ptr.is_null() {
106            None
107        } else {
108            Some(Self { ptr })
109        }
110    }
111
112    #[must_use]
113    pub fn from_command_queue(command_queue: &CommandQueue) -> Option<Self> {
114        let ptr = unsafe { ffi::mps_command_buffer_from_command_queue(command_queue.as_ptr()) };
115        if ptr.is_null() {
116            None
117        } else {
118            Some(Self { ptr })
119        }
120    }
121
122    pub fn set_predicate(&self, predicate: &Predicate) {
123        unsafe { ffi::mps_command_buffer_set_predicate(self.ptr, predicate.as_ptr()) };
124    }
125
126    pub fn clear_predicate(&self) {
127        unsafe { ffi::mps_command_buffer_clear_predicate(self.ptr) };
128    }
129
130    pub fn prefetch_heap_for_workload_size(&self, size: usize) {
131        unsafe { ffi::mps_command_buffer_prefetch_heap(self.ptr, size) };
132    }
133
134    pub fn commit_and_continue(&self) {
135        unsafe { ffi::mps_command_buffer_commit_and_continue(self.ptr) };
136    }
137}