Skip to main content

opencl3/
platform.rs

1// Copyright (c) 2020-2024 Via Technology Ltd.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//    http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#![allow(clippy::missing_safety_doc)]
16
17pub use cl3::platform;
18
19use super::Result;
20use cl3::device;
21#[allow(unused_imports)]
22use cl3::dx9_media_sharing;
23#[allow(unused_imports)]
24use cl3::ext;
25#[allow(unused_imports)]
26use cl3::program;
27#[allow(unused_imports)]
28use cl3::types::{
29    cl_device_id, cl_device_type, cl_name_version, cl_platform_id, cl_platform_info, cl_uint,
30    cl_ulong, cl_version,
31};
32#[allow(unused_imports)]
33use libc::{c_void, intptr_t};
34
35/// An OpenCL platform id and methods to query it.
36///
37/// The query methods calls clGetPlatformInfo with the relevant param_name, see:
38/// [Platform Queries](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#platform-queries-table).
39#[derive(Copy, Clone, Debug)]
40pub struct Platform {
41    id: intptr_t,
42}
43
44impl From<cl_platform_id> for Platform {
45    fn from(value: cl_platform_id) -> Self {
46        Self {
47            id: value as intptr_t,
48        }
49    }
50}
51
52impl From<Platform> for cl_platform_id {
53    fn from(value: Platform) -> Self {
54        value.id as Self
55    }
56}
57
58unsafe impl Send for Platform {}
59unsafe impl Sync for Platform {}
60
61impl Platform {
62    pub fn new(id: cl_platform_id) -> Self {
63        Self { id: id as intptr_t }
64    }
65
66    /// Accessor for the underlying platform id.
67    pub const fn id(&self) -> cl_platform_id {
68        self.id as cl_platform_id
69    }
70
71    /// Get the ids of available devices of the given type on the Platform.
72    /// # Examples
73    /// ```
74    /// use opencl3::platform::get_platforms;
75    /// use cl3::device::CL_DEVICE_TYPE_GPU;
76    ///
77    /// let platforms = get_platforms().unwrap();
78    /// assert!(0 < platforms.len());
79    ///
80    /// // Choose a the first platform
81    /// let platform = &platforms[0];
82    /// let device_ids = platform.get_devices(CL_DEVICE_TYPE_GPU).unwrap();
83    /// println!("CL_DEVICE_TYPE_GPU count: {}", device_ids.len());
84    /// assert!(0 < device_ids.len());
85    /// ```
86    pub fn get_devices(&self, device_type: cl_device_type) -> Result<Vec<cl_device_id>> {
87        Ok(device::get_device_ids(self.id(), device_type)?)
88    }
89
90    #[cfg(any(feature = "cl_khr_dx9_media_sharing", feature = "dynamic"))]
91    pub unsafe fn get_device_ids_from_dx9_intel(
92        &self,
93        dx9_device_source: dx9_media_sharing::cl_dx9_device_source_intel,
94        dx9_object: *mut c_void,
95        dx9_device_set: dx9_media_sharing::cl_dx9_device_set_intel,
96    ) -> Result<Vec<cl_device_id>> {
97        unsafe {
98            Ok(dx9_media_sharing::get_device_ids_from_dx9_intel(
99                self.id(),
100                dx9_device_source,
101                dx9_object,
102                dx9_device_set,
103            )?)
104        }
105    }
106
107    /// The OpenCL profile supported by the Platform,
108    /// it can be FULL_PROFILE or EMBEDDED_PROFILE.  
109    pub fn profile(&self) -> Result<String> {
110        Ok(platform::get_platform_info(self.id(), platform::CL_PLATFORM_PROFILE)?.into())
111    }
112
113    /// The OpenCL profile version supported by the Platform,
114    /// e.g. OpenCL 1.2, OpenCL 2.0, OpenCL 2.1, etc.  
115    pub fn version(&self) -> Result<String> {
116        Ok(platform::get_platform_info(self.id(), platform::CL_PLATFORM_VERSION)?.into())
117    }
118
119    /// The OpenCL Platform name string.  
120    pub fn name(&self) -> Result<String> {
121        Ok(platform::get_platform_info(self.id(), platform::CL_PLATFORM_NAME)?.into())
122    }
123
124    /// The OpenCL Platform vendor string.  
125    pub fn vendor(&self) -> Result<String> {
126        Ok(platform::get_platform_info(self.id(), platform::CL_PLATFORM_VENDOR)?.into())
127    }
128
129    /// A space separated list of extension names supported by the Platform.  
130    pub fn extensions(&self) -> Result<String> {
131        Ok(platform::get_platform_info(self.id(), platform::CL_PLATFORM_EXTENSIONS)?.into())
132    }
133
134    /// The resolution of the host timer in nanoseconds as used by
135    /// clGetDeviceAndHostTimer.  
136    /// CL_VERSION_2_1
137    pub fn host_timer_resolution(&self) -> Result<cl_ulong> {
138        Ok(
139            platform::get_platform_info(self.id(), platform::CL_PLATFORM_HOST_TIMER_RESOLUTION)?
140                .into(),
141        )
142    }
143
144    /// The detailed (major, minor, patch) version supported by the platform.  
145    /// CL_VERSION_3_0
146    pub fn numeric_version(&self) -> Result<cl_version> {
147        Ok(platform::get_platform_info(self.id(), platform::CL_PLATFORM_NUMERIC_VERSION)?.into())
148    }
149
150    /// An array of description (name and version) structures that lists all the
151    /// extensions supported by the platform.  
152    /// CL_VERSION_3_0
153    pub fn extensions_with_version(&self) -> Result<Vec<cl_name_version>> {
154        Ok(
155            platform::get_platform_info(self.id(), platform::CL_PLATFORM_EXTENSIONS_WITH_VERSION)?
156                .into(),
157        )
158    }
159
160    /// cl_khr_external_memory
161    pub fn platform_external_memory_import_handle_types_khr(&self) -> Result<Vec<cl_name_version>> {
162        Ok(platform::get_platform_info(
163            self.id(),
164            ext::CL_PLATFORM_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR,
165        )?
166        .into())
167    }
168
169    /// cl_khr_external_semaphore
170    pub fn platform_semaphore_import_handle_types_khr(&self) -> Result<Vec<cl_name_version>> {
171        Ok(platform::get_platform_info(
172            self.id(),
173            ext::CL_PLATFORM_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR,
174        )?
175        .into())
176    }
177
178    /// cl_khr_external_semaphore
179    pub fn platform_semaphore_export_handle_types_khr(&self) -> Result<Vec<cl_name_version>> {
180        Ok(platform::get_platform_info(
181            self.id(),
182            ext::CL_PLATFORM_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR,
183        )?
184        .into())
185    }
186
187    /// cl_khr_semaphore
188    pub fn platform_semaphore_types_khr(&self) -> Result<Vec<cl_name_version>> {
189        Ok(platform::get_platform_info(self.id(), ext::CL_PLATFORM_SEMAPHORE_TYPES_KHR)?.into())
190    }
191
192    /// Get data about an OpenCL platform.
193    /// Calls clGetPlatformInfo to get the desired data about the platform.
194    pub fn get_data(&self, param_name: cl_platform_info) -> Result<Vec<u8>> {
195        Ok(platform::get_platform_data(self.id(), param_name)?)
196    }
197
198    /// Unload an OpenCL compiler for a platform.
199    /// CL_VERSION_1_2
200    ///
201    /// # Safety
202    ///
203    /// Compiling is unsafe after the compiler has been unloaded.
204    #[cfg(any(feature = "CL_VERSION_1_2", feature = "dynamic"))]
205    pub unsafe fn unload_compiler(&self) -> Result<()> {
206        unsafe { Ok(program::unload_platform_compiler(self.id())?) }
207    }
208}
209
210/// Get the available OpenCL platforms.  
211/// # Examples
212/// ```
213/// use opencl3::platform::get_platforms;
214///
215/// let platforms = get_platforms().unwrap();
216/// println!("Number of OpenCL platforms: {}", platforms.len());
217/// assert!(0 < platforms.len());
218/// ```
219/// returns a Result containing a vector of available Platforms
220/// or the error code from the OpenCL C API function.
221pub fn get_platforms() -> Result<Vec<Platform>> {
222    let platform_ids = platform::get_platform_ids()?;
223    Ok(platform_ids
224        .iter()
225        .map(|id| Platform::new(*id))
226        .collect::<Vec<Platform>>())
227}
228
229#[cfg(any(feature = "cl_khr_icd", feature = "dynamic"))]
230pub fn icd_get_platform_ids_khr() -> Result<Vec<Platform>> {
231    let platform_ids = ext::icd_get_platform_ids_khr()?;
232    Ok(platform_ids
233        .iter()
234        .map(|id| Platform::new(*id))
235        .collect::<Vec<Platform>>())
236}
237
238#[cfg(test)]
239mod tests {
240    use super::*;
241
242    #[test]
243    fn test_get_platforms() {
244        let platforms = get_platforms().unwrap();
245        println!("Number of platforms: {}", platforms.len());
246        assert!(0 < platforms.len());
247
248        for platform in platforms {
249            println!("Platform Debug Trait: {:?}", platform);
250            println!("CL_PLATFORM_NAME: {}", platform.name().unwrap());
251            println!("CL_PLATFORM_PROFILE: {}", platform.profile().unwrap());
252
253            let value = platform.version().unwrap();
254            println!("CL_PLATFORM_VERSION: {:?}", value);
255
256            println!("CL_PLATFORM_VENDOR: {}", platform.vendor().unwrap());
257            println!(
258                "CL_PLATFORM_EXTENSIONS: {:?}",
259                platform.extensions().unwrap()
260            );
261
262            // CL_VERSION_2_1 value, may not be supported
263            match platform.host_timer_resolution() {
264                Ok(value) => {
265                    println!("CL_PLATFORM_HOST_TIMER_RESOLUTION: {}", value)
266                }
267                Err(e) => println!(
268                    "OpenCL error, CL_PLATFORM_HOST_TIMER_RESOLUTION: {:?}, {}",
269                    e, e
270                ),
271            };
272
273            println!();
274        }
275    }
276}