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 qsort(picds, npicds, sizeof(*picds),
370 static inline void _find_and_check_platforms(cl_uint num_icds) {
373 for( i=0; i<num_icds; i++){
374 debug(D_LOG, "Checking ICD %i/%i", i, num_icds);
375 dump_vendor_icd("before looking for platforms", &_icds[i]);
376 struct vendor_icd *picd = &_icds[i];
377 void* dlh = _icds[i].dl_handle;
378 picd->ext_fn_ptr = _get_function_addr(dlh, NULL, "clGetExtensionFunctionAddress");
379 clIcdGetPlatformIDsKHR_fn plt_fn_ptr =
380 _get_function_addr(dlh, picd->ext_fn_ptr, "clIcdGetPlatformIDsKHR");
381 clGetPlatformInfo_fn plt_info_ptr =
382 _get_function_addr(dlh, picd->ext_fn_ptr, "clGetPlatformInfo");
383 if( picd->ext_fn_ptr == NULL
384 || plt_fn_ptr == NULL
385 || plt_info_ptr == NULL) {
386 debug(D_WARN, "Missing symbols in ICD, skipping it");
389 cl_uint num_platforms=0;
391 error = (*plt_fn_ptr)(0, NULL, &num_platforms);
392 if( error != CL_SUCCESS || num_platforms == 0) {
393 debug(D_LOG, "No platform in ICD, skipping it");
396 cl_platform_id *platforms = (cl_platform_id *) malloc( sizeof(cl_platform_id) * num_platforms);
397 error = (*plt_fn_ptr)(num_platforms, platforms, NULL);
398 if( error != CL_SUCCESS ){
400 debug(D_WARN, "Error in loading ICD platforms, skipping ICD");
403 cl_uint num_valid_platforms=0;
405 debug(D_LOG, "Try to load %d platforms", num_platforms);
406 if (_allocate_platforms(num_platforms) < num_platforms) {
408 debug(D_WARN, "Not enought platform allocated. Skipping ICD");
411 for(j=0; j<num_platforms; j++) {
412 debug(D_LOG, "Checking platform %i", j);
413 struct platform_icd *p=&_picds[_num_picds];
414 char *param_value=NULL;
415 p->extension_suffix=NULL;
419 if (debug_ocl_icd_mask & D_DUMP) {
420 int log=debug_ocl_icd_mask & D_TRACE;
421 debug_ocl_icd_mask &= ~D_TRACE;
422 dump_platform(p->vicd->ext_fn_ptr, p->pid);
423 debug_ocl_icd_mask |= log;
427 /* Allow to workaround a bug in the Intel ICD used
428 * with optirun (search for NVidia Optimus for more info)
430 const char* str=getenv("OCL_ICD_ASSUME_ICD_EXTENSION");
431 if (! str || str[0]==0) {
432 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_EXTENSIONS, "extensions");
433 if (param_value == NULL){
434 debug(D_WARN, "Skipping platform %i", j);
437 debug(D_DUMP, "Supported extensions: %s", param_value);
438 if( strstr(param_value, "cl_khr_icd") == NULL){
440 debug(D_WARN, "Missing khr extension in platform %i, skipping it", j);
446 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_ICD_SUFFIX_KHR, "suffix");
447 if (param_value == NULL){
448 debug(D_WARN, "Skipping platform %i", j);
451 p->extension_suffix = param_value;
452 debug(D_DUMP|D_LOG, "Extension suffix: %s", param_value);
454 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_PROFILE, "profile");
455 if (param_value != NULL){
456 debug(D_DUMP, "Profile: %s", param_value);
459 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_VERSION, "version");
460 p->version = param_value;
461 if (param_value != NULL){
462 debug(D_DUMP, "Version: %s", param_value);
465 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_NAME, "name");
466 if (param_value != NULL){
467 debug(D_DUMP, "Name: %s", param_value);
470 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_VENDOR, "vendor");
471 if (param_value != NULL){
472 debug(D_DUMP, "Vendor: %s", param_value);
477 num_valid_platforms++;
480 if( num_valid_platforms != 0 ) {
481 if ( _num_icds != i ) {
482 picd->dl_handle = dlh;
484 dump_vendor_icd("after looking for platforms", &_icds[_num_icds]);
486 picd->num_platforms = num_valid_platforms;
492 _sort_platforms(&_picds[0], _num_picds);
495 static void __initClIcd( void ) {
497 cl_uint num_icds = 0;
500 const char* dir_path=getenv("OCL_ICD_VENDORS");
501 if (! dir_path || dir_path[0]==0) {
502 debug(D_DUMP, "OCL_ICD_VENDORS empty or not defined, using %s", ETC_OPENCL_VENDORS);
503 dir_path=ETC_OPENCL_VENDORS;
508 int ret=stat(dir_path, &buf);
509 if (ret != 0 && errno != ENOENT) {
510 debug(D_WARN, "Cannot stat '%s'. Aborting", dir_path);
512 if (ret == 0 && S_ISDIR(buf.st_mode)) {
518 debug(D_LOG,"Only loading '%s' as an ICD", dir_path);
522 debug(D_LOG,"Reading icd list from '%s'", dir_path);
523 dir = opendir(dir_path);
525 if (errno == ENOTDIR) {
526 debug(D_DUMP, "%s is not a directory, trying to use it as a ICD libname",
532 num_icds = _find_num_icds(dir);
538 _icds = (struct vendor_icd*)malloc(num_icds * sizeof(struct vendor_icd));
544 if (_string_end_with_icd(dir_path)) {
546 if (! _string_with_slash(dir_path)) {
547 num_icds = _open_driver(0, ETC_OPENCL_VENDORS, dir_path);
550 num_icds = _open_driver(0, NULL, dir_path);
553 num_icds = _load_icd(0, dir_path);
556 num_icds = _open_drivers(dir, dir_path);
562 _find_and_check_platforms(num_icds);
567 if (_num_icds < num_icds) {
568 _icds = (struct vendor_icd*)realloc(_icds, _num_icds * sizeof(struct vendor_icd));
570 debug(D_WARN, "%d valid vendor(s)!", _num_icds);
589 static pthread_once_t once_init = PTHREAD_ONCE_INIT;
593 volatile static __thread int in_init = 0;
594 volatile static cl_uint _initialized = 0;
596 static void _initClIcd_real( void ) {
599 /* probably reentrency, in_init is a __thread variable */
600 debug(D_WARN, "Executing init while already in init!");
603 __sync_synchronize();
604 pthread_once(&once_init, &__initClIcd);
605 __sync_synchronize();
609 if (__sync_bool_compare_and_swap(&gard, 0, 1)) {
611 __sync_synchronize();
613 __sync_synchronize();
617 /* probably reentrency (could also be preemptive user-level threads). */
619 /* someone else started __initClIcd(). We wait until it ends. */
620 debug(D_WARN, "Waiting end of init");
621 while (!_initialized) {
622 __sync_synchronize();
624 debug(D_WARN, "Wait done");
631 static inline void _initClIcd( void ) {
632 if( __builtin_expect (_initialized, 1) )
637 cl_platform_id __attribute__((visibility("internal")))
638 getDefaultPlatformID() {
639 static cl_platform_id defaultPlatformID=NULL;
640 static int defaultSet=0;
644 if(_num_picds == 0) {
647 const char *default_platform = getenv("OPENCL_ICD_DEFAULT_PLATFORM");
648 int num_default_platform;
650 if (! default_platform) {
651 num_default_platform = 0;
653 num_default_platform = strtol(default_platform, &end_scan, 10);
654 if (*default_platform == '\0' || *end_scan != '\0') {
658 if (num_default_platform < 0 || num_default_platform >= _num_picds) {
661 defaultPlatformID=_picds[num_default_platform].pid;
665 return defaultPlatformID;
668 #pragma GCC visibility pop
669 #define hidden_alias(name) \
670 typeof(name) name##_hid __attribute__ ((alias (#name), visibility("hidden")))
673 CL_ICDL_OCL_VERSION=1,
679 static cl_int clGetICDLoaderInfoOCLICD(
680 cl_icdl_info param_name,
681 size_t param_value_size,
683 size_t * param_value_size_ret)
685 char cl_icdl_ocl_version[] = "OpenCL 1.2";
686 char cl_icdl_version[] = PACKAGE_VERSION;
687 char cl_icdl_name[] = PACKAGE_NAME;
688 char cl_icdl_vendor[] = "OCL Icd free software";
692 #define oclcase(name, NAME) \
693 case CL_ICDL_##NAME: \
694 string_p = cl_icdl_##name; \
695 size_string = sizeof(cl_icdl_##name); \
698 switch ( param_name ) {
699 oclcase(ocl_version,OCL_VERSION);
700 oclcase(version,VERSION);
702 oclcase(vendor,VENDOR);
704 return CL_INVALID_VALUE;
708 if( param_value != NULL ) {
709 if( size_string > param_value_size )
710 return CL_INVALID_VALUE;
711 memcpy(param_value, string_p, size_string);
713 if( param_value_size_ret != NULL )
714 *param_value_size_ret = size_string;
718 CL_API_ENTRY void * CL_API_CALL
719 clGetExtensionFunctionAddress(const char * func_name) CL_API_SUFFIX__VERSION_1_0 {
722 if( func_name == NULL )
724 cl_uint suffix_length;
726 void * return_value=NULL;
727 struct func_desc const * fn=&function_description[0];
728 int lenfn=strlen(func_name);
730 (strcmp(func_name+lenfn-3, "KHR")==0 || strcmp(func_name+lenfn-3, "EXT")==0)) {
731 while (fn->name != NULL) {
732 if (strcmp(func_name, fn->name)==0)
737 for(i=0; i<_num_picds; i++) {
738 suffix_length = strlen(_picds[i].extension_suffix);
739 if( suffix_length > strlen(func_name) )
741 if(strcmp(_picds[i].extension_suffix, &func_name[strlen(func_name)-suffix_length]) == 0)
742 RETURN((*_picds[i].vicd->ext_fn_ptr)(func_name));
744 if(strcmp(func_name, "clGetICDLoaderInfoOCLICD") == 0) {
745 return (void*)(void*(*)(void))(&clGetICDLoaderInfoOCLICD);
747 RETURN(return_value);
749 hidden_alias(clGetExtensionFunctionAddress);
751 CL_API_ENTRY cl_int CL_API_CALL
752 clGetPlatformIDs(cl_uint num_entries,
753 cl_platform_id * platforms,
754 cl_uint * num_platforms) CL_API_SUFFIX__VERSION_1_0 {
757 if( platforms == NULL && num_platforms == NULL )
758 RETURN(CL_INVALID_VALUE);
759 if( num_entries == 0 && platforms != NULL )
760 RETURN(CL_INVALID_VALUE);
761 if( _num_icds == 0 || _num_picds == 0 ) {
762 if ( num_platforms != NULL )
764 RETURN(CL_PLATFORM_NOT_FOUND_KHR);
768 if( num_platforms != NULL ){
769 *num_platforms = _num_picds;
771 if( platforms != NULL ) {
772 cl_uint n_platforms = _num_picds < num_entries ? _num_picds : num_entries;
773 for( i=0; i<n_platforms; i++) {
774 *(platforms++) = _picds[i].pid;
779 hidden_alias(clGetPlatformIDs);
781 #define RETURN_WITH_ERRCODE(errvar, errvalue, retvalue) \
789 #define CHECK_PLATFORM(__pid) \
791 cl_platform_id _pid=(__pid); \
794 for( j=0; j<_num_picds; j++) { \
795 if( _picds[j].pid == _pid) { \
803 CL_API_ENTRY cl_context CL_API_CALL
804 clCreateContext(const cl_context_properties * properties ,
805 cl_uint num_devices ,
806 const cl_device_id * devices ,
807 void (CL_CALLBACK * pfn_notify )(const char *, const void *, size_t, void *),
809 cl_int * errcode_ret ){
813 if( properties != NULL){
814 while( properties[i] != 0 ) {
815 if( properties[i] == CL_CONTEXT_PLATFORM ) {
816 if((struct _cl_platform_id *) properties[i+1] == NULL) {
818 *errcode_ret = CL_INVALID_PLATFORM;
822 if( !CHECK_PLATFORM((cl_platform_id) properties[i+1]) ) {
823 RETURN_WITH_ERRCODE(errcode_ret, CL_INVALID_PLATFORM, NULL);
826 RETURN(((struct _cl_platform_id *) properties[i+1])
827 ->dispatch->clCreateContext(properties, num_devices, devices,
828 pfn_notify, user_data, errcode_ret));
833 if(devices == NULL || num_devices == 0) {
834 RETURN_WITH_ERRCODE(errcode_ret, CL_INVALID_VALUE, NULL);
836 if((struct _cl_device_id *)devices[0] == NULL) {
837 RETURN_WITH_ERRCODE(errcode_ret, CL_INVALID_DEVICE, NULL);
839 RETURN(((struct _cl_device_id *)devices[0])
840 ->dispatch->clCreateContext(properties, num_devices, devices,
841 pfn_notify, user_data, errcode_ret));
843 hidden_alias(clCreateContext);
845 CL_API_ENTRY cl_context CL_API_CALL
846 clCreateContextFromType(const cl_context_properties * properties ,
847 cl_device_type device_type ,
848 void (CL_CALLBACK * pfn_notify )(const char *, const void *, size_t, void *),
850 cl_int * errcode_ret ){
853 if(_num_picds == 0) {
857 if( properties != NULL){
858 while( properties[i] != 0 ) {
859 if( properties[i] == CL_CONTEXT_PLATFORM ) {
860 if( (struct _cl_platform_id *) properties[i+1] == NULL ) {
863 if( !CHECK_PLATFORM((cl_platform_id) properties[i+1]) ) {
867 return ((struct _cl_platform_id *) properties[i+1])
868 ->dispatch->clCreateContextFromType(properties, device_type,
869 pfn_notify, user_data, errcode_ret);
874 const char *default_platform = getenv("OPENCL_ICD_DEFAULT_PLATFORM");
875 int num_default_platform;
877 if (! default_platform) {
878 num_default_platform = 0;
880 num_default_platform = strtol(default_platform, &end_scan, 10);
881 if (*default_platform == '\0' || *end_scan != '\0') {
885 if (num_default_platform < 0 || num_default_platform >= _num_picds) {
888 RETURN(_picds[num_default_platform].pid->dispatch->clCreateContextFromType
889 (properties, device_type, pfn_notify, user_data, errcode_ret));
892 RETURN_WITH_ERRCODE(errcode_ret, CL_INVALID_PLATFORM, NULL);
894 hidden_alias(clCreateContextFromType);
896 CL_API_ENTRY cl_int CL_API_CALL
897 clGetGLContextInfoKHR(const cl_context_properties * properties ,
898 cl_gl_context_info param_name ,
899 size_t param_value_size ,
901 size_t * param_value_size_ret ){
905 if( properties != NULL){
906 while( properties[i] != 0 ) {
907 if( properties[i] == CL_CONTEXT_PLATFORM ) {
908 if( (struct _cl_platform_id *) properties[i+1] == NULL ) {
909 RETURN(CL_INVALID_PLATFORM);
911 if( !CHECK_PLATFORM((cl_platform_id) properties[i+1]) ) {
912 RETURN(CL_INVALID_PLATFORM);
915 RETURN(((struct _cl_platform_id *) properties[i+1])
916 ->dispatch->clGetGLContextInfoKHR(properties, param_name,
917 param_value_size, param_value, param_value_size_ret));
922 RETURN(CL_INVALID_PLATFORM);
924 hidden_alias(clGetGLContextInfoKHR);
926 CL_API_ENTRY cl_int CL_API_CALL
927 clWaitForEvents(cl_uint num_events ,
928 const cl_event * event_list ){
930 if( num_events == 0 || event_list == NULL )
931 RETURN(CL_INVALID_VALUE);
932 if( (struct _cl_event *)event_list[0] == NULL )
933 RETURN(CL_INVALID_EVENT);
934 RETURN(((struct _cl_event *)event_list[0])
935 ->dispatch->clWaitForEvents(num_events, event_list));
937 hidden_alias(clWaitForEvents);
939 CL_API_ENTRY cl_int CL_API_CALL
940 clUnloadCompiler( void ){
944 hidden_alias(clUnloadCompiler);