• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #![allow(non_snake_case)]
2 
3 use crate::api::context::*;
4 use crate::api::device::*;
5 use crate::api::event::*;
6 use crate::api::kernel::*;
7 use crate::api::memory::*;
8 use crate::api::platform::*;
9 use crate::api::program::*;
10 use crate::api::queue::*;
11 use crate::api::types::*;
12 use crate::api::util::*;
13 
14 use mesa_rust_util::ptr::*;
15 use rusticl_opencl_gen::*;
16 
17 use std::ffi::CStr;
18 use std::ptr;
19 use std::sync::Arc;
20 
21 pub static DISPATCH: cl_icd_dispatch = cl_icd_dispatch {
22     clGetPlatformIDs: Some(cl_get_platform_ids),
23     clGetPlatformInfo: Some(cl_get_platform_info),
24     clGetDeviceIDs: Some(cl_get_device_ids),
25     clGetDeviceInfo: Some(cl_get_device_info),
26     clCreateContext: Some(cl_create_context),
27     clCreateContextFromType: Some(cl_create_context_from_type),
28     clRetainContext: Some(cl_retain_context),
29     clReleaseContext: Some(cl_release_context),
30     clGetContextInfo: Some(cl_get_context_info),
31     clCreateCommandQueue: Some(cl_create_command_queue),
32     clRetainCommandQueue: Some(cl_retain_command_queue),
33     clReleaseCommandQueue: Some(cl_release_command_queue),
34     clGetCommandQueueInfo: Some(cl_get_command_queue_info),
35     clSetCommandQueueProperty: None,
36     clCreateBuffer: Some(cl_create_buffer),
37     clCreateImage2D: Some(cl_create_image_2d),
38     clCreateImage3D: Some(cl_create_image_3d),
39     clRetainMemObject: Some(cl_retain_mem_object),
40     clReleaseMemObject: Some(cl_release_mem_object),
41     clGetSupportedImageFormats: Some(cl_get_supported_image_formats),
42     clGetMemObjectInfo: Some(cl_get_mem_object_info),
43     clGetImageInfo: Some(cl_get_image_info),
44     clCreateSampler: Some(cl_create_sampler),
45     clRetainSampler: Some(cl_retain_sampler),
46     clReleaseSampler: Some(cl_release_sampler),
47     clGetSamplerInfo: Some(cl_get_sampler_info),
48     clCreateProgramWithSource: Some(cl_create_program_with_source),
49     clCreateProgramWithBinary: Some(cl_create_program_with_binary),
50     clRetainProgram: Some(cl_retain_program),
51     clReleaseProgram: Some(cl_release_program),
52     clBuildProgram: Some(cl_build_program),
53     clUnloadCompiler: None,
54     clGetProgramInfo: Some(cl_get_program_info),
55     clGetProgramBuildInfo: Some(cl_get_program_build_info),
56     clCreateKernel: Some(cl_create_kernel),
57     clCreateKernelsInProgram: Some(cl_create_kernels_in_program),
58     clRetainKernel: Some(cl_retain_kernel),
59     clReleaseKernel: Some(cl_release_kernel),
60     clSetKernelArg: Some(cl_set_kernel_arg),
61     clGetKernelInfo: Some(cl_get_kernel_info),
62     clGetKernelWorkGroupInfo: Some(cl_get_kernel_work_group_info),
63     clWaitForEvents: Some(cl_wait_for_events),
64     clGetEventInfo: Some(cl_get_event_info),
65     clRetainEvent: Some(cl_retain_event),
66     clReleaseEvent: Some(cl_release_event),
67     clGetEventProfilingInfo: Some(cl_get_event_profiling_info),
68     clFlush: Some(cl_flush),
69     clFinish: Some(cl_finish),
70     clEnqueueReadBuffer: Some(cl_enqueue_read_buffer),
71     clEnqueueWriteBuffer: Some(cl_enqueue_write_buffer),
72     clEnqueueCopyBuffer: Some(cl_enqueue_copy_buffer),
73     clEnqueueReadImage: Some(cl_enqueue_read_image),
74     clEnqueueWriteImage: Some(cl_enqueue_write_image),
75     clEnqueueCopyImage: Some(cl_enqueue_copy_image),
76     clEnqueueCopyImageToBuffer: Some(cl_enqueue_copy_image_to_buffer),
77     clEnqueueCopyBufferToImage: Some(cl_enqueue_copy_buffer_to_image),
78     clEnqueueMapBuffer: Some(cl_enqueue_map_buffer),
79     clEnqueueMapImage: Some(cl_enqueue_map_image),
80     clEnqueueUnmapMemObject: Some(cl_enqueue_unmap_mem_object),
81     clEnqueueNDRangeKernel: Some(cl_enqueue_ndrange_kernel),
82     clEnqueueTask: Some(cl_enqueue_task),
83     clEnqueueNativeKernel: None,
84     clEnqueueMarker: Some(cl_enqueue_marker),
85     clEnqueueWaitForEvents: None,
86     clEnqueueBarrier: Some(cl_enqueue_barrier),
87     clGetExtensionFunctionAddress: Some(cl_get_extension_function_address),
88     clCreateFromGLBuffer: Some(cl_create_from_gl_buffer),
89     clCreateFromGLTexture2D: Some(cl_create_from_gl_texture_2d),
90     clCreateFromGLTexture3D: Some(cl_create_from_gl_texture_3d),
91     clCreateFromGLRenderbuffer: Some(cl_create_from_gl_renderbuffer),
92     clGetGLObjectInfo: Some(cl_get_gl_object_info),
93     clGetGLTextureInfo: Some(cl_get_gl_texture_info),
94     clEnqueueAcquireGLObjects: Some(cl_enqueue_acquire_gl_objects),
95     clEnqueueReleaseGLObjects: Some(cl_enqueue_release_gl_objects),
96     clGetGLContextInfoKHR: Some(cl_get_gl_context_info_khr),
97     clGetDeviceIDsFromD3D10KHR: ptr::null_mut(),
98     clCreateFromD3D10BufferKHR: ptr::null_mut(),
99     clCreateFromD3D10Texture2DKHR: ptr::null_mut(),
100     clCreateFromD3D10Texture3DKHR: ptr::null_mut(),
101     clEnqueueAcquireD3D10ObjectsKHR: ptr::null_mut(),
102     clEnqueueReleaseD3D10ObjectsKHR: ptr::null_mut(),
103     clSetEventCallback: Some(cl_set_event_callback),
104     clCreateSubBuffer: Some(cl_create_sub_buffer),
105     clSetMemObjectDestructorCallback: Some(cl_set_mem_object_destructor_callback),
106     clCreateUserEvent: Some(cl_create_user_event),
107     clSetUserEventStatus: Some(cl_set_user_event_status),
108     clEnqueueReadBufferRect: Some(cl_enqueue_read_buffer_rect),
109     clEnqueueWriteBufferRect: Some(cl_enqueue_write_buffer_rect),
110     clEnqueueCopyBufferRect: Some(cl_enqueue_copy_buffer_rect),
111     clCreateSubDevicesEXT: None,
112     clRetainDeviceEXT: None,
113     clReleaseDeviceEXT: None,
114     clCreateEventFromGLsyncKHR: None,
115     clCreateSubDevices: None,
116     clRetainDevice: Some(cl_retain_device),
117     clReleaseDevice: Some(cl_release_device),
118     clCreateImage: Some(cl_create_image),
119     clCreateProgramWithBuiltInKernels: None,
120     clCompileProgram: Some(cl_compile_program),
121     clLinkProgram: Some(cl_link_program),
122     clUnloadPlatformCompiler: Some(cl_unload_platform_compiler),
123     clGetKernelArgInfo: Some(cl_get_kernel_arg_info),
124     clEnqueueFillBuffer: Some(cl_enqueue_fill_buffer),
125     clEnqueueFillImage: Some(cl_enqueue_fill_image),
126     clEnqueueMigrateMemObjects: Some(cl_enqueue_migrate_mem_objects),
127     clEnqueueMarkerWithWaitList: Some(cl_enqueue_marker_with_wait_list),
128     clEnqueueBarrierWithWaitList: Some(cl_enqueue_barrier_with_wait_list),
129     clGetExtensionFunctionAddressForPlatform: Some(cl_get_extension_function_address_for_platform),
130     clCreateFromGLTexture: Some(cl_create_from_gl_texture),
131     clGetDeviceIDsFromD3D11KHR: ptr::null_mut(),
132     clCreateFromD3D11BufferKHR: ptr::null_mut(),
133     clCreateFromD3D11Texture2DKHR: ptr::null_mut(),
134     clCreateFromD3D11Texture3DKHR: ptr::null_mut(),
135     clCreateFromDX9MediaSurfaceKHR: ptr::null_mut(),
136     clEnqueueAcquireD3D11ObjectsKHR: ptr::null_mut(),
137     clEnqueueReleaseD3D11ObjectsKHR: ptr::null_mut(),
138     clGetDeviceIDsFromDX9MediaAdapterKHR: ptr::null_mut(),
139     clEnqueueAcquireDX9MediaSurfacesKHR: ptr::null_mut(),
140     clEnqueueReleaseDX9MediaSurfacesKHR: ptr::null_mut(),
141     clCreateFromEGLImageKHR: None,
142     clEnqueueAcquireEGLObjectsKHR: None,
143     clEnqueueReleaseEGLObjectsKHR: None,
144     clCreateEventFromEGLSyncKHR: None,
145     clCreateCommandQueueWithProperties: Some(cl_create_command_queue_with_properties),
146     clCreatePipe: Some(cl_create_pipe),
147     clGetPipeInfo: Some(cl_get_pipe_info),
148     clSVMAlloc: Some(cl_svm_alloc),
149     clSVMFree: Some(cl_svm_free),
150     clEnqueueSVMFree: Some(cl_enqueue_svm_free),
151     clEnqueueSVMMemcpy: Some(cl_enqueue_svm_memcpy),
152     clEnqueueSVMMemFill: Some(cl_enqueue_svm_mem_fill),
153     clEnqueueSVMMap: Some(cl_enqueue_svm_map),
154     clEnqueueSVMUnmap: Some(cl_enqueue_svm_unmap),
155     clCreateSamplerWithProperties: Some(cl_create_sampler_with_properties),
156     clSetKernelArgSVMPointer: Some(cl_set_kernel_arg_svm_pointer),
157     clSetKernelExecInfo: Some(cl_set_kernel_exec_info),
158     clGetKernelSubGroupInfoKHR: Some(cl_get_kernel_sub_group_info),
159     clCloneKernel: Some(cl_clone_kernel),
160     clCreateProgramWithIL: Some(cl_create_program_with_il),
161     clEnqueueSVMMigrateMem: Some(cl_enqueue_svm_migrate_mem),
162     clGetDeviceAndHostTimer: Some(cl_get_device_and_host_timer),
163     clGetHostTimer: Some(cl_get_host_timer),
164     clGetKernelSubGroupInfo: Some(cl_get_kernel_sub_group_info),
165     clSetDefaultDeviceCommandQueue: Some(cl_set_default_device_command_queue),
166     clSetProgramReleaseCallback: Some(cl_set_program_release_callback),
167     clSetProgramSpecializationConstant: Some(cl_set_program_specialization_constant),
168     clCreateBufferWithProperties: Some(cl_create_buffer_with_properties),
169     clCreateImageWithProperties: Some(cl_create_image_with_properties),
170     clSetContextDestructorCallback: Some(cl_set_context_destructor_callback),
171 };
172 
173 pub type CLError = cl_int;
174 pub type CLResult<T> = Result<T, CLError>;
175 
176 #[derive(Clone, Copy, PartialEq)]
177 #[repr(u32)]
178 pub enum RusticlTypes {
179     // random number
180     Buffer = 0xec4cf9a9,
181     Context,
182     Device,
183     Event,
184     Image,
185     Kernel,
186     Program,
187     Queue,
188     Sampler,
189 }
190 
191 impl RusticlTypes {
u32(&self) -> u32192     pub const fn u32(&self) -> u32 {
193         *self as u32
194     }
195 
from_u32(val: u32) -> Option<Self>196     pub const fn from_u32(val: u32) -> Option<Self> {
197         let result = match val {
198             0xec4cf9a9 => Self::Buffer,
199             0xec4cf9aa => Self::Context,
200             0xec4cf9ab => Self::Device,
201             0xec4cf9ac => Self::Event,
202             0xec4cf9ad => Self::Image,
203             0xec4cf9ae => Self::Kernel,
204             0xec4cf9af => Self::Program,
205             0xec4cf9b0 => Self::Queue,
206             0xec4cf9b1 => Self::Sampler,
207             _ => return None,
208         };
209         debug_assert!(result.u32() == val);
210         Some(result)
211     }
212 }
213 
214 #[repr(C)]
215 pub struct CLObjectBase<const ERR: i32> {
216     dispatch: &'static cl_icd_dispatch,
217     rusticl_type: u32,
218 }
219 
220 impl<const ERR: i32> CLObjectBase<ERR> {
new(t: RusticlTypes) -> Self221     pub fn new(t: RusticlTypes) -> Self {
222         Self {
223             dispatch: &DISPATCH,
224             rusticl_type: t.u32(),
225         }
226     }
227 
check_ptr(ptr: *const Self) -> CLResult<RusticlTypes>228     pub fn check_ptr(ptr: *const Self) -> CLResult<RusticlTypes> {
229         if ptr.is_null() {
230             return Err(ERR);
231         }
232 
233         unsafe {
234             if !::std::ptr::eq((*ptr).dispatch, &DISPATCH) {
235                 return Err(ERR);
236             }
237 
238             let Some(ty) = RusticlTypes::from_u32((*ptr).rusticl_type) else {
239                 return Err(ERR);
240             };
241 
242             Ok(ty)
243         }
244     }
245 
get_type(&self) -> CLResult<RusticlTypes>246     pub fn get_type(&self) -> CLResult<RusticlTypes> {
247         RusticlTypes::from_u32(self.rusticl_type).ok_or(ERR)
248     }
249 }
250 
251 pub trait ReferenceCountedAPIPointer<T, const ERR: i32> {
get_ptr(&self) -> CLResult<*const T>252     fn get_ptr(&self) -> CLResult<*const T>;
253 
254     // TODO:  I can't find a trait that would let me say T: pointer so that
255     // I can do the cast in the main trait implementation.  So we need to
256     // implement that as part of the macro where we know the real type.
from_ptr(ptr: *const T) -> Self257     fn from_ptr(ptr: *const T) -> Self;
258 }
259 
260 pub trait BaseCLObject<'a, const ERR: i32, CL: ReferenceCountedAPIPointer<Self, ERR> + 'a>:
261     Sized
262 {
ref_from_raw(obj: CL) -> CLResult<&'a Self>263     fn ref_from_raw(obj: CL) -> CLResult<&'a Self> {
264         let obj = obj.get_ptr()?;
265         // SAFETY: `get_ptr` already checks if it's one of our pointers and not null
266         Ok(unsafe { &*obj })
267     }
268 
refs_from_arr(objs: *const CL, count: u32) -> CLResult<Vec<&'a Self>> where CL: Copy,269     fn refs_from_arr(objs: *const CL, count: u32) -> CLResult<Vec<&'a Self>>
270     where
271         CL: Copy,
272     {
273         // CL spec requires validation for obj arrays, both values have to make sense
274         if objs.is_null() && count > 0 || !objs.is_null() && count == 0 {
275             return Err(CL_INVALID_VALUE);
276         }
277 
278         let mut res = Vec::new();
279         if objs.is_null() || count == 0 {
280             return Ok(res);
281         }
282 
283         for i in 0..count as usize {
284             res.push(Self::ref_from_raw(unsafe { *objs.add(i) })?);
285         }
286         Ok(res)
287     }
288 }
289 
290 pub trait CLObject<'a, const ERR: i32, CL: ReferenceCountedAPIPointer<Self, ERR> + 'a>:
291     Sized + BaseCLObject<'a, ERR, CL>
292 {
as_cl(&self) -> CL293     fn as_cl(&self) -> CL {
294         CL::from_ptr(self)
295     }
296 }
297 
298 pub trait ArcedCLObject<'a, const ERR: i32, CL: ReferenceCountedAPIPointer<Self, ERR> + 'a>:
299     Sized + BaseCLObject<'a, ERR, CL>
300 {
301     /// Note: this operation increases the internal ref count as `ref_from_raw` is the better option
302     /// when an Arc is not needed.
arc_from_raw(ptr: CL) -> CLResult<Arc<Self>>303     fn arc_from_raw(ptr: CL) -> CLResult<Arc<Self>> {
304         let ptr = ptr.get_ptr()?;
305         // SAFETY: `get_ptr` already checks if it's one of our pointers.
306         Ok(unsafe {
307             Arc::increment_strong_count(ptr);
308             Arc::from_raw(ptr)
309         })
310     }
311 
arcs_from_arr(objs: *const CL, count: u32) -> CLResult<Vec<Arc<Self>>> where CL: Copy,312     fn arcs_from_arr(objs: *const CL, count: u32) -> CLResult<Vec<Arc<Self>>>
313     where
314         CL: Copy,
315     {
316         // CL spec requires validation for obj arrays, both values have to make sense
317         if objs.is_null() && count > 0 || !objs.is_null() && count == 0 {
318             return Err(CL_INVALID_VALUE);
319         }
320 
321         let mut res = Vec::new();
322         if objs.is_null() || count == 0 {
323             return Ok(res);
324         }
325 
326         for i in 0..count as usize {
327             unsafe {
328                 res.push(Self::arc_from_raw(*objs.add(i))?);
329             }
330         }
331         Ok(res)
332     }
333 
refcnt(ptr: CL) -> CLResult<u32>334     fn refcnt(ptr: CL) -> CLResult<u32> {
335         let ptr = ptr.get_ptr()?;
336         // SAFETY: `get_ptr` already checks if it's one of our pointers.
337         let arc = unsafe { Arc::from_raw(ptr) };
338         let res = Arc::strong_count(&arc);
339         // leak the arc again, so we don't reduce the refcount by dropping `arc`
340         let _ = Arc::into_raw(arc);
341         Ok(res as u32)
342     }
343 
into_cl(self: Arc<Self>) -> CL344     fn into_cl(self: Arc<Self>) -> CL {
345         CL::from_ptr(Arc::into_raw(self))
346     }
347 
release(ptr: CL) -> CLResult<()>348     fn release(ptr: CL) -> CLResult<()> {
349         let ptr = ptr.get_ptr()?;
350         // SAFETY: `get_ptr` already checks if it's one of our pointers.
351         unsafe { Arc::decrement_strong_count(ptr) };
352         Ok(())
353     }
354 
retain(ptr: CL) -> CLResult<()>355     fn retain(ptr: CL) -> CLResult<()> {
356         let ptr = ptr.get_ptr()?;
357         // SAFETY: `get_ptr` already checks if it's one of our pointers.
358         unsafe { Arc::increment_strong_count(ptr) };
359         Ok(())
360     }
361 }
362 
363 #[macro_export]
364 macro_rules! impl_cl_type_trait_base {
365     (@BASE $cl: ident, $t: ident, [$($types: ident),+], $err: ident, $($field:ident).+) => {
366         impl $crate::api::icd::ReferenceCountedAPIPointer<$t, $err> for $cl {
367             fn get_ptr(&self) -> CLResult<*const $t> {
368                 type Base = $crate::api::icd::CLObjectBase<$err>;
369                 let t = Base::check_ptr(self.cast())?;
370                 if ![$($crate::api::icd::RusticlTypes::$types),+].contains(&t) {
371                     return Err($err);
372                 }
373 
374                 let offset = ::mesa_rust_util::offset_of!($t, $($field).+);
375                 let mut obj_ptr: *const u8 = self.cast();
376                 // SAFETY: We offset the pointer back from the ICD specified base type to our
377                 //         internal type.
378                 unsafe { obj_ptr = obj_ptr.sub(offset) }
379 
380                 let obj_ptr: *const $t = obj_ptr.cast();
381 
382                 // Check at compile-time that we indeed got the right path
383                 unsafe { let _: &Base = &(*obj_ptr).$($field).+; }
384 
385                 Ok(obj_ptr)
386             }
387 
388             fn from_ptr(ptr: *const $t) -> Self {
389                 if ptr.is_null() {
390                     return std::ptr::null_mut();
391                 }
392                 let offset = ::mesa_rust_util::offset_of!($t, $($field).+);
393                 // SAFETY: The resulting pointer is safe as we simply offset into the ICD specified
394                 //         base type.
395                 unsafe { (ptr as *const u8).add(offset) as Self }
396             }
397         }
398 
399         impl $crate::api::icd::BaseCLObject<'_, $err, $cl> for $t {}
400 
401         impl $t {
402             fn _ensure_send_sync(&self) -> impl Send + Sync + '_ {
403                 self
404             }
405         }
406 
407         // there are two reason to implement those traits for all objects
408         //   1. it speeds up operations
409         //   2. we want to check for real equality more explicit to stay conformant with the API
410         //      and to not break in subtle ways e.g. using CL objects as keys in HashMaps.
411         impl std::cmp::Eq for $t {}
412         impl std::cmp::PartialEq for $t {
413             fn eq(&self, other: &Self) -> bool {
414                 (self as *const Self) == (other as *const Self)
415             }
416         }
417 
418         impl std::hash::Hash for $t {
419             fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
420                 (self as *const Self).hash(state);
421             }
422         }
423     };
424 
425     ($cl: ident, $t: ident, [$($types: ident),+], $err: ident, $($field:ident).+) => {
426         $crate::impl_cl_type_trait_base!(@BASE $cl, $t, [$($types),+], $err, $($field).+);
427         impl $crate::api::icd::CLObject<'_, $err, $cl> for $t {}
428     };
429 
430     ($cl: ident, $t: ident, [$($types: ident),+], $err: ident) => {
431         $crate::impl_cl_type_trait_base!($cl, $t, [$($types),+], $err, base);
432     };
433 }
434 
435 #[macro_export]
436 macro_rules! impl_cl_type_trait {
437     ($cl: ident, $t: ident, $err: ident, $($field:ident).+) => {
438         $crate::impl_cl_type_trait_base!(@BASE $cl, $t, [$t], $err, $($field).+);
439         impl $crate::api::icd::ArcedCLObject<'_, $err, $cl> for $t {}
440     };
441 
442     ($cl: ident, $t: ident, $err: ident) => {
443         $crate::impl_cl_type_trait!($cl, $t, $err, base);
444     };
445 }
446 
447 // We need those functions exported
448 
449 #[no_mangle]
clGetPlatformInfo( platform: cl_platform_id, param_name: cl_platform_info, param_value_size: usize, param_value: *mut ::std::ffi::c_void, param_value_size_ret: *mut usize, ) -> cl_int450 extern "C" fn clGetPlatformInfo(
451     platform: cl_platform_id,
452     param_name: cl_platform_info,
453     param_value_size: usize,
454     param_value: *mut ::std::ffi::c_void,
455     param_value_size_ret: *mut usize,
456 ) -> cl_int {
457     cl_get_platform_info(
458         platform,
459         param_name,
460         param_value_size,
461         param_value,
462         param_value_size_ret,
463     )
464 }
465 
466 #[no_mangle]
clGetExtensionFunctionAddress( function_name: *const ::std::os::raw::c_char, ) -> *mut ::std::ffi::c_void467 extern "C" fn clGetExtensionFunctionAddress(
468     function_name: *const ::std::os::raw::c_char,
469 ) -> *mut ::std::ffi::c_void {
470     cl_get_extension_function_address(function_name)
471 }
472 
473 #[no_mangle]
clIcdGetPlatformIDsKHR( num_entries: cl_uint, platforms: *mut cl_platform_id, num_platforms: *mut cl_uint, ) -> cl_int474 extern "C" fn clIcdGetPlatformIDsKHR(
475     num_entries: cl_uint,
476     platforms: *mut cl_platform_id,
477     num_platforms: *mut cl_uint,
478 ) -> cl_int {
479     cl_get_platform_ids(num_entries, platforms, num_platforms)
480 }
481 
cl_get_extension_function_address( function_name: *const ::std::os::raw::c_char, ) -> *mut ::std::ffi::c_void482 extern "C" fn cl_get_extension_function_address(
483     function_name: *const ::std::os::raw::c_char,
484 ) -> *mut ::std::ffi::c_void {
485     if function_name.is_null() {
486         return ptr::null_mut();
487     }
488     match unsafe { CStr::from_ptr(function_name) }.to_str().unwrap() {
489         // cl_khr_create_command_queue
490         "clCreateCommandQueueWithPropertiesKHR" => {
491             cl_create_command_queue_with_properties as *mut ::std::ffi::c_void
492         }
493 
494         // cl_khr_icd
495         "clGetPlatformInfo" => cl_get_platform_info as *mut ::std::ffi::c_void,
496         "clIcdGetPlatformIDsKHR" => cl_get_platform_ids as *mut ::std::ffi::c_void,
497 
498         // cl_khr_il_program
499         "clCreateProgramWithILKHR" => cl_create_program_with_il as *mut ::std::ffi::c_void,
500 
501         // cl_khr_gl_sharing
502         "clCreateFromGLBuffer" => cl_create_from_gl_buffer as *mut ::std::ffi::c_void,
503         "clCreateFromGLRenderbuffer" => cl_create_from_gl_renderbuffer as *mut ::std::ffi::c_void,
504         "clCreateFromGLTexture" => cl_create_from_gl_texture as *mut ::std::ffi::c_void,
505         "clCreateFromGLTexture2D" => cl_create_from_gl_texture_2d as *mut ::std::ffi::c_void,
506         "clCreateFromGLTexture3D" => cl_create_from_gl_texture_3d as *mut ::std::ffi::c_void,
507         "clEnqueueAcquireGLObjects" => cl_enqueue_acquire_gl_objects as *mut ::std::ffi::c_void,
508         "clEnqueueReleaseGLObjects" => cl_enqueue_release_gl_objects as *mut ::std::ffi::c_void,
509         "clGetGLContextInfoKHR" => cl_get_gl_context_info_khr as *mut ::std::ffi::c_void,
510         "clGetGLObjectInfo" => cl_get_gl_object_info as *mut ::std::ffi::c_void,
511         "clGetGLTextureInfo" => cl_get_gl_texture_info as *mut ::std::ffi::c_void,
512 
513         // cl_arm_shared_virtual_memory
514         "clEnqueueSVMFreeARM" => cl_enqueue_svm_free_arm as *mut ::std::ffi::c_void,
515         "clEnqueueSVMMapARM" => cl_enqueue_svm_map_arm as *mut ::std::ffi::c_void,
516         "clEnqueueSVMMemcpyARM" => cl_enqueue_svm_memcpy_arm as *mut ::std::ffi::c_void,
517         "clEnqueueSVMMemFillARM" => cl_enqueue_svm_mem_fill_arm as *mut ::std::ffi::c_void,
518         "clEnqueueSVMUnmapARM" => cl_enqueue_svm_unmap_arm as *mut ::std::ffi::c_void,
519         "clSetKernelArgSVMPointerARM" => cl_set_kernel_arg_svm_pointer as *mut ::std::ffi::c_void,
520         "clSetKernelExecInfoARM" => cl_set_kernel_exec_info as *mut ::std::ffi::c_void,
521         "clSVMAllocARM" => cl_svm_alloc as *mut ::std::ffi::c_void,
522         "clSVMFreeARM" => cl_svm_free as *mut ::std::ffi::c_void,
523 
524         // DPCPP bug https://github.com/intel/llvm/issues/9964
525         "clSetProgramSpecializationConstant" => {
526             cl_set_program_specialization_constant as *mut ::std::ffi::c_void
527         }
528 
529         _ => ptr::null_mut(),
530     }
531 }
532 
cl_link_program( context: cl_context, num_devices: cl_uint, device_list: *const cl_device_id, options: *const ::std::os::raw::c_char, num_input_programs: cl_uint, input_programs: *const cl_program, pfn_notify: Option<FuncProgramCB>, user_data: *mut ::std::os::raw::c_void, errcode_ret: *mut cl_int, ) -> cl_program533 extern "C" fn cl_link_program(
534     context: cl_context,
535     num_devices: cl_uint,
536     device_list: *const cl_device_id,
537     options: *const ::std::os::raw::c_char,
538     num_input_programs: cl_uint,
539     input_programs: *const cl_program,
540     pfn_notify: Option<FuncProgramCB>,
541     user_data: *mut ::std::os::raw::c_void,
542     errcode_ret: *mut cl_int,
543 ) -> cl_program {
544     let (ptr, err) = match link_program(
545         context,
546         num_devices,
547         device_list,
548         options,
549         num_input_programs,
550         input_programs,
551         pfn_notify,
552         user_data,
553     ) {
554         Ok((prog, code)) => (prog, code),
555         Err(e) => (ptr::null_mut(), e),
556     };
557 
558     errcode_ret.write_checked(err);
559     ptr
560 }
561 
cl_get_extension_function_address_for_platform( _platform: cl_platform_id, function_name: *const ::std::os::raw::c_char, ) -> *mut ::std::os::raw::c_void562 extern "C" fn cl_get_extension_function_address_for_platform(
563     _platform: cl_platform_id,
564     function_name: *const ::std::os::raw::c_char,
565 ) -> *mut ::std::os::raw::c_void {
566     cl_get_extension_function_address(function_name)
567 }
568 
cl_svm_alloc( context: cl_context, flags: cl_svm_mem_flags, size: usize, alignment: ::std::os::raw::c_uint, ) -> *mut ::std::os::raw::c_void569 extern "C" fn cl_svm_alloc(
570     context: cl_context,
571     flags: cl_svm_mem_flags,
572     size: usize,
573     alignment: ::std::os::raw::c_uint,
574 ) -> *mut ::std::os::raw::c_void {
575     svm_alloc(context, flags, size, alignment).unwrap_or(ptr::null_mut())
576 }
577 
cl_svm_free(context: cl_context, svm_pointer: *mut ::std::os::raw::c_void)578 extern "C" fn cl_svm_free(context: cl_context, svm_pointer: *mut ::std::os::raw::c_void) {
579     svm_free(context, svm_pointer as usize).ok();
580 }
581 
cl_get_kernel_sub_group_info( kernel: cl_kernel, device: cl_device_id, param_name: cl_kernel_sub_group_info, input_value_size: usize, input_value: *const ::std::os::raw::c_void, param_value_size: usize, param_value: *mut ::std::os::raw::c_void, param_value_size_ret: *mut usize, ) -> cl_int582 extern "C" fn cl_get_kernel_sub_group_info(
583     kernel: cl_kernel,
584     device: cl_device_id,
585     param_name: cl_kernel_sub_group_info,
586     input_value_size: usize,
587     input_value: *const ::std::os::raw::c_void,
588     param_value_size: usize,
589     param_value: *mut ::std::os::raw::c_void,
590     param_value_size_ret: *mut usize,
591 ) -> cl_int {
592     match kernel.get_info_obj(
593         (device, input_value_size, input_value, param_value_size),
594         param_name,
595         param_value_size,
596         param_value,
597         param_value_size_ret,
598     ) {
599         Ok(_) => CL_SUCCESS as cl_int,
600         Err(e) => e,
601     }
602 }
603