xref: /aosp_15_r20/external/mesa3d/src/gallium/frontends/rusticl/api/icd.rs (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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::platform::*;
10 use crate::api::program::*;
11 use crate::api::queue::*;
12 use crate::api::types::*;
13 use crate::api::util::*;
14 
15 use mesa_rust_util::ptr::*;
16 use rusticl_opencl_gen::*;
17 
18 use std::ffi::c_char;
19 use std::ffi::c_void;
20 use std::ffi::CStr;
21 use std::ptr;
22 use std::sync::Arc;
23 
24 pub static DISPATCH: cl_icd_dispatch = cl_icd_dispatch {
25     clGetPlatformIDs: Some(clGetPlatformIDs),
26     clGetPlatformInfo: Some(clGetPlatformInfo),
27     clGetDeviceIDs: Some(clGetDeviceIDs),
28     clGetDeviceInfo: Some(clGetDeviceInfo),
29     clCreateContext: Some(clCreateContext),
30     clCreateContextFromType: Some(clCreateContextFromType),
31     clRetainContext: Some(clRetainContext),
32     clReleaseContext: Some(clReleaseContext),
33     clGetContextInfo: Some(clGetContextInfo),
34     clCreateCommandQueue: Some(clCreateCommandQueue),
35     clRetainCommandQueue: Some(clRetainCommandQueue),
36     clReleaseCommandQueue: Some(clReleaseCommandQueue),
37     clGetCommandQueueInfo: Some(clGetCommandQueueInfo),
38     clSetCommandQueueProperty: Some(clSetCommandQueueProperty),
39     clCreateBuffer: Some(clCreateBuffer),
40     clCreateImage2D: Some(clCreateImage2D),
41     clCreateImage3D: Some(clCreateImage3D),
42     clRetainMemObject: Some(clRetainMemObject),
43     clReleaseMemObject: Some(clReleaseMemObject),
44     clGetSupportedImageFormats: Some(clGetSupportedImageFormats),
45     clGetMemObjectInfo: Some(clGetMemObjectInfo),
46     clGetImageInfo: Some(clGetImageInfo),
47     clCreateSampler: Some(clCreateSampler),
48     clRetainSampler: Some(clRetainSampler),
49     clReleaseSampler: Some(clReleaseSampler),
50     clGetSamplerInfo: Some(clGetSamplerInfo),
51     clCreateProgramWithSource: Some(clCreateProgramWithSource),
52     clCreateProgramWithBinary: Some(clCreateProgramWithBinary),
53     clRetainProgram: Some(clRetainProgram),
54     clReleaseProgram: Some(clReleaseProgram),
55     clBuildProgram: Some(clBuildProgram),
56     clUnloadCompiler: None,
57     clGetProgramInfo: Some(clGetProgramInfo),
58     clGetProgramBuildInfo: Some(clGetProgramBuildInfo),
59     clCreateKernel: Some(clCreateKernel),
60     clCreateKernelsInProgram: Some(clCreateKernelsInProgram),
61     clRetainKernel: Some(clRetainKernel),
62     clReleaseKernel: Some(clReleaseKernel),
63     clSetKernelArg: Some(clSetKernelArg),
64     clGetKernelInfo: Some(clGetKernelInfo),
65     clGetKernelWorkGroupInfo: Some(clGetKernelWorkGroupInfo),
66     clWaitForEvents: Some(clWaitForEvents),
67     clGetEventInfo: Some(clGetEventInfo),
68     clRetainEvent: Some(clRetainEvent),
69     clReleaseEvent: Some(clReleaseEvent),
70     clGetEventProfilingInfo: Some(clGetEventProfilingInfo),
71     clFlush: Some(clFlush),
72     clFinish: Some(clFinish),
73     clEnqueueReadBuffer: Some(clEnqueueReadBuffer),
74     clEnqueueWriteBuffer: Some(clEnqueueWriteBuffer),
75     clEnqueueCopyBuffer: Some(clEnqueueCopyBuffer),
76     clEnqueueReadImage: Some(clEnqueueReadImage),
77     clEnqueueWriteImage: Some(clEnqueueWriteImage),
78     clEnqueueCopyImage: Some(clEnqueueCopyImage),
79     clEnqueueCopyImageToBuffer: Some(clEnqueueCopyImageToBuffer),
80     clEnqueueCopyBufferToImage: Some(clEnqueueCopyBufferToImage),
81     clEnqueueMapBuffer: Some(clEnqueueMapBuffer),
82     clEnqueueMapImage: Some(clEnqueueMapImage),
83     clEnqueueUnmapMemObject: Some(clEnqueueUnmapMemObject),
84     clEnqueueNDRangeKernel: Some(clEnqueueNDRangeKernel),
85     clEnqueueTask: Some(clEnqueueTask),
86     clEnqueueNativeKernel: None,
87     clEnqueueMarker: Some(clEnqueueMarker),
88     clEnqueueWaitForEvents: None,
89     clEnqueueBarrier: Some(clEnqueueBarrier),
90     clGetExtensionFunctionAddress: Some(clGetExtensionFunctionAddress),
91     clCreateFromGLBuffer: Some(clCreateFromGLBuffer),
92     clCreateFromGLTexture2D: Some(clCreateFromGLTexture2D),
93     clCreateFromGLTexture3D: Some(clCreateFromGLTexture3D),
94     clCreateFromGLRenderbuffer: Some(clCreateFromGLRenderbuffer),
95     clGetGLObjectInfo: Some(clGetGLObjectInfo),
96     clGetGLTextureInfo: Some(clGetGLTextureInfo),
97     clEnqueueAcquireGLObjects: Some(clEnqueueAcquireGLObjects),
98     clEnqueueReleaseGLObjects: Some(clEnqueueReleaseGLObjects),
99     clGetGLContextInfoKHR: Some(clGetGLContextInfoKHR),
100     clGetDeviceIDsFromD3D10KHR: ptr::null_mut(),
101     clCreateFromD3D10BufferKHR: ptr::null_mut(),
102     clCreateFromD3D10Texture2DKHR: ptr::null_mut(),
103     clCreateFromD3D10Texture3DKHR: ptr::null_mut(),
104     clEnqueueAcquireD3D10ObjectsKHR: ptr::null_mut(),
105     clEnqueueReleaseD3D10ObjectsKHR: ptr::null_mut(),
106     clSetEventCallback: Some(clSetEventCallback),
107     clCreateSubBuffer: Some(clCreateSubBuffer),
108     clSetMemObjectDestructorCallback: Some(clSetMemObjectDestructorCallback),
109     clCreateUserEvent: Some(clCreateUserEvent),
110     clSetUserEventStatus: Some(clSetUserEventStatus),
111     clEnqueueReadBufferRect: Some(clEnqueueReadBufferRect),
112     clEnqueueWriteBufferRect: Some(clEnqueueWriteBufferRect),
113     clEnqueueCopyBufferRect: Some(clEnqueueCopyBufferRect),
114     clCreateSubDevicesEXT: None,
115     clRetainDeviceEXT: None,
116     clReleaseDeviceEXT: None,
117     clCreateEventFromGLsyncKHR: None,
118     clCreateSubDevices: Some(clCreateSubDevices),
119     clRetainDevice: Some(clRetainDevice),
120     clReleaseDevice: Some(clReleaseDevice),
121     clCreateImage: Some(clCreateImage),
122     clCreateProgramWithBuiltInKernels: None,
123     clCompileProgram: Some(clCompileProgram),
124     clLinkProgram: Some(clLinkProgram),
125     clUnloadPlatformCompiler: Some(clUnloadPlatformCompiler),
126     clGetKernelArgInfo: Some(clGetKernelArgInfo),
127     clEnqueueFillBuffer: Some(clEnqueueFillBuffer),
128     clEnqueueFillImage: Some(clEnqueueFillImage),
129     clEnqueueMigrateMemObjects: Some(clEnqueueMigrateMemObjects),
130     clEnqueueMarkerWithWaitList: Some(clEnqueueMarkerWithWaitList),
131     clEnqueueBarrierWithWaitList: Some(clEnqueueBarrierWithWaitList),
132     clGetExtensionFunctionAddressForPlatform: Some(clGetExtensionFunctionAddressForPlatform),
133     clCreateFromGLTexture: Some(clCreateFromGLTexture),
134     clGetDeviceIDsFromD3D11KHR: ptr::null_mut(),
135     clCreateFromD3D11BufferKHR: ptr::null_mut(),
136     clCreateFromD3D11Texture2DKHR: ptr::null_mut(),
137     clCreateFromD3D11Texture3DKHR: ptr::null_mut(),
138     clCreateFromDX9MediaSurfaceKHR: ptr::null_mut(),
139     clEnqueueAcquireD3D11ObjectsKHR: ptr::null_mut(),
140     clEnqueueReleaseD3D11ObjectsKHR: ptr::null_mut(),
141     clGetDeviceIDsFromDX9MediaAdapterKHR: ptr::null_mut(),
142     clEnqueueAcquireDX9MediaSurfacesKHR: ptr::null_mut(),
143     clEnqueueReleaseDX9MediaSurfacesKHR: ptr::null_mut(),
144     clCreateFromEGLImageKHR: None,
145     clEnqueueAcquireEGLObjectsKHR: None,
146     clEnqueueReleaseEGLObjectsKHR: None,
147     clCreateEventFromEGLSyncKHR: None,
148     clCreateCommandQueueWithProperties: Some(clCreateCommandQueueWithProperties),
149     clCreatePipe: Some(clCreatePipe),
150     clGetPipeInfo: Some(clGetPipeInfo),
151     clSVMAlloc: Some(clSVMAlloc),
152     clSVMFree: Some(clSVMFree),
153     clEnqueueSVMFree: Some(clEnqueueSVMFree),
154     clEnqueueSVMMemcpy: Some(clEnqueueSVMMemcpy),
155     clEnqueueSVMMemFill: Some(clEnqueueSVMMemFill),
156     clEnqueueSVMMap: Some(clEnqueueSVMMap),
157     clEnqueueSVMUnmap: Some(clEnqueueSVMUnmap),
158     clCreateSamplerWithProperties: Some(clCreateSamplerWithProperties),
159     clSetKernelArgSVMPointer: Some(clSetKernelArgSVMPointer),
160     clSetKernelExecInfo: Some(clSetKernelExecInfo),
161     clGetKernelSubGroupInfoKHR: Some(clGetKernelSubGroupInfo),
162     clCloneKernel: Some(clCloneKernel),
163     clCreateProgramWithIL: Some(clCreateProgramWithIL),
164     clEnqueueSVMMigrateMem: Some(clEnqueueSVMMigrateMem),
165     clGetDeviceAndHostTimer: Some(clGetDeviceAndHostTimer),
166     clGetHostTimer: Some(clGetHostTimer),
167     clGetKernelSubGroupInfo: Some(clGetKernelSubGroupInfo),
168     clSetDefaultDeviceCommandQueue: Some(clSetDefaultDeviceCommandQueue),
169     clSetProgramReleaseCallback: Some(clSetProgramReleaseCallback),
170     clSetProgramSpecializationConstant: Some(clSetProgramSpecializationConstant),
171     clCreateBufferWithProperties: Some(clCreateBufferWithProperties),
172     clCreateImageWithProperties: Some(clCreateImageWithProperties),
173     clSetContextDestructorCallback: Some(clSetContextDestructorCallback),
174 };
175 
176 pub type CLError = cl_int;
177 pub type CLResult<T> = Result<T, CLError>;
178 
179 #[derive(Clone, Copy, PartialEq)]
180 #[repr(u32)]
181 pub enum RusticlTypes {
182     // random number
183     Buffer = 0xec4cf9a9,
184     Context,
185     Device,
186     Event,
187     Image,
188     Kernel,
189     Program,
190     Queue,
191     Sampler,
192 }
193 
194 impl RusticlTypes {
u32(&self) -> u32195     pub const fn u32(&self) -> u32 {
196         *self as u32
197     }
198 
from_u32(val: u32) -> Option<Self>199     pub const fn from_u32(val: u32) -> Option<Self> {
200         let result = match val {
201             0xec4cf9a9 => Self::Buffer,
202             0xec4cf9aa => Self::Context,
203             0xec4cf9ab => Self::Device,
204             0xec4cf9ac => Self::Event,
205             0xec4cf9ad => Self::Image,
206             0xec4cf9ae => Self::Kernel,
207             0xec4cf9af => Self::Program,
208             0xec4cf9b0 => Self::Queue,
209             0xec4cf9b1 => Self::Sampler,
210             _ => return None,
211         };
212         debug_assert!(result.u32() == val);
213         Some(result)
214     }
215 }
216 
217 #[repr(C)]
218 pub struct CLObjectBase<const ERR: i32> {
219     dispatch: &'static cl_icd_dispatch,
220     rusticl_type: u32,
221 }
222 
223 impl<const ERR: i32> CLObjectBase<ERR> {
new(t: RusticlTypes) -> Self224     pub fn new(t: RusticlTypes) -> Self {
225         Self {
226             dispatch: &DISPATCH,
227             rusticl_type: t.u32(),
228         }
229     }
230 
check_ptr(ptr: *const Self) -> CLResult<RusticlTypes>231     pub fn check_ptr(ptr: *const Self) -> CLResult<RusticlTypes> {
232         if ptr.is_null() {
233             return Err(ERR);
234         }
235 
236         unsafe {
237             if !::std::ptr::eq((*ptr).dispatch, &DISPATCH) {
238                 return Err(ERR);
239             }
240 
241             let Some(ty) = RusticlTypes::from_u32((*ptr).rusticl_type) else {
242                 return Err(ERR);
243             };
244 
245             Ok(ty)
246         }
247     }
248 
get_type(&self) -> CLResult<RusticlTypes>249     pub fn get_type(&self) -> CLResult<RusticlTypes> {
250         RusticlTypes::from_u32(self.rusticl_type).ok_or(ERR)
251     }
252 }
253 
254 pub trait ReferenceCountedAPIPointer<T, const ERR: i32> {
get_ptr(&self) -> CLResult<*const T>255     fn get_ptr(&self) -> CLResult<*const T>;
256 
257     // TODO:  I can't find a trait that would let me say T: pointer so that
258     // I can do the cast in the main trait implementation.  So we need to
259     // implement that as part of the macro where we know the real type.
from_ptr(ptr: *const T) -> Self260     fn from_ptr(ptr: *const T) -> Self;
261 }
262 
263 pub trait BaseCLObject<'a, const ERR: i32, CL: ReferenceCountedAPIPointer<Self, ERR> + 'a>:
264     Sized
265 {
ref_from_raw(obj: CL) -> CLResult<&'a Self>266     fn ref_from_raw(obj: CL) -> CLResult<&'a Self> {
267         let obj = obj.get_ptr()?;
268         // SAFETY: `get_ptr` already checks if it's one of our pointers and not null
269         Ok(unsafe { &*obj })
270     }
271 
refs_from_arr(objs: *const CL, count: u32) -> CLResult<Vec<&'a Self>> where CL: Copy,272     fn refs_from_arr(objs: *const CL, count: u32) -> CLResult<Vec<&'a Self>>
273     where
274         CL: Copy,
275     {
276         // CL spec requires validation for obj arrays, both values have to make sense
277         if objs.is_null() && count > 0 || !objs.is_null() && count == 0 {
278             return Err(CL_INVALID_VALUE);
279         }
280 
281         let mut res = Vec::new();
282         if objs.is_null() || count == 0 {
283             return Ok(res);
284         }
285 
286         for i in 0..count as usize {
287             res.push(Self::ref_from_raw(unsafe { *objs.add(i) })?);
288         }
289         Ok(res)
290     }
291 }
292 
293 pub trait ArcedCLObject<'a, const ERR: i32, CL: ReferenceCountedAPIPointer<Self, ERR> + 'a>:
294     Sized + BaseCLObject<'a, ERR, CL>
295 {
296     /// Note: this operation increases the internal ref count as `ref_from_raw` is the better option
297     /// when an Arc is not needed.
arc_from_raw(ptr: CL) -> CLResult<Arc<Self>>298     fn arc_from_raw(ptr: CL) -> CLResult<Arc<Self>> {
299         let ptr = ptr.get_ptr()?;
300         // SAFETY: `get_ptr` already checks if it's one of our pointers.
301         Ok(unsafe {
302             Arc::increment_strong_count(ptr);
303             Arc::from_raw(ptr)
304         })
305     }
306 
arcs_from_arr(objs: *const CL, count: u32) -> CLResult<Vec<Arc<Self>>> where CL: Copy,307     fn arcs_from_arr(objs: *const CL, count: u32) -> CLResult<Vec<Arc<Self>>>
308     where
309         CL: Copy,
310     {
311         // CL spec requires validation for obj arrays, both values have to make sense
312         if objs.is_null() && count > 0 || !objs.is_null() && count == 0 {
313             return Err(CL_INVALID_VALUE);
314         }
315 
316         let mut res = Vec::new();
317         if objs.is_null() || count == 0 {
318             return Ok(res);
319         }
320 
321         for i in 0..count as usize {
322             unsafe {
323                 res.push(Self::arc_from_raw(*objs.add(i))?);
324             }
325         }
326         Ok(res)
327     }
328 
refcnt(ptr: CL) -> CLResult<u32>329     fn refcnt(ptr: CL) -> CLResult<u32> {
330         let ptr = ptr.get_ptr()?;
331         // SAFETY: `get_ptr` already checks if it's one of our pointers.
332         let arc = unsafe { Arc::from_raw(ptr) };
333         let res = Arc::strong_count(&arc);
334         // leak the arc again, so we don't reduce the refcount by dropping `arc`
335         let _ = Arc::into_raw(arc);
336         Ok(res as u32)
337     }
338 
into_cl(self: Arc<Self>) -> CL339     fn into_cl(self: Arc<Self>) -> CL {
340         CL::from_ptr(Arc::into_raw(self))
341     }
342 
release(ptr: CL) -> CLResult<()>343     fn release(ptr: CL) -> CLResult<()> {
344         let ptr = ptr.get_ptr()?;
345         // SAFETY: `get_ptr` already checks if it's one of our pointers.
346         unsafe { Arc::decrement_strong_count(ptr) };
347         Ok(())
348     }
349 
retain(ptr: CL) -> CLResult<()>350     fn retain(ptr: CL) -> CLResult<()> {
351         let ptr = ptr.get_ptr()?;
352         // SAFETY: `get_ptr` already checks if it's one of our pointers.
353         unsafe { Arc::increment_strong_count(ptr) };
354         Ok(())
355     }
356 }
357 
358 #[macro_export]
359 macro_rules! impl_cl_type_trait_base {
360     (@BASE $cl: ident, $t: ident, [$($types: ident),+], $err: ident, $($field:ident).+) => {
361         impl $crate::api::icd::ReferenceCountedAPIPointer<$t, $err> for $cl {
362             fn get_ptr(&self) -> CLResult<*const $t> {
363                 type Base = $crate::api::icd::CLObjectBase<$err>;
364                 let t = Base::check_ptr(self.cast())?;
365                 if ![$($crate::api::icd::RusticlTypes::$types),+].contains(&t) {
366                     return Err($err);
367                 }
368 
369                 let offset = ::mesa_rust_util::offset_of!($t, $($field).+);
370                 // SAFETY: We offset the pointer back from the ICD specified base type to our
371                 //         internal type.
372                 let obj_ptr: *const $t = unsafe { self.byte_sub(offset) }.cast();
373 
374                 // Check at compile-time that we indeed got the right path
375                 unsafe { let _: &Base = &(*obj_ptr).$($field).+; }
376 
377                 Ok(obj_ptr)
378             }
379 
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.byte_add(offset) as Self }
388             }
389         }
390 
391         impl $crate::api::icd::BaseCLObject<'_, $err, $cl> for $t {}
392 
393         impl $t {
394             fn _ensure_send_sync(&self) -> impl Send + Sync + '_ {
395                 self
396             }
397         }
398 
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                 std::ptr::addr_eq(self, other)
407             }
408         }
409 
410         impl std::hash::Hash for $t {
411             fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
412                 std::ptr::from_ref(self).hash(state);
413             }
414         }
415     };
416 
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     };
420 
421     ($cl: ident, $t: ident, [$($types: ident),+], $err: ident) => {
422         $crate::impl_cl_type_trait_base!($cl, $t, [$($types),+], $err, base);
423     };
424 }
425 
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     };
432 
433     ($cl: ident, $t: ident, $err: ident) => {
434         $crate::impl_cl_type_trait!($cl, $t, $err, base);
435     };
436 }
437 
438 // We need those functions exported
439 
440 #[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_int441 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     platform::clGetPlatformInfo(
449         platform,
450         param_name,
451         param_value_size,
452         param_value,
453         param_value_size_ret,
454     )
455 }
456 
457 #[no_mangle]
clIcdGetPlatformIDsKHR( num_entries: cl_uint, platforms: *mut cl_platform_id, num_platforms: *mut cl_uint, ) -> cl_int458 extern "C" fn clIcdGetPlatformIDsKHR(
459     num_entries: cl_uint,
460     platforms: *mut cl_platform_id,
461     num_platforms: *mut cl_uint,
462 ) -> cl_int {
463     clGetPlatformIDs(num_entries, platforms, num_platforms)
464 }
465 
466 macro_rules! cl_ext_func {
467     ($func:ident: $api_type:ident) => {{
468         let _func: $api_type = Some($func);
469         $func as *mut ::std::ffi::c_void
470     }};
471 }
472 
473 #[rustfmt::skip]
474 #[no_mangle]
clGetExtensionFunctionAddress( function_name: *const c_char, ) -> *mut c_void475 extern "C" fn clGetExtensionFunctionAddress(
476     function_name: *const c_char,
477 ) -> *mut c_void {
478     if function_name.is_null() {
479         return ptr::null_mut();
480     }
481     match unsafe { CStr::from_ptr(function_name) }.to_str().unwrap() {
482         // cl_khr_create_command_queue
483         "clCreateCommandQueueWithPropertiesKHR" => cl_ext_func!(clCreateCommandQueueWithProperties: clCreateCommandQueueWithPropertiesKHR_fn),
484 
485         // cl_khr_icd
486         "clGetPlatformInfo" => cl_ext_func!(clGetPlatformInfo: cl_api_clGetPlatformInfo),
487         "clIcdGetPlatformIDsKHR" => cl_ext_func!(clIcdGetPlatformIDsKHR: clIcdGetPlatformIDsKHR_fn),
488 
489         // cl_khr_il_program
490         "clCreateProgramWithILKHR" => cl_ext_func!(clCreateProgramWithIL: clCreateProgramWithILKHR_fn),
491 
492         // cl_khr_gl_sharing
493         "clCreateFromGLBuffer" => cl_ext_func!(clCreateFromGLBuffer: cl_api_clCreateFromGLBuffer),
494         "clCreateFromGLRenderbuffer" => cl_ext_func!(clCreateFromGLRenderbuffer: cl_api_clCreateFromGLRenderbuffer),
495         "clCreateFromGLTexture" => cl_ext_func!(clCreateFromGLTexture: cl_api_clCreateFromGLTexture),
496         "clCreateFromGLTexture2D" => cl_ext_func!(clCreateFromGLTexture2D: cl_api_clCreateFromGLTexture2D),
497         "clCreateFromGLTexture3D" => cl_ext_func!(clCreateFromGLTexture3D: cl_api_clCreateFromGLTexture3D),
498         "clEnqueueAcquireGLObjects" => cl_ext_func!(clEnqueueAcquireGLObjects: cl_api_clEnqueueAcquireGLObjects),
499         "clEnqueueReleaseGLObjects" => cl_ext_func!(clEnqueueReleaseGLObjects: cl_api_clEnqueueReleaseGLObjects),
500         "clGetGLContextInfoKHR" => cl_ext_func!(clGetGLContextInfoKHR: cl_api_clGetGLContextInfoKHR),
501         "clGetGLObjectInfo" => cl_ext_func!(clGetGLObjectInfo: cl_api_clGetGLObjectInfo),
502         "clGetGLTextureInfo" => cl_ext_func!(clGetGLTextureInfo: cl_api_clGetGLTextureInfo),
503 
504         // cl_khr_suggested_local_work_size
505         "clGetKernelSuggestedLocalWorkSizeKHR" => cl_ext_func!(clGetKernelSuggestedLocalWorkSizeKHR: clGetKernelSuggestedLocalWorkSizeKHR_fn),
506 
507         // cl_arm_shared_virtual_memory
508         "clEnqueueSVMFreeARM" => cl_ext_func!(clEnqueueSVMFreeARM: cl_api_clEnqueueSVMFree),
509         "clEnqueueSVMMapARM" => cl_ext_func!(clEnqueueSVMMapARM: cl_api_clEnqueueSVMMap),
510         "clEnqueueSVMMemcpyARM" => cl_ext_func!(clEnqueueSVMMemcpyARM: cl_api_clEnqueueSVMMemcpy),
511         "clEnqueueSVMMemFillARM" => cl_ext_func!(clEnqueueSVMMemFillARM: cl_api_clEnqueueSVMMemFill),
512         "clEnqueueSVMUnmapARM" => cl_ext_func!(clEnqueueSVMUnmapARM: cl_api_clEnqueueSVMUnmap),
513         "clSetKernelArgSVMPointerARM" => cl_ext_func!(clSetKernelArgSVMPointer: cl_api_clSetKernelArgSVMPointer),
514         "clSetKernelExecInfoARM" => cl_ext_func!(clSetKernelExecInfo: cl_api_clSetKernelExecInfo),
515         "clSVMAllocARM" => cl_ext_func!(clSVMAlloc: cl_api_clSVMAlloc),
516         "clSVMFreeARM" => cl_ext_func!(clSVMFree: cl_api_clSVMFree),
517 
518         // DPCPP bug https://github.com/intel/llvm/issues/9964
519         "clSetProgramSpecializationConstant" => cl_ext_func!(clSetProgramSpecializationConstant: cl_api_clSetProgramSpecializationConstant),
520 
521         _ => ptr::null_mut(),
522     }
523 }
524 
clLinkProgram( 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_program525 extern "C" fn clLinkProgram(
526     context: cl_context,
527     num_devices: cl_uint,
528     device_list: *const cl_device_id,
529     options: *const ::std::os::raw::c_char,
530     num_input_programs: cl_uint,
531     input_programs: *const cl_program,
532     pfn_notify: Option<FuncProgramCB>,
533     user_data: *mut ::std::os::raw::c_void,
534     errcode_ret: *mut cl_int,
535 ) -> cl_program {
536     let (ptr, err) = match link_program(
537         context,
538         num_devices,
539         device_list,
540         options,
541         num_input_programs,
542         input_programs,
543         pfn_notify,
544         user_data,
545     ) {
546         Ok((prog, code)) => (prog, code),
547         Err(e) => (ptr::null_mut(), e),
548     };
549 
550     errcode_ret.write_checked(err);
551     ptr
552 }
553 
clGetExtensionFunctionAddressForPlatform( _platform: cl_platform_id, function_name: *const ::std::os::raw::c_char, ) -> *mut ::std::os::raw::c_void554 extern "C" fn clGetExtensionFunctionAddressForPlatform(
555     _platform: cl_platform_id,
556     function_name: *const ::std::os::raw::c_char,
557 ) -> *mut ::std::os::raw::c_void {
558     clGetExtensionFunctionAddress(function_name)
559 }
560 
clSVMAlloc( context: cl_context, flags: cl_svm_mem_flags, size: usize, alignment: ::std::os::raw::c_uint, ) -> *mut ::std::os::raw::c_void561 extern "C" fn clSVMAlloc(
562     context: cl_context,
563     flags: cl_svm_mem_flags,
564     size: usize,
565     alignment: ::std::os::raw::c_uint,
566 ) -> *mut ::std::os::raw::c_void {
567     svm_alloc(context, flags, size, alignment).unwrap_or(ptr::null_mut())
568 }
569 
clSVMFree(context: cl_context, svm_pointer: *mut ::std::os::raw::c_void)570 extern "C" fn clSVMFree(context: cl_context, svm_pointer: *mut ::std::os::raw::c_void) {
571     svm_free(context, svm_pointer as usize).ok();
572 }
573 
clGetKernelSubGroupInfo( 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_int574 extern "C" fn clGetKernelSubGroupInfo(
575     kernel: cl_kernel,
576     device: cl_device_id,
577     param_name: cl_kernel_sub_group_info,
578     input_value_size: usize,
579     input_value: *const ::std::os::raw::c_void,
580     param_value_size: usize,
581     param_value: *mut ::std::os::raw::c_void,
582     param_value_size_ret: *mut usize,
583 ) -> cl_int {
584     match kernel.get_info_obj(
585         (device, input_value_size, input_value, param_value_size),
586         param_name,
587         param_value_size,
588         param_value,
589         param_value_size_ret,
590     ) {
591         Ok(_) => CL_SUCCESS as cl_int,
592         Err(e) => e,
593     }
594 }
595