2 Copyright (c) 2012, Brice Videau <brice.videau@imag.fr>
3 Copyright (c) 2012, Vincent Danjean <Vincent.Danjean@ens-lyon.org>
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
9 1. Redistributions of source code must retain the above copyright notice, this
10 list of conditions and the following disclaimer.
11 2. Redistributions in binary form must reproduce the above copyright notice,
12 this list of conditions and the following disclaimer in the documentation
13 and/or other materials provided with the distribution.
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/types.h>
40 #pragma GCC diagnostic push
41 # pragma GCC diagnostic ignored "-Wcpp"
42 # define CL_USE_DEPRECATED_OPENCL_1_1_APIS
43 # include <CL/opencl.h>
44 #pragma GCC diagnostic pop
46 #pragma GCC visibility push(hidden)
48 #include "ocl_icd_loader.h"
49 #define DEBUG_OCL_ICD_PROVIDE_DUMP_FIELD
50 #include "ocl_icd_debug.h"
52 #define ETC_OPENCL_VENDORS "/etc/OpenCL/vendors"
54 int debug_ocl_icd_mask=0;
56 typedef __typeof__(clGetPlatformInfo) *clGetPlatformInfo_fn;
58 inline void dump_vendor_icd(const char* info, const struct vendor_icd *v) {
59 debug(D_DUMP, "%s %p={ num=%i, handle=%p, f=%p}\n", info,
60 v, v->num_platforms, v->dl_handle, v->ext_fn_ptr);
63 struct vendor_icd *_icds=NULL;
64 struct platform_icd *_picds=NULL;
65 static cl_uint _num_icds = 0;
66 cl_uint _num_picds = 0;
69 # define _clS(x) [-x] = #x
70 # define MAX_CL_ERRORS (-CL_INVALID_DEVICE_PARTITION_COUNT)
71 static char const * const clErrorStr[MAX_CL_ERRORS+1] = {
73 _clS(CL_DEVICE_NOT_FOUND),
74 _clS(CL_DEVICE_NOT_AVAILABLE),
75 _clS(CL_COMPILER_NOT_AVAILABLE),
76 _clS(CL_MEM_OBJECT_ALLOCATION_FAILURE),
77 _clS(CL_OUT_OF_RESOURCES),
78 _clS(CL_OUT_OF_HOST_MEMORY),
79 _clS(CL_PROFILING_INFO_NOT_AVAILABLE),
80 _clS(CL_MEM_COPY_OVERLAP),
81 _clS(CL_IMAGE_FORMAT_MISMATCH),
82 _clS(CL_IMAGE_FORMAT_NOT_SUPPORTED),
83 _clS(CL_BUILD_PROGRAM_FAILURE),
85 _clS(CL_MISALIGNED_SUB_BUFFER_OFFSET),
86 _clS(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST),
87 _clS(CL_COMPILE_PROGRAM_FAILURE),
88 _clS(CL_LINKER_NOT_AVAILABLE),
89 _clS(CL_LINK_PROGRAM_FAILURE),
90 _clS(CL_DEVICE_PARTITION_FAILED),
91 _clS(CL_KERNEL_ARG_INFO_NOT_AVAILABLE),
92 _clS(CL_INVALID_VALUE),
93 _clS(CL_INVALID_DEVICE_TYPE),
94 _clS(CL_INVALID_PLATFORM),
95 _clS(CL_INVALID_DEVICE),
96 _clS(CL_INVALID_CONTEXT),
97 _clS(CL_INVALID_QUEUE_PROPERTIES),
98 _clS(CL_INVALID_COMMAND_QUEUE),
99 _clS(CL_INVALID_HOST_PTR),
100 _clS(CL_INVALID_MEM_OBJECT),
101 _clS(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR),
102 _clS(CL_INVALID_IMAGE_SIZE),
103 _clS(CL_INVALID_SAMPLER),
104 _clS(CL_INVALID_BINARY),
105 _clS(CL_INVALID_BUILD_OPTIONS),
106 _clS(CL_INVALID_PROGRAM),
107 _clS(CL_INVALID_PROGRAM_EXECUTABLE),
108 _clS(CL_INVALID_KERNEL_NAME),
109 _clS(CL_INVALID_KERNEL_DEFINITION),
110 _clS(CL_INVALID_KERNEL),
111 _clS(CL_INVALID_ARG_INDEX),
112 _clS(CL_INVALID_ARG_VALUE),
113 _clS(CL_INVALID_ARG_SIZE),
114 _clS(CL_INVALID_KERNEL_ARGS),
115 _clS(CL_INVALID_WORK_DIMENSION),
116 _clS(CL_INVALID_WORK_GROUP_SIZE),
117 _clS(CL_INVALID_WORK_ITEM_SIZE),
118 _clS(CL_INVALID_GLOBAL_OFFSET),
119 _clS(CL_INVALID_EVENT_WAIT_LIST),
120 _clS(CL_INVALID_EVENT),
121 _clS(CL_INVALID_OPERATION),
122 _clS(CL_INVALID_GL_OBJECT),
123 _clS(CL_INVALID_BUFFER_SIZE),
124 _clS(CL_INVALID_MIP_LEVEL),
125 _clS(CL_INVALID_GLOBAL_WORK_SIZE),
126 _clS(CL_INVALID_PROPERTY),
127 _clS(CL_INVALID_IMAGE_DESCRIPTOR),
128 _clS(CL_INVALID_COMPILER_OPTIONS),
129 _clS(CL_INVALID_LINKER_OPTIONS),
130 _clS(CL_INVALID_DEVICE_PARTITION_COUNT)
135 static char* _clerror2string (cl_int error) __attribute__((unused));
136 static char* _clerror2string (cl_int error) {
138 if (-error > MAX_CL_ERRORS || error > 0) {
139 debug(D_WARN, "Unknown error code %d", error);
140 RETURN_STR("OpenCL Error");
142 const char *ret=clErrorStr[-error];
144 debug(D_WARN, "Unknown error code %d", error);
145 RETURN_STR("OpenCL Error");
149 static char number[15];
151 RETURN_STR("CL_SUCCESS");
153 snprintf(number, 15, "%i", error);
158 static inline int _string_end_with_icd(const char* str) {
159 size_t len = strlen(str);
160 if( len<5 || strcmp(str + len - 4, ".icd" ) != 0 ) {
166 static inline int _string_with_slash(const char* str) {
167 return strchr(str, '/') != NULL;
170 static inline unsigned int _find_num_icds(DIR *dir) {
171 unsigned int num_icds = 0;
173 while( (ent=readdir(dir)) != NULL ){
174 if (_string_end_with_icd(ent->d_name)) {
182 static inline unsigned int _load_icd(int num_icds, const char* lib_path) {
184 debug(D_LOG, "Loading ICD '%s'", lib_path);
186 _icds[num_icds].dl_handle = dlopen(lib_path, RTLD_LAZY|RTLD_LOCAL);//|RTLD_DEEPBIND);
187 if(_icds[num_icds].dl_handle != NULL) {
188 debug(D_LOG, "ICD[%i] loaded", num_icds);
191 debug(D_WARN, "error while dlopening the IDL: '%s',\n => skipping ICD", dlerror());
196 static inline unsigned int _open_driver(unsigned int num_icds,
197 const char*dir_path, const char*file_path) {
200 unsigned int lib_path_length;
201 if (dir_path != NULL) {
202 lib_path_length = strlen(dir_path) + strlen(file_path) + 2;
203 lib_path = malloc(lib_path_length*sizeof(char));
204 sprintf(lib_path,"%s/%s", dir_path, file_path);
206 lib_path_length = strlen(file_path) + 1;
207 lib_path = malloc(lib_path_length*sizeof(char));
208 sprintf(lib_path,"%s", file_path);
210 debug(D_LOG, "Considering file '%s'", lib_path);
211 FILE *f = fopen(lib_path,"r");
217 fseek(f, 0, SEEK_END);
218 lib_path_length = ftell(f)+1;
219 fseek(f, 0, SEEK_SET);
220 if(lib_path_length == 1) {
221 debug(D_WARN, "File contents too short, skipping ICD");
225 lib_path = malloc(lib_path_length*sizeof(char));
226 err = fgets(lib_path, lib_path_length, f);
230 debug(D_WARN, "Error while loading file contents, skipping ICD");
234 lib_path_length = strnlen(lib_path, lib_path_length);
236 if( lib_path[lib_path_length-1] == '\n' )
237 lib_path[lib_path_length-1] = '\0';
239 num_icds += _load_icd(num_icds, lib_path);
245 static inline unsigned int _open_drivers(DIR *dir, const char* dir_path) {
246 unsigned int num_icds = 0;
248 while( (ent=readdir(dir)) != NULL ){
249 if(! _string_end_with_icd(ent->d_name)) {
252 num_icds = _open_driver(num_icds, dir_path, ent->d_name);
258 static void* _get_function_addr(void* dlh, clGetExtensionFunctionAddress_fn fn, const char*name) {
260 debug(D_LOG,"Looking for function %s",name);
261 addr1=dlsym(dlh, name);
263 debug(D_WARN, "Missing global symbol '%s' in ICD, should be skipped", name);
269 debug(D_WARN, "Missing function '%s' in ICD, should be skipped", name);
272 if (addr1 && addr2 && addr1!=addr2) {
273 debug(D_WARN, "Function and symbol '%s' have different addresses (%p != %p)!", name, addr2, addr1);
277 if (!addr2) addr2=addr1;
281 static int _allocate_platforms(int req) {
282 static cl_uint allocated=0;
283 debug(D_LOG,"Requesting allocation for %d platforms",req);
284 if (allocated - _num_picds < req) {
286 _picds=(struct platform_icd*)malloc(req*sizeof(struct platform_icd));
288 req = req - (allocated - _num_picds);
289 _picds=(struct platform_icd*)realloc(_picds, (allocated+req)*sizeof(struct platform_icd));
293 RETURN(allocated - _num_picds);
296 static char* _malloc_clGetPlatformInfo(clGetPlatformInfo_fn plt_info_ptr,
297 cl_platform_id pid, cl_platform_info cname, char* sname) {
299 size_t param_value_size_ret;
300 error = plt_info_ptr(pid, cname, 0, NULL, ¶m_value_size_ret);
301 if (error != CL_SUCCESS) {
302 debug(D_WARN, "Error %s while requesting %s in platform %p",
303 _clerror2string(error), sname, pid);
306 char *param_value = (char *)malloc(sizeof(char)*param_value_size_ret);
307 if (param_value == NULL) {
308 debug(D_WARN, "Error in malloc while requesting %s in platform %p",
312 error = plt_info_ptr(pid, cname, param_value_size_ret, param_value, NULL);
313 if (error != CL_SUCCESS){
315 debug(D_WARN, "Error %s while requesting %s in platform %p",
316 _clerror2string(error), sname, pid);
319 RETURN_STR(param_value);
322 static void _count_devices(struct platform_icd *p) {
325 /* Ensure they are 0 in case of errors */
326 p->ngpus = p->ncpus = p->ndevs = 0;
328 error = clGetDeviceIDs(p->pid, CL_DEVICE_TYPE_GPU, 0, NULL, &(p->ngpus));
329 if (error != CL_SUCCESS && error != CL_DEVICE_NOT_FOUND){
330 debug(D_WARN, "Error %s while counting GPU devices in platform %p",
331 _clerror2string(error), p->pid);
334 error = clGetDeviceIDs(p->pid, CL_DEVICE_TYPE_CPU, 0, NULL, &(p->ncpus));
335 if (error != CL_SUCCESS && error != CL_DEVICE_NOT_FOUND){
336 debug(D_WARN, "Error %s while counting CPU devices in platform %p",
337 _clerror2string(error), p->pid);
340 error = clGetDeviceIDs(p->pid, CL_DEVICE_TYPE_ALL, 0, NULL, &(p->ndevs));
341 if (error != CL_SUCCESS && error != CL_DEVICE_NOT_FOUND){
342 debug(D_WARN, "Error %s while counting ALL devices in platform %p",
343 _clerror2string(error), p->pid);
348 static int _cmp_platforms(const void *_a, const void *_b) {
349 const struct platform_icd *a=(const struct platform_icd *)_a;
350 const struct platform_icd *b=(const struct platform_icd *)_b;
352 /* sort first platforms handling max gpu */
353 if (a->ngpus > b->ngpus) return -1;
354 if (a->ngpus < b->ngpus) return 1;
355 /* sort next platforms handling max cpu */
356 if (a->ncpus > b->ncpus) return -1;
357 if (a->ncpus < b->ncpus) return 1;
358 /* sort then platforms handling max devices */
359 if (a->ndevs > b->ndevs) return -1;
360 if (a->ndevs < b->ndevs) return 1;
361 /* else consider platforms equal */
365 static void _sort_platforms(struct platform_icd *picds, int npicds) {
366 debug(D_WARN, "Nb platefroms: %i", npicds);
368 char* ocl_sort=getenv("OCL_ICD_PLATFORM_SORT");
369 if (ocl_sort!=NULL && !strcmp(ocl_sort, "none")) {
370 debug(D_LOG, "Platform not sorted");
372 if (ocl_sort!=NULL && strcmp(ocl_sort, "devices")) {
373 debug(D_WARN, "Unknown platform sort algorithm requested: %s", ocl_sort);
374 debug(D_WARN, "Switching do the 'devices' algorithm");
377 debug(D_LOG, "Platform sorted by GPU, CPU, DEV");
378 for (i=0; i<npicds; i++) {
379 _count_devices(&picds[i]);
381 qsort(picds, npicds, sizeof(*picds),
387 static inline void _find_and_check_platforms(cl_uint num_icds) {
390 for( i=0; i<num_icds; i++){
391 debug(D_LOG, "Checking ICD %i/%i", i, num_icds);
392 dump_vendor_icd("before looking for platforms", &_icds[i]);
393 struct vendor_icd *picd = &_icds[i];
394 void* dlh = _icds[i].dl_handle;
395 picd->ext_fn_ptr = _get_function_addr(dlh, NULL, "clGetExtensionFunctionAddress");
396 clIcdGetPlatformIDsKHR_fn plt_fn_ptr =
397 _get_function_addr(dlh, picd->ext_fn_ptr, "clIcdGetPlatformIDsKHR");
398 clGetPlatformInfo_fn plt_info_ptr =
399 _get_function_addr(dlh, picd->ext_fn_ptr, "clGetPlatformInfo");
400 if( picd->ext_fn_ptr == NULL
401 || plt_fn_ptr == NULL
402 || plt_info_ptr == NULL) {
403 debug(D_WARN, "Missing symbols in ICD, skipping it");
406 cl_uint num_platforms=0;
408 error = (*plt_fn_ptr)(0, NULL, &num_platforms);
409 if( error != CL_SUCCESS || num_platforms == 0) {
410 debug(D_LOG, "No platform in ICD, skipping it");
413 cl_platform_id *platforms = (cl_platform_id *) malloc( sizeof(cl_platform_id) * num_platforms);
414 error = (*plt_fn_ptr)(num_platforms, platforms, NULL);
415 if( error != CL_SUCCESS ){
417 debug(D_WARN, "Error in loading ICD platforms, skipping ICD");
420 cl_uint num_valid_platforms=0;
422 debug(D_LOG, "Try to load %d platforms", num_platforms);
423 if (_allocate_platforms(num_platforms) < num_platforms) {
425 debug(D_WARN, "Not enought platform allocated. Skipping ICD");
428 for(j=0; j<num_platforms; j++) {
429 debug(D_LOG, "Checking platform %i", j);
430 struct platform_icd *p=&_picds[_num_picds];
431 char *param_value=NULL;
432 p->extension_suffix=NULL;
436 if (debug_ocl_icd_mask & D_DUMP) {
437 int log=debug_ocl_icd_mask & D_TRACE;
438 debug_ocl_icd_mask &= ~D_TRACE;
439 dump_platform(p->vicd->ext_fn_ptr, p->pid);
440 debug_ocl_icd_mask |= log;
444 /* Allow to workaround a bug in the Intel ICD used
445 * with optirun (search for NVidia Optimus for more info)
447 const char* str=getenv("OCL_ICD_ASSUME_ICD_EXTENSION");
448 if (! str || str[0]==0) {
449 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_EXTENSIONS, "extensions");
450 if (param_value == NULL){
451 debug(D_WARN, "Skipping platform %i", j);
454 debug(D_DUMP, "Supported extensions: %s", param_value);
455 if( strstr(param_value, "cl_khr_icd") == NULL){
457 debug(D_WARN, "Missing khr extension in platform %i, skipping it", j);
463 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_ICD_SUFFIX_KHR, "suffix");
464 if (param_value == NULL){
465 debug(D_WARN, "Skipping platform %i", j);
468 p->extension_suffix = param_value;
469 debug(D_DUMP|D_LOG, "Extension suffix: %s", param_value);
471 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_PROFILE, "profile");
472 if (param_value != NULL){
473 debug(D_DUMP, "Profile: %s", param_value);
476 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_VERSION, "version");
477 p->version = param_value;
478 if (param_value != NULL){
479 debug(D_DUMP, "Version: %s", param_value);
482 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_NAME, "name");
483 if (param_value != NULL){
484 debug(D_DUMP, "Name: %s", param_value);
487 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_VENDOR, "vendor");
488 if (param_value != NULL){
489 debug(D_DUMP, "Vendor: %s", param_value);
493 num_valid_platforms++;
496 if( num_valid_platforms != 0 ) {
497 if ( _num_icds != i ) {
498 picd->dl_handle = dlh;
500 dump_vendor_icd("after looking for platforms", &_icds[_num_icds]);
502 picd->num_platforms = num_valid_platforms;
508 _sort_platforms(&_picds[0], _num_picds);
511 static void __initClIcd( void ) {
513 cl_uint num_icds = 0;
516 const char* dir_path=getenv("OCL_ICD_VENDORS");
517 const char* vendor_path=getenv("OPENCL_VENDOR_PATH");
518 if (! vendor_path || vendor_path[0]==0) {
519 vendor_path=ETC_OPENCL_VENDORS;
520 debug(D_DUMP, "OPENCL_VENDOR_PATH unset or empty. Using hard-coded path '%s'", vendor_path);
522 debug(D_DUMP, "OPENCL_VENDOR_PATH set to '%s', using it", vendor_path);
524 if (! dir_path || dir_path[0]==0) {
525 dir_path=vendor_path;
526 debug(D_DUMP, "OCL_ICD_VENDORS empty or not defined, using vendors path '%s'", dir_path);
531 int ret=stat(dir_path, &buf);
532 if (ret != 0 && errno != ENOENT) {
533 debug(D_WARN, "Cannot stat '%s'. Aborting", dir_path);
535 if (ret == 0 && S_ISDIR(buf.st_mode)) {
541 debug(D_LOG,"Only loading '%s' as an ICD", dir_path);
545 debug(D_LOG,"Reading icd list from '%s'", dir_path);
546 dir = opendir(dir_path);
548 if (errno == ENOTDIR) {
549 debug(D_DUMP, "%s is not a directory, trying to use it as a ICD libname",
555 num_icds = _find_num_icds(dir);
561 _icds = (struct vendor_icd*)malloc(num_icds * sizeof(struct vendor_icd));
567 if (_string_end_with_icd(dir_path)) {
569 if (! _string_with_slash(dir_path)) {
570 num_icds = _open_driver(0, vendor_path, dir_path);
573 num_icds = _open_driver(0, NULL, dir_path);
576 num_icds = _load_icd(0, dir_path);
579 num_icds = _open_drivers(dir, dir_path);
585 _find_and_check_platforms(num_icds);
590 if (_num_icds < num_icds) {
591 _icds = (struct vendor_icd*)realloc(_icds, _num_icds * sizeof(struct vendor_icd));
593 debug(D_WARN, "%d valid vendor(s)!", _num_icds);
612 static pthread_once_t once_init = PTHREAD_ONCE_INIT;
616 volatile static __thread int in_init = 0;
617 volatile static cl_uint _initialized = 0;
619 static void _initClIcd_real( void ) {
622 /* probably reentrency, in_init is a __thread variable */
623 debug(D_WARN, "Executing init while already in init!");
626 __sync_synchronize();
627 pthread_once(&once_init, &__initClIcd);
628 __sync_synchronize();
632 if (__sync_bool_compare_and_swap(&gard, 0, 1)) {
634 __sync_synchronize();
636 __sync_synchronize();
640 /* probably reentrency (could also be preemptive user-level threads). */
642 /* someone else started __initClIcd(). We wait until it ends. */
643 debug(D_WARN, "Waiting end of init");
644 while (!_initialized) {
645 __sync_synchronize();
647 debug(D_WARN, "Wait done");
654 static inline void _initClIcd( void ) {
655 if( __builtin_expect (_initialized, 1) )
660 cl_platform_id __attribute__((visibility("internal")))
661 getDefaultPlatformID() {
662 static cl_platform_id defaultPlatformID=NULL;
663 static int defaultSet=0;
667 if(_num_picds == 0) {
670 const char *default_platform = getenv("OCL_ICD_DEFAULT_PLATFORM");
671 int num_default_platform;
673 if (! default_platform) {
674 num_default_platform = 0;
676 num_default_platform = strtol(default_platform, &end_scan, 10);
677 if (*default_platform == '\0' || *end_scan != '\0') {
681 if (num_default_platform < 0 || num_default_platform >= _num_picds) {
684 defaultPlatformID=_picds[num_default_platform].pid;
688 return defaultPlatformID;
691 #pragma GCC visibility pop
692 #define hidden_alias(name) \
693 typeof(name) name##_hid __attribute__ ((alias (#name), visibility("hidden")))
696 CL_ICDL_OCL_VERSION=1,
702 static cl_int clGetICDLoaderInfoOCLICD(
703 cl_icdl_info param_name,
704 size_t param_value_size,
706 size_t * param_value_size_ret)
708 static const char cl_icdl_ocl_version[] = "OpenCL " OCL_ICD_OPENCL_VERSION;
709 static const char cl_icdl_version[] = PACKAGE_VERSION;
710 static const char cl_icdl_name[] = PACKAGE_NAME;
711 static const char cl_icdl_vendor[] = "OCL Icd free software";
714 const char * string_p;
715 #define oclcase(name, NAME) \
716 case CL_ICDL_##NAME: \
717 string_p = cl_icdl_##name; \
718 size_string = sizeof(cl_icdl_##name); \
721 switch ( param_name ) {
722 oclcase(ocl_version,OCL_VERSION);
723 oclcase(version,VERSION);
725 oclcase(vendor,VENDOR);
727 return CL_INVALID_VALUE;
731 if( param_value != NULL ) {
732 if( size_string > param_value_size )
733 return CL_INVALID_VALUE;
734 memcpy(param_value, string_p, size_string);
736 if( param_value_size_ret != NULL )
737 *param_value_size_ret = size_string;
741 CL_API_ENTRY void * CL_API_CALL
742 clGetExtensionFunctionAddress(const char * func_name) CL_API_SUFFIX__VERSION_1_0 {
745 if( func_name == NULL )
747 cl_uint suffix_length;
749 void * return_value=NULL;
750 struct func_desc const * fn=&function_description[0];
751 int lenfn=strlen(func_name);
753 (strcmp(func_name+lenfn-3, "KHR")==0 || strcmp(func_name+lenfn-3, "EXT")==0)) {
754 while (fn->name != NULL) {
755 if (strcmp(func_name, fn->name)==0)
760 for(i=0; i<_num_picds; i++) {
761 suffix_length = strlen(_picds[i].extension_suffix);
762 if( suffix_length > strlen(func_name) )
764 if(strcmp(_picds[i].extension_suffix, &func_name[strlen(func_name)-suffix_length]) == 0)
765 RETURN((*_picds[i].vicd->ext_fn_ptr)(func_name));
767 if(strcmp(func_name, "clGetICDLoaderInfoOCLICD") == 0) {
768 return (void*)(void*(*)(void))(&clGetICDLoaderInfoOCLICD);
770 RETURN(return_value);
772 hidden_alias(clGetExtensionFunctionAddress);
774 CL_API_ENTRY cl_int CL_API_CALL
775 clGetPlatformIDs(cl_uint num_entries,
776 cl_platform_id * platforms,
777 cl_uint * num_platforms) CL_API_SUFFIX__VERSION_1_0 {
780 if( platforms == NULL && num_platforms == NULL )
781 RETURN(CL_INVALID_VALUE);
782 if( num_entries == 0 && platforms != NULL )
783 RETURN(CL_INVALID_VALUE);
784 if( _num_icds == 0 || _num_picds == 0 ) {
785 if ( num_platforms != NULL )
787 RETURN(CL_PLATFORM_NOT_FOUND_KHR);
791 if( num_platforms != NULL ){
792 *num_platforms = _num_picds;
794 if( platforms != NULL ) {
795 cl_uint n_platforms = _num_picds < num_entries ? _num_picds : num_entries;
796 for( i=0; i<n_platforms; i++) {
797 *(platforms++) = _picds[i].pid;
802 hidden_alias(clGetPlatformIDs);
804 #define RETURN_WITH_ERRCODE(errvar, errvalue, retvalue) \
812 #define CHECK_PLATFORM(__pid) \
814 cl_platform_id _pid=(__pid); \
817 for( j=0; j<_num_picds; j++) { \
818 if( _picds[j].pid == _pid) { \
826 CL_API_ENTRY cl_context CL_API_CALL
827 clCreateContext(const cl_context_properties * properties ,
828 cl_uint num_devices ,
829 const cl_device_id * devices ,
830 void (CL_CALLBACK * pfn_notify )(const char *, const void *, size_t, void *),
832 cl_int * errcode_ret ){
836 if( properties != NULL){
837 while( properties[i] != 0 ) {
838 if( properties[i] == CL_CONTEXT_PLATFORM ) {
839 if((struct _cl_platform_id *) properties[i+1] == NULL) {
841 *errcode_ret = CL_INVALID_PLATFORM;
845 if( !CHECK_PLATFORM((cl_platform_id) properties[i+1]) ) {
846 RETURN_WITH_ERRCODE(errcode_ret, CL_INVALID_PLATFORM, NULL);
849 RETURN(((struct _cl_platform_id *) properties[i+1])
850 ->dispatch->clCreateContext(properties, num_devices, devices,
851 pfn_notify, user_data, errcode_ret));
856 if(devices == NULL || num_devices == 0) {
857 RETURN_WITH_ERRCODE(errcode_ret, CL_INVALID_VALUE, NULL);
859 if((struct _cl_device_id *)devices[0] == NULL) {
860 RETURN_WITH_ERRCODE(errcode_ret, CL_INVALID_DEVICE, NULL);
862 RETURN(((struct _cl_device_id *)devices[0])
863 ->dispatch->clCreateContext(properties, num_devices, devices,
864 pfn_notify, user_data, errcode_ret));
866 hidden_alias(clCreateContext);
868 CL_API_ENTRY cl_context CL_API_CALL
869 clCreateContextFromType(const cl_context_properties * properties ,
870 cl_device_type device_type ,
871 void (CL_CALLBACK * pfn_notify )(const char *, const void *, size_t, void *),
873 cl_int * errcode_ret ){
876 if(_num_picds == 0) {
880 if( properties != NULL){
881 while( properties[i] != 0 ) {
882 if( properties[i] == CL_CONTEXT_PLATFORM ) {
883 if( (struct _cl_platform_id *) properties[i+1] == NULL ) {
886 if( !CHECK_PLATFORM((cl_platform_id) properties[i+1]) ) {
890 return ((struct _cl_platform_id *) properties[i+1])
891 ->dispatch->clCreateContextFromType(properties, device_type,
892 pfn_notify, user_data, errcode_ret);
897 cl_platform_id default_platform=getDefaultPlatformID();
898 RETURN(default_platform->dispatch->clCreateContextFromType
899 (properties, device_type, pfn_notify, user_data, errcode_ret));
902 RETURN_WITH_ERRCODE(errcode_ret, CL_INVALID_PLATFORM, NULL);
904 hidden_alias(clCreateContextFromType);
906 CL_API_ENTRY cl_int CL_API_CALL
907 clGetGLContextInfoKHR(const cl_context_properties * properties ,
908 cl_gl_context_info param_name ,
909 size_t param_value_size ,
911 size_t * param_value_size_ret ){
915 if( properties != NULL){
916 while( properties[i] != 0 ) {
917 if( properties[i] == CL_CONTEXT_PLATFORM ) {
918 if( (struct _cl_platform_id *) properties[i+1] == NULL ) {
919 RETURN(CL_INVALID_PLATFORM);
921 if( !CHECK_PLATFORM((cl_platform_id) properties[i+1]) ) {
922 RETURN(CL_INVALID_PLATFORM);
925 RETURN(((struct _cl_platform_id *) properties[i+1])
926 ->dispatch->clGetGLContextInfoKHR(properties, param_name,
927 param_value_size, param_value, param_value_size_ret));
932 RETURN(CL_INVALID_PLATFORM);
934 hidden_alias(clGetGLContextInfoKHR);
936 CL_API_ENTRY cl_int CL_API_CALL
937 clWaitForEvents(cl_uint num_events ,
938 const cl_event * event_list ){
940 if( num_events == 0 || event_list == NULL )
941 RETURN(CL_INVALID_VALUE);
942 if( (struct _cl_event *)event_list[0] == NULL )
943 RETURN(CL_INVALID_EVENT);
944 RETURN(((struct _cl_event *)event_list[0])
945 ->dispatch->clWaitForEvents(num_events, event_list));
947 hidden_alias(clWaitForEvents);
949 CL_API_ENTRY cl_int CL_API_CALL
950 clUnloadCompiler( void ){
954 hidden_alias(clUnloadCompiler);