1use std::fmt;
2use std::mem::ManuallyDrop;
3
4use crate::Platform;
5
6use crate::ffi::cl_device_id;
7use crate::ll;
8use crate::ll::{ClDeviceID, DevicePtr, DeviceType, Output};
9
10#[inline]
11fn from_low_level_vec(devices: Vec<ClDeviceID>) -> Vec<Device> {
12 devices.into_iter().map(|d| Device::new(d)).collect()
13}
14
15pub struct Device {
16 inner: ManuallyDrop<ClDeviceID>,
17 _unconstructable: (),
18}
19
20impl Device {
21 pub fn new(device_id: ClDeviceID) -> Device {
22 Device {
23 inner: ManuallyDrop::new(device_id),
24 _unconstructable: (),
25 }
26 }
27}
28
29impl Drop for Device {
30 fn drop(&mut self) {
31 unsafe {
32 ManuallyDrop::drop(&mut self.inner);
33 }
34 }
35}
36
37impl Clone for Device {
38 fn clone(&self) -> Device {
39 Device {
40 inner: ManuallyDrop::new((*self.inner).clone()),
41 _unconstructable: (),
42 }
43 }
44}
45
46impl DevicePtr for Device {
47 unsafe fn device_ptr(&self) -> cl_device_id {
48 self.inner.device_ptr()
49 }
50}
51
52impl Device {
53 pub fn low_level_device(&self) -> &ClDeviceID {
54 &*self.inner
55 }
56
57 pub fn list_devices_by_type(
58 platform: &Platform,
59 device_type: DeviceType,
60 ) -> Output<Vec<Device>> {
61 let device_ids = ll::list_devices_by_type(platform.low_level_platform(), device_type)?;
62 Ok(from_low_level_vec(device_ids))
63 }
64
65 pub fn list_default_devices(platform: &Platform) -> Output<Vec<Device>> {
66 Device::list_devices_by_type(platform, DeviceType::DEFAULT)
67 }
68
69 pub fn list_all_devices(platform: &Platform) -> Output<Vec<Device>> {
70 Device::list_devices_by_type(platform, DeviceType::ALL)
71 }
72
73 pub fn list_cpu_devices(platform: &Platform) -> Output<Vec<Device>> {
74 Device::list_devices_by_type(platform, DeviceType::CPU)
75 }
76
77 pub fn list_gpu_devices(platform: &Platform) -> Output<Vec<Device>> {
78 Device::list_devices_by_type(platform, DeviceType::GPU)
79 }
80
81 pub fn list_accelerator_devices(platform: &Platform) -> Output<Vec<Device>> {
82 Device::list_devices_by_type(platform, DeviceType::ACCELERATOR)
83 }
84
85 pub fn list_custom_devices(platform: &Platform) -> Output<Vec<Device>> {
86 Device::list_devices_by_type(platform, DeviceType::CUSTOM)
87 }
88}
89
90unsafe impl Send for Device {}
91unsafe impl Sync for Device {}
92
93impl PartialEq for Device {
94 fn eq(&self, other: &Self) -> bool {
95 self.low_level_device() == other.low_level_device()
96 }
97}
98
99impl Eq for Device {}
100
101impl fmt::Debug for Device {
102 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
103 let ptr = unsafe { self.low_level_device().device_ptr() };
105 write!(f, "Device{{ptr: {:?}}}", ptr)
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use super::Device;
112 use super::DeviceType;
113 use crate::ffi::*;
114 use crate::ll::*;
115 use crate::platform::Platform;
116 use crate::testing;
117
118 #[test]
119 fn device_all_lists_all_devices() {
120 let platform = Platform::default();
121 let devices = Device::list_all_devices(&platform).expect("Failed to list all devices");
122 assert!(devices.len() > 0);
123 }
124
125 #[test]
126 fn devices_of_many_types_can_be_listed_for_a_platform() {
127 let platform = Platform::default();
128 let _ = Device::list_default_devices(&platform);
129 let _ = Device::list_cpu_devices(&platform);
130 let _ = Device::list_gpu_devices(&platform);
131 let _ = Device::list_accelerator_devices(&platform);
132 let _ = Device::list_custom_devices(&platform);
133 }
134
135 #[test]
136 fn devices_of_many_types_can_be_listed_for_a_platform_via_flags() {
137 let platform = Platform::default();
138 let _ = Device::list_devices_by_type(&platform, DeviceType::ALL);
139 let _ = Device::list_devices_by_type(&platform, DeviceType::CPU);
140 let _ = Device::list_devices_by_type(&platform, DeviceType::GPU);
141 let _ = Device::list_devices_by_type(&platform, DeviceType::ACCELERATOR);
142 let _ = Device::list_devices_by_type(&platform, DeviceType::CUSTOM);
143 }
144
145 #[test]
146 fn device_fmt_works() {
147 let device = testing::get_device();
148 let formatted = format!("{:?}", device);
149 assert!(formatted.starts_with("Device{ptr: 0x")); }
151
152 #[test]
153 fn device_implements_device_ptr() {
154 let device = testing::get_device();
155 let device_id: cl_device_id = unsafe { device.device_ptr() };
156 assert!(!device_id.is_null());
157 assert_ne!(device_id, UNUSABLE_DEVICE_ID);
158 }
159}