opencl_core/
device.rs

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 name = self.device_name().unwrap();
104        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")); //== "".contains("Device{"));
150    }
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}