cl3/
device.rs

1// Copyright (c) 2020-2025 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//! `OpenCL` Device API.
16
17#![allow(unused_unsafe)]
18#![allow(non_camel_case_types, non_upper_case_globals)]
19#![allow(
20    clippy::not_unsafe_ptr_arg_deref,
21    clippy::too_many_lines,
22    clippy::wildcard_in_or_patterns
23)]
24
25pub use opencl_sys::{
26    CL_DEVICE_ADDRESS_BITS, CL_DEVICE_AFFINITY_DOMAIN_L1_CACHE, CL_DEVICE_AFFINITY_DOMAIN_L2_CACHE,
27    CL_DEVICE_AFFINITY_DOMAIN_L3_CACHE, CL_DEVICE_AFFINITY_DOMAIN_L4_CACHE,
28    CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE, CL_DEVICE_AFFINITY_DOMAIN_NUMA,
29    CL_DEVICE_ATOMIC_FENCE_CAPABILITIES, CL_DEVICE_ATOMIC_MEMORY_CAPABILITIES,
30    CL_DEVICE_ATOMIC_ORDER_ACQ_REL, CL_DEVICE_ATOMIC_ORDER_RELAXED, CL_DEVICE_ATOMIC_ORDER_SEQ_CST,
31    CL_DEVICE_ATOMIC_SCOPE_ALL_DEVICES, CL_DEVICE_ATOMIC_SCOPE_DEVICE,
32    CL_DEVICE_ATOMIC_SCOPE_WORK_GROUP, CL_DEVICE_ATOMIC_SCOPE_WORK_ITEM, CL_DEVICE_AVAILABLE,
33    CL_DEVICE_AVAILABLE_ASYNC_QUEUES_AMD, CL_DEVICE_BOARD_NAME_AMD, CL_DEVICE_BUILT_IN_KERNELS,
34    CL_DEVICE_BUILT_IN_KERNELS_WITH_VERSION, CL_DEVICE_COMMAND_BUFFER_CAPABILITIES_KHR,
35    CL_DEVICE_COMMAND_BUFFER_REQUIRED_QUEUE_PROPERTIES_KHR, CL_DEVICE_COMPILER_AVAILABLE,
36    CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV, CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV,
37    CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES, CL_DEVICE_DOUBLE_FP_CONFIG, CL_DEVICE_ENDIAN_LITTLE,
38    CL_DEVICE_ERROR_CORRECTION_SUPPORT, CL_DEVICE_EXECUTION_CAPABILITIES, CL_DEVICE_EXTENSIONS,
39    CL_DEVICE_EXTENSIONS_WITH_VERSION, CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR,
40    CL_DEVICE_FEATURE_CAPABILITIES_INTEL, CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT,
41    CL_DEVICE_GFXIP_MAJOR_AMD, CL_DEVICE_GFXIP_MINOR_AMD, CL_DEVICE_GLOBAL_FREE_MEMORY_AMD,
42    CL_DEVICE_GLOBAL_MEM_CACHE_SIZE, CL_DEVICE_GLOBAL_MEM_CACHE_TYPE,
43    CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE, CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD,
44    CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD, CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD,
45    CL_DEVICE_GLOBAL_MEM_SIZE, CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE,
46    CL_DEVICE_GPU_OVERLAP_NV, CL_DEVICE_HALF_FP_CONFIG, CL_DEVICE_HOST_UNIFIED_MEMORY,
47    CL_DEVICE_ID_INTEL, CL_DEVICE_IL_VERSION, CL_DEVICE_ILS_WITH_VERSION,
48    CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE,
49    CL_DEVICE_IMAGE_MAX_BUFFER_SIZE, CL_DEVICE_IMAGE_PITCH_ALIGNMENT, CL_DEVICE_IMAGE_SUPPORT,
50    CL_DEVICE_IMAGE2D_MAX_HEIGHT, CL_DEVICE_IMAGE2D_MAX_WIDTH, CL_DEVICE_IMAGE3D_MAX_DEPTH,
51    CL_DEVICE_IMAGE3D_MAX_HEIGHT, CL_DEVICE_IMAGE3D_MAX_WIDTH,
52    CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_4x8BIT_PACKED_KHR,
53    CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_8BIT_KHR,
54    CL_DEVICE_INTEGER_DOT_PRODUCT_CAPABILITIES_KHR, CL_DEVICE_INTEGRATED_MEMORY_NV,
55    CL_DEVICE_IP_VERSION_INTEL, CL_DEVICE_KERNEL_CLOCK_CAPABILITIES_KHR,
56    CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV, CL_DEVICE_LATEST_CONFORMANCE_VERSION_PASSED,
57    CL_DEVICE_LINKER_AVAILABLE, CL_DEVICE_LOCAL_MEM_BANKS_AMD, CL_DEVICE_LOCAL_MEM_SIZE,
58    CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD, CL_DEVICE_LOCAL_MEM_TYPE, CL_DEVICE_LUID_KHR,
59    CL_DEVICE_LUID_VALID_KHR, CL_DEVICE_MAX_CLOCK_FREQUENCY, CL_DEVICE_MAX_COMPUTE_UNITS,
60    CL_DEVICE_MAX_CONSTANT_ARGS, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE,
61    CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE, CL_DEVICE_MAX_MEM_ALLOC_SIZE, CL_DEVICE_MAX_NUM_SUB_GROUPS,
62    CL_DEVICE_MAX_ON_DEVICE_EVENTS, CL_DEVICE_MAX_ON_DEVICE_QUEUES, CL_DEVICE_MAX_PARAMETER_SIZE,
63    CL_DEVICE_MAX_PIPE_ARGS, CL_DEVICE_MAX_READ_IMAGE_ARGS, CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS,
64    CL_DEVICE_MAX_SAMPLERS, CL_DEVICE_MAX_WORK_GROUP_SIZE, CL_DEVICE_MAX_WORK_GROUP_SIZE_AMD,
65    CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, CL_DEVICE_MAX_WORK_ITEM_SIZES,
66    CL_DEVICE_MAX_WRITE_IMAGE_ARGS, CL_DEVICE_MEM_BASE_ADDR_ALIGN,
67    CL_DEVICE_MEMORY_CAPABILITIES_IMG, CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE, CL_DEVICE_NAME,
68    CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR, CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE,
69    CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT, CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF,
70    CL_DEVICE_NATIVE_VECTOR_WIDTH_INT, CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG,
71    CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT, CL_DEVICE_NODE_MASK_KHR,
72    CL_DEVICE_NON_UNIFORM_WORK_GROUP_SUPPORT, CL_DEVICE_NOT_FOUND,
73    CL_DEVICE_NUM_EUS_PER_SUB_SLICE_INTEL, CL_DEVICE_NUM_SLICES_INTEL,
74    CL_DEVICE_NUM_SUB_SLICES_PER_SLICE_INTEL, CL_DEVICE_NUM_THREADS_PER_EU_INTEL,
75    CL_DEVICE_NUMERIC_VERSION, CL_DEVICE_OPENCL_C_ALL_VERSIONS, CL_DEVICE_OPENCL_C_FEATURES,
76    CL_DEVICE_OPENCL_C_VERSION, CL_DEVICE_PARENT_DEVICE, CL_DEVICE_PARTITION_AFFINITY_DOMAIN,
77    CL_DEVICE_PARTITION_MAX_SUB_DEVICES, CL_DEVICE_PARTITION_PROPERTIES, CL_DEVICE_PARTITION_TYPE,
78    CL_DEVICE_PCI_BUS_ID_NV, CL_DEVICE_PCI_BUS_INFO_KHR, CL_DEVICE_PCI_SLOT_ID_NV,
79    CL_DEVICE_PCIE_ID_AMD, CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS, CL_DEVICE_PIPE_MAX_PACKET_SIZE,
80    CL_DEVICE_PIPE_SUPPORT, CL_DEVICE_PLATFORM, CL_DEVICE_PREFERRED_CONSTANT_BUFFER_SIZE_AMD,
81    CL_DEVICE_PREFERRED_GLOBAL_ATOMIC_ALIGNMENT, CL_DEVICE_PREFERRED_INTEROP_USER_SYNC,
82    CL_DEVICE_PREFERRED_LOCAL_ATOMIC_ALIGNMENT, CL_DEVICE_PREFERRED_PLATFORM_ATOMIC_ALIGNMENT,
83    CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE,
84    CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF,
85    CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG,
86    CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT, CL_DEVICE_PREFERRED_WORK_GROUP_SIZE_AMD,
87    CL_DEVICE_PREFERRED_WORK_GROUP_SIZE_MULTIPLE, CL_DEVICE_PRINTF_BUFFER_SIZE, CL_DEVICE_PROFILE,
88    CL_DEVICE_PROFILING_TIMER_OFFSET_AMD, CL_DEVICE_PROFILING_TIMER_RESOLUTION,
89    CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE, CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE,
90    CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES, CL_DEVICE_QUEUE_ON_HOST_PROPERTIES,
91    CL_DEVICE_QUEUE_REPLACEABLE_DEFAULT, CL_DEVICE_QUEUE_SUPPORTED, CL_DEVICE_REFERENCE_COUNT,
92    CL_DEVICE_REGISTERS_PER_BLOCK_NV, CL_DEVICE_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR,
93    CL_DEVICE_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR, CL_DEVICE_SEMAPHORE_TYPES_KHR,
94    CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD, CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD,
95    CL_DEVICE_SIMD_WIDTH_AMD, CL_DEVICE_SINGLE_FP_CONFIG,
96    CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS, CL_DEVICE_SVM_ATOMICS,
97    CL_DEVICE_SVM_CAPABILITIES, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER, CL_DEVICE_SVM_FINE_GRAIN_BUFFER,
98    CL_DEVICE_SVM_FINE_GRAIN_SYSTEM, CL_DEVICE_THREAD_TRACE_SUPPORTED_AMD, CL_DEVICE_TOPOLOGY_AMD,
99    CL_DEVICE_TYPE, CL_DEVICE_TYPE_ACCELERATOR, CL_DEVICE_TYPE_ALL, CL_DEVICE_TYPE_CPU,
100    CL_DEVICE_TYPE_CUSTOM, CL_DEVICE_TYPE_DEFAULT, CL_DEVICE_TYPE_GPU, CL_DEVICE_UUID_KHR,
101    CL_DEVICE_VENDOR, CL_DEVICE_VENDOR_ID, CL_DEVICE_VERSION, CL_DEVICE_WARP_SIZE_NV,
102    CL_DEVICE_WAVEFRONT_WIDTH_AMD, CL_DEVICE_WORK_GROUP_COLLECTIVE_FUNCTIONS_SUPPORT,
103    CL_DRIVER_UUID_KHR, CL_DRIVER_VERSION, CL_EXEC_KERNEL, CL_EXEC_NATIVE_KERNEL, CL_FALSE,
104    CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT, CL_FP_DENORM, CL_FP_FMA, CL_FP_INF_NAN,
105    CL_FP_ROUND_TO_INF, CL_FP_ROUND_TO_NEAREST, CL_FP_ROUND_TO_ZERO, CL_FP_SOFT_FLOAT, CL_GLOBAL,
106    CL_LOCAL, CL_LUID_SIZE_KHR, CL_NONE, CL_READ_ONLY_CACHE, CL_READ_WRITE_CACHE, CL_SUCCESS,
107    CL_TRUE, CL_UUID_SIZE_KHR, CL_VERSION_MAJOR_BITS, CL_VERSION_MAJOR_MASK, CL_VERSION_MINOR_BITS,
108    CL_VERSION_MINOR_MASK, CL_VERSION_PATCH_BITS, CL_VERSION_PATCH_MASK, cl_amd_device_topology,
109    cl_command_queue, cl_context, cl_device_fp_config, cl_device_id, cl_device_info,
110    cl_device_integer_dot_product_acceleration_properties_khr, cl_device_partition_property,
111    cl_device_pci_bus_info_khr, cl_device_svm_capabilities, cl_device_type, cl_double, cl_float,
112    cl_int, cl_name_version, cl_platform_id, cl_uint, cl_ulong,
113};
114
115use super::info_type::InfoType;
116use super::{api_info_size, api_info_value, api_info_vector};
117use libc::{c_void, intptr_t, size_t};
118use std::mem;
119use std::ptr;
120
121/// Get the list of available devices of the given type on a platform.
122/// Calls clGetDeviceIDs to get the available device ids on the platform.
123///  # Examples
124/// ```
125/// use cl3::platform::get_platform_ids;
126/// use cl3::device::{get_device_ids, CL_DEVICE_TYPE_GPU};
127///
128/// let platform_ids = get_platform_ids().unwrap();
129/// assert!(0 < platform_ids.len());
130///
131/// // Choose a the first platform
132/// let platform_id = platform_ids[0];
133///
134/// let device_ids = get_device_ids(platform_id, CL_DEVICE_TYPE_GPU).unwrap();
135/// println!("CL_DEVICE_TYPE_GPU count: {}", device_ids.len());
136/// assert!(0 < device_ids.len());
137/// ```
138/// * `platform` - the `cl_platform_id` of the `OpenCL` platform.
139/// * `device_type` - the type of device, see
140///   [Device Types](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#device-types-table).
141///
142/// returns a Result containing a vector of available device ids
143/// or the error code from the `OpenCL` C API function.
144pub fn get_device_ids(
145    platform: cl_platform_id,
146    device_type: cl_device_type,
147) -> Result<Vec<cl_device_id>, cl_int> {
148    // Get the number of devices of device_type
149    let mut count: cl_uint = 0;
150    let mut status = unsafe {
151        cl_call!(clGetDeviceIDs(
152            platform,
153            device_type,
154            0,
155            ptr::null_mut(),
156            &raw mut count
157        ))
158    };
159
160    if (CL_SUCCESS != status) && (CL_DEVICE_NOT_FOUND != status) {
161        Err(status)
162    } else if 0 < count {
163        // Get the device ids.
164        let len = count as size_t;
165        let mut ids: Vec<cl_device_id> = Vec::with_capacity(len);
166        unsafe {
167            status = cl_call!(clGetDeviceIDs(
168                platform,
169                device_type,
170                count,
171                ids.as_mut_ptr(),
172                ptr::null_mut(),
173            ));
174            ids.set_len(len);
175        };
176
177        if CL_SUCCESS == status {
178            Ok(ids)
179        } else {
180            Err(status)
181        }
182    } else {
183        Ok(Vec::default())
184    }
185}
186
187/// Get data about an `OpenCL` device.
188/// Calls clGetDeviceInfo to get the desired data about the device.
189pub fn get_device_data(
190    device: cl_device_id,
191    param_name: cl_device_info,
192) -> Result<Vec<u8>, cl_int> {
193    api_info_size!(get_size, clGetDeviceInfo);
194    let size = get_size(device, param_name)?;
195    api_info_vector!(get_vector, u8, clGetDeviceInfo);
196    get_vector(device, param_name, size)
197}
198
199/// Get specific information about an `OpenCL` device.
200/// Calls clGetDeviceInfo to get the desired information about the device.
201///  # Examples
202/// ```
203/// use cl3::platform::get_platform_ids;
204/// use cl3::device::{get_device_ids, get_device_info, CL_DEVICE_TYPE, CL_DEVICE_TYPE_GPU, CL_DEVICE_VENDOR, CL_DEVICE_VERSION};
205/// use cl3::types::cl_ulong;
206///
207/// let platform_ids = get_platform_ids().unwrap();
208/// assert!(0 < platform_ids.len());
209///
210/// // Choose a the first platform
211/// let platform_id = platform_ids[0];
212///
213/// let device_ids = get_device_ids(platform_id, CL_DEVICE_TYPE_GPU).unwrap();
214/// println!("CL_DEVICE_TYPE_GPU count: {}", device_ids.len());
215/// assert!(0 < device_ids.len());
216///
217/// // Choose the first device
218/// let device_id = device_ids[0];
219///
220/// let value = get_device_info(device_id, CL_DEVICE_TYPE).unwrap();
221/// let value = cl_ulong::from(value);
222/// println!("CL_DEVICE_TYPE: {}", value);
223/// assert_eq!(CL_DEVICE_TYPE_GPU, value);
224///
225/// let value = get_device_info(device_id, CL_DEVICE_VENDOR).unwrap();
226/// let value = String::from(value);
227/// println!("CL_DEVICE_VENDOR: {}", value);
228/// assert!(!value.is_empty());
229///
230/// let value = get_device_info(device_id, CL_DEVICE_VERSION).unwrap();
231/// let value:String = value.into();
232/// println!("CL_DEVICE_VERSION: {}", value);
233/// assert!(!value.is_empty());
234/// ```
235/// * `device` - the `cl_device_id` of the `OpenCL` device.
236/// * `param_name` - the type of device information being queried, see
237///   [Device Queries](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#device-queries-table).
238///
239/// returns a Result containing the desired information in an `InfoType` enum
240/// or the error code from the `OpenCL` C API function.
241pub fn get_device_info(
242    device: cl_device_id,
243    param_name: cl_device_info,
244) -> Result<InfoType, cl_int> {
245    api_info_size!(get_size, clGetDeviceInfo);
246
247    match param_name {
248        CL_DEVICE_VENDOR_ID
249        | CL_DEVICE_MAX_COMPUTE_UNITS
250        | CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS
251        | CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR
252        | CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT
253        | CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT
254        | CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG
255        | CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT
256        | CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE
257        | CL_DEVICE_MAX_CLOCK_FREQUENCY
258        | CL_DEVICE_ADDRESS_BITS
259        | CL_DEVICE_MAX_READ_IMAGE_ARGS
260        | CL_DEVICE_MAX_WRITE_IMAGE_ARGS
261        | CL_DEVICE_IMAGE_SUPPORT
262        | CL_DEVICE_MAX_SAMPLERS
263        | CL_DEVICE_MEM_BASE_ADDR_ALIGN
264        | CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE
265        | CL_DEVICE_GLOBAL_MEM_CACHE_TYPE
266        | CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE
267        | CL_DEVICE_MAX_CONSTANT_ARGS
268        | CL_DEVICE_LOCAL_MEM_TYPE
269        | CL_DEVICE_ERROR_CORRECTION_SUPPORT
270        | CL_DEVICE_ENDIAN_LITTLE
271        | CL_DEVICE_AVAILABLE
272        | CL_DEVICE_COMPILER_AVAILABLE
273        | CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF
274        | CL_DEVICE_HOST_UNIFIED_MEMORY
275        | CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR
276        | CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT
277        | CL_DEVICE_NATIVE_VECTOR_WIDTH_INT
278        | CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG
279        | CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT
280        | CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE
281        | CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF
282        | CL_DEVICE_LINKER_AVAILABLE
283        | CL_DEVICE_PARTITION_MAX_SUB_DEVICES
284        | CL_DEVICE_REFERENCE_COUNT
285        | CL_DEVICE_PREFERRED_INTEROP_USER_SYNC
286        | CL_DEVICE_IMAGE_PITCH_ALIGNMENT
287        | CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT
288        | CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS
289        | CL_DEVICE_MAX_ON_DEVICE_QUEUES
290        | CL_DEVICE_MAX_ON_DEVICE_EVENTS
291        | CL_DEVICE_MAX_PIPE_ARGS
292        | CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS
293        | CL_DEVICE_PIPE_MAX_PACKET_SIZE
294        | CL_DEVICE_PREFERRED_PLATFORM_ATOMIC_ALIGNMENT
295        | CL_DEVICE_PREFERRED_GLOBAL_ATOMIC_ALIGNMENT
296        | CL_DEVICE_PREFERRED_LOCAL_ATOMIC_ALIGNMENT
297        | CL_DEVICE_MAX_NUM_SUB_GROUPS
298        | CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS
299
300        | CL_DEVICE_NUMERIC_VERSION // CL_VERSION_3_0
301        | CL_DEVICE_NON_UNIFORM_WORK_GROUP_SUPPORT // CL_VERSION_3_0
302        | CL_DEVICE_WORK_GROUP_COLLECTIVE_FUNCTIONS_SUPPORT // CL_VERSION_3_0
303        | CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT // CL_VERSION_3_0
304        | CL_DEVICE_PIPE_SUPPORT // CL_VERSION_3_0
305
306        | CL_DEVICE_LUID_VALID_KHR // cl_khr_device_uuid
307        | CL_DEVICE_NODE_MASK_KHR // cl_khr_device_uuid
308
309        | CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV // cl_nv_device_attribute_query
310        | CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV // cl_nv_device_attribute_query
311        | CL_DEVICE_REGISTERS_PER_BLOCK_NV // cl_nv_device_attribute_query
312        | CL_DEVICE_WARP_SIZE_NV // cl_nv_device_attribute_query
313        | CL_DEVICE_GPU_OVERLAP_NV // cl_nv_device_attribute_query
314        | CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV // cl_nv_device_attribute_query
315        | CL_DEVICE_INTEGRATED_MEMORY_NV // cl_nv_device_attribute_query
316
317        | CL_DEVICE_PCI_BUS_ID_NV // cl_nv_device_attribute_query, undocumented
318        | CL_DEVICE_PCI_SLOT_ID_NV // cl_nv_device_attribute_query, undocumented
319
320        | CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD // cl_amd_device_attribute_query
321        | CL_DEVICE_SIMD_WIDTH_AMD // cl_amd_device_attribute_query
322        | CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD // cl_amd_device_attribute_query
323        | CL_DEVICE_WAVEFRONT_WIDTH_AMD // cl_amd_device_attribute_query
324        | CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD // cl_amd_device_attribute_query
325        | CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD // cl_amd_device_attribute_query
326        | CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD // cl_amd_device_attribute_query
327        | CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD // cl_amd_device_attribute_query
328        | CL_DEVICE_LOCAL_MEM_BANKS_AMD // cl_amd_device_attribute_query
329        | CL_DEVICE_THREAD_TRACE_SUPPORTED_AMD // cl_amd_device_attribute_query
330        | CL_DEVICE_GFXIP_MAJOR_AMD // cl_amd_device_attribute_query
331        | CL_DEVICE_GFXIP_MINOR_AMD // cl_amd_device_attribute_query
332        | CL_DEVICE_AVAILABLE_ASYNC_QUEUES_AMD // cl_amd_device_attribute_query
333        | CL_DEVICE_PCIE_ID_AMD // cl_amd_device_attribute_query
334        | CL_DEVICE_IP_VERSION_INTEL // cl_intel_device_attribute_query
335        | CL_DEVICE_ID_INTEL // cl_intel_device_attribute_query
336        | CL_DEVICE_NUM_SLICES_INTEL // cl_intel_device_attribute_query
337        | CL_DEVICE_NUM_SUB_SLICES_PER_SLICE_INTEL // cl_intel_device_attribute_query
338        | CL_DEVICE_NUM_EUS_PER_SUB_SLICE_INTEL // cl_intel_device_attribute_query
339        | CL_DEVICE_NUM_THREADS_PER_EU_INTEL // cl_intel_device_attribute_query
340        => {
341            api_info_value!(get_value, cl_uint, clGetDeviceInfo);
342            Ok(InfoType::Uint(get_value(device, param_name)?))
343        }
344
345        CL_DEVICE_TYPE
346        | CL_DEVICE_MAX_MEM_ALLOC_SIZE
347        | CL_DEVICE_SINGLE_FP_CONFIG
348        | CL_DEVICE_GLOBAL_MEM_CACHE_SIZE
349        | CL_DEVICE_GLOBAL_MEM_SIZE
350        | CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE
351        | CL_DEVICE_LOCAL_MEM_SIZE
352        | CL_DEVICE_EXECUTION_CAPABILITIES
353        | CL_DEVICE_QUEUE_ON_HOST_PROPERTIES
354        | CL_DEVICE_DOUBLE_FP_CONFIG
355        | CL_DEVICE_HALF_FP_CONFIG
356        | CL_DEVICE_SVM_CAPABILITIES
357        | CL_DEVICE_ATOMIC_MEMORY_CAPABILITIES // CL_VERSION_3_0
358        | CL_DEVICE_ATOMIC_FENCE_CAPABILITIES // CL_VERSION_3_0
359        | CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES // CL_VERSION_3_0
360        | CL_DEVICE_INTEGER_DOT_PRODUCT_CAPABILITIES_KHR
361        | CL_DEVICE_FEATURE_CAPABILITIES_INTEL // cl_intel_device_attribute_query
362        | CL_DEVICE_COMMAND_BUFFER_CAPABILITIES_KHR // cl_khr_command_buffer
363        | CL_DEVICE_COMMAND_BUFFER_REQUIRED_QUEUE_PROPERTIES_KHR // cl_khr_command_buffer
364        | CL_DEVICE_MEMORY_CAPABILITIES_IMG // cl_device_kernel_clock_capabilities_khr
365        | CL_DEVICE_KERNEL_CLOCK_CAPABILITIES_KHR // cl_device_kernel_clock_capabilities_khr
366        => {
367            api_info_value!(get_value, cl_ulong, clGetDeviceInfo);
368            Ok(InfoType::Ulong(get_value(device, param_name)?))
369        }
370
371        CL_DEVICE_MAX_WORK_GROUP_SIZE
372        | CL_DEVICE_IMAGE2D_MAX_WIDTH
373        | CL_DEVICE_IMAGE2D_MAX_HEIGHT
374        | CL_DEVICE_IMAGE3D_MAX_WIDTH
375        | CL_DEVICE_IMAGE3D_MAX_HEIGHT
376        | CL_DEVICE_IMAGE3D_MAX_DEPTH
377        | CL_DEVICE_MAX_PARAMETER_SIZE
378        | CL_DEVICE_PROFILING_TIMER_RESOLUTION
379        | CL_DEVICE_IMAGE_MAX_BUFFER_SIZE
380        | CL_DEVICE_IMAGE_MAX_ARRAY_SIZE
381        | CL_DEVICE_PRINTF_BUFFER_SIZE
382        | CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE
383        | CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE
384        | CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE
385        | CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE
386        | CL_DEVICE_PREFERRED_WORK_GROUP_SIZE_MULTIPLE // CL_VERSION_3_0
387        | CL_DEVICE_PROFILING_TIMER_OFFSET_AMD // cl_amd_device_attribute_query
388        | CL_DEVICE_GLOBAL_FREE_MEMORY_AMD // cl_amd_device_attribute_query
389        | CL_DEVICE_PREFERRED_WORK_GROUP_SIZE_AMD // cl_amd_device_attribute_query
390        | CL_DEVICE_MAX_WORK_GROUP_SIZE_AMD // cl_amd_device_attribute_query
391        | CL_DEVICE_PREFERRED_CONSTANT_BUFFER_SIZE_AMD // cl_amd_device_attribute_query
392        => {
393            api_info_value!(get_value, size_t, clGetDeviceInfo);
394            Ok(InfoType::Size(get_value(device, param_name)?))
395        }
396
397        CL_DEVICE_PLATFORM | CL_DEVICE_PARENT_DEVICE => {
398            api_info_value!(get_value, intptr_t, clGetDeviceInfo);
399            Ok(InfoType::Ptr(get_value(device, param_name)?))
400        }
401
402        CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR // cl_khr_external_memory
403        | CL_DEVICE_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR // cl_khr_external_semaphore
404        | CL_DEVICE_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR // cl_khr_external_semaphore
405        | CL_DEVICE_SEMAPHORE_TYPES_KHR // cl_khr_semaphore
406        => {
407            api_info_vector!(get_vec, cl_uint, clGetDeviceInfo);
408            let size = get_size(device, param_name)?;
409            Ok(InfoType::VecUshort(get_vec(device, param_name, size)?))
410        }
411
412        CL_DEVICE_PARTITION_AFFINITY_DOMAIN => {
413            api_info_vector!(get_vec, cl_ulong, clGetDeviceInfo);
414            let size = get_size(device, param_name)?;
415            Ok(InfoType::VecUlong(get_vec(device, param_name, size)?))
416        }
417
418        CL_DEVICE_MAX_WORK_ITEM_SIZES => {
419            api_info_vector!(get_vec, size_t, clGetDeviceInfo);
420            let size = get_size(device, param_name)?;
421            Ok(InfoType::VecSize(get_vec(device, param_name, size)?))
422        }
423
424        CL_DEVICE_PARTITION_PROPERTIES
425        | CL_DEVICE_PARTITION_TYPE
426        | CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES => {
427            api_info_vector!(get_vec, intptr_t, clGetDeviceInfo);
428            let size = get_size(device, param_name)?;
429            Ok(InfoType::VecIntPtr(get_vec(device, param_name, size)?))
430        }
431
432        // CL_VERSION_3_0
433        CL_DEVICE_EXTENSIONS_WITH_VERSION
434        | CL_DEVICE_ILS_WITH_VERSION
435        | CL_DEVICE_BUILT_IN_KERNELS_WITH_VERSION
436        | CL_DEVICE_OPENCL_C_ALL_VERSIONS
437        | CL_DEVICE_OPENCL_C_FEATURES => {
438            api_info_vector!(get_vec, cl_name_version, clGetDeviceInfo);
439            let size = get_size(device, param_name)?;
440            Ok(InfoType::VecNameVersion(get_vec(device, param_name, size)?))
441        }
442
443        CL_DEVICE_UUID_KHR // cl_khr_device_uuid
444        | CL_DRIVER_UUID_KHR // cl_khr_device_uuid
445        => {
446            let mut value: [u8; CL_UUID_SIZE_KHR] = [0; CL_UUID_SIZE_KHR];
447            let status = unsafe {
448                cl_call!(clGetDeviceInfo(
449                    device,
450                    param_name,
451                    CL_UUID_SIZE_KHR,
452                    value.as_mut_ptr().cast::<c_void>(),
453                     ptr::null_mut(),))
454                    };
455            if CL_SUCCESS == status {
456                Ok(InfoType::Uuid(value))
457            } else {
458                Err(status)
459            }
460        }
461
462        CL_DEVICE_LUID_KHR // cl_khr_device_uuid
463        => {
464            let mut value: [u8; CL_LUID_SIZE_KHR] = [0; CL_LUID_SIZE_KHR];
465            let status = unsafe {
466                cl_call!(clGetDeviceInfo(
467                    device,
468                    param_name,
469                    CL_LUID_SIZE_KHR,
470                    value.as_mut_ptr().cast::<c_void>(),
471                    ptr::null_mut(),))
472                };
473            if CL_SUCCESS == status {
474                Ok(InfoType::Luid(value))
475            } else {
476                Err(status)
477            }
478        }
479
480        CL_DEVICE_NAME
481        | CL_DEVICE_VENDOR
482        | CL_DRIVER_VERSION
483        | CL_DEVICE_PROFILE
484        | CL_DEVICE_VERSION
485        | CL_DEVICE_EXTENSIONS
486        | CL_DEVICE_OPENCL_C_VERSION
487        | CL_DEVICE_BUILT_IN_KERNELS
488        | CL_DEVICE_IL_VERSION
489        | CL_DEVICE_LATEST_CONFORMANCE_VERSION_PASSED // CL_VERSION_3_0
490        | CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_8BIT_KHR // cl_device_integer_dot_product_acceleration_properties_khr
491        | CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_4x8BIT_PACKED_KHR // cl_device_integer_dot_product_acceleration_properties_khr
492        | CL_DEVICE_TOPOLOGY_AMD // cl_amd_device_attribute_query
493        | CL_DEVICE_BOARD_NAME_AMD // cl_amd_device_attribute_query
494        | CL_DEVICE_PCI_BUS_INFO_KHR // cl_khr_pci_bus_info
495        | _
496        => {
497            Ok(InfoType::VecUchar(get_device_data(device, param_name)?))
498        }
499    }
500}
501
502/// Convert a u8 slice (e.g. from `get_device_info`) into a `cl_amd_device_topology structure`.
503///
504/// # Panics
505///
506/// `if bytes.len() != size_of::<cl_amd_device_topology>`
507#[must_use]
508pub fn get_amd_device_topology(bytes: &[u8]) -> cl_amd_device_topology {
509    let size = bytes.len();
510    assert_eq!(size, std::mem::size_of::<cl_amd_device_topology>());
511    let mut topology = cl_amd_device_topology::default();
512    unsafe {
513        std::slice::from_raw_parts_mut(std::ptr::addr_of_mut!(topology).cast::<u8>(), size)
514            .copy_from_slice(bytes);
515    }
516    topology
517}
518
519/// Convert a u8 slice (e.g. from `get_device_info`) into a `cl_device_pci_bus_info_khr structure`.
520///
521/// # Panics
522///
523/// `if bytes.len() != size_of::<cl_device_pci_bus_info_khr>`
524#[must_use]
525pub fn get_device_pci_bus_info_khr(bytes: &[u8]) -> cl_device_pci_bus_info_khr {
526    let size = bytes.len();
527    assert_eq!(size, std::mem::size_of::<cl_device_pci_bus_info_khr>());
528    let mut pci_bus_info = cl_device_pci_bus_info_khr::default();
529    unsafe {
530        std::slice::from_raw_parts_mut(std::ptr::addr_of_mut!(pci_bus_info).cast::<u8>(), size)
531            .copy_from_slice(bytes);
532    }
533    pci_bus_info
534}
535
536/// Convert a u8 slice (e.g. from `get_device_info`) into a `cl_device_integer_dot_product_acceleration_properties_khr structure`.
537///
538/// # Panics
539///
540/// if `bytes.len() != size_of::<cl_device_integer_dot_product_acceleration_properties_khr>`
541#[must_use]
542pub fn get_device_integer_dot_product_acceleration_properties_khr(
543    bytes: &[u8],
544) -> cl_device_integer_dot_product_acceleration_properties_khr {
545    let size = bytes.len();
546    assert_eq!(
547        size,
548        std::mem::size_of::<cl_device_integer_dot_product_acceleration_properties_khr>()
549    );
550    let mut value = cl_device_integer_dot_product_acceleration_properties_khr::default();
551    unsafe {
552        std::slice::from_raw_parts_mut(std::ptr::addr_of_mut!(value).cast::<u8>(), size)
553            .copy_from_slice(bytes);
554    }
555    value
556}
557
558// cl_device_partition_property:
559pub const CL_DEVICE_PARTITION_EQUALLY: cl_device_partition_property = 0x1086;
560pub const CL_DEVICE_PARTITION_BY_COUNTS: cl_device_partition_property = 0x1087;
561pub const CL_DEVICE_PARTITION_BY_COUNTS_LIST_END: cl_device_partition_property = 0x0;
562pub const CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN: cl_device_partition_property = 0x1088;
563
564// helper function for create_sub_devices
565#[cfg(any(feature = "CL_VERSION_1_2", feature = "dynamic"))]
566#[inline]
567fn count_sub_devices(
568    in_device: cl_device_id,
569    properties: &[cl_device_partition_property],
570) -> Result<cl_uint, cl_int> {
571    let mut count: cl_uint = 0;
572    let status: cl_int = unsafe {
573        cl_call!(clCreateSubDevices(
574            in_device,
575            properties.as_ptr(),
576            0,
577            ptr::null_mut(),
578            &raw mut count,
579        ))
580    };
581    if CL_SUCCESS == status {
582        Ok(count)
583    } else {
584        Err(status)
585    }
586}
587
588/// Create sub-devices by partitioning an `OpenCL` device.
589/// Calls `clCreateSubDevices` to get the partitioned sub-devices.
590///
591/// * `in_device` - the `cl_device_id` of the `OpenCL` device to partition.
592/// * `properties` - the slice of `cl_device_partition_property`, see
593///   [Subdevice Partition](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#subdevice-partition-table).
594///
595/// returns a Result containing a vector of available sub-device ids
596/// or the error code from the `OpenCL` C API function.
597#[cfg(any(feature = "CL_VERSION_1_2", feature = "dynamic"))]
598#[inline]
599#[allow(clippy::cast_possible_truncation)]
600pub fn create_sub_devices(
601    in_device: cl_device_id,
602    properties: &[cl_device_partition_property],
603) -> Result<Vec<cl_device_id>, cl_int> {
604    // get the number of partitions
605    let num_devices: cl_uint = count_sub_devices(in_device, properties)?;
606
607    // partition in_device
608    let mut ids: Vec<cl_device_id> = Vec::with_capacity(num_devices as size_t);
609    let status: cl_int = unsafe {
610        ids.set_len(num_devices as size_t);
611        cl_call!(clCreateSubDevices(
612            in_device,
613            properties.as_ptr(),
614            num_devices * mem::size_of::<cl_device_id>() as cl_uint,
615            ids.as_mut_ptr(),
616            ptr::null_mut(),
617        ))
618    };
619
620    if CL_SUCCESS == status {
621        Ok(ids)
622    } else {
623        Err(status)
624    }
625}
626
627/// Retain an `OpenCL` device.
628/// Calls `clRetainDevice` to increment the device reference count
629/// if device is a valid sub-device created by a call to clCreateSubDevices.
630///
631/// * `device` - the `cl_device_id` of the `OpenCL` device.
632///
633/// returns an empty Result or the error code from the `OpenCL` C API function.
634///
635/// # Safety
636///
637/// This function is unsafe because it changes the `OpenCL` object reference count.
638#[cfg(any(feature = "CL_VERSION_1_2", feature = "dynamic"))]
639#[inline]
640pub unsafe fn retain_device(device: cl_device_id) -> Result<(), cl_int> {
641    let status: cl_int = cl_call!(clRetainDevice(device));
642    if CL_SUCCESS == status {
643        Ok(())
644    } else {
645        Err(status)
646    }
647}
648
649/// Release an `OpenCL` device.
650/// Calls `clReleaseDevice` to decrement the device reference count
651/// if device is a valid sub-device created by a call to clCreateSubDevices.
652///
653/// * `device` - the `cl_device_id` of the `OpenCL` device.
654///
655/// returns an empty Result or the error code from the `OpenCL` C API function.
656///
657/// # Safety
658///
659/// This function is unsafe because it changes the `OpenCL` object reference count.
660#[cfg(any(feature = "CL_VERSION_1_2", feature = "dynamic"))]
661#[inline]
662pub unsafe fn release_device(device: cl_device_id) -> Result<(), cl_int> {
663    let status: cl_int = cl_call!(clReleaseDevice(device));
664    if CL_SUCCESS == status {
665        Ok(())
666    } else {
667        Err(status)
668    }
669}
670
671/// Replace the default command queue on an `OpenCL` device.
672/// Calls `clSetDefaultDeviceCommandQueue` to replace the default command queue
673/// `CL_VERSION_2_1`
674///
675/// * `context` - the `OpenCL` context used to create `command_queue`.
676/// * `device` - a valid `OpenCL` device associated with context.
677/// * `command_queue` - a command queue object which replaces the default
678///   device command queue.
679///
680/// returns an empty Result or the error code from the `OpenCL` C API function.
681#[cfg(any(feature = "CL_VERSION_2_1", feature = "dynamic"))]
682#[inline]
683pub fn set_default_device_command_queue(
684    context: cl_context,
685    device: cl_device_id,
686    command_queue: cl_command_queue,
687) -> Result<(), cl_int> {
688    let status: cl_int = unsafe {
689        cl_call!(clSetDefaultDeviceCommandQueue(
690            context,
691            device,
692            command_queue
693        ))
694    };
695    if CL_SUCCESS == status {
696        Ok(())
697    } else {
698        Err(status)
699    }
700}
701
702/// Query device and host timestamps.
703/// Calls `clGetDeviceAndHostTimer`
704/// `CL_VERSION_2_1`
705///
706/// * `device` - a valid `OpenCL` device.
707///
708/// returns a Result containing `device_timestamp` and `host_timestamp` in a 2D array
709/// or the error code from the `OpenCL` C API function.
710#[cfg(any(feature = "CL_VERSION_2_1", feature = "dynamic"))]
711#[inline]
712pub fn get_device_and_host_timer(device: cl_device_id) -> Result<[cl_ulong; 2], cl_int> {
713    let mut device_timestamp: cl_ulong = 0;
714    let mut host_timestamp: cl_ulong = 0;
715    let status: cl_int = unsafe {
716        cl_call!(clGetDeviceAndHostTimer(
717            device,
718            &raw mut device_timestamp,
719            &raw mut host_timestamp
720        ))
721    };
722    if CL_SUCCESS == status {
723        Ok([device_timestamp, host_timestamp])
724    } else {
725        Err(status)
726    }
727}
728
729/// The current value of the host clock as seen by device.
730/// Calls `clGetHostTimer`
731/// `CL_VERSION_2_1`
732///
733/// * `device` - a valid `OpenCL` `device`.
734///
735/// returns a Result containing `host_timestamp`
736/// or the error code from the `OpenCL` C API function.
737#[cfg(any(feature = "CL_VERSION_2_1", feature = "dynamic"))]
738#[inline]
739pub fn get_host_timer(device: cl_device_id) -> Result<cl_ulong, cl_int> {
740    let mut host_timestamp: cl_ulong = 0;
741    let status: cl_int = unsafe { cl_call!(clGetHostTimer(device, &raw mut host_timestamp)) };
742    if CL_SUCCESS == status {
743        Ok(host_timestamp)
744    } else {
745        Err(status)
746    }
747}
748// #endif
749
750/// Device Vendor Ids.
751///
752/// The `PCie` IDs of some `OpenCL` device vendors as returned by `get_device_info`,
753/// i.e.: `clGetDeviceInfo` - `CL_DEVICE_VENDOR_ID`
754/// They were obtained from the `PCIe` ID Repository: <https://pci-ids.ucw.cz/>
755pub const AMD_DEVICE_VENDOR_ID: cl_uint = 0x1002;
756pub const IBM_DEVICE_VENDOR_ID: cl_uint = 0x1014;
757pub const APPLE_DEVICE_VENDOR_ID: cl_uint = 0x106b;
758pub const NVIDIA_DEVICE_VENDOR_ID: cl_uint = 0x10de;
759pub const XILINX_DEVICE_VENDOR_ID: cl_uint = 0x10ee;
760pub const BROADCOM_DEVICE_VENDOR_ID: cl_uint = 0x1166;
761pub const ALTERA_DEVICE_VENDOR_ID: cl_uint = 0x1172;
762pub const ARM_DEVICE_VENDOR_ID: cl_uint = 0x13b5;
763pub const VIA_TECHNOLOGIES_DEVICE_VENDOR_ID: cl_uint = 0x1412;
764pub const TEXAS_INSTRUMENTS_DEVICE_VENDOR_ID: cl_uint = 0x104c;
765pub const QUALCOMM_DEVICE_VENDOR_ID: cl_uint = 0x168c;
766pub const INTEL_DEVICE_VENDOR_ID: cl_uint = 0x8086;
767// Integrated AMD cards on Apple don't have the usual AMD ID
768pub const AMD_ON_APPLE_DEVICE_VENDOR_ID: cl_uint = 0x0102_1d00;
769
770/// A text representation of an `OpenCL` vendor id.
771#[must_use]
772pub const fn vendor_id_text(vendor_id: cl_uint) -> &'static str {
773    match vendor_id {
774        AMD_DEVICE_VENDOR_ID => "AMD",
775        IBM_DEVICE_VENDOR_ID => "IBM",
776        NVIDIA_DEVICE_VENDOR_ID => "NVIDIA",
777        XILINX_DEVICE_VENDOR_ID => "XILINX",
778        BROADCOM_DEVICE_VENDOR_ID => "BROADCOM",
779        ALTERA_DEVICE_VENDOR_ID => "ALTERA",
780        ARM_DEVICE_VENDOR_ID => "ARM",
781        VIA_TECHNOLOGIES_DEVICE_VENDOR_ID => "VIA_TECHNOLOGIES",
782        TEXAS_INSTRUMENTS_DEVICE_VENDOR_ID => "TEXAS_INSTRUMENTS",
783        QUALCOMM_DEVICE_VENDOR_ID => "QUALCOMM",
784        INTEL_DEVICE_VENDOR_ID => "INTEL",
785        AMD_ON_APPLE_DEVICE_VENDOR_ID => "AMD_ON_APPLE",
786
787        _ => "UNKNOWN_VENDOR",
788    }
789}
790
791/// A text representation of an `OpenCL` device type, see:
792/// [Device Types](https://www.khronos.org/registry/OpenCL/specs/3.0-unified/html/OpenCL_API.html#device-types-table).
793#[must_use]
794pub const fn device_type_text(dev_type: cl_device_type) -> &'static str {
795    match dev_type {
796        CL_DEVICE_TYPE_DEFAULT => "CL_DEVICE_TYPE_DEFAULT",
797        CL_DEVICE_TYPE_CPU => "CL_DEVICE_TYPE_CPU",
798        CL_DEVICE_TYPE_GPU => "CL_DEVICE_TYPE_GPU",
799        CL_DEVICE_TYPE_ACCELERATOR => "CL_DEVICE_TYPE_ACCELERATOR",
800        CL_DEVICE_TYPE_CUSTOM => "CL_DEVICE_TYPE_CUSTOM",
801        CL_DEVICE_TYPE_ALL => "CL_DEVICE_TYPE_ALL",
802
803        _ => "COMBINED_DEVICE_TYPE",
804    }
805}
806
807#[cfg(test)]
808mod tests {
809    use super::*;
810    use crate::error_codes::ClError;
811    use crate::platform::{CL_PLATFORM_VERSION, get_platform_ids, get_platform_info};
812
813    #[test]
814    fn test_get_platform_devices() {
815        let platform_ids = get_platform_ids().unwrap();
816        assert!(0 < platform_ids.len());
817
818        let device_ids = get_device_ids(platform_ids[0], CL_DEVICE_TYPE_ALL).unwrap();
819        println!("Platform[0]->number of devices: {}", device_ids.len());
820        assert!(0 < device_ids.len());
821    }
822
823    #[test]
824    fn test_get_device_info() {
825        let platform_ids = get_platform_ids().unwrap();
826
827        // Choose the first platform
828        let platform_id = platform_ids[0];
829
830        let device_ids = get_device_ids(platform_id, CL_DEVICE_TYPE_GPU).unwrap();
831        println!("CL_DEVICE_TYPE_GPU count: {}", device_ids.len());
832        assert!(0 < device_ids.len());
833
834        let device_id = device_ids[0];
835
836        let value = get_device_info(device_id, CL_DEVICE_TYPE).unwrap();
837        let value: cl_ulong = value.into();
838        println!("CL_DEVICE_TYPE: {}", value);
839        println!("Device type is: {}", device_type_text(value));
840        assert!(0 < value);
841        let value = get_device_info(device_id, CL_DEVICE_VENDOR_ID).unwrap();
842        let value: cl_uint = value.into();
843        println!("CL_DEVICE_VENDOR_ID: {:X}", value);
844        println!("Device vendor is: {}", vendor_id_text(value));
845        assert!(0 < value);
846
847        let value = get_device_info(device_id, CL_DEVICE_VERSION).unwrap();
848        let value: String = value.into();
849        println!("CL_DEVICE_VERSION: {}", value);
850        assert!(!value.is_empty());
851
852        let opencl_2: &str = "OpenCL 2";
853        let is_opencl_2: bool = value.contains(opencl_2);
854
855        let opencl_2_1: &str = "OpenCL 2.1";
856        let is_opencl_2_1: bool = value.contains(opencl_2_1);
857
858        let value = get_device_info(device_id, CL_DEVICE_MAX_COMPUTE_UNITS).unwrap();
859        let value = cl_uint::from(value);
860        println!("CL_DEVICE_MAX_COMPUTE_UNITS: {}", value);
861        assert!(0 < value);
862
863        let value = get_device_info(device_id, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS).unwrap();
864        let value = cl_uint::from(value);
865        println!("CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS: {}", value);
866        assert!(0 < value);
867
868        let value = get_device_info(device_id, CL_DEVICE_MAX_WORK_GROUP_SIZE).unwrap();
869        let value: size_t = From::from(value);
870        println!("CL_DEVICE_MAX_WORK_GROUP_SIZE: {}", value);
871        assert!(0 < value);
872
873        let value = get_device_info(device_id, CL_DEVICE_MAX_WORK_ITEM_SIZES).unwrap();
874        let value = Vec::<size_t>::from(value);
875        println!("CL_DEVICE_MAX_WORK_ITEM_SIZES len: {:?}", value.len());
876        println!("CL_DEVICE_MAX_WORK_ITEM_SIZES: {:?}", value);
877        assert!(0 < value.len());
878
879        let value = get_device_info(device_id, CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR).unwrap();
880        let value = cl_uint::from(value);
881        println!("CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR: {}", value);
882        assert!(0 < value);
883
884        let value = get_device_info(device_id, CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT).unwrap();
885        let value = cl_uint::from(value);
886        println!("CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT: {}", value);
887        assert!(0 < value);
888
889        let value = get_device_info(device_id, CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT).unwrap();
890        let value = cl_uint::from(value);
891        println!("CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT: {}", value);
892        assert!(0 < value);
893
894        let value = get_device_info(device_id, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG).unwrap();
895        let value = cl_uint::from(value);
896        println!("CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG: {}", value);
897        assert!(0 < value);
898
899        let value = get_device_info(device_id, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT).unwrap();
900        let value = cl_uint::from(value);
901        assert!(0 < value);
902
903        let value = get_device_info(device_id, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE).unwrap();
904        let value = cl_uint::from(value);
905        println!("CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE: {}", value);
906        assert!(0 < value);
907
908        let value = get_device_info(device_id, CL_DEVICE_MAX_CLOCK_FREQUENCY).unwrap();
909        let value = cl_uint::from(value);
910        println!("CL_DEVICE_MAX_CLOCK_FREQUENCY: {}", value);
911        assert!(0 < value);
912
913        let value = get_device_info(device_id, CL_DEVICE_ADDRESS_BITS).unwrap();
914        let value = cl_uint::from(value);
915        println!("CL_DEVICE_ADDRESS_BITS: {}", value);
916        assert!(0 < value);
917
918        let value = get_device_info(device_id, CL_DEVICE_MAX_READ_IMAGE_ARGS).unwrap();
919        let value = cl_uint::from(value);
920        println!("CL_DEVICE_MAX_READ_IMAGE_ARGS: {}", value);
921        assert!(0 < value);
922
923        let value = get_device_info(device_id, CL_DEVICE_MAX_WRITE_IMAGE_ARGS).unwrap();
924        let value = cl_uint::from(value);
925        println!("CL_DEVICE_MAX_WRITE_IMAGE_ARGS: {}", value);
926        assert!(0 < value);
927
928        let value = get_device_info(device_id, CL_DEVICE_MAX_MEM_ALLOC_SIZE).unwrap();
929        let value = cl_ulong::from(value);
930        println!("CL_DEVICE_MAX_MEM_ALLOC_SIZE: {}", value);
931        assert!(0 < value);
932
933        let value = get_device_info(device_id, CL_DEVICE_IMAGE2D_MAX_WIDTH).unwrap();
934        let value = size_t::from(value);
935        println!("CL_DEVICE_IMAGE2D_MAX_WIDTH: {}", value);
936        assert!(0 < value);
937
938        let value = get_device_info(device_id, CL_DEVICE_IMAGE2D_MAX_HEIGHT).unwrap();
939        let value = size_t::from(value);
940        println!("CL_DEVICE_IMAGE2D_MAX_HEIGHT: {}", value);
941        assert!(0 < value);
942
943        let value = get_device_info(device_id, CL_DEVICE_IMAGE3D_MAX_WIDTH).unwrap();
944        let value = size_t::from(value);
945        println!("CL_DEVICE_IMAGE3D_MAX_WIDTH: {}", value);
946        assert!(0 < value);
947
948        let value = get_device_info(device_id, CL_DEVICE_IMAGE3D_MAX_HEIGHT).unwrap();
949        let value = size_t::from(value);
950        println!("CL_DEVICE_IMAGE3D_MAX_HEIGHT: {}", value);
951        assert!(0 < value);
952
953        let value = get_device_info(device_id, CL_DEVICE_IMAGE3D_MAX_DEPTH).unwrap();
954        let value = size_t::from(value);
955        println!("CL_DEVICE_IMAGE3D_MAX_DEPTH: {}", value);
956        assert!(0 < value);
957
958        let value = get_device_info(device_id, CL_DEVICE_IMAGE_SUPPORT).unwrap();
959        let value = cl_uint::from(value);
960        println!("CL_DEVICE_IMAGE_SUPPORT: {}", value);
961        assert!(0 < value);
962
963        let value = get_device_info(device_id, CL_DEVICE_MAX_PARAMETER_SIZE).unwrap();
964        let value = size_t::from(value);
965        println!("CL_DEVICE_MAX_PARAMETER_SIZE: {}", value);
966        assert!(0 < value);
967
968        let value = get_device_info(device_id, CL_DEVICE_MAX_SAMPLERS).unwrap();
969        let value = cl_uint::from(value);
970        println!("CL_DEVICE_MAX_SAMPLERS: {}", value);
971        assert!(0 < value);
972
973        let value = get_device_info(device_id, CL_DEVICE_MEM_BASE_ADDR_ALIGN).unwrap();
974        let value = cl_uint::from(value);
975        println!("CL_DEVICE_MEM_BASE_ADDR_ALIGN: {}", value);
976        assert!(0 < value);
977
978        let value = get_device_info(device_id, CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE).unwrap();
979        let value = cl_uint::from(value);
980        println!("CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE: {}", value);
981        assert!(0 < value);
982
983        let value = get_device_info(device_id, CL_DEVICE_SINGLE_FP_CONFIG).unwrap();
984        let value = cl_ulong::from(value);
985        println!("CL_DEVICE_SINGLE_FP_CONFIG: {}", value);
986        assert!(0 < value);
987
988        let value = get_device_info(device_id, CL_DEVICE_GLOBAL_MEM_CACHE_TYPE).unwrap();
989        let value = cl_uint::from(value);
990        println!("CL_DEVICE_GLOBAL_MEM_CACHE_TYPE: {}", value);
991        assert!(0 < value);
992
993        let value = get_device_info(device_id, CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE).unwrap();
994        let value = cl_uint::from(value);
995        println!("CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE: {}", value);
996        assert!(0 < value);
997
998        let value = get_device_info(device_id, CL_DEVICE_GLOBAL_MEM_CACHE_SIZE).unwrap();
999        let value = cl_ulong::from(value);
1000        println!("CL_DEVICE_GLOBAL_MEM_CACHE_SIZE: {}", value);
1001        assert!(0 < value);
1002
1003        let value = get_device_info(device_id, CL_DEVICE_GLOBAL_MEM_SIZE).unwrap();
1004        let value = cl_ulong::from(value);
1005        println!("CL_DEVICE_GLOBAL_MEM_SIZE: {}", value);
1006        assert!(0 < value);
1007
1008        let value = get_device_info(device_id, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE).unwrap();
1009        let value = cl_ulong::from(value);
1010        println!("CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE: {}", value);
1011        assert!(0 < value);
1012
1013        let value = get_device_info(device_id, CL_DEVICE_MAX_CONSTANT_ARGS).unwrap();
1014        let value = cl_uint::from(value);
1015        println!("CL_DEVICE_MAX_CONSTANT_ARGS: {}", value);
1016        assert!(0 < value);
1017
1018        let value = get_device_info(device_id, CL_DEVICE_LOCAL_MEM_TYPE).unwrap();
1019        let value = cl_uint::from(value);
1020        println!("CL_DEVICE_LOCAL_MEM_TYPE: {}", value);
1021        assert!(0 < value);
1022
1023        let value = get_device_info(device_id, CL_DEVICE_LOCAL_MEM_SIZE).unwrap();
1024        let value = cl_ulong::from(value);
1025        println!("CL_DEVICE_LOCAL_MEM_SIZE: {}", value);
1026        assert!(0 < value);
1027
1028        let value = get_device_info(device_id, CL_DEVICE_ERROR_CORRECTION_SUPPORT).unwrap();
1029        let value = cl_uint::from(value);
1030        println!("CL_DEVICE_ERROR_CORRECTION_SUPPORT: {}", value);
1031
1032        let value = get_device_info(device_id, CL_DEVICE_PROFILING_TIMER_RESOLUTION).unwrap();
1033        let value = size_t::from(value);
1034        println!("CL_DEVICE_PROFILING_TIMER_RESOLUTION: {}", value);
1035        assert!(0 < value);
1036
1037        let value = get_device_info(device_id, CL_DEVICE_ENDIAN_LITTLE).unwrap();
1038        let value = cl_uint::from(value);
1039        println!("CL_DEVICE_ENDIAN_LITTLE: {}", value);
1040        assert!(0 < value);
1041
1042        let value = get_device_info(device_id, CL_DEVICE_AVAILABLE).unwrap();
1043        let value = cl_uint::from(value);
1044        println!("CL_DEVICE_AVAILABLE: {}", value);
1045        assert!(0 < value);
1046
1047        let value = get_device_info(device_id, CL_DEVICE_COMPILER_AVAILABLE).unwrap();
1048        let value = cl_uint::from(value);
1049        println!("CL_DEVICE_COMPILER_AVAILABLE: {}", value);
1050        assert!(0 < value);
1051
1052        let value = get_device_info(device_id, CL_DEVICE_EXECUTION_CAPABILITIES).unwrap();
1053        let value = cl_ulong::from(value);
1054        println!("CL_DEVICE_EXECUTION_CAPABILITIES: {}", value);
1055        assert!(0 < value);
1056
1057        if is_opencl_2 {
1058            let value = get_device_info(device_id, CL_DEVICE_QUEUE_ON_HOST_PROPERTIES).unwrap();
1059            let value = cl_ulong::from(value);
1060            println!("CL_DEVICE_QUEUE_ON_HOST_PROPERTIES: {}", value);
1061            assert!(0 < value);
1062        }
1063
1064        let value = get_device_info(device_id, CL_DEVICE_NAME).unwrap();
1065        let value = String::from(value);
1066        println!("CL_DEVICE_NAME: {}", value);
1067        assert!(!value.is_empty());
1068
1069        let value = get_device_info(device_id, CL_DEVICE_VENDOR).unwrap();
1070        let value = String::from(value);
1071        println!("CL_DEVICE_VENDOR: {}", value);
1072        assert!(!value.is_empty());
1073
1074        let value = get_device_info(device_id, CL_DRIVER_VERSION).unwrap();
1075        let value = String::from(value);
1076        println!("CL_DRIVER_VERSION: {}", value);
1077        assert!(!value.is_empty());
1078
1079        let value = get_device_info(device_id, CL_DEVICE_PROFILE).unwrap();
1080        let value = String::from(value);
1081        println!("CL_DEVICE_PROFILE: {}", value);
1082        assert!(!value.is_empty());
1083
1084        let value = get_device_info(device_id, CL_DEVICE_EXTENSIONS).unwrap();
1085        let value = String::from(value);
1086        println!("CL_DEVICE_EXTENSIONS: {}", value);
1087        assert!(!value.is_empty());
1088
1089        let value = get_device_info(device_id, CL_DEVICE_PLATFORM).unwrap();
1090        let value = intptr_t::from(value);
1091        println!("CL_DEVICE_PLATFORM: {}", value);
1092        assert!(0 < value);
1093
1094        // Device may not support double fp precision
1095        match get_device_info(device_id, CL_DEVICE_DOUBLE_FP_CONFIG) {
1096            Ok(value) => {
1097                let value = cl_ulong::from(value);
1098                println!("CL_DEVICE_DOUBLE_FP_CONFIG: {}", value)
1099            }
1100            Err(e) => println!("OpenCL error, CL_DEVICE_DOUBLE_FP_CONFIG: {}", ClError(e)),
1101        };
1102
1103        // Device may not support half fp precision
1104        match get_device_info(device_id, CL_DEVICE_HALF_FP_CONFIG) {
1105            Ok(value) => {
1106                let value = cl_ulong::from(value);
1107                println!("CL_DEVICE_HALF_FP_CONFIG: {}", value)
1108            }
1109            Err(e) => println!("OpenCL error, CL_DEVICE_HALF_FP_CONFIG: {}", ClError(e)),
1110        };
1111
1112        let value = get_device_info(device_id, CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF).unwrap();
1113        let value = cl_uint::from(value);
1114        println!("CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF: {}", value);
1115
1116        let value = get_device_info(device_id, CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR).unwrap();
1117        let value = cl_uint::from(value);
1118        println!("CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR: {}", value);
1119        assert!(0 < value);
1120
1121        let value = get_device_info(device_id, CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT).unwrap();
1122        let value = cl_uint::from(value);
1123        println!("CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT: {}", value);
1124        assert!(0 < value);
1125
1126        let value = get_device_info(device_id, CL_DEVICE_NATIVE_VECTOR_WIDTH_INT).unwrap();
1127        let value = cl_uint::from(value);
1128        println!("CL_DEVICE_NATIVE_VECTOR_WIDTH_INT: {}", value);
1129        assert!(0 < value);
1130
1131        let value = get_device_info(device_id, CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG).unwrap();
1132        let value = cl_uint::from(value);
1133        println!("CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG: {}", value);
1134        assert!(0 < value);
1135
1136        let value = get_device_info(device_id, CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT).unwrap();
1137        let value = cl_uint::from(value);
1138        println!("CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT: {}", value);
1139        assert!(0 < value);
1140
1141        let value = get_device_info(device_id, CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE).unwrap();
1142        let value = cl_uint::from(value);
1143        println!("CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE: {}", value);
1144        assert!(0 < value);
1145
1146        let value = get_device_info(device_id, CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF).unwrap();
1147        let value = cl_uint::from(value);
1148        println!("CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF: {}", value);
1149
1150        let value = get_device_info(device_id, CL_DEVICE_OPENCL_C_VERSION).unwrap();
1151        let value = String::from(value);
1152        println!("CL_DEVICE_OPENCL_C_VERSION: {}", value);
1153        assert!(!value.is_empty());
1154
1155        let value = get_device_info(device_id, CL_DEVICE_LINKER_AVAILABLE).unwrap();
1156        let value = cl_uint::from(value);
1157        println!("CL_DEVICE_LINKER_AVAILABLE: {}", value);
1158        assert!(0 < value);
1159
1160        let value = get_device_info(device_id, CL_DEVICE_BUILT_IN_KERNELS).unwrap();
1161        let value = String::from(value);
1162        println!("CL_DEVICE_BUILT_IN_KERNELS: {}", value);
1163
1164        let value = get_device_info(device_id, CL_DEVICE_IMAGE_MAX_BUFFER_SIZE).unwrap();
1165        let value = size_t::from(value);
1166        println!("CL_DEVICE_IMAGE_MAX_BUFFER_SIZE: {}", value);
1167        assert!(0 < value);
1168
1169        let value = get_device_info(device_id, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE).unwrap();
1170        let value = size_t::from(value);
1171        println!("CL_DEVICE_IMAGE_MAX_ARRAY_SIZE: {}", value);
1172        assert!(0 < value);
1173
1174        let value = get_device_info(device_id, CL_DEVICE_PARENT_DEVICE).unwrap();
1175        let value = intptr_t::from(value);
1176        println!("CL_DEVICE_PARENT_DEVICE: {}", value);
1177        assert!(0 == value);
1178
1179        let value = get_device_info(device_id, CL_DEVICE_PARTITION_MAX_SUB_DEVICES).unwrap();
1180        let value = cl_uint::from(value);
1181        println!("CL_DEVICE_PARTITION_MAX_SUB_DEVICES: {}", value);
1182
1183        let value = get_device_info(device_id, CL_DEVICE_PARTITION_PROPERTIES).unwrap();
1184        let value = Vec::<intptr_t>::from(value);
1185        println!("CL_DEVICE_PARTITION_PROPERTIES: {}", value.len());
1186        println!("CL_DEVICE_PARTITION_PROPERTIES: {:?}", value);
1187        assert!(0 < value.len());
1188
1189        let value = get_device_info(device_id, CL_DEVICE_PARTITION_AFFINITY_DOMAIN).unwrap();
1190        let value = Vec::<cl_ulong>::from(value);
1191        println!("CL_DEVICE_PARTITION_AFFINITY_DOMAIN: {}", value.len());
1192        println!("CL_DEVICE_PARTITION_AFFINITY_DOMAIN: {:?}", value);
1193        assert!(0 < value.len());
1194
1195        let value = get_device_info(device_id, CL_DEVICE_PARTITION_TYPE).unwrap();
1196        let value = Vec::<intptr_t>::from(value);
1197        println!("CL_DEVICE_PARTITION_TYPE: {}", value.len());
1198        println!("CL_DEVICE_PARTITION_TYPE: {:?}", value);
1199
1200        let value = get_device_info(device_id, CL_DEVICE_REFERENCE_COUNT).unwrap();
1201        let value = cl_uint::from(value);
1202        println!("CL_DEVICE_REFERENCE_COUNT: {}", value);
1203        assert!(0 < value);
1204
1205        let value = get_device_info(device_id, CL_DEVICE_PREFERRED_INTEROP_USER_SYNC).unwrap();
1206        let value = cl_uint::from(value);
1207        println!("CL_DEVICE_PREFERRED_INTEROP_USER_SYNC: {}", value);
1208
1209        let value = get_device_info(device_id, CL_DEVICE_PRINTF_BUFFER_SIZE).unwrap();
1210        let value = size_t::from(value);
1211        println!("CL_DEVICE_PRINTF_BUFFER_SIZE: {}", value);
1212        assert!(0 < value);
1213
1214        // cl_khr_device_uuid extension
1215        match get_device_info(device_id, CL_DEVICE_UUID_KHR) {
1216            Ok(value) => {
1217                println!("CL_DEVICE_UUID_KHR: {}", value);
1218            }
1219            Err(e) => println!("OpenCL error, CL_DEVICE_UUID_KHR: {}", ClError(e)),
1220        };
1221
1222        // cl_khr_device_uuid extension
1223        match get_device_info(device_id, CL_DRIVER_UUID_KHR) {
1224            Ok(value) => {
1225                println!("CL_DRIVER_UUID_KHR: {}", value);
1226            }
1227            Err(e) => println!("OpenCL error, CL_DRIVER_UUID_KHR: {}", ClError(e)),
1228        };
1229
1230        // cl_khr_device_uuid extension
1231        match get_device_info(device_id, CL_DEVICE_LUID_VALID_KHR) {
1232            Ok(value) => {
1233                let value = cl_uint::from(value);
1234                println!("CL_DEVICE_LUID_VALID_KHR: {:?}", value);
1235            }
1236            Err(e) => println!("OpenCL error, CL_DEVICE_LUID_VALID_KHR: {}", ClError(e)),
1237        };
1238
1239        // cl_khr_device_uuid extension
1240        match get_device_info(device_id, CL_DEVICE_LUID_KHR) {
1241            Ok(value) => {
1242                println!("CL_DEVICE_LUID_KHR: {}", value);
1243            }
1244            Err(e) => println!("OpenCL error, CL_DEVICE_LUID_KHR: {}", ClError(e)),
1245        };
1246
1247        // cl_khr_device_uuid extension
1248        match get_device_info(device_id, CL_DEVICE_NODE_MASK_KHR) {
1249            Ok(value) => {
1250                let value = cl_uint::from(value);
1251                println!("CL_DEVICE_NODE_MASK_KHR: {:?}", value);
1252            }
1253            Err(e) => println!("OpenCL error, CL_DEVICE_NODE_MASK_KHR: {}", ClError(e)),
1254        };
1255
1256        // Nvidia specific extension
1257        match get_device_info(device_id, CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV) {
1258            Ok(value) => {
1259                let value = cl_uint::from(value);
1260                println!("CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV: {}", value)
1261            }
1262            Err(e) => println!(
1263                "OpenCL error, CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV: {}",
1264                ClError(e)
1265            ),
1266        };
1267
1268        // Nvidia specific extension
1269        match get_device_info(device_id, CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV) {
1270            Ok(value) => {
1271                let value = cl_uint::from(value);
1272                println!("CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV: {}", value)
1273            }
1274            Err(e) => println!(
1275                "OpenCL error, CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV: {}",
1276                ClError(e)
1277            ),
1278        };
1279
1280        // Nvidia specific extension
1281        match get_device_info(device_id, CL_DEVICE_REGISTERS_PER_BLOCK_NV) {
1282            Ok(value) => {
1283                let value = cl_uint::from(value);
1284                println!("CL_DEVICE_REGISTERS_PER_BLOCK_NV: {}", value)
1285            }
1286            Err(e) => println!(
1287                "OpenCL error, CL_DEVICE_REGISTERS_PER_BLOCK_NV: {}",
1288                ClError(e)
1289            ),
1290        };
1291
1292        // Nvidia specific extension
1293        match get_device_info(device_id, CL_DEVICE_WARP_SIZE_NV) {
1294            Ok(value) => {
1295                let value = cl_uint::from(value);
1296                println!("CL_DEVICE_WARP_SIZE_NV: {}", value)
1297            }
1298            Err(e) => println!("OpenCL error, CL_DEVICE_WARP_SIZE_NV: {}", ClError(e)),
1299        };
1300
1301        // Nvidia specific extension
1302        match get_device_info(device_id, CL_DEVICE_GPU_OVERLAP_NV) {
1303            Ok(value) => {
1304                let value = cl_uint::from(value);
1305                println!("CL_DEVICE_GPU_OVERLAP_NV: {}", value)
1306            }
1307            Err(e) => println!("OpenCL error, CL_DEVICE_GPU_OVERLAP_NV: {}", ClError(e)),
1308        };
1309
1310        // Nvidia specific extension
1311        match get_device_info(device_id, CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV) {
1312            Ok(value) => {
1313                let value = cl_uint::from(value);
1314                println!("CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV: {}", value)
1315            }
1316            Err(e) => println!(
1317                "OpenCL error, CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV: {}",
1318                ClError(e)
1319            ),
1320        };
1321
1322        // Nvidia specific extension
1323        match get_device_info(device_id, CL_DEVICE_INTEGRATED_MEMORY_NV) {
1324            Ok(value) => {
1325                let value = cl_uint::from(value);
1326                println!("CL_DEVICE_INTEGRATED_MEMORY_NV: {}", value)
1327            }
1328            Err(e) => println!(
1329                "OpenCL error, CL_DEVICE_INTEGRATED_MEMORY_NV: {}",
1330                ClError(e)
1331            ),
1332        };
1333
1334        // Nvidia specific extension, undocumented
1335        match get_device_info(device_id, CL_DEVICE_PCI_BUS_ID_NV) {
1336            Ok(value) => {
1337                let value = cl_uint::from(value);
1338                println!("CL_DEVICE_PCI_BUS_ID_NV: {}", value)
1339            }
1340            Err(e) => println!("OpenCL error, CL_DEVICE_PCI_BUS_ID_NV: {}", ClError(e)),
1341        };
1342
1343        // Nvidia specific extension, undocumented
1344        match get_device_info(device_id, CL_DEVICE_PCI_SLOT_ID_NV) {
1345            Ok(value) => {
1346                let value = cl_uint::from(value);
1347                println!("CL_DEVICE_PCI_SLOT_ID_NV: {}", value)
1348            }
1349            Err(e) => println!("OpenCL error, CL_DEVICE_PCI_SLOT_ID_NV: {}", ClError(e)),
1350        };
1351
1352        match get_device_info(device_id, CL_DEVICE_PROFILING_TIMER_OFFSET_AMD) {
1353            Ok(value) => {
1354                let value = size_t::from(value);
1355                println!("CL_DEVICE_PROFILING_TIMER_OFFSET_AMD: {}", value)
1356            }
1357            Err(e) => println!(
1358                "OpenCL error, CL_DEVICE_PROFILING_TIMER_OFFSET_AMD: {}",
1359                ClError(e)
1360            ),
1361        };
1362
1363        match get_device_info(device_id, CL_DEVICE_TOPOLOGY_AMD) {
1364            Ok(value) => {
1365                let value = Vec::<u8>::from(value);
1366                println!("CL_DEVICE_TOPOLOGY_AMD: {:?}", value);
1367
1368                let topology = get_amd_device_topology(&value);
1369                println!("CL_DEVICE_TOPOLOGY_AMD bus: {}", topology.bus);
1370                println!("CL_DEVICE_TOPOLOGY_AMD device: {}", topology.device);
1371                println!("CL_DEVICE_TOPOLOGY_AMD function: {}", topology.function);
1372            }
1373            Err(e) => println!("OpenCL error, CL_DEVICE_TOPOLOGY_AMD: {}", ClError(e)),
1374        };
1375
1376        match get_device_info(device_id, CL_DEVICE_BOARD_NAME_AMD) {
1377            Ok(value) => {
1378                let value = String::from(value);
1379                println!("CL_DEVICE_BOARD_NAME_AMD: {}", value)
1380            }
1381            Err(e) => println!("OpenCL error, CL_DEVICE_BOARD_NAME_AMD: {}", ClError(e)),
1382        };
1383
1384        match get_device_info(device_id, CL_DEVICE_GLOBAL_FREE_MEMORY_AMD) {
1385            Ok(value) => {
1386                let value = size_t::from(value);
1387                println!("CL_DEVICE_GLOBAL_FREE_MEMORY_AMD: {}", value)
1388            }
1389            Err(e) => println!(
1390                "OpenCL error, CL_DEVICE_GLOBAL_FREE_MEMORY_AMD: {}",
1391                ClError(e)
1392            ),
1393        };
1394
1395        match get_device_info(device_id, CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD) {
1396            Ok(value) => {
1397                let value = cl_uint::from(value);
1398                println!("CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD: {}", value)
1399            }
1400            Err(e) => println!(
1401                "OpenCL error, CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD: {}",
1402                ClError(e)
1403            ),
1404        };
1405
1406        match get_device_info(device_id, CL_DEVICE_SIMD_WIDTH_AMD) {
1407            Ok(value) => {
1408                let value = cl_uint::from(value);
1409                println!("CL_DEVICE_SIMD_WIDTH_AMD: {}", value)
1410            }
1411            Err(e) => println!("OpenCL error, CL_DEVICE_SIMD_WIDTH_AMD: {}", ClError(e)),
1412        };
1413
1414        match get_device_info(device_id, CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD) {
1415            Ok(value) => {
1416                let value = cl_uint::from(value);
1417                println!("CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD: {}", value)
1418            }
1419            Err(e) => println!(
1420                "OpenCL error, CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD: {}",
1421                ClError(e)
1422            ),
1423        };
1424
1425        match get_device_info(device_id, CL_DEVICE_WAVEFRONT_WIDTH_AMD) {
1426            Ok(value) => {
1427                let value = cl_uint::from(value);
1428                println!("CL_DEVICE_WAVEFRONT_WIDTH_AMD: {}", value)
1429            }
1430            Err(e) => println!(
1431                "OpenCL error, CL_DEVICE_WAVEFRONT_WIDTH_AMD: {}",
1432                ClError(e)
1433            ),
1434        };
1435
1436        match get_device_info(device_id, CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD) {
1437            Ok(value) => {
1438                let value = cl_uint::from(value);
1439                println!("CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD: {}", value)
1440            }
1441            Err(e) => println!(
1442                "OpenCL error, CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD: {}",
1443                ClError(e)
1444            ),
1445        };
1446
1447        match get_device_info(device_id, CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD) {
1448            Ok(value) => {
1449                let value = cl_uint::from(value);
1450                println!("CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD: {}", value)
1451            }
1452            Err(e) => println!(
1453                "OpenCL error, CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD: {}",
1454                ClError(e)
1455            ),
1456        };
1457
1458        match get_device_info(device_id, CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD) {
1459            Ok(value) => {
1460                let value = cl_uint::from(value);
1461                println!("CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD: {}", value)
1462            }
1463            Err(e) => println!(
1464                "OpenCL error, CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD: {}",
1465                ClError(e)
1466            ),
1467        };
1468
1469        match get_device_info(device_id, CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD) {
1470            Ok(value) => {
1471                let value = cl_uint::from(value);
1472                println!("CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD: {}", value)
1473            }
1474            Err(e) => println!(
1475                "OpenCL error, CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD: {}",
1476                ClError(e)
1477            ),
1478        };
1479
1480        match get_device_info(device_id, CL_DEVICE_LOCAL_MEM_BANKS_AMD) {
1481            Ok(value) => {
1482                let value = cl_uint::from(value);
1483                println!("CL_DEVICE_LOCAL_MEM_BANKS_AMD: {}", value)
1484            }
1485            Err(e) => println!(
1486                "OpenCL error, CL_DEVICE_LOCAL_MEM_BANKS_AMD: {}",
1487                ClError(e)
1488            ),
1489        };
1490
1491        match get_device_info(device_id, CL_DEVICE_THREAD_TRACE_SUPPORTED_AMD) {
1492            Ok(value) => {
1493                let value = cl_uint::from(value);
1494                println!("CL_DEVICE_THREAD_TRACE_SUPPORTED_AMD: {}", value)
1495            }
1496            Err(e) => println!(
1497                "OpenCL error, CL_DEVICE_THREAD_TRACE_SUPPORTED_AMD: {}",
1498                ClError(e)
1499            ),
1500        };
1501
1502        match get_device_info(device_id, CL_DEVICE_GFXIP_MAJOR_AMD) {
1503            Ok(value) => {
1504                let value = cl_uint::from(value);
1505                println!("CL_DEVICE_GFXIP_MAJOR_AMD: {}", value)
1506            }
1507            Err(e) => println!("OpenCL error, CL_DEVICE_GFXIP_MAJOR_AMD: {}", ClError(e)),
1508        };
1509
1510        match get_device_info(device_id, CL_DEVICE_GFXIP_MINOR_AMD) {
1511            Ok(value) => {
1512                let value = cl_uint::from(value);
1513                println!("CL_DEVICE_GFXIP_MINOR_AMD: {}", value)
1514            }
1515            Err(e) => println!("OpenCL error, CL_DEVICE_GFXIP_MINOR_AMD: {}", ClError(e)),
1516        };
1517
1518        match get_device_info(device_id, CL_DEVICE_AVAILABLE_ASYNC_QUEUES_AMD) {
1519            Ok(value) => {
1520                let value = cl_uint::from(value);
1521                println!("CL_DEVICE_AVAILABLE_ASYNC_QUEUES_AMD: {}", value)
1522            }
1523            Err(e) => println!(
1524                "OpenCL error, CL_DEVICE_AVAILABLE_ASYNC_QUEUES_AMD: {}",
1525                ClError(e)
1526            ),
1527        };
1528
1529        match get_device_info(device_id, CL_DEVICE_PREFERRED_WORK_GROUP_SIZE_AMD) {
1530            Ok(value) => {
1531                let value = size_t::from(value);
1532                println!("CL_DEVICE_PREFERRED_WORK_GROUP_SIZE_AMD: {}", value)
1533            }
1534            Err(e) => println!(
1535                "OpenCL error, CL_DEVICE_PREFERRED_WORK_GROUP_SIZE_AMD: {}",
1536                ClError(e)
1537            ),
1538        };
1539
1540        match get_device_info(device_id, CL_DEVICE_MAX_WORK_GROUP_SIZE_AMD) {
1541            Ok(value) => {
1542                let value = size_t::from(value);
1543                println!("CL_DEVICE_MAX_WORK_GROUP_SIZE_AMD: {}", value)
1544            }
1545            Err(e) => println!(
1546                "OpenCL error, CL_DEVICE_MAX_WORK_GROUP_SIZE_AMD: {}",
1547                ClError(e)
1548            ),
1549        };
1550
1551        match get_device_info(device_id, CL_DEVICE_PREFERRED_CONSTANT_BUFFER_SIZE_AMD) {
1552            Ok(value) => {
1553                let value = size_t::from(value);
1554                println!("CL_DEVICE_PREFERRED_CONSTANT_BUFFER_SIZE_AMD: {}", value)
1555            }
1556            Err(e) => println!(
1557                "OpenCL error, CL_DEVICE_PREFERRED_CONSTANT_BUFFER_SIZE_AMD: {}",
1558                ClError(e)
1559            ),
1560        };
1561
1562        match get_device_info(device_id, CL_DEVICE_PCIE_ID_AMD) {
1563            Ok(value) => {
1564                let value = cl_uint::from(value);
1565                println!("CL_DEVICE_PCIE_ID_AMD: {}", value)
1566            }
1567            Err(e) => println!("OpenCL error, CL_DEVICE_PCIE_ID_AMD: {}", ClError(e)),
1568        };
1569
1570        match get_device_info(device_id, CL_DEVICE_PCI_BUS_INFO_KHR) {
1571            Ok(value) => {
1572                let value = Vec::<u8>::from(value);
1573                println!("CL_DEVICE_PCI_BUS_INFO_KHR: {:?}", value);
1574
1575                let pci_bus_info = get_device_pci_bus_info_khr(&value);
1576                println!(
1577                    "CL_DEVICE_PCI_BUS_INFO_KHR pci_domain: {}",
1578                    pci_bus_info.pci_domain
1579                );
1580                println!(
1581                    "CL_DEVICE_PCI_BUS_INFO_KHR pci_bus: {}",
1582                    pci_bus_info.pci_bus
1583                );
1584                println!(
1585                    "CL_DEVICE_PCI_BUS_INFO_KHR pci_device: {}",
1586                    pci_bus_info.pci_device
1587                );
1588                println!(
1589                    "CL_DEVICE_PCI_BUS_INFO_KHR pci_function: {}",
1590                    pci_bus_info.pci_function
1591                );
1592            }
1593            Err(e) => println!("OpenCL error, CL_DEVICE_PCI_BUS_INFO_KHR: {}", ClError(e)),
1594        };
1595
1596        match get_device_info(device_id, CL_DEVICE_IP_VERSION_INTEL) {
1597            Ok(value) => {
1598                let value = cl_uint::from(value);
1599                println!("CL_DEVICE_IP_VERSION_INTEL: {:?}", value)
1600            }
1601            Err(e) => println!("OpenCL error, CL_DEVICE_IP_VERSION_INTEL: {}", ClError(e)),
1602        };
1603
1604        match get_device_info(device_id, CL_DEVICE_ID_INTEL) {
1605            Ok(value) => {
1606                let value = cl_uint::from(value);
1607                println!("CL_DEVICE_ID_INTEL: {}", value)
1608            }
1609            Err(e) => println!("OpenCL error, CL_DEVICE_ID_INTEL: {}", ClError(e)),
1610        };
1611
1612        match get_device_info(device_id, CL_DEVICE_NUM_SLICES_INTEL) {
1613            Ok(value) => {
1614                let value = cl_uint::from(value);
1615                println!("CL_DEVICE_NUM_SLICES_INTEL: {}", value)
1616            }
1617            Err(e) => println!("OpenCL error, CL_DEVICE_NUM_SLICES_INTEL: {}", ClError(e)),
1618        };
1619
1620        match get_device_info(device_id, CL_DEVICE_NUM_SUB_SLICES_PER_SLICE_INTEL) {
1621            Ok(value) => {
1622                let value = cl_uint::from(value);
1623                println!("CL_DEVICE_NUM_SUB_SLICES_PER_SLICE_INTEL: {}", value)
1624            }
1625            Err(e) => println!(
1626                "OpenCL error, CL_DEVICE_NUM_SUB_SLICES_PER_SLICE_INTEL: {}",
1627                ClError(e)
1628            ),
1629        };
1630
1631        match get_device_info(device_id, CL_DEVICE_NUM_EUS_PER_SUB_SLICE_INTEL) {
1632            Ok(value) => {
1633                let value = cl_uint::from(value);
1634                println!("CL_DEVICE_NUM_EUS_PER_SUB_SLICE_INTEL: {}", value)
1635            }
1636            Err(e) => println!(
1637                "OpenCL error, CL_DEVICE_NUM_EUS_PER_SUB_SLICE_INTEL: {}",
1638                ClError(e)
1639            ),
1640        };
1641
1642        match get_device_info(device_id, CL_DEVICE_NUM_THREADS_PER_EU_INTEL) {
1643            Ok(value) => {
1644                let value = cl_uint::from(value);
1645                println!("CL_DEVICE_NUM_THREADS_PER_EU_INTEL: {}", value)
1646            }
1647            Err(e) => println!(
1648                "OpenCL error, CL_DEVICE_NUM_THREADS_PER_EU_INTEL: {}",
1649                ClError(e)
1650            ),
1651        };
1652
1653        match get_device_info(device_id, CL_DEVICE_FEATURE_CAPABILITIES_INTEL) {
1654            Ok(value) => {
1655                let value = cl_ulong::from(value);
1656                println!("CL_DEVICE_FEATURE_CAPABILITIES_INTEL: {}", value)
1657            }
1658            Err(e) => println!(
1659                "OpenCL error, CL_DEVICE_FEATURE_CAPABILITIES_INTEL: {}",
1660                ClError(e)
1661            ),
1662        };
1663
1664        match get_device_info(device_id, CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR) {
1665            Ok(value) => {
1666                let value: Vec<u32> = value.into();
1667                println!(
1668                    "CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR: {:?}",
1669                    value
1670                )
1671            }
1672            Err(e) => println!(
1673                "OpenCL error, CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR: {}",
1674                ClError(e)
1675            ),
1676        };
1677
1678        match get_device_info(device_id, CL_DEVICE_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR) {
1679            Ok(value) => {
1680                let value: Vec<u32> = value.into();
1681                println!("CL_DEVICE_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR: {:?}", value)
1682            }
1683            Err(e) => println!(
1684                "OpenCL error, CL_DEVICE_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR: {}",
1685                ClError(e)
1686            ),
1687        };
1688
1689        match get_device_info(device_id, CL_DEVICE_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR) {
1690            Ok(value) => {
1691                let value: Vec<u32> = value.into();
1692                println!("CL_DEVICE_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR: {:?}", value)
1693            }
1694            Err(e) => println!(
1695                "OpenCL error, CL_DEVICE_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR: {}",
1696                ClError(e)
1697            ),
1698        };
1699
1700        match get_device_info(device_id, CL_DEVICE_SEMAPHORE_TYPES_KHR) {
1701            Ok(value) => {
1702                let value: Vec<u32> = value.into();
1703                println!("CL_DEVICE_SEMAPHORE_TYPES_KHR: {:?}", value)
1704            }
1705            Err(e) => println!(
1706                "OpenCL error, CL_DEVICE_SEMAPHORE_TYPES_KHR: {}",
1707                ClError(e)
1708            ),
1709        };
1710
1711        match get_device_info(device_id, CL_DEVICE_COMMAND_BUFFER_CAPABILITIES_KHR) {
1712            Ok(value) => {
1713                let value: cl_ulong = value.into();
1714                println!("CL_DEVICE_COMMAND_BUFFER_CAPABILITIES_KHR: {}", value)
1715            }
1716            Err(e) => println!(
1717                "OpenCL error, CL_DEVICE_COMMAND_BUFFER_CAPABILITIES_KHR: {}",
1718                ClError(e)
1719            ),
1720        };
1721
1722        match get_device_info(
1723            device_id,
1724            CL_DEVICE_COMMAND_BUFFER_REQUIRED_QUEUE_PROPERTIES_KHR,
1725        ) {
1726            Ok(value) => {
1727                let value: cl_ulong = value.into();
1728                println!(
1729                    "CL_DEVICE_COMMAND_BUFFER_REQUIRED_QUEUE_PROPERTIES_KHR: {}",
1730                    value
1731                )
1732            }
1733            Err(e) => println!(
1734                "OpenCL error, CL_DEVICE_COMMAND_BUFFER_REQUIRED_QUEUE_PROPERTIES_KHR: {}",
1735                ClError(e)
1736            ),
1737        };
1738
1739        // CL_VERSION_2_0
1740        if is_opencl_2 {
1741            let value = get_device_info(device_id, CL_DEVICE_IMAGE_PITCH_ALIGNMENT).unwrap();
1742            let value = cl_uint::from(value);
1743            println!("CL_DEVICE_IMAGE_PITCH_ALIGNMENT: {}", value);
1744            assert!(0 < value);
1745
1746            let value = get_device_info(device_id, CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT).unwrap();
1747            let value = cl_uint::from(value);
1748            println!("CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT: {}", value);
1749            assert!(0 < value);
1750
1751            let value = get_device_info(device_id, CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS).unwrap();
1752            let value = cl_uint::from(value);
1753            println!("CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS: {}", value);
1754            assert!(0 < value);
1755
1756            let value = get_device_info(device_id, CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE).unwrap();
1757            let value = size_t::from(value);
1758            println!("CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE: {}", value);
1759            assert!(0 < value);
1760
1761            let value = get_device_info(device_id, CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES).unwrap();
1762            let value = Vec::<intptr_t>::from(value);
1763            println!("CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES: {}", value.len());
1764            println!("CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES: {:?}", value);
1765            assert!(0 < value.len());
1766
1767            let value =
1768                get_device_info(device_id, CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE).unwrap();
1769            let value = size_t::from(value);
1770            println!("CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE: {}", value);
1771            assert!(0 < value);
1772
1773            let value = get_device_info(device_id, CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE).unwrap();
1774            let value = size_t::from(value);
1775            println!("CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE: {}", value);
1776            assert!(0 < value);
1777
1778            let value = get_device_info(device_id, CL_DEVICE_MAX_ON_DEVICE_QUEUES).unwrap();
1779            let value = cl_uint::from(value);
1780            println!("CL_DEVICE_MAX_ON_DEVICE_QUEUES: {}", value);
1781            assert!(0 < value);
1782
1783            let value = get_device_info(device_id, CL_DEVICE_MAX_ON_DEVICE_EVENTS).unwrap();
1784            let value = cl_uint::from(value);
1785            println!("CL_DEVICE_MAX_ON_DEVICE_EVENTS: {}", value);
1786            assert!(0 < value);
1787
1788            let value = get_device_info(device_id, CL_DEVICE_SVM_CAPABILITIES).unwrap();
1789            let value = cl_ulong::from(value);
1790            println!("CL_DEVICE_SVM_CAPABILITIES: {}", value);
1791            assert!(0 < value);
1792
1793            let value =
1794                get_device_info(device_id, CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE).unwrap();
1795            let value = size_t::from(value);
1796            println!("CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE: {}", value);
1797            assert!(0 < value);
1798
1799            let value = get_device_info(device_id, CL_DEVICE_MAX_PIPE_ARGS).unwrap();
1800            let value = cl_uint::from(value);
1801            println!("CL_DEVICE_MAX_PIPE_ARGS: {}", value);
1802            assert!(0 < value);
1803
1804            let value = get_device_info(device_id, CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS).unwrap();
1805            let value = cl_uint::from(value);
1806            println!("CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS: {}", value);
1807            assert!(0 < value);
1808
1809            let value = get_device_info(device_id, CL_DEVICE_PIPE_MAX_PACKET_SIZE).unwrap();
1810            let value = cl_uint::from(value);
1811            println!("CL_DEVICE_PIPE_MAX_PACKET_SIZE: {}", value);
1812            assert!(0 < value);
1813
1814            let value =
1815                get_device_info(device_id, CL_DEVICE_PREFERRED_PLATFORM_ATOMIC_ALIGNMENT).unwrap();
1816            let value = cl_uint::from(value);
1817            println!("CL_DEVICE_PREFERRED_PLATFORM_ATOMIC_ALIGNMENT: {}", value);
1818            // assert!(0 < value);
1819
1820            let value =
1821                get_device_info(device_id, CL_DEVICE_PREFERRED_GLOBAL_ATOMIC_ALIGNMENT).unwrap();
1822            let value = cl_uint::from(value);
1823            println!("CL_DEVICE_PREFERRED_GLOBAL_ATOMIC_ALIGNMENT: {}", value);
1824            // assert!(0 < value);
1825
1826            let value =
1827                get_device_info(device_id, CL_DEVICE_PREFERRED_LOCAL_ATOMIC_ALIGNMENT).unwrap();
1828            let value = cl_uint::from(value);
1829            println!("CL_DEVICE_PREFERRED_LOCAL_ATOMIC_ALIGNMENT: {}", value);
1830            // assert!(0 < value);
1831
1832            // CL_VERSION_2_1
1833            if is_opencl_2_1 {
1834                let value = get_device_info(device_id, CL_DEVICE_IL_VERSION).unwrap();
1835                let value = String::from(value);
1836                println!("CL_DEVICE_IL_VERSION: {}", value);
1837                assert!(!value.is_empty());
1838
1839                let value = get_device_info(device_id, CL_DEVICE_MAX_NUM_SUB_GROUPS).unwrap();
1840                let value = cl_uint::from(value);
1841                println!("CL_DEVICE_MAX_NUM_SUB_GROUPS: {}", value);
1842                assert!(0 < value);
1843
1844                let value =
1845                    get_device_info(device_id, CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS)
1846                        .unwrap();
1847                let value = cl_uint::from(value);
1848                println!(
1849                    "CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS: {}",
1850                    value
1851                );
1852                assert!(0 < value);
1853            }
1854        }
1855    }
1856
1857    #[test]
1858    #[cfg(any(feature = "CL_VERSION_3_0", feature = "dynamic"))]
1859    fn test_get_device_info_3_0() {
1860        let platform_ids = get_platform_ids().unwrap();
1861
1862        // Choose the first OpenCL 3 platform with an OpenCL 3 GPU device
1863        let opencl_3: &str = "OpenCL 3";
1864        let mut device_3: Option<cl_device_id> = None;
1865        for id in platform_ids {
1866            let value = get_platform_info(id, CL_PLATFORM_VERSION).unwrap();
1867            let value: String = value.into();
1868            if value.contains(opencl_3) {
1869                let device_ids = get_device_ids(id, CL_DEVICE_TYPE_GPU).unwrap();
1870                for device_id in device_ids {
1871                    if get_device_info(device_id, CL_DEVICE_NUMERIC_VERSION).is_ok() {
1872                        device_3 = Some(device_id);
1873                        break;
1874                    }
1875                }
1876            }
1877        }
1878
1879        if let Some(device_id) = device_3 {
1880            let value = get_device_info(device_id, CL_DEVICE_NUMERIC_VERSION).unwrap();
1881            let value = cl_uint::from(value);
1882            println!("CL_DEVICE_NUMERIC_VERSION: {}", value);
1883            assert!(0 < value);
1884
1885            let value = get_device_info(device_id, CL_DEVICE_EXTENSIONS_WITH_VERSION).unwrap();
1886            let value = Vec::<cl_name_version>::from(value);
1887            println!("CL_DEVICE_EXTENSIONS_WITH_VERSION: {}", value.len());
1888            println!("CL_DEVICE_EXTENSIONS_WITH_VERSION: {:?}", value);
1889            assert!(0 < value.len());
1890
1891            let value = get_device_info(device_id, CL_DEVICE_ILS_WITH_VERSION).unwrap();
1892            let value = Vec::<cl_name_version>::from(value);
1893            println!("CL_DEVICE_ILS_WITH_VERSION: {}", value.len());
1894            println!("CL_DEVICE_ILS_WITH_VERSION: {:?}", value);
1895            // assert!(0 < value.len());
1896
1897            let value =
1898                get_device_info(device_id, CL_DEVICE_BUILT_IN_KERNELS_WITH_VERSION).unwrap();
1899            let value = Vec::<cl_name_version>::from(value);
1900            println!("CL_DEVICE_BUILT_IN_KERNELS_WITH_VERSION: {}", value.len());
1901            println!("CL_DEVICE_BUILT_IN_KERNELS_WITH_VERSION: {:?}", value);
1902            // assert!(0 < value.len());
1903
1904            let value = get_device_info(device_id, CL_DEVICE_ATOMIC_MEMORY_CAPABILITIES).unwrap();
1905            let value = cl_ulong::from(value);
1906            println!("CL_DEVICE_ATOMIC_MEMORY_CAPABILITIES: {}", value);
1907            assert!(0 < value);
1908
1909            let value = get_device_info(device_id, CL_DEVICE_ATOMIC_MEMORY_CAPABILITIES).unwrap();
1910            let value = cl_ulong::from(value);
1911            println!("CL_DEVICE_ATOMIC_FENCE_CAPABILITIES: {}", value);
1912            assert!(0 < value);
1913
1914            let value =
1915                get_device_info(device_id, CL_DEVICE_NON_UNIFORM_WORK_GROUP_SUPPORT).unwrap();
1916            let value = cl_uint::from(value);
1917            println!("CL_DEVICE_NON_UNIFORM_WORK_GROUP_SUPPORT: {}", value);
1918            // assert!(0 < value);
1919
1920            let value = get_device_info(device_id, CL_DEVICE_OPENCL_C_ALL_VERSIONS).unwrap();
1921            let value = Vec::<cl_name_version>::from(value);
1922            println!("CL_DEVICE_OPENCL_C_ALL_VERSIONS: {}", value.len());
1923            println!("CL_DEVICE_OPENCL_C_ALL_VERSIONS: {:?}", value);
1924            assert!(0 < value.len());
1925
1926            let value =
1927                get_device_info(device_id, CL_DEVICE_PREFERRED_WORK_GROUP_SIZE_MULTIPLE).unwrap();
1928            let value = size_t::from(value);
1929            println!("CL_DEVICE_PREFERRED_WORK_GROUP_SIZE_MULTIPLE: {}", value);
1930            assert!(0 < value);
1931
1932            let value =
1933                get_device_info(device_id, CL_DEVICE_WORK_GROUP_COLLECTIVE_FUNCTIONS_SUPPORT)
1934                    .unwrap();
1935            let value = cl_uint::from(value);
1936            println!(
1937                "CL_DEVICE_WORK_GROUP_COLLECTIVE_FUNCTIONS_SUPPORT: {}",
1938                value
1939            );
1940            // assert!(0 < value);
1941
1942            let value =
1943                get_device_info(device_id, CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT).unwrap();
1944            let value = cl_uint::from(value);
1945            println!("CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT: {}", value);
1946            // assert!(0 < value);
1947
1948            let value = get_device_info(device_id, CL_DEVICE_OPENCL_C_FEATURES).unwrap();
1949            let value = Vec::<cl_name_version>::from(value);
1950            println!("CL_DEVICE_OPENCL_C_FEATURES: {}", value.len());
1951            println!("CL_DEVICE_OPENCL_C_FEATURES: {:?}", value);
1952            assert!(0 < value.len());
1953
1954            let value = get_device_info(device_id, CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES).unwrap();
1955            let value = cl_ulong::from(value);
1956            println!("CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES: {}", value);
1957            // assert!(0 < value);
1958
1959            let value = get_device_info(device_id, CL_DEVICE_PIPE_SUPPORT).unwrap();
1960            let value = cl_uint::from(value);
1961            println!("CL_DEVICE_PIPE_SUPPORT: {}", value);
1962            // assert!(0 < value);
1963
1964            let value =
1965                get_device_info(device_id, CL_DEVICE_LATEST_CONFORMANCE_VERSION_PASSED).unwrap();
1966            let value = String::from(value);
1967            println!("CL_DEVICE_LATEST_CONFORMANCE_VERSION_PASSED: {}", value);
1968            assert!(!value.is_empty());
1969        }
1970    }
1971
1972    #[cfg(any(feature = "CL_VERSION_1_2", feature = "dynamic"))]
1973    #[test]
1974    fn test_get_sub_devices() {
1975        let platform_ids = get_platform_ids().unwrap();
1976        assert!(0 < platform_ids.len());
1977
1978        // Find an `OpenCL` device with sub devices
1979
1980        let mut device_id = ptr::null_mut();
1981        let mut has_sub_devices: bool = false;
1982
1983        for p in platform_ids {
1984            let device_ids = get_device_ids(p, CL_DEVICE_TYPE_CPU).unwrap();
1985
1986            for dev_id in device_ids {
1987                let value = get_device_info(dev_id, CL_DEVICE_PARTITION_MAX_SUB_DEVICES).unwrap();
1988                let max_sub_devices = cl_uint::from(value);
1989
1990                has_sub_devices = 1 < max_sub_devices;
1991                if has_sub_devices {
1992                    device_id = dev_id;
1993                    break;
1994                }
1995            }
1996        }
1997
1998        if has_sub_devices {
1999            let properties: [cl_device_partition_property; 3] = [CL_DEVICE_PARTITION_EQUALLY, 2, 0];
2000            let sub_devices = create_sub_devices(device_id, &properties).unwrap();
2001
2002            println!("CL_DEVICE_TYPE_CPU count: {}", sub_devices.len());
2003            assert!(0 < sub_devices.len());
2004
2005            for device in sub_devices {
2006                unsafe { release_device(device).unwrap() };
2007            }
2008        } else {
2009            println!("OpenCL device capable of sub division not found");
2010        }
2011    }
2012}