mtl_gpu/device/
properties.rs1use std::ffi::c_void;
6
7use mtl_foundation::{Referencing, UInteger};
8use mtl_sys::{msg_send_0, msg_send_2, sel};
9
10use super::{Architecture, Device};
11use crate::enums::{ArgumentBuffersTier, DeviceLocation, ReadWriteTextureTier};
12use crate::types::SamplePosition;
13
14impl Device {
15 #[inline]
26 pub fn name(&self) -> &str {
27 unsafe {
28 let ns_string: *mut c_void = msg_send_0(self.as_ptr(), sel!(name));
29 if ns_string.is_null() {
30 return "";
31 }
32 let c_str: *const std::ffi::c_char = msg_send_0(ns_string, sel!(UTF8String));
33 if c_str.is_null() {
34 return "";
35 }
36 std::ffi::CStr::from_ptr(c_str).to_str().unwrap_or("")
37 }
38 }
39
40 #[inline]
44 pub fn architecture(&self) -> Option<Architecture> {
45 unsafe {
46 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(architecture));
47 if ptr.is_null() {
48 return None;
49 }
50 let _: *mut c_void = msg_send_0(ptr, sel!(retain));
52 Architecture::from_raw(ptr)
53 }
54 }
55
56 #[inline]
62 pub fn registry_id(&self) -> u64 {
63 unsafe { msg_send_0(self.as_ptr(), sel!(registryID)) }
64 }
65
66 #[inline]
70 pub fn location(&self) -> DeviceLocation {
71 unsafe { msg_send_0(self.as_ptr(), sel!(location)) }
72 }
73
74 #[inline]
78 pub fn location_number(&self) -> UInteger {
79 unsafe { msg_send_0(self.as_ptr(), sel!(locationNumber)) }
80 }
81
82 #[inline]
88 pub fn has_unified_memory(&self) -> bool {
89 unsafe { msg_send_0(self.as_ptr(), sel!(hasUnifiedMemory)) }
90 }
91
92 #[inline]
96 pub fn is_headless(&self) -> bool {
97 unsafe { msg_send_0(self.as_ptr(), sel!(isHeadless)) }
98 }
99
100 #[inline]
104 pub fn is_low_power(&self) -> bool {
105 unsafe { msg_send_0(self.as_ptr(), sel!(isLowPower)) }
106 }
107
108 #[inline]
112 pub fn is_removable(&self) -> bool {
113 unsafe { msg_send_0(self.as_ptr(), sel!(isRemovable)) }
114 }
115
116 #[inline]
120 pub fn current_allocated_size(&self) -> UInteger {
121 unsafe { msg_send_0(self.as_ptr(), sel!(currentAllocatedSize)) }
122 }
123
124 #[inline]
128 pub fn recommended_max_working_set_size(&self) -> u64 {
129 unsafe { msg_send_0(self.as_ptr(), sel!(recommendedMaxWorkingSetSize)) }
130 }
131
132 #[inline]
136 pub fn read_write_texture_support(&self) -> ReadWriteTextureTier {
137 unsafe { msg_send_0(self.as_ptr(), sel!(readWriteTextureSupport)) }
138 }
139
140 #[inline]
144 pub fn argument_buffers_support(&self) -> ArgumentBuffersTier {
145 unsafe { msg_send_0(self.as_ptr(), sel!(argumentBuffersSupport)) }
146 }
147
148 #[inline]
152 pub fn peer_group_id(&self) -> u64 {
153 unsafe { msg_send_0(self.as_ptr(), sel!(peerGroupID)) }
154 }
155
156 #[inline]
160 pub fn peer_index(&self) -> u32 {
161 unsafe { msg_send_0(self.as_ptr(), sel!(peerIndex)) }
162 }
163
164 #[inline]
168 pub fn peer_count(&self) -> u32 {
169 unsafe { msg_send_0(self.as_ptr(), sel!(peerCount)) }
170 }
171
172 #[inline]
176 pub fn max_transfer_rate(&self) -> u64 {
177 unsafe { msg_send_0(self.as_ptr(), sel!(maxTransferRate)) }
178 }
179
180 #[inline]
184 pub fn should_maximize_concurrent_compilation(&self) -> bool {
185 unsafe { msg_send_0(self.as_ptr(), sel!(shouldMaximizeConcurrentCompilation)) }
186 }
187
188 #[inline]
192 pub fn set_should_maximize_concurrent_compilation(&self, value: bool) {
193 unsafe {
194 mtl_sys::msg_send_1::<(), bool>(
195 self.as_ptr(),
196 sel!(setShouldMaximizeConcurrentCompilation:),
197 value,
198 );
199 }
200 }
201
202 #[inline]
206 pub fn maximum_concurrent_compilation_task_count(&self) -> UInteger {
207 unsafe { msg_send_0(self.as_ptr(), sel!(maximumConcurrentCompilationTaskCount)) }
208 }
209
210 #[inline]
214 pub fn query_timestamp_frequency(&self) -> u64 {
215 unsafe { msg_send_0(self.as_ptr(), sel!(queryTimestampFrequency)) }
216 }
217
218 #[inline]
222 pub fn sample_timestamps(&self) -> (u64, u64) {
223 let mut cpu_timestamp: u64 = 0;
224 let mut gpu_timestamp: u64 = 0;
225 unsafe {
226 msg_send_2::<(), *mut u64, *mut u64>(
227 self.as_ptr(),
228 sel!(sampleTimestamps: gpuTimestamp:),
229 &mut cpu_timestamp as *mut u64,
230 &mut gpu_timestamp as *mut u64,
231 );
232 }
233 (cpu_timestamp, gpu_timestamp)
234 }
235
236 #[inline]
240 pub fn get_default_sample_positions(&self, positions: &mut [SamplePosition]) {
241 unsafe {
242 msg_send_2::<(), *mut SamplePosition, usize>(
243 self.as_ptr(),
244 sel!(getDefaultSamplePositions: count:),
245 positions.as_mut_ptr(),
246 positions.len(),
247 );
248 }
249 }
250
251 #[deprecated(note = "Use are_barycentric_coords_supported() instead")]
259 #[inline]
260 pub fn barycentric_coords_supported(&self) -> bool {
261 self.are_barycentric_coords_supported()
262 }
263
264 #[deprecated(note = "Use are_programmable_sample_positions_supported() instead")]
268 #[inline]
269 pub fn programmable_sample_positions_supported(&self) -> bool {
270 self.are_programmable_sample_positions_supported()
271 }
272
273 #[deprecated(note = "Use are_raster_order_groups_supported() instead")]
277 #[inline]
278 pub fn raster_order_groups_supported(&self) -> bool {
279 self.are_raster_order_groups_supported()
280 }
281
282 #[deprecated(note = "Use is_headless() instead")]
286 #[inline]
287 pub fn headless(&self) -> bool {
288 self.is_headless()
289 }
290
291 #[deprecated(note = "Use is_low_power() instead")]
295 #[inline]
296 pub fn low_power(&self) -> bool {
297 self.is_low_power()
298 }
299
300 #[deprecated(note = "Use is_removable() instead")]
304 #[inline]
305 pub fn removable(&self) -> bool {
306 self.is_removable()
307 }
308
309 #[deprecated(note = "Use is_depth24_stencil8_pixel_format_supported() instead")]
313 #[inline]
314 pub fn depth24_stencil8_pixel_format_supported(&self) -> bool {
315 self.is_depth24_stencil8_pixel_format_supported()
316 }
317}
318
319#[cfg(test)]
320mod tests {
321 use crate::device::system_default;
322
323 #[test]
324 fn test_device_properties() {
325 let device = system_default().expect("no Metal device");
326
327 assert!(!device.name().is_empty());
329
330 assert!(device.registry_id() != 0);
332
333 let arch = device.architecture();
335 assert!(arch.is_some());
336 }
337
338 #[test]
339 fn test_device_timestamps() {
340 let device = system_default().expect("no Metal device");
341
342 let (cpu, gpu) = device.sample_timestamps();
343 assert!(cpu > 0);
345 assert!(gpu > 0);
346 }
347}