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!", name);
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 inline void _find_and_check_platforms(cl_uint num_icds) {
351 for( i=0; i<num_icds; i++){
352 debug(D_LOG, "Checking ICD %i/%i", i, num_icds);
353 dump_vendor_icd("before looking for platforms", &_icds[i]);
354 struct vendor_icd *picd = &_icds[i];
355 void* dlh = _icds[i].dl_handle;
356 picd->ext_fn_ptr = _get_function_addr(dlh, NULL, "clGetExtensionFunctionAddress");
357 clIcdGetPlatformIDsKHR_fn plt_fn_ptr =
358 _get_function_addr(dlh, picd->ext_fn_ptr, "clIcdGetPlatformIDsKHR");
359 clGetPlatformInfo_fn plt_info_ptr =
360 _get_function_addr(dlh, picd->ext_fn_ptr, "clGetPlatformInfo");
361 if( picd->ext_fn_ptr == NULL
362 || plt_fn_ptr == NULL
363 || plt_info_ptr == NULL) {
364 debug(D_WARN, "Missing symbols in ICD, skipping it");
367 cl_uint num_platforms=0;
369 error = (*plt_fn_ptr)(0, NULL, &num_platforms);
370 if( error != CL_SUCCESS || num_platforms == 0) {
371 debug(D_LOG, "No platform in ICD, skipping it");
374 cl_platform_id *platforms = (cl_platform_id *) malloc( sizeof(cl_platform_id) * num_platforms);
375 error = (*plt_fn_ptr)(num_platforms, platforms, NULL);
376 if( error != CL_SUCCESS ){
378 debug(D_WARN, "Error in loading ICD platforms, skipping ICD");
381 cl_uint num_valid_platforms=0;
383 debug(D_LOG, "Try to load %d platforms", num_platforms);
384 if (_allocate_platforms(num_platforms) < num_platforms) {
386 debug(D_WARN, "Not enought platform allocated. Skipping ICD");
389 for(j=0; j<num_platforms; j++) {
390 debug(D_LOG, "Checking platform %i", j);
391 struct platform_icd *p=&_picds[_num_picds];
392 char *param_value=NULL;
393 p->extension_suffix=NULL;
397 if (debug_ocl_icd_mask & D_DUMP) {
398 int log=debug_ocl_icd_mask & D_TRACE;
399 debug_ocl_icd_mask &= ~D_TRACE;
400 dump_platform(p->vicd->ext_fn_ptr, p->pid);
401 debug_ocl_icd_mask |= log;
405 /* Allow to workaround a bug in the Intel ICD used
406 * with optirun (search for NVidia Optimus for more info)
408 const char* str=getenv("OCL_ICD_ASSUME_ICD_EXTENSION");
409 if (! str || str[0]==0) {
410 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_EXTENSIONS, "extensions");
411 if (param_value == NULL){
412 debug(D_WARN, "Skipping platform %i", j);
415 debug(D_DUMP, "Supported extensions: %s", param_value);
416 if( strstr(param_value, "cl_khr_icd") == NULL){
418 debug(D_WARN, "Missing khr extension in platform %i, skipping it", j);
424 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_ICD_SUFFIX_KHR, "suffix");
425 if (param_value == NULL){
426 debug(D_WARN, "Skipping platform %i", j);
429 p->extension_suffix = param_value;
430 debug(D_DUMP|D_LOG, "Extension suffix: %s", param_value);
432 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_PROFILE, "profile");
433 if (param_value != NULL){
434 debug(D_DUMP, "Profile: %s", param_value);
437 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_VERSION, "version");
438 p->version = param_value;
439 if (param_value != NULL){
440 debug(D_DUMP, "Version: %s", param_value);
443 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_NAME, "name");
444 if (param_value != NULL){
445 debug(D_DUMP, "Name: %s", param_value);
448 param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_VENDOR, "vendor");
449 if (param_value != NULL){
450 debug(D_DUMP, "Vendor: %s", param_value);
455 num_valid_platforms++;
458 if( num_valid_platforms != 0 ) {
459 if ( _num_icds != i ) {
460 picd->dl_handle = dlh;
462 dump_vendor_icd("after looking for platforms", &_icds[_num_icds]);
464 picd->num_platforms = num_valid_platforms;
472 static void __initClIcd( void ) {
474 cl_uint num_icds = 0;
477 const char* dir_path=getenv("OCL_ICD_VENDORS");
478 if (! dir_path || dir_path[0]==0) {
479 debug(D_DUMP, "OCL_ICD_VENDORS empty or not defined, using %s", ETC_OPENCL_VENDORS);
480 dir_path=ETC_OPENCL_VENDORS;
485 int ret=stat(dir_path, &buf);
486 if (ret != 0 && errno != ENOENT) {
487 debug(D_WARN, "Cannot stat '%s'. Aborting", dir_path);
489 if (ret == 0 && S_ISDIR(buf.st_mode)) {
495 debug(D_LOG,"Only loading '%s' as an ICD", dir_path);
499 debug(D_LOG,"Reading icd list from '%s'", dir_path);
500 dir = opendir(dir_path);
502 if (errno == ENOTDIR) {
503 debug(D_DUMP, "%s is not a directory, trying to use it as a ICD libname",
509 num_icds = _find_num_icds(dir);
515 _icds = (struct vendor_icd*)malloc(num_icds * sizeof(struct vendor_icd));
521 if (_string_end_with_icd(dir_path)) {
523 if (! _string_with_slash(dir_path)) {
524 num_icds = _open_driver(0, ETC_OPENCL_VENDORS, dir_path);
527 num_icds = _open_driver(0, NULL, dir_path);
530 num_icds = _load_icd(0, dir_path);
533 num_icds = _open_drivers(dir, dir_path);
539 _find_and_check_platforms(num_icds);
544 if (_num_icds < num_icds) {
545 _icds = (struct vendor_icd*)realloc(_icds, _num_icds * sizeof(struct vendor_icd));
547 debug(D_WARN, "%d valid vendor(s)!", _num_icds);
566 static pthread_once_t once_init = PTHREAD_ONCE_INIT;
570 volatile static __thread int in_init = 0;
571 volatile static cl_uint _initialized = 0;
573 static void _initClIcd_real( void ) {
576 /* probably reentrency, in_init is a __thread variable */
577 debug(D_WARN, "Executing init while already in init!");
580 __sync_synchronize();
581 pthread_once(&once_init, &__initClIcd);
582 __sync_synchronize();
586 if (__sync_bool_compare_and_swap(&gard, 0, 1)) {
588 __sync_synchronize();
590 __sync_synchronize();
594 /* probably reentrency (could also be preemptive user-level threads). */
596 /* someone else started __initClIcd(). We wait until it ends. */
597 debug(D_WARN, "Waiting end of init");
598 while (!_initialized) {
599 __sync_synchronize();
601 debug(D_WARN, "Wait done");
608 static inline void _initClIcd( void ) {
609 if( __builtin_expect (_initialized, 1) )
614 cl_platform_id __attribute__((visibility("internal")))
615 getDefaultPlatformID() {
616 static cl_platform_id defaultPlatformID=NULL;
617 static int defaultSet=0;
621 if(_num_picds == 0) {
624 const char *default_platform = getenv("OPENCL_ICD_DEFAULT_PLATFORM");
625 int num_default_platform;
627 if (! default_platform) {
628 num_default_platform = 0;
630 num_default_platform = strtol(default_platform, &end_scan, 10);
631 if (*default_platform == '\0' || *end_scan != '\0') {
635 if (num_default_platform < 0 || num_default_platform >= _num_picds) {
638 defaultPlatformID=_picds[num_default_platform].pid;
642 return defaultPlatformID;
645 #pragma GCC visibility pop
646 #define hidden_alias(name) \
647 typeof(name) name##_hid __attribute__ ((alias (#name), visibility("hidden")))
650 CL_ICDL_OCL_VERSION=1,
656 static cl_int clGetICDLoaderInfoOCLICD(
657 cl_icdl_info param_name,
658 size_t param_value_size,
660 size_t * param_value_size_ret)
662 char cl_icdl_ocl_version[] = "OpenCL 1.2";
663 char cl_icdl_version[] = PACKAGE_VERSION;
664 char cl_icdl_name[] = PACKAGE_NAME;
665 char cl_icdl_vendor[] = "OCL Icd free software";
669 #define oclcase(name, NAME) \
670 case CL_ICDL_##NAME: \
671 string_p = cl_icdl_##name; \
672 size_string = sizeof(cl_icdl_##name); \
675 switch ( param_name ) {
676 oclcase(ocl_version,OCL_VERSION);
677 oclcase(version,VERSION);
679 oclcase(vendor,VENDOR);
681 return CL_INVALID_VALUE;
685 if( param_value != NULL ) {
686 if( size_string > param_value_size )
687 return CL_INVALID_VALUE;
688 memcpy(param_value, string_p, size_string);
690 if( param_value_size_ret != NULL )
691 *param_value_size_ret = size_string;
695 CL_API_ENTRY void * CL_API_CALL
696 clGetExtensionFunctionAddress(const char * func_name) CL_API_SUFFIX__VERSION_1_0 {
699 if( func_name == NULL )
701 cl_uint suffix_length;
703 void * return_value=NULL;
704 struct func_desc const * fn=&function_description[0];
705 int lenfn=strlen(func_name);
707 (strcmp(func_name+lenfn-3, "KHR")==0 || strcmp(func_name+lenfn-3, "EXT")==0)) {
708 while (fn->name != NULL) {
709 if (strcmp(func_name, fn->name)==0)
714 for(i=0; i<_num_picds; i++) {
715 suffix_length = strlen(_picds[i].extension_suffix);
716 if( suffix_length > strlen(func_name) )
718 if(strcmp(_picds[i].extension_suffix, &func_name[strlen(func_name)-suffix_length]) == 0)
719 RETURN((*_picds[i].vicd->ext_fn_ptr)(func_name));
721 if(strcmp(func_name, "clGetICDLoaderInfoOCLICD") == 0) {
722 return (void*)(void*(*)(void))(&clGetICDLoaderInfoOCLICD);
724 RETURN(return_value);
726 hidden_alias(clGetExtensionFunctionAddress);
728 CL_API_ENTRY cl_int CL_API_CALL
729 clGetPlatformIDs(cl_uint num_entries,
730 cl_platform_id * platforms,
731 cl_uint * num_platforms) CL_API_SUFFIX__VERSION_1_0 {
734 if( platforms == NULL && num_platforms == NULL )
735 RETURN(CL_INVALID_VALUE);
736 if( num_entries == 0 && platforms != NULL )
737 RETURN(CL_INVALID_VALUE);
738 if( _num_icds == 0 || _num_picds == 0 ) {
739 if ( num_platforms != NULL )
741 RETURN(CL_PLATFORM_NOT_FOUND_KHR);
745 if( num_platforms != NULL ){
746 *num_platforms = _num_picds;
748 if( platforms != NULL ) {
749 cl_uint n_platforms = _num_picds < num_entries ? _num_picds : num_entries;
750 for( i=0; i<n_platforms; i++) {
751 *(platforms++) = _picds[i].pid;
756 hidden_alias(clGetPlatformIDs);
758 #define RETURN_WITH_ERRCODE(errvar, errvalue, retvalue) \
766 #define CHECK_PLATFORM(__pid) \
768 cl_platform_id _pid=(__pid); \
771 for( j=0; j<_num_picds; j++) { \
772 if( _picds[j].pid == _pid) { \
780 CL_API_ENTRY cl_context CL_API_CALL
781 clCreateContext(const cl_context_properties * properties ,
782 cl_uint num_devices ,
783 const cl_device_id * devices ,
784 void (CL_CALLBACK * pfn_notify )(const char *, const void *, size_t, void *),
786 cl_int * errcode_ret ){
790 if( properties != NULL){
791 while( properties[i] != 0 ) {
792 if( properties[i] == CL_CONTEXT_PLATFORM ) {
793 if((struct _cl_platform_id *) properties[i+1] == NULL) {
795 *errcode_ret = CL_INVALID_PLATFORM;
799 if( !CHECK_PLATFORM((cl_platform_id) properties[i+1]) ) {
800 RETURN_WITH_ERRCODE(errcode_ret, CL_INVALID_PLATFORM, NULL);
803 RETURN(((struct _cl_platform_id *) properties[i+1])
804 ->dispatch->clCreateContext(properties, num_devices, devices,
805 pfn_notify, user_data, errcode_ret));
810 if(devices == NULL || num_devices == 0) {
811 RETURN_WITH_ERRCODE(errcode_ret, CL_INVALID_VALUE, NULL);
813 if((struct _cl_device_id *)devices[0] == NULL) {
814 RETURN_WITH_ERRCODE(errcode_ret, CL_INVALID_DEVICE, NULL);
816 RETURN(((struct _cl_device_id *)devices[0])
817 ->dispatch->clCreateContext(properties, num_devices, devices,
818 pfn_notify, user_data, errcode_ret));
820 hidden_alias(clCreateContext);
822 CL_API_ENTRY cl_context CL_API_CALL
823 clCreateContextFromType(const cl_context_properties * properties ,
824 cl_device_type device_type ,
825 void (CL_CALLBACK * pfn_notify )(const char *, const void *, size_t, void *),
827 cl_int * errcode_ret ){
830 if(_num_picds == 0) {
834 if( properties != NULL){
835 while( properties[i] != 0 ) {
836 if( properties[i] == CL_CONTEXT_PLATFORM ) {
837 if( (struct _cl_platform_id *) properties[i+1] == NULL ) {
840 if( !CHECK_PLATFORM((cl_platform_id) properties[i+1]) ) {
844 return ((struct _cl_platform_id *) properties[i+1])
845 ->dispatch->clCreateContextFromType(properties, device_type,
846 pfn_notify, user_data, errcode_ret);
851 const char *default_platform = getenv("OPENCL_ICD_DEFAULT_PLATFORM");
852 int num_default_platform;
854 if (! default_platform) {
855 num_default_platform = 0;
857 num_default_platform = strtol(default_platform, &end_scan, 10);
858 if (*default_platform == '\0' || *end_scan != '\0') {
862 if (num_default_platform < 0 || num_default_platform >= _num_picds) {
865 RETURN(_picds[num_default_platform].pid->dispatch->clCreateContextFromType
866 (properties, device_type, pfn_notify, user_data, errcode_ret));
869 RETURN_WITH_ERRCODE(errcode_ret, CL_INVALID_PLATFORM, NULL);
871 hidden_alias(clCreateContextFromType);
873 CL_API_ENTRY cl_int CL_API_CALL
874 clGetGLContextInfoKHR(const cl_context_properties * properties ,
875 cl_gl_context_info param_name ,
876 size_t param_value_size ,
878 size_t * param_value_size_ret ){
882 if( properties != NULL){
883 while( properties[i] != 0 ) {
884 if( properties[i] == CL_CONTEXT_PLATFORM ) {
885 if( (struct _cl_platform_id *) properties[i+1] == NULL ) {
886 RETURN(CL_INVALID_PLATFORM);
888 if( !CHECK_PLATFORM((cl_platform_id) properties[i+1]) ) {
889 RETURN(CL_INVALID_PLATFORM);
892 RETURN(((struct _cl_platform_id *) properties[i+1])
893 ->dispatch->clGetGLContextInfoKHR(properties, param_name,
894 param_value_size, param_value, param_value_size_ret));
899 RETURN(CL_INVALID_PLATFORM);
901 hidden_alias(clGetGLContextInfoKHR);
903 CL_API_ENTRY cl_int CL_API_CALL
904 clWaitForEvents(cl_uint num_events ,
905 const cl_event * event_list ){
907 if( num_events == 0 || event_list == NULL )
908 RETURN(CL_INVALID_VALUE);
909 if( (struct _cl_event *)event_list[0] == NULL )
910 RETURN(CL_INVALID_EVENT);
911 RETURN(((struct _cl_event *)event_list[0])
912 ->dispatch->clWaitForEvents(num_events, event_list));
914 hidden_alias(clWaitForEvents);
916 CL_API_ENTRY cl_int CL_API_CALL
917 clUnloadCompiler( void ){
921 hidden_alias(clUnloadCompiler);