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