2 Copyright (c) 2012, Brice Videau <brice.videau@imag.fr>
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
8 1. Redistributions of source code must retain the above copyright notice, this
9 list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright notice,
11 this list of conditions and the following disclaimer in the documentation
12 and/or other materials provided with the distribution.
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <CL/opencl.h>
33 #pragma GCC visibility push(hidden)
35 #include "ocl_icd_loader.h"
37 typedef CL_API_ENTRY void * (CL_API_CALL *clGetExtensionFunctionAddress_fn)(const char * /* func_name */) CL_API_SUFFIX__VERSION_1_0;
39 static cl_uint _initialized = 0;
40 static cl_uint _num_valid_vendors = 0;
41 static cl_uint *_vendors_num_platforms = NULL;
42 static cl_platform_id **_vendors_platforms = NULL;
43 static void **_vendor_dl_handles = NULL;
44 static clGetExtensionFunctionAddress_fn *_ext_fn_ptr = NULL;
45 static char** _vendors_extension_suffixes = NULL;
46 static const char *_dir_path="/etc/OpenCL/vendors/";
48 static inline cl_uint _find_num_vendors(DIR *dir) {
49 cl_uint num_vendors = 0;
51 while( (ent=readdir(dir)) != NULL ){
52 if( strcmp(ent->d_name,".") == 0 || strcmp(ent->d_name,"..") == 0 )
54 cl_uint d_name_len = strlen(ent->d_name);
55 if( strcmp(ent->d_name + d_name_len - 4, ".icd" ) != 0 )
57 // printf("%s%s\n", _dir_path, ent->d_name);
64 static inline cl_uint _open_drivers(DIR *dir) {
65 cl_uint num_vendors = 0;
67 while( (ent=readdir(dir)) != NULL ){
68 if( strcmp(ent->d_name,".") == 0 || strcmp(ent->d_name,"..") == 0 )
70 cl_uint d_name_len = strlen(ent->d_name);
71 if( strcmp(ent->d_name + d_name_len - 4, ".icd" ) != 0 )
75 unsigned int lib_path_length = strlen(_dir_path) + strlen(ent->d_name) + 1;
76 lib_path = malloc(lib_path_length*sizeof(char));
77 sprintf(lib_path,"%s%s", _dir_path, ent->d_name);
78 FILE *f = fopen(lib_path,"r");
81 fseek(f, 0, SEEK_END);
82 lib_path_length = ftell(f)+1;
83 fseek(f, 0, SEEK_SET);
84 if(lib_path_length == 1) {
88 lib_path = malloc(lib_path_length*sizeof(char));
89 err = fgets(lib_path, lib_path_length, f);
96 lib_path_length = strlen(lib_path);
98 if( lib_path[lib_path_length-1] == '\n' )
99 lib_path[lib_path_length-1] = '\0';
101 _vendor_dl_handles[num_vendors] = dlopen(lib_path, RTLD_LAZY|RTLD_LOCAL);//|RTLD_DEEPBIND);
103 if(_vendor_dl_handles[num_vendors] != NULL)
109 static inline void _find_and_check_platforms(cl_uint num_vendors) {
111 _num_valid_vendors = 0;
112 for( i=0; i<num_vendors; i++){
113 cl_uint num_valid_platforms=0;
114 cl_uint num_platforms=0;
115 cl_platform_id *platforms;
117 _ext_fn_ptr[_num_valid_vendors] = dlsym(_vendor_dl_handles[i], "clGetExtensionFunctionAddress");
118 clIcdGetPlatformIDsKHR_fn plt_fn_ptr;
119 if( _ext_fn_ptr[_num_valid_vendors] == NULL )
121 plt_fn_ptr = (*_ext_fn_ptr[_num_valid_vendors])("clIcdGetPlatformIDsKHR");
122 if( plt_fn_ptr == NULL )
124 error = (*plt_fn_ptr)(0, NULL, &num_platforms);
125 if( error != CL_SUCCESS || num_platforms == 0)
127 platforms = (cl_platform_id *) malloc( sizeof(cl_platform_id) * num_platforms);
128 error = (*plt_fn_ptr)(num_platforms, platforms, NULL);
129 if( error != CL_SUCCESS ){
133 _vendors_platforms[_num_valid_vendors] = (cl_platform_id *)malloc(num_platforms * sizeof(cl_platform_id));
135 for(j=0; j<num_platforms; j++) {
136 size_t param_value_size_ret;
137 error = ((struct _cl_platform_id *)platforms[j])->dispatch->clGetPlatformInfo(platforms[j], CL_PLATFORM_EXTENSIONS, 0, NULL, ¶m_value_size_ret);
138 if (error != CL_SUCCESS)
140 char *param_value = (char *)malloc(sizeof(char)*param_value_size_ret);
141 error = ((struct _cl_platform_id *)platforms[j])->dispatch->clGetPlatformInfo(platforms[j], CL_PLATFORM_EXTENSIONS, param_value_size_ret, param_value, NULL);
142 if (error != CL_SUCCESS){
146 if( strstr(param_value, "cl_khr_icd") == NULL){
151 error = ((struct _cl_platform_id *)platforms[j])->dispatch->clGetPlatformInfo(platforms[j], CL_PLATFORM_ICD_SUFFIX_KHR, 0, NULL, ¶m_value_size_ret);
152 if (error != CL_SUCCESS)
154 param_value = (char *)malloc(sizeof(char)*param_value_size_ret);
155 error = ((struct _cl_platform_id *)platforms[j])->dispatch->clGetPlatformInfo(platforms[j], CL_PLATFORM_ICD_SUFFIX_KHR, param_value_size_ret, param_value, NULL);
156 if (error != CL_SUCCESS){
160 _vendors_extension_suffixes[_num_valid_vendors] = param_value;
161 _vendors_platforms[_num_valid_vendors][num_valid_platforms] = platforms[j];
162 num_valid_platforms++;
164 if( num_valid_platforms != 0 ) {
165 _vendors_num_platforms[_num_valid_vendors] = num_valid_platforms;
166 _num_valid_vendors++;
168 free(_vendors_platforms[_num_valid_vendors]);
169 dlclose(_vendor_dl_handles[i]);
175 static void _initClIcd( void ) {
178 cl_uint num_vendors = 0;
180 dir = opendir(_dir_path);
182 _num_valid_vendors = 0;
187 num_vendors = _find_num_vendors(dir);
188 // printf("%d vendor(s)!\n", num_vendors);
189 if(num_vendors == 0) {
190 _num_valid_vendors = 0;
195 _vendor_dl_handles = (void **)malloc(num_vendors * sizeof(void *));
196 num_vendors = _open_drivers(dir);
197 // printf("%d vendor(s)!\n", num_vendors);
198 if(num_vendors == 0) {
199 free( _vendor_dl_handles );
200 _num_valid_vendors = 0;
205 _ext_fn_ptr = (clGetExtensionFunctionAddress_fn *)malloc(num_vendors * sizeof(clGetExtensionFunctionAddress_fn));
206 _vendors_extension_suffixes = (char **) malloc (sizeof(char *) * num_vendors);
207 _vendors_num_platforms = (cl_uint *)malloc(num_vendors * sizeof(cl_uint));
208 _vendors_platforms = (cl_platform_id **)malloc(num_vendors * sizeof(cl_platform_id *));
209 _find_and_check_platforms(num_vendors);
210 if(_num_valid_vendors == 0){
211 free( _vendor_dl_handles );
213 free( _vendors_extension_suffixes );
214 free( _vendors_platforms );
215 free( _vendors_num_platforms );
217 // printf("%d valid vendor(s)!\n", _num_valid_vendors);
221 #pragma GCC visibility pop
223 CL_API_ENTRY void * CL_API_CALL clGetExtensionFunctionAddress(const char * func_name) CL_API_SUFFIX__VERSION_1_0 {
226 if( func_name == NULL )
228 cl_uint suffix_length;
230 void * return_value=NULL;
231 struct func_desc const * fn=&function_description[0];
232 while (fn->name != NULL) {
233 if (strcmp(func_name, fn->name)==0)
237 for(i=0; i<_num_valid_vendors; i++) {
238 suffix_length = strlen(_vendors_extension_suffixes[i]);
239 if( suffix_length > strlen(func_name) )
241 if(strcmp(_vendors_extension_suffixes[i], &func_name[strlen(func_name)-suffix_length]) == 0)
242 return (*_ext_fn_ptr[i])(func_name);
247 CL_API_ENTRY cl_int CL_API_CALL
248 clGetPlatformIDs(cl_uint num_entries,
249 cl_platform_id * platforms,
250 cl_uint * num_platforms) CL_API_SUFFIX__VERSION_1_0 {
253 if( platforms == NULL && num_platforms == NULL )
254 return CL_INVALID_VALUE;
255 if( num_entries == 0 && platforms != NULL )
256 return CL_INVALID_VALUE;
257 if( _num_valid_vendors == 0)
258 return CL_PLATFORM_NOT_FOUND_KHR;
261 cl_uint n_platforms=0;
262 for(i=0; i<_num_valid_vendors; i++) {
263 n_platforms += _vendors_num_platforms[i];
265 if( num_platforms != NULL ){
266 *num_platforms = n_platforms;
268 if( platforms != NULL ) {
269 n_platforms = n_platforms < num_entries ? n_platforms : num_entries;
270 for( i=0; i<_num_valid_vendors; i++) {
272 for(j=0; j<_vendors_num_platforms[i]; j++) {
273 *(platforms++) = _vendors_platforms[i][j];
275 if( n_platforms == 0 )