rusticl/icd: remove CLObject
[mesa.git] / src / gallium / frontends / rusticl / api / icd.rs
blob7af9b53266c0b42a9c2f8638ce533887ebc129f5
1 #![allow(non_snake_case)]
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::*;
14 use mesa_rust_util::ptr::*;
15 use rusticl_opencl_gen::*;
17 use std::ffi::CStr;
18 use std::ptr;
19 use std::sync::Arc;
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),
173 pub type CLError = cl_int;
174 pub type CLResult<T> = Result<T, CLError>;
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,
191 impl RusticlTypes {
192     pub const fn u32(&self) -> u32 {
193         *self as u32
194     }
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     }
214 #[repr(C)]
215 pub struct CLObjectBase<const ERR: i32> {
216     dispatch: &'static cl_icd_dispatch,
217     rusticl_type: u32,
220 impl<const ERR: i32> CLObjectBase<ERR> {
221     pub fn new(t: RusticlTypes) -> Self {
222         Self {
223             dispatch: &DISPATCH,
224             rusticl_type: t.u32(),
225         }
226     }
228     pub fn check_ptr(ptr: *const Self) -> CLResult<RusticlTypes> {
229         if ptr.is_null() {
230             return Err(ERR);
231         }
233         unsafe {
234             if !::std::ptr::eq((*ptr).dispatch, &DISPATCH) {
235                 return Err(ERR);
236             }
238             let Some(ty) = RusticlTypes::from_u32((*ptr).rusticl_type) else {
239                 return Err(ERR);
240             };
242             Ok(ty)
243         }
244     }
246     pub fn get_type(&self) -> CLResult<RusticlTypes> {
247         RusticlTypes::from_u32(self.rusticl_type).ok_or(ERR)
248     }
251 pub trait ReferenceCountedAPIPointer<T, const ERR: i32> {
252     fn get_ptr(&self) -> CLResult<*const T>;
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.
257     fn from_ptr(ptr: *const T) -> Self;
260 pub trait BaseCLObject<'a, const ERR: i32, CL: ReferenceCountedAPIPointer<Self, ERR> + 'a>:
261     Sized
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     }
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         }
278         let mut res = Vec::new();
279         if objs.is_null() || count == 0 {
280             return Ok(res);
281         }
283         for i in 0..count as usize {
284             res.push(Self::ref_from_raw(unsafe { *objs.add(i) })?);
285         }
286         Ok(res)
287     }
290 pub trait ArcedCLObject<'a, const ERR: i32, CL: ReferenceCountedAPIPointer<Self, ERR> + 'a>:
291     Sized + BaseCLObject<'a, ERR, CL>
293     /// Note: this operation increases the internal ref count as `ref_from_raw` is the better option
294     /// when an Arc is not needed.
295     fn arc_from_raw(ptr: CL) -> CLResult<Arc<Self>> {
296         let ptr = ptr.get_ptr()?;
297         // SAFETY: `get_ptr` already checks if it's one of our pointers.
298         Ok(unsafe {
299             Arc::increment_strong_count(ptr);
300             Arc::from_raw(ptr)
301         })
302     }
304     fn arcs_from_arr(objs: *const CL, count: u32) -> CLResult<Vec<Arc<Self>>>
305     where
306         CL: Copy,
307     {
308         // CL spec requires validation for obj arrays, both values have to make sense
309         if objs.is_null() && count > 0 || !objs.is_null() && count == 0 {
310             return Err(CL_INVALID_VALUE);
311         }
313         let mut res = Vec::new();
314         if objs.is_null() || count == 0 {
315             return Ok(res);
316         }
318         for i in 0..count as usize {
319             unsafe {
320                 res.push(Self::arc_from_raw(*objs.add(i))?);
321             }
322         }
323         Ok(res)
324     }
326     fn refcnt(ptr: CL) -> CLResult<u32> {
327         let ptr = ptr.get_ptr()?;
328         // SAFETY: `get_ptr` already checks if it's one of our pointers.
329         let arc = unsafe { Arc::from_raw(ptr) };
330         let res = Arc::strong_count(&arc);
331         // leak the arc again, so we don't reduce the refcount by dropping `arc`
332         let _ = Arc::into_raw(arc);
333         Ok(res as u32)
334     }
336     fn into_cl(self: Arc<Self>) -> CL {
337         CL::from_ptr(Arc::into_raw(self))
338     }
340     fn release(ptr: CL) -> CLResult<()> {
341         let ptr = ptr.get_ptr()?;
342         // SAFETY: `get_ptr` already checks if it's one of our pointers.
343         unsafe { Arc::decrement_strong_count(ptr) };
344         Ok(())
345     }
347     fn retain(ptr: CL) -> CLResult<()> {
348         let ptr = ptr.get_ptr()?;
349         // SAFETY: `get_ptr` already checks if it's one of our pointers.
350         unsafe { Arc::increment_strong_count(ptr) };
351         Ok(())
352     }
355 #[macro_export]
356 macro_rules! impl_cl_type_trait_base {
357     (@BASE $cl: ident, $t: ident, [$($types: ident),+], $err: ident, $($field:ident).+) => {
358         impl $crate::api::icd::ReferenceCountedAPIPointer<$t, $err> for $cl {
359             fn get_ptr(&self) -> CLResult<*const $t> {
360                 type Base = $crate::api::icd::CLObjectBase<$err>;
361                 let t = Base::check_ptr(self.cast())?;
362                 if ![$($crate::api::icd::RusticlTypes::$types),+].contains(&t) {
363                     return Err($err);
364                 }
366                 let offset = ::mesa_rust_util::offset_of!($t, $($field).+);
367                 let mut obj_ptr: *const u8 = self.cast();
368                 // SAFETY: We offset the pointer back from the ICD specified base type to our
369                 //         internal type.
370                 unsafe { obj_ptr = obj_ptr.sub(offset) }
372                 let obj_ptr: *const $t = obj_ptr.cast();
374                 // Check at compile-time that we indeed got the right path
375                 unsafe { let _: &Base = &(*obj_ptr).$($field).+; }
377                 Ok(obj_ptr)
378             }
380             fn from_ptr(ptr: *const $t) -> Self {
381                 if ptr.is_null() {
382                     return std::ptr::null_mut();
383                 }
384                 let offset = ::mesa_rust_util::offset_of!($t, $($field).+);
385                 // SAFETY: The resulting pointer is safe as we simply offset into the ICD specified
386                 //         base type.
387                 unsafe { (ptr as *const u8).add(offset) as Self }
388             }
389         }
391         impl $crate::api::icd::BaseCLObject<'_, $err, $cl> for $t {}
393         impl $t {
394             fn _ensure_send_sync(&self) -> impl Send + Sync + '_ {
395                 self
396             }
397         }
399         // there are two reason to implement those traits for all objects
400         //   1. it speeds up operations
401         //   2. we want to check for real equality more explicit to stay conformant with the API
402         //      and to not break in subtle ways e.g. using CL objects as keys in HashMaps.
403         impl std::cmp::Eq for $t {}
404         impl std::cmp::PartialEq for $t {
405             fn eq(&self, other: &Self) -> bool {
406                 (self as *const Self) == (other as *const Self)
407             }
408         }
410         impl std::hash::Hash for $t {
411             fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
412                 (self as *const Self).hash(state);
413             }
414         }
415     };
417     ($cl: ident, $t: ident, [$($types: ident),+], $err: ident, $($field:ident).+) => {
418         $crate::impl_cl_type_trait_base!(@BASE $cl, $t, [$($types),+], $err, $($field).+);
419     };
421     ($cl: ident, $t: ident, [$($types: ident),+], $err: ident) => {
422         $crate::impl_cl_type_trait_base!($cl, $t, [$($types),+], $err, base);
423     };
426 #[macro_export]
427 macro_rules! impl_cl_type_trait {
428     ($cl: ident, $t: ident, $err: ident, $($field:ident).+) => {
429         $crate::impl_cl_type_trait_base!(@BASE $cl, $t, [$t], $err, $($field).+);
430         impl $crate::api::icd::ArcedCLObject<'_, $err, $cl> for $t {}
431     };
433     ($cl: ident, $t: ident, $err: ident) => {
434         $crate::impl_cl_type_trait!($cl, $t, $err, base);
435     };
438 // We need those functions exported
440 #[no_mangle]
441 extern "C" fn clGetPlatformInfo(
442     platform: cl_platform_id,
443     param_name: cl_platform_info,
444     param_value_size: usize,
445     param_value: *mut ::std::ffi::c_void,
446     param_value_size_ret: *mut usize,
447 ) -> cl_int {
448     cl_get_platform_info(
449         platform,
450         param_name,
451         param_value_size,
452         param_value,
453         param_value_size_ret,
454     )
457 #[no_mangle]
458 extern "C" fn clGetExtensionFunctionAddress(
459     function_name: *const ::std::os::raw::c_char,
460 ) -> *mut ::std::ffi::c_void {
461     cl_get_extension_function_address(function_name)
464 #[no_mangle]
465 extern "C" fn clIcdGetPlatformIDsKHR(
466     num_entries: cl_uint,
467     platforms: *mut cl_platform_id,
468     num_platforms: *mut cl_uint,
469 ) -> cl_int {
470     cl_get_platform_ids(num_entries, platforms, num_platforms)
473 extern "C" fn cl_get_extension_function_address(
474     function_name: *const ::std::os::raw::c_char,
475 ) -> *mut ::std::ffi::c_void {
476     if function_name.is_null() {
477         return ptr::null_mut();
478     }
479     match unsafe { CStr::from_ptr(function_name) }.to_str().unwrap() {
480         // cl_khr_create_command_queue
481         "clCreateCommandQueueWithPropertiesKHR" => {
482             cl_create_command_queue_with_properties as *mut ::std::ffi::c_void
483         }
485         // cl_khr_icd
486         "clGetPlatformInfo" => cl_get_platform_info as *mut ::std::ffi::c_void,
487         "clIcdGetPlatformIDsKHR" => cl_get_platform_ids as *mut ::std::ffi::c_void,
489         // cl_khr_il_program
490         "clCreateProgramWithILKHR" => cl_create_program_with_il as *mut ::std::ffi::c_void,
492         // cl_khr_gl_sharing
493         "clCreateFromGLBuffer" => cl_create_from_gl_buffer as *mut ::std::ffi::c_void,
494         "clCreateFromGLRenderbuffer" => cl_create_from_gl_renderbuffer as *mut ::std::ffi::c_void,
495         "clCreateFromGLTexture" => cl_create_from_gl_texture as *mut ::std::ffi::c_void,
496         "clCreateFromGLTexture2D" => cl_create_from_gl_texture_2d as *mut ::std::ffi::c_void,
497         "clCreateFromGLTexture3D" => cl_create_from_gl_texture_3d as *mut ::std::ffi::c_void,
498         "clEnqueueAcquireGLObjects" => cl_enqueue_acquire_gl_objects as *mut ::std::ffi::c_void,
499         "clEnqueueReleaseGLObjects" => cl_enqueue_release_gl_objects as *mut ::std::ffi::c_void,
500         "clGetGLContextInfoKHR" => cl_get_gl_context_info_khr as *mut ::std::ffi::c_void,
501         "clGetGLObjectInfo" => cl_get_gl_object_info as *mut ::std::ffi::c_void,
502         "clGetGLTextureInfo" => cl_get_gl_texture_info as *mut ::std::ffi::c_void,
504         // cl_khr_suggested_local_work_size
505         "clGetKernelSuggestedLocalWorkSizeKHR" => {
506             cl_get_kernel_suggested_local_work_size_khr as *mut ::std::ffi::c_void
507         }
509         // cl_arm_shared_virtual_memory
510         "clEnqueueSVMFreeARM" => cl_enqueue_svm_free_arm as *mut ::std::ffi::c_void,
511         "clEnqueueSVMMapARM" => cl_enqueue_svm_map_arm as *mut ::std::ffi::c_void,
512         "clEnqueueSVMMemcpyARM" => cl_enqueue_svm_memcpy_arm as *mut ::std::ffi::c_void,
513         "clEnqueueSVMMemFillARM" => cl_enqueue_svm_mem_fill_arm as *mut ::std::ffi::c_void,
514         "clEnqueueSVMUnmapARM" => cl_enqueue_svm_unmap_arm as *mut ::std::ffi::c_void,
515         "clSetKernelArgSVMPointerARM" => cl_set_kernel_arg_svm_pointer as *mut ::std::ffi::c_void,
516         "clSetKernelExecInfoARM" => cl_set_kernel_exec_info as *mut ::std::ffi::c_void,
517         "clSVMAllocARM" => cl_svm_alloc as *mut ::std::ffi::c_void,
518         "clSVMFreeARM" => cl_svm_free as *mut ::std::ffi::c_void,
520         // DPCPP bug https://github.com/intel/llvm/issues/9964
521         "clSetProgramSpecializationConstant" => {
522             cl_set_program_specialization_constant as *mut ::std::ffi::c_void
523         }
525         _ => ptr::null_mut(),
526     }
529 extern "C" fn cl_link_program(
530     context: cl_context,
531     num_devices: cl_uint,
532     device_list: *const cl_device_id,
533     options: *const ::std::os::raw::c_char,
534     num_input_programs: cl_uint,
535     input_programs: *const cl_program,
536     pfn_notify: Option<FuncProgramCB>,
537     user_data: *mut ::std::os::raw::c_void,
538     errcode_ret: *mut cl_int,
539 ) -> cl_program {
540     let (ptr, err) = match link_program(
541         context,
542         num_devices,
543         device_list,
544         options,
545         num_input_programs,
546         input_programs,
547         pfn_notify,
548         user_data,
549     ) {
550         Ok((prog, code)) => (prog, code),
551         Err(e) => (ptr::null_mut(), e),
552     };
554     errcode_ret.write_checked(err);
555     ptr
558 extern "C" fn cl_get_extension_function_address_for_platform(
559     _platform: cl_platform_id,
560     function_name: *const ::std::os::raw::c_char,
561 ) -> *mut ::std::os::raw::c_void {
562     cl_get_extension_function_address(function_name)
565 extern "C" fn cl_svm_alloc(
566     context: cl_context,
567     flags: cl_svm_mem_flags,
568     size: usize,
569     alignment: ::std::os::raw::c_uint,
570 ) -> *mut ::std::os::raw::c_void {
571     svm_alloc(context, flags, size, alignment).unwrap_or(ptr::null_mut())
574 extern "C" fn cl_svm_free(context: cl_context, svm_pointer: *mut ::std::os::raw::c_void) {
575     svm_free(context, svm_pointer as usize).ok();
578 extern "C" fn cl_get_kernel_sub_group_info(
579     kernel: cl_kernel,
580     device: cl_device_id,
581     param_name: cl_kernel_sub_group_info,
582     input_value_size: usize,
583     input_value: *const ::std::os::raw::c_void,
584     param_value_size: usize,
585     param_value: *mut ::std::os::raw::c_void,
586     param_value_size_ret: *mut usize,
587 ) -> cl_int {
588     match kernel.get_info_obj(
589         (device, input_value_size, input_value, param_value_size),
590         param_name,
591         param_value_size,
592         param_value,
593         param_value_size_ret,
594     ) {
595         Ok(_) => CL_SUCCESS as cl_int,
596         Err(e) => e,
597     }