• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::api::icd::*;
2 use crate::api::types::IdpAccelProps;
3 use crate::api::util::*;
4 use crate::core::device::*;
5 use crate::core::platform::*;
6 use crate::core::version::*;
7 
8 use mesa_rust_gen::*;
9 use mesa_rust_util::ptr::*;
10 use rusticl_opencl_gen::*;
11 use rusticl_proc_macros::cl_entrypoint;
12 use rusticl_proc_macros::cl_info_entrypoint;
13 
14 use std::cmp::min;
15 use std::ffi::CStr;
16 use std::mem::size_of;
17 use std::ptr;
18 
19 const SPIRV_SUPPORT_STRING: &CStr = c"SPIR-V_1.0 SPIR-V_1.1 SPIR-V_1.2 SPIR-V_1.3 SPIR-V_1.4";
20 const SPIRV_SUPPORT: [cl_name_version; 5] = [
21     mk_cl_version_ext(1, 0, 0, "SPIR-V"),
22     mk_cl_version_ext(1, 1, 0, "SPIR-V"),
23     mk_cl_version_ext(1, 2, 0, "SPIR-V"),
24     mk_cl_version_ext(1, 3, 0, "SPIR-V"),
25     mk_cl_version_ext(1, 4, 0, "SPIR-V"),
26 ];
27 type ClDevIdpAccelProps = cl_device_integer_dot_product_acceleration_properties_khr;
28 
29 #[cl_info_entrypoint(clGetDeviceInfo)]
30 unsafe impl CLInfo<cl_device_info> for cl_device_id {
query(&self, q: cl_device_info, v: CLInfoValue) -> CLResult<CLInfoRes>31     fn query(&self, q: cl_device_info, v: CLInfoValue) -> CLResult<CLInfoRes> {
32         let dev = Device::ref_from_raw(*self)?;
33 
34         // curses you CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_4x8BIT_PACKED_KHR
35         #[allow(non_upper_case_globals)]
36         match q {
37             CL_DEVICE_ADDRESS_BITS => v.write::<cl_uint>(dev.address_bits()),
38             CL_DEVICE_ATOMIC_FENCE_CAPABILITIES => v.write::<cl_device_atomic_capabilities>(
39                 (CL_DEVICE_ATOMIC_ORDER_RELAXED
40                     | CL_DEVICE_ATOMIC_ORDER_ACQ_REL
41                     | CL_DEVICE_ATOMIC_SCOPE_WORK_GROUP)
42                     as cl_device_atomic_capabilities,
43             ),
44             CL_DEVICE_ATOMIC_MEMORY_CAPABILITIES => v.write::<cl_device_atomic_capabilities>(
45                 (CL_DEVICE_ATOMIC_ORDER_RELAXED | CL_DEVICE_ATOMIC_SCOPE_WORK_GROUP)
46                     as cl_device_atomic_capabilities,
47             ),
48             CL_DEVICE_AVAILABLE => v.write::<bool>(true),
49             CL_DEVICE_BUILT_IN_KERNELS => v.write::<&CStr>(c""),
50             CL_DEVICE_BUILT_IN_KERNELS_WITH_VERSION => v.write::<&[cl_name_version]>(&[]),
51             CL_DEVICE_COMPILER_AVAILABLE => v.write::<bool>(true),
52             CL_DEVICE_CROSS_DEVICE_SHARED_MEM_CAPABILITIES_INTEL => {
53                 v.write::<cl_device_device_enqueue_capabilities>(0)
54             }
55             CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES => {
56                 v.write::<cl_device_device_enqueue_capabilities>(0)
57             }
58             CL_DEVICE_DEVICE_MEM_CAPABILITIES_INTEL => {
59                 v.write::<cl_device_unified_shared_memory_capabilities_intel>(0)
60             }
61             CL_DEVICE_DOUBLE_FP_CONFIG => v.write::<cl_device_fp_config>(
62                 if dev.fp64_supported() {
63                     let mut fp64_config = CL_FP_FMA
64                         | CL_FP_ROUND_TO_NEAREST
65                         | CL_FP_ROUND_TO_ZERO
66                         | CL_FP_ROUND_TO_INF
67                         | CL_FP_INF_NAN
68                         | CL_FP_DENORM;
69                     if dev.fp64_is_softfp() {
70                         fp64_config |= CL_FP_SOFT_FLOAT;
71                     }
72                     fp64_config
73                 } else {
74                     0
75                 }
76                 .into(),
77             ),
78             CL_DEVICE_ENDIAN_LITTLE => v.write::<bool>(dev.little_endian()),
79             CL_DEVICE_ERROR_CORRECTION_SUPPORT => v.write::<bool>(false),
80             CL_DEVICE_EXECUTION_CAPABILITIES => {
81                 v.write::<cl_device_exec_capabilities>(CL_EXEC_KERNEL.into())
82             }
83             CL_DEVICE_EXTENSIONS => v.write::<&str>(&dev.extension_string),
84             CL_DEVICE_EXTENSIONS_WITH_VERSION => v.write::<&[cl_name_version]>(&dev.extensions),
85             CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT => v.write::<bool>(false),
86             CL_DEVICE_GLOBAL_MEM_CACHE_TYPE => v.write::<cl_device_mem_cache_type>(CL_NONE),
87             CL_DEVICE_GLOBAL_MEM_CACHE_SIZE => v.write::<cl_ulong>(0),
88             CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE => v.write::<cl_uint>(0),
89             CL_DEVICE_GLOBAL_MEM_SIZE => v.write::<cl_ulong>(dev.global_mem_size()),
90             CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE => v.write::<usize>(0),
91             // Provided by the cl_khr_fp16 extension.
92             CL_DEVICE_HALF_FP_CONFIG if dev.fp16_supported() => {
93                 v.write::<cl_device_fp_config>((CL_FP_ROUND_TO_NEAREST | CL_FP_INF_NAN).into())
94             }
95             CL_DEVICE_HOST_MEM_CAPABILITIES_INTEL => {
96                 v.write::<cl_device_unified_shared_memory_capabilities_intel>(0)
97             }
98             CL_DEVICE_HOST_UNIFIED_MEMORY => v.write::<bool>(dev.unified_memory()),
99             CL_DEVICE_IL_VERSION => v.write::<&CStr>(SPIRV_SUPPORT_STRING),
100             CL_DEVICE_ILS_WITH_VERSION => v.write::<Vec<cl_name_version>>(SPIRV_SUPPORT.to_vec()),
101             CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT => {
102                 v.write::<cl_uint>(dev.image_base_address_alignment())
103             }
104             CL_DEVICE_IMAGE_MAX_ARRAY_SIZE => v.write::<usize>(dev.image_array_size()),
105             CL_DEVICE_IMAGE_MAX_BUFFER_SIZE => v.write::<usize>(dev.image_buffer_max_size_pixels()),
106             CL_DEVICE_IMAGE_PITCH_ALIGNMENT => v.write::<cl_uint>(dev.image_pitch_alignment()),
107             CL_DEVICE_IMAGE_SUPPORT => v.write::<bool>(dev.caps.has_images),
108             CL_DEVICE_IMAGE2D_MAX_HEIGHT => v.write::<usize>(dev.caps.image_2d_size as usize),
109             CL_DEVICE_IMAGE2D_MAX_WIDTH => v.write::<usize>(dev.caps.image_2d_size as usize),
110             CL_DEVICE_IMAGE3D_MAX_HEIGHT => v.write::<usize>(dev.image_3d_size()),
111             CL_DEVICE_IMAGE3D_MAX_WIDTH => v.write::<usize>(dev.image_3d_size()),
112             CL_DEVICE_IMAGE3D_MAX_DEPTH => v.write::<usize>(dev.image_3d_size()),
113             CL_DEVICE_INTEGER_DOT_PRODUCT_CAPABILITIES_KHR => {
114                 v.write::<cl_device_integer_dot_product_capabilities_khr>(
115                     (CL_DEVICE_INTEGER_DOT_PRODUCT_INPUT_4x8BIT_PACKED_KHR
116                         | CL_DEVICE_INTEGER_DOT_PRODUCT_INPUT_4x8BIT_KHR)
117                         .into(),
118                 )
119             }
120             CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_8BIT_KHR => v
121                 .write::<ClDevIdpAccelProps>({
122                     let pack = dev.pack_32_4x8_supported();
123                     let sdot = dev.sdot_4x8_supported() && pack;
124                     let udot = dev.udot_4x8_supported() && pack;
125                     let sudot = dev.sudot_4x8_supported() && pack;
126                     let sdot_sat = dev.sdot_4x8_sat_supported() && pack;
127                     let udot_sat = dev.udot_4x8_sat_supported() && pack;
128                     let sudot_sat = dev.sudot_4x8_sat_supported() && pack;
129                     IdpAccelProps::new(
130                         sdot.into(),
131                         udot.into(),
132                         sudot.into(),
133                         sdot_sat.into(),
134                         udot_sat.into(),
135                         sudot_sat.into(),
136                     )
137                 }),
138             CL_DEVICE_INTEGER_DOT_PRODUCT_ACCELERATION_PROPERTIES_4x8BIT_PACKED_KHR => {
139                 v.write::<ClDevIdpAccelProps>({
140                     IdpAccelProps::new(
141                         dev.sdot_4x8_supported().into(),
142                         dev.udot_4x8_supported().into(),
143                         dev.sudot_4x8_supported().into(),
144                         dev.sdot_4x8_sat_supported().into(),
145                         dev.udot_4x8_sat_supported().into(),
146                         dev.sudot_4x8_sat_supported().into(),
147                     )
148                 })
149             }
150 
151             CL_DEVICE_LATEST_CONFORMANCE_VERSION_PASSED => {
152                 v.write::<&CStr>(dev.screen().cl_cts_version())
153             }
154             CL_DEVICE_LINKER_AVAILABLE => v.write::<bool>(true),
155             CL_DEVICE_LOCAL_MEM_SIZE => v.write::<cl_ulong>(dev.local_mem_size()),
156             // TODO add query for CL_LOCAL vs CL_GLOBAL
157             CL_DEVICE_LOCAL_MEM_TYPE => v.write::<cl_device_local_mem_type>(CL_GLOBAL),
158             CL_DEVICE_LUID_KHR => v.write::<[cl_uchar; CL_LUID_SIZE_KHR as usize]>(
159                 dev.screen().device_luid().unwrap_or_default(),
160             ),
161             CL_DEVICE_LUID_VALID_KHR => {
162                 v.write::<cl_bool>(dev.screen().device_luid().is_some().into())
163             }
164             CL_DEVICE_MAX_CLOCK_FREQUENCY => v.write::<cl_uint>(dev.max_clock_freq()),
165             CL_DEVICE_MAX_COMPUTE_UNITS => v.write::<cl_uint>(dev.max_compute_units()),
166             // TODO atm implemented as mem_const
167             CL_DEVICE_MAX_CONSTANT_ARGS => v.write::<cl_uint>(dev.const_max_count()),
168             CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE => v.write::<cl_ulong>(dev.const_max_size()),
169             CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE => v.write::<usize>(0),
170             CL_DEVICE_MAX_MEM_ALLOC_SIZE => v.write::<cl_ulong>(dev.max_mem_alloc()),
171             CL_DEVICE_MAX_NUM_SUB_GROUPS => v.write::<cl_uint>(if dev.subgroups_supported() {
172                 dev.max_subgroups()
173             } else {
174                 0
175             }),
176             CL_DEVICE_MAX_ON_DEVICE_EVENTS => v.write::<cl_uint>(0),
177             CL_DEVICE_MAX_ON_DEVICE_QUEUES => v.write::<cl_uint>(0),
178             CL_DEVICE_MAX_PARAMETER_SIZE => v.write::<usize>(dev.param_max_size()),
179             CL_DEVICE_MAX_PIPE_ARGS => v.write::<cl_uint>(0),
180             CL_DEVICE_MAX_READ_IMAGE_ARGS => v.write::<cl_uint>(dev.caps.max_read_images),
181             CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS => v.write::<cl_uint>(if dev.caps.has_rw_images {
182                 dev.caps.max_write_images
183             } else {
184                 0
185             }),
186             CL_DEVICE_MAX_SAMPLERS => v.write::<cl_uint>(dev.max_samplers()),
187             CL_DEVICE_MAX_WORK_GROUP_SIZE => v.write::<usize>(dev.max_threads_per_block()),
188             CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS => v.write::<cl_uint>(dev.max_grid_dimensions()),
189             CL_DEVICE_MAX_WORK_ITEM_SIZES => v.write::<Vec<usize>>(dev.max_block_sizes()),
190             CL_DEVICE_MAX_WRITE_IMAGE_ARGS => v.write::<cl_uint>(dev.caps.max_write_images),
191             // TODO proper retrival from devices
192             CL_DEVICE_MEM_BASE_ADDR_ALIGN => v.write::<cl_uint>(0x1000),
193             CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE => {
194                 v.write::<cl_uint>(16 * size_of::<cl_ulong>() as cl_uint)
195             }
196             CL_DEVICE_NAME => v.write::<&CStr>(dev.screen().name()),
197             CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR => v.write::<cl_uint>(1),
198             CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE => v.write::<cl_uint>(dev.fp64_supported().into()),
199             CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT => v.write::<cl_uint>(1),
200             CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF => v.write::<cl_uint>(dev.fp16_supported().into()),
201             CL_DEVICE_NATIVE_VECTOR_WIDTH_INT => v.write::<cl_uint>(1),
202             CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG => v.write::<cl_uint>(1),
203             CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT => v.write::<cl_uint>(1),
204             CL_DEVICE_NODE_MASK_KHR => {
205                 v.write::<cl_uint>(dev.screen().device_node_mask().unwrap_or_default())
206             }
207             CL_DEVICE_NON_UNIFORM_WORK_GROUP_SUPPORT => v.write::<bool>(false),
208             CL_DEVICE_NUMERIC_VERSION => v.write::<cl_version>(dev.cl_version.into()),
209             CL_DEVICE_OPENCL_C_ALL_VERSIONS => v.write::<&[cl_name_version]>(&dev.clc_versions),
210             CL_DEVICE_OPENCL_C_FEATURES => v.write::<&[cl_name_version]>(&dev.clc_features),
211             CL_DEVICE_OPENCL_C_NUMERIC_VERSION_KHR => {
212                 v.write::<cl_version_khr>(dev.clc_version.into())
213             }
214             CL_DEVICE_OPENCL_C_VERSION => {
215                 v.write::<&str>(&format!("OpenCL C {} ", dev.clc_version.api_str()))
216             }
217             // TODO subdevice support
218             CL_DEVICE_PARENT_DEVICE => v.write::<cl_device_id>(cl_device_id::from_ptr(ptr::null())),
219             CL_DEVICE_PARTITION_AFFINITY_DOMAIN => v.write::<cl_device_affinity_domain>(0),
220             CL_DEVICE_PARTITION_MAX_SUB_DEVICES => v.write::<cl_uint>(0),
221             CL_DEVICE_PARTITION_PROPERTIES => v.write::<&[cl_device_partition_property]>(&[0]),
222             CL_DEVICE_PARTITION_TYPE => v.write::<&[cl_device_partition_property]>(&[]),
223             CL_DEVICE_PCI_BUS_INFO_KHR => {
224                 v.write::<cl_device_pci_bus_info_khr>(dev.pci_info().ok_or(CL_INVALID_VALUE)?)
225             }
226             CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS => v.write::<cl_uint>(0),
227             CL_DEVICE_PIPE_MAX_PACKET_SIZE => v.write::<cl_uint>(0),
228             CL_DEVICE_PIPE_SUPPORT => v.write::<bool>(false),
229             CL_DEVICE_PLATFORM => v.write::<cl_platform_id>(Platform::get().as_ptr()),
230             CL_DEVICE_PREFERRED_GLOBAL_ATOMIC_ALIGNMENT => v.write::<cl_uint>(0),
231             CL_DEVICE_PREFERRED_INTEROP_USER_SYNC => v.write::<bool>(true),
232             CL_DEVICE_PREFERRED_LOCAL_ATOMIC_ALIGNMENT => v.write::<cl_uint>(0),
233             CL_DEVICE_PREFERRED_PLATFORM_ATOMIC_ALIGNMENT => v.write::<cl_uint>(0),
234             CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR => v.write::<cl_uint>(1),
235             CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE => {
236                 v.write::<cl_uint>(dev.fp64_supported().into())
237             }
238             CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT => v.write::<cl_uint>(1),
239             CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF => {
240                 v.write::<cl_uint>(dev.fp16_supported().into())
241             }
242             CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT => v.write::<cl_uint>(1),
243             CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG => v.write::<cl_uint>(1),
244             CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT => v.write::<cl_uint>(1),
245             CL_DEVICE_PREFERRED_WORK_GROUP_SIZE_MULTIPLE => {
246                 v.write::<usize>(dev.subgroup_sizes()[0])
247             }
248             CL_DEVICE_PRINTF_BUFFER_SIZE => v.write::<usize>(dev.printf_buffer_size()),
249             CL_DEVICE_PROFILE => v.write::<&CStr>(if dev.embedded {
250                 c"EMBEDDED_PROFILE"
251             } else {
252                 c"FULL_PROFILE"
253             }),
254             CL_DEVICE_PROFILING_TIMER_RESOLUTION => {
255                 v.write::<usize>(dev.caps.timer_resolution as usize)
256             }
257             CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE => v.write::<cl_uint>(0),
258             CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE => v.write::<cl_uint>(0),
259             CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES => v.write::<cl_command_queue_properties>(0),
260             CL_DEVICE_QUEUE_ON_HOST_PROPERTIES => v.write::<cl_command_queue_properties>(
261                 (CL_QUEUE_PROFILING_ENABLE | CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE).into(),
262             ),
263             CL_DEVICE_REFERENCE_COUNT => v.write::<cl_uint>(1),
264             CL_DEVICE_SHARED_SYSTEM_MEM_CAPABILITIES_INTEL => {
265                 v.write::<cl_device_unified_shared_memory_capabilities_intel>(0)
266             }
267             CL_DEVICE_SINGLE_DEVICE_SHARED_MEM_CAPABILITIES_INTEL => {
268                 v.write::<cl_device_unified_shared_memory_capabilities_intel>(0)
269             }
270             CL_DEVICE_SINGLE_FP_CONFIG => v.write::<cl_device_fp_config>(
271                 (CL_FP_ROUND_TO_NEAREST | CL_FP_INF_NAN) as cl_device_fp_config,
272             ),
273             CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS => v.write::<bool>(false),
274             CL_DEVICE_SUB_GROUP_SIZES_INTEL => {
275                 v.write::<Vec<usize>>(if dev.subgroups_supported() {
276                     dev.subgroup_sizes()
277                 } else {
278                     vec![0; 1]
279                 })
280             }
281             CL_DEVICE_SVM_CAPABILITIES | CL_DEVICE_SVM_CAPABILITIES_ARM => {
282                 v.write::<cl_device_svm_capabilities>(
283                     if dev.svm_supported() {
284                         CL_DEVICE_SVM_COARSE_GRAIN_BUFFER
285                             | CL_DEVICE_SVM_FINE_GRAIN_BUFFER
286                             | CL_DEVICE_SVM_FINE_GRAIN_SYSTEM
287                     } else {
288                         0
289                     }
290                     .into(),
291                 )
292             }
293             CL_DEVICE_TYPE => {
294                 // CL_DEVICE_TYPE_DEFAULT ... will never be returned in CL_DEVICE_TYPE for any
295                 // OpenCL device.
296                 v.write::<cl_device_type>((dev.device_type & !CL_DEVICE_TYPE_DEFAULT).into())
297             }
298             CL_DEVICE_UUID_KHR => v.write::<[cl_uchar; CL_UUID_SIZE_KHR as usize]>(
299                 dev.screen().device_uuid().unwrap_or_default(),
300             ),
301             CL_DEVICE_VENDOR => v.write::<&CStr>(dev.screen().device_vendor()),
302             CL_DEVICE_VENDOR_ID => v.write::<cl_uint>(dev.vendor_id()),
303             CL_DEVICE_VERSION => v.write::<&str>(&format!("OpenCL {} ", dev.cl_version.api_str())),
304             CL_DRIVER_UUID_KHR => v.write::<[cl_char; CL_UUID_SIZE_KHR as usize]>(
305                 dev.screen().driver_uuid().unwrap_or_default(),
306             ),
307             CL_DRIVER_VERSION => v.write::<&CStr>(unsafe { CStr::from_ptr(mesa_version_string()) }),
308             CL_DEVICE_WORK_GROUP_COLLECTIVE_FUNCTIONS_SUPPORT => v.write::<bool>(false),
309             // CL_INVALID_VALUE if param_name is not one of the supported values
310             // CL_INVALID_VALUE [...] if param_name is a value that is available as an extension and the corresponding extension is not supported by the device.
311             _ => Err(CL_INVALID_VALUE),
312         }
313     }
314 }
315 
316 #[cl_entrypoint(clGetDeviceIDs)]
get_device_ids( platform: cl_platform_id, device_type: cl_device_type, num_entries: cl_uint, devices: *mut cl_device_id, num_devices: *mut cl_uint, ) -> CLResult<()>317 fn get_device_ids(
318     platform: cl_platform_id,
319     device_type: cl_device_type,
320     num_entries: cl_uint,
321     devices: *mut cl_device_id,
322     num_devices: *mut cl_uint,
323 ) -> CLResult<()> {
324     // CL_INVALID_PLATFORM if platform is not a valid platform.
325     platform.get_ref()?;
326 
327     // CL_INVALID_DEVICE_TYPE if device_type is not a valid value.
328     check_cl_device_type(device_type)?;
329 
330     // CL_INVALID_VALUE if num_entries is equal to zero and devices is not NULL
331     if num_entries == 0 && !devices.is_null() {
332         return Err(CL_INVALID_VALUE);
333     }
334 
335     // CL_INVALID_VALUE [...] if both num_devices and devices are NULL.
336     if num_devices.is_null() && devices.is_null() {
337         return Err(CL_INVALID_VALUE);
338     }
339 
340     let devs = get_devs_for_type(device_type);
341     // CL_DEVICE_NOT_FOUND if no OpenCL devices that matched device_type were found
342     if devs.is_empty() {
343         return Err(CL_DEVICE_NOT_FOUND);
344     }
345 
346     // num_devices returns the number of OpenCL devices available that match device_type. If
347     // num_devices is NULL, this argument is ignored.
348     num_devices.write_checked(devs.len() as cl_uint);
349 
350     if !devices.is_null() {
351         let n = min(num_entries as usize, devs.len());
352 
353         #[allow(clippy::needless_range_loop)]
354         for i in 0..n {
355             unsafe {
356                 *devices.add(i) = cl_device_id::from_ptr(devs[i]);
357             }
358         }
359     }
360 
361     Ok(())
362 }
363 
364 #[cl_entrypoint(clRetainDevice)]
retain_device(_device: cl_device_id) -> CLResult<()>365 fn retain_device(_device: cl_device_id) -> CLResult<()> {
366     Ok(())
367 }
368 
369 #[cl_entrypoint(clReleaseDevice)]
release_device(_device: cl_device_id) -> CLResult<()>370 fn release_device(_device: cl_device_id) -> CLResult<()> {
371     Ok(())
372 }
373 
374 #[cl_entrypoint(clCreateSubDevices)]
create_sub_devices( _device: cl_device_id, _properties: *const cl_device_partition_property, _num_devices: cl_uint, _out_devices: *mut cl_device_id, _num_devices_ret: *mut cl_uint, ) -> CLResult<()>375 fn create_sub_devices(
376     _device: cl_device_id,
377     _properties: *const cl_device_partition_property,
378     _num_devices: cl_uint,
379     _out_devices: *mut cl_device_id,
380     _num_devices_ret: *mut cl_uint,
381 ) -> CLResult<()> {
382     // CL_INVALID_VALUE if values specified in properties are not valid or
383     // if values specified in properties are valid but not supported by the
384     // device.
385     Err(CL_INVALID_VALUE)
386 }
387 
388 #[cl_entrypoint(clGetDeviceAndHostTimer)]
get_device_and_host_timer( device: cl_device_id, device_timestamp: *mut cl_ulong, host_timestamp: *mut cl_ulong, ) -> CLResult<()>389 fn get_device_and_host_timer(
390     device: cl_device_id,
391     device_timestamp: *mut cl_ulong,
392     host_timestamp: *mut cl_ulong,
393 ) -> CLResult<()> {
394     if device_timestamp.is_null() {
395         // CL_INVALID_VALUE if host_timestamp or device_timestamp is NULL
396         return Err(CL_INVALID_VALUE);
397     }
398 
399     get_host_timer(device, host_timestamp)?;
400     // There is a requirement that the two timestamps
401     // are synchronised, but don't need to be the same,
402     // but as it is, the same timestamp is the best to
403     // use for both
404 
405     // Safe because null check on device_timestamp above
406     // and host_timestamp null check in get_host_timer
407     unsafe {
408         *device_timestamp = *host_timestamp;
409     };
410 
411     Ok(())
412 }
413 
414 #[cl_entrypoint(clGetHostTimer)]
get_host_timer(device_id: cl_device_id, host_timestamp: *mut cl_ulong) -> CLResult<()>415 fn get_host_timer(device_id: cl_device_id, host_timestamp: *mut cl_ulong) -> CLResult<()> {
416     if host_timestamp.is_null() {
417         // CL_INVALID_VALUE if host_timestamp is NULL
418         return Err(CL_INVALID_VALUE);
419     }
420 
421     let device = Device::ref_from_raw(device_id)?;
422 
423     if !device.caps.has_timestamp {
424         // CL_INVALID_OPERATION if the platform associated with device does not support device and host timer synchronization
425         return Err(CL_INVALID_OPERATION);
426     }
427 
428     // Currently the best clock we have for the host_timestamp
429     host_timestamp.write_checked(device.screen().get_timestamp());
430 
431     Ok(())
432 }
433 
434 #[cl_entrypoint(clSetDefaultDeviceCommandQueue)]
set_default_device_command_queue( _context: cl_context, _device: cl_device_id, _command_queue: cl_command_queue, ) -> CLResult<()>435 fn set_default_device_command_queue(
436     _context: cl_context,
437     _device: cl_device_id,
438     _command_queue: cl_command_queue,
439 ) -> CLResult<()> {
440     Err(CL_INVALID_OPERATION)
441 }
442