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 $api_entries_array = []
33 $cl_objects = ["platform_id", "device_id", "context", "command_queue", "mem", "program", "kernel", "event", "sampler"]
34 $know_entries = { 1 => "clGetPlatformInfo", 0 => "clGetPlatformIDs", 2 => "clGetDeviceIDs" }
35 $use_name_in_test = { 1 => "clGetPlatformInfo", 0 => "clGetPlatformIDs", 2 => "clGetDeviceIDs" }
36 # do not call these functions when trying to discover the mapping
38 "clUnloadCompiler", # No parameters so no way to forward to an ICD, OpenCL 1.0
39 "clGetPlatformIDs", # Implemented directly within the ICD Loader, not forwarded to ICD
41 # windows function to ignore when loading the database
42 $windows_funcs = ["clGetDeviceIDsFromD3D10KHR", "clCreateFromD3D10BufferKHR",
43 "clCreateFromD3D10Texture2DKHR", "clCreateFromD3D10Texture3DKHR",
44 "clEnqueueAcquireD3D10ObjectsKHR", "clEnqueueReleaseD3D10ObjectsKHR",
45 "clGetDeviceIDsFromD3D11KHR", "clCreateFromD3D11BufferKHR",
46 "clCreateFromD3D11Texture2DKHR", "clCreateFromD3D11Texture3DKHR",
47 "clEnqueueAcquireD3D11ObjectsKHR", "clEnqueueReleaseD3D11ObjectsKHR",
48 "clGetDeviceIDsFromDX9MediaAdapterKHR", "clCreateFromDX9MediaSurfaceKHR",
49 "clEnqueueAcquireDX9MediaSurfacesKHR", "clEnqueueReleaseDX9MediaSurfacesKHR"]
50 # do not create weak functions for these ones in the discovering program
51 $noweak_funcs = ["clGetExtensionFunctionAddress", "clGetPlatformIDs",
52 "clGetPlatformInfo", "clGetGLContextInfoKHR", "clUnloadCompiler",
53 "clCreateContext", "clCreateContextFromType", "clWaitForEvents"]
54 # functions written specifically in the loader
55 $specific_loader_funcs = ["clGetExtensionFunctionAddress","clGetPlatformIDs",
56 "clGetGLContextInfoKHR", "clUnloadCompiler",
57 "clCreateContext", "clCreateContextFromType", "clWaitForEvents"]
58 $header_files = ["/usr/include/CL/cl.h", "/usr/include/CL/cl_gl.h",
59 "/usr/include/CL/cl_ext.h", "/usr/include/CL/cl_gl_ext.h"]
60 $windows_header_files = ["/usr/include/CL/cl_dx9_media_sharing.h", "/usr/include/CL/cl_d3d11.h", "/usr/include/CL/cl_d3d10.h"]
61 $cl_data_type_error = { "cl_platform_id" => "CL_INVALID_PLATFORM",
62 "cl_device_id" => "CL_INVALID_DEVICE",
63 "cl_context" => "CL_INVALID_CONTEXT",
64 "cl_command_queue" => "CL_INVALID_COMMAND_QUEUE",
65 "cl_mem" => "CL_INVALID_MEM_OBJECT",
66 "cl_program" => "CL_INVALID_PROGRAM",
67 "cl_kernel" => "CL_INVALID_KERNEL",
68 "cl_event" => "CL_INVALID_EVENT",
69 "cl_sampler" => "CL_INVALID_SAMPLER"}
70 $non_standard_error = [ "clGetExtensionFunctionAddressForPlatform", "clSVMAlloc" ]
71 $versions_entries = []
74 Copyright (c) 2012, Brice Videau <brice.videau@imag.fr>
75 Copyright (c) 2012, Vincent Danjean <Vincent.Danjean@ens-lyon.org>
78 Redistribution and use in source and binary forms, with or without
79 modification, are permitted provided that the following conditions are met:
81 1. Redistributions of source code must retain the above copyright notice, this
82 list of conditions and the following disclaimer.
83 2. Redistributions in binary form must reproduce the above copyright notice,
84 this list of conditions and the following disclaimer in the documentation
85 and/or other materials provided with the distribution.
87 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
88 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
89 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
90 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
91 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
92 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
93 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
94 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
95 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
96 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
98 Do not edit this file. It is automatically generated.
101 ##########################################################
102 ##########################################################
104 def self.parse_headers
106 $header_files.each{ |fname|
107 f = File::open(fname)
109 api_entries += doc.scan(/CL_API_ENTRY.*?;/m)
112 api_entries.each{ |entry|
115 entry_name = entry.match(/CL_API_CALL(.*?)\(/m)[1].strip
117 entry_name = entry.match(/(\S*?)\(/m)[1].strip
119 next if entry_name.match('\*')
120 next if entry_name.match("INTEL")
121 next if entry_name.match("APPLE")
122 $api_entries[entry_name] = entry.gsub("\r","")
124 # $api_entries.each{ |key, value|
125 # puts "#{key}: #{value}"
129 def self.load_database(yamlfile, with_windows=false)
130 doc = YAML::load_file(yamlfile)
133 $versions_entries = Hash::new { |hash,key| hash[key]=[] }
136 doc.each { |key, value|
137 #puts (key.to_s+":: "+value)
139 entry_name = value.match(/CL_API_CALL(.*?)\(/m)[1].strip
141 entry_name = value.match(/(\S*?)\(/m)[1].strip
143 next if (!with_windows) && $windows_funcs.include?(entry_name)
144 version = value.match(/SUFFIX__VERSION_(\d_\d)/m)[1]
145 $versions_entries[version].push(entry_name)
146 $known_entries[key] = entry_name
147 $key_entries[entry_name] = key
148 $api_entries[entry_name] = value
150 $api_entries_array = []
151 ($known_entries.length+$buff).times { |i|
152 #puts (i.to_s+": "+$known_entries[i])
153 if $known_entries[i] then
154 $api_entries_array.push( $api_entries[$known_entries[i]] )
156 $api_entries_array.push( "CL_API_ENTRY cl_int CL_API_CALL clUnknown#{i}(void);" )
161 def self.include_headers
163 $header_files.each { |h|
164 if h.match('^/usr/include/') then
165 headers += "#include <#{h[13..-1]}>\n"
167 headers += "#include \"#{h}\"\n"
173 ##########################################################
174 ##########################################################
176 def self.generate_libdummy_icd_header
177 libdummy_icd_structures = "/**\n#{$license}\n*/\n"
178 libdummy_icd_structures += "#include <CL/opencl.h>\n"
179 libdummy_icd_structures += self.include_headers
180 libdummy_icd_structures += "\n\nstruct _cl_icd_dispatch;\n"
181 libdummy_icd_structures += "struct _cl_platform_id { struct _cl_icd_dispatch *dispatch; };\n\n"
182 libdummy_icd_structures += "struct _cl_icd_dispatch {\n"
183 ($api_entries.length+$buff).times { |i|
184 if( $known_entries[i] ) then
185 libdummy_icd_structures += " void(*known#{i})(void);\n"
187 libdummy_icd_structures += " void(*unknown#{i})(void);\n"
190 libdummy_icd_structures += "};\n\n"
191 libdummy_icd_structures += "#pragma GCC visibility push(hidden)\n\n"
192 libdummy_icd_structures += "struct _cl_icd_dispatch master_dispatch; \n\n"
193 $use_name_in_test.each { |k, f|
194 libdummy_icd_structures += "typeof(#{f}) INT#{f};\n"
196 libdummy_icd_structures += "#pragma GCC visibility pop\n\n"
197 return libdummy_icd_structures
200 def self.generate_libdummy_icd_source
201 libdummy_icd_source = "/**\n#{$license}\n*/\n\n"
202 libdummy_icd_source += "#include <stdio.h>\n\n"
203 libdummy_icd_source += "#include \"libdummy_icd_gen.h\"\n\n"
204 libdummy_icd_source += "#include \"libdummy_icd.h\"\n\n"
205 (0...$api_entries.length+$buff).each { |i|
206 libdummy_icd_source += "void dummyFunc#{i}(void){ printf(\"#{i} : \"); fflush(NULL); }\n"
208 libdummy_icd_source += "\nstruct _cl_icd_dispatch master_dispatch = {\n"
210 ($api_entries.length+$buff).times { |i|
211 comma="" if (i == $api_entries.length+$buff-1)
212 if( $use_name_in_test[i] ) then
213 libdummy_icd_source += " (void(*)(void))& INT#{$known_entries[i]}#{comma}\n"
215 libdummy_icd_source += " (void(*)(void))& dummyFunc#{i}#{comma}\n"
218 libdummy_icd_source += "};\n"
219 return libdummy_icd_source
222 def self.generate_run_dummy_icd_source
223 run_dummy_icd = "/**\n#{$license}\n*/\n"
224 run_dummy_icd += "#include <stdlib.h>\n"
225 run_dummy_icd += "#include <stdio.h>\n"
226 run_dummy_icd += "#pragma GCC diagnostic push\n"
227 run_dummy_icd += "# pragma GCC diagnostic ignored \"-Wcpp\"\n"
228 run_dummy_icd += "# define CL_USE_DEPRECATED_OPENCL_1_0_APIS\n"
229 run_dummy_icd += "# define CL_USE_DEPRECATED_OPENCL_1_1_APIS\n"
230 run_dummy_icd += "# define CL_USE_DEPRECATED_OPENCL_1_2_APIS\n"
231 run_dummy_icd += "# include <CL/opencl.h>\n"
232 run_dummy_icd += self.include_headers
233 run_dummy_icd += "#pragma GCC diagnostic pop\n"
234 run_dummy_icd += "\n\n"
235 $api_entries.each_key { |func_name|
236 next if $forbidden_funcs.include?(func_name)
237 run_dummy_icd += $api_entries[func_name]+";\n"
239 run_dummy_icd += "\n\n"
240 run_dummy_icd += "void call_all_OpenCL_functions(cl_platform_id chosen_platform) {\n"
241 run_dummy_icd += " cl_context_properties properties[] = { CL_CONTEXT_PLATFORM, (cl_context_properties)chosen_platform, 0 };\n"
242 $api_entries.each_key { |func_name|
243 next if $forbidden_funcs.include?(func_name)
244 if func_name == "clCreateContext" then
245 run_dummy_icd += " #{func_name}(properties,1,(cl_device_id*)&chosen_platform,NULL,NULL,NULL);\n"
246 elsif func_name == "clGetGLContextInfoKHR" then
247 run_dummy_icd += " #{func_name}(properties,CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR, 0, NULL, NULL);\n"
248 elsif func_name == "clCreateContextFromType" then
249 run_dummy_icd += " #{func_name}(properties,CL_DEVICE_TYPE_CPU,NULL,NULL,NULL);\n"
250 elsif func_name == "clWaitForEvents" then
251 run_dummy_icd += " #{func_name}(1,(cl_event*)&chosen_platform);\n"
252 elsif func_name == "clGetExtensionFunctionAddress" then
253 run_dummy_icd += " #{func_name}(\"extLIG\");\n"
254 elsif func_name == "clUnloadCompiler" then
255 run_dummy_icd += " #{func_name}();\n"
257 params = $api_entries[func_name].gsub(/[[:space:]]+/, ' ')
258 params.gsub!(/[\/][*](([^*]*)[*][^\/])*[^*]*[*][\/]/,'')
259 params.gsub!(/^[^(]*[(] *(.*[^ ]) *[)][^)]*$/, '\1')
260 params = params.gsub(/[^,(]+([(][^)]*[)])*[^,]*/) { |p|
262 p.gsub!("user_func", "")
263 if false && p.match(/[*]/) then
269 if func_name != "clGetPlatformIDs" then
270 params.gsub!(/^([^0]*)0/, '\1chosen_platform')
272 run_dummy_icd += " #{func_name}(#{params});\n"
274 run_dummy_icd += " printf(\"%s\\n\", \"#{func_name}\");\n"
275 run_dummy_icd += "#ifdef OCL_ICD_PRINT_EXPECTED\n"
276 run_dummy_icd += " printf(\"#{$key_entries[func_name]} : %s (expected)\\n\", \"#{func_name}\");\n"
277 run_dummy_icd += "#endif\n"
278 run_dummy_icd += " fflush(NULL);\n"
280 run_dummy_icd += " return;\n}\n"
284 def self.generate_run_dummy_icd_weak_source
285 run_dummy_icd_weak = "/**\n#{$license}\n*/\n"
286 run_dummy_icd_weak += <<EOF
287 #define _GNU_SOURCE 1
292 run_dummy_icd_weak += "#pragma GCC diagnostic push\n"
293 run_dummy_icd_weak += "# pragma GCC diagnostic ignored \"-Wcpp\"\n"
294 run_dummy_icd_weak += "# define CL_USE_DEPRECATED_OPENCL_1_0_APIS\n"
295 run_dummy_icd_weak += "# define CL_USE_DEPRECATED_OPENCL_1_1_APIS\n"
296 run_dummy_icd_weak += "# define CL_USE_DEPRECATED_OPENCL_1_2_APIS\n"
297 run_dummy_icd_weak += "# include <CL/opencl.h>\n"
298 run_dummy_icd_weak += self.include_headers
299 run_dummy_icd_weak += "#pragma GCC diagnostic pop\n"
301 $api_entries.each { |func_name, entry|
302 next if $noweak_funcs.include?(func_name)
303 clean_entry = entry.sub(/(.*\)).*/m,'\1').gsub("/*","").gsub("*/","").gsub("\r","") + "{\n"
304 return_type = entry.match(/CL_API_ENTRY (.*) CL_API_CALL/)[1]
305 parameters = clean_entry.match(/\(.*\)/m)[0][1..-2]
306 parameters.gsub!(/\[.*?\]/,"")
307 parameters.sub!(/\(.*?\*\s*(.*?)\)\s*\(.*?\)/m,'\1')
308 run_dummy_icd_weak += clean_entry.gsub(/\*\[.*?\]/,"* ").gsub(/\[.+?\]/,"")
309 first_parameter = parameters.match(/.*?\,/m)
310 if not first_parameter then
311 first_parameter = parameters.match(/.*/m)[0]
313 first_parameter = first_parameter[0][0..-2]
315 fps = first_parameter.split
316 run_dummy_icd_weak += " void (*p)()=dlsym(RTLD_NEXT, \"#{func_name}\");\n"
317 ps = parameters.split(",")
318 ps = ps.collect { |p|
320 p = p[-1].gsub("*","")
323 run_dummy_icd_weak += " if(p) {\n"
324 run_dummy_icd_weak += " return((*(typeof(#{func_name})*)p)("
325 run_dummy_icd_weak += ps.join(", ")
326 run_dummy_icd_weak += "));\n"
327 run_dummy_icd_weak += " } else {\n"
328 run_dummy_icd_weak += " printf(\"-1 : \");\n"
329 run_dummy_icd_weak += " return (#{return_type})0;\n"
330 run_dummy_icd_weak += " }\n"
331 run_dummy_icd_weak += "}\n\n"
333 return run_dummy_icd_weak
336 def self.generate_sources(from_headers=true, from_database=false, database=nil)
340 if from_database then
341 load_database(database)
343 File.open('libdummy_icd_gen.h','w') { |f|
344 f.puts generate_libdummy_icd_header
346 File.open('libdummy_icd_gen.c','w') { |f|
347 f.puts generate_libdummy_icd_source
349 File.open('run_dummy_icd_gen.c','w') { |f|
350 f.puts generate_run_dummy_icd_source
352 File.open('run_dummy_icd_weak_gen.c','w') { |f|
353 f.puts generate_run_dummy_icd_weak_source
357 ##########################################################
358 ##########################################################
360 def self.generate_ocl_icd_header
361 ocl_icd_header = "/**\n#{$license}\n*/\n\n"
362 ocl_icd_header += "#ifndef OCL_ICD_H\n"
363 ocl_icd_header += "#define OCL_ICD_H\n"
364 ocl_icd_header += "#pragma GCC diagnostic push\n"
365 ocl_icd_header += "# pragma GCC diagnostic ignored \"-Wcpp\"\n"
366 ocl_icd_header += "# define CL_USE_DEPRECATED_OPENCL_1_0_APIS\n"
367 ocl_icd_header += "# define CL_USE_DEPRECATED_OPENCL_1_1_APIS\n"
368 ocl_icd_header += "# define CL_USE_DEPRECATED_OPENCL_1_2_APIS\n"
369 ocl_icd_header += "# include <CL/opencl.h>\n"
370 ocl_icd_header += self.include_headers
371 ocl_icd_header += "#pragma GCC diagnostic pop\n"
372 ocl_icd_header += <<EOF
374 #define OCL_ICD_API_VERSION 1
375 #define OCL_ICD_IDENTIFIED_FUNCTIONS #{$known_entries.count}
377 struct _cl_icd_dispatch {
380 $api_entries_array.each { |entry|
381 version = entry.split("\n").
382 grep(/ CL_API_SUFFIX__(VERSION_[0-9_]+)[^0-9_]/).join('').
383 gsub(/.* CL_API_SUFFIX__(VERSION_[0-9_]+)[^0-9_].*$/, '\1')
384 if (version != '') then
385 ocl_icd_header += '#ifdef CL_'+version+"\n"
387 ocl_icd_header += entry.gsub("\r","").
388 sub(/CL_API_CALL\n?(.*?)\(/m,'(CL_API_CALL*\1)('+"\n ").
389 gsub(/\) (CL_API_SUFFIX__VERSION)/m,"\n) \\1").gsub(/\s*$/,'').
390 gsub(/^[\t ]+/," ").gsub(/^([^\t ])/, ' \1') + "\n"
391 if (version != '') then
392 ocl_icd_header += '#else'+"\n"
393 ocl_icd_header += ' CL_API_ENTRY cl_int (CL_API_CALL* clUnknown'+nb.to_s+")(void);\n"
394 ocl_icd_header += '#endif'+"\n"
396 ocl_icd_header += "\n"
399 ocl_icd_header += "};\n"
400 ocl_icd_header += "#endif\n\n"
401 return ocl_icd_header
404 def self.generate_ocl_icd_loader_header
405 ocl_icd_header = "/**\n#{$license}\n*/\n\n"
406 ocl_icd_header += "#include \"ocl_icd.h\"\n\n"
407 ocl_icd_header += <<EOF
411 void(*const addr)(void);
413 typedef __typeof__(clGetExtensionFunctionAddress) *clGetExtensionFunctionAddress_fn;
414 extern const struct func_desc function_description[];
416 cl_uint num_platforms;
418 clGetExtensionFunctionAddress_fn ext_fn_ptr;
421 struct platform_icd {
422 char * extension_suffix;
424 struct vendor_icd *vicd;
426 cl_uint ngpus; /* number of GPU devices */
427 cl_uint ncpus; /* number of CPU devices */
428 cl_uint ndevs; /* total number of devices, of all types */
432 ocl_icd_header += "extern struct _cl_icd_dispatch master_dispatch;\n"
433 $cl_objects.each { |o|
434 ocl_icd_header += "struct _cl_#{o} { struct _cl_icd_dispatch *dispatch; };\n"
436 return ocl_icd_header
439 def self.generate_ocl_icd_loader_map
440 ocl_icd_loader_map = "/**\n#{$license}\n*/\n\n"
442 $versions_entries.keys.sort.each { |version|
443 ocl_icd_loader_map += "OPENCL_#{version.sub('_','.')} {\n";
444 ocl_icd_loader_map += " global:\n";
445 $versions_entries[version].each { |symb|
446 ocl_icd_loader_map += " #{symb};\n"
448 if (prev_version == "") then
449 ocl_icd_loader_map += " local:\n";
450 ocl_icd_loader_map += " *;\n";
452 ocl_icd_loader_map += "} #{prev_version};\n\n";
453 prev_version="OPENCL_#{version.sub('_','.')}";
455 return ocl_icd_loader_map
458 def self.generate_ocl_icd_bindings_source
459 ocl_icd_bindings_source = "/**\n#{$license}\n*/\n"
460 ocl_icd_bindings_source += "#include \"ocl_icd.h\"\n"
461 ocl_icd_bindings_source += "struct _cl_icd_dispatch master_dispatch = {\n"
462 ($api_entries.length+$buff-1).times { |i|
463 if( $known_entries[i] ) then
464 ocl_icd_bindings_source += " #{$known_entries[i]},\n"
466 ocl_icd_bindings_source += " (void *) NULL,\n"
469 if( $known_entries[$api_entries.length+$buff-1] ) then
470 ocl_icd_bindings_source += " #{$known_entries[$api_entries.length+$buff-1]}\n"
472 ocl_icd_bindings_source += " (void *) NULL\n"
474 ocl_icd_bindings_source += "};\n"
475 ocl_icd_bindings_source += <<EOF
477 CL_API_ENTRY cl_int CL_API_CALL clIcdGetPlatformIDsKHR(
479 cl_platform_id *platforms,
480 cl_uint *num_platforms) {
481 if( platforms == NULL && num_platforms == NULL )
482 return CL_INVALID_VALUE;
483 if( num_entries == 0 && platforms != NULL )
484 return CL_INVALID_VALUE;
485 #error You have to fill the commented lines with corresponding variables from your library
486 // if( your_number_of_platforms == 0)
487 // return CL_PLATFORM_NOT_FOUND_KHR;
488 // if( num_platforms != NULL )
489 // *num_platforms = your_number_of_platforms;
490 if( platforms != NULL ) {
492 // for( i=0; i<(your_number_of_platforms<num_entries?your_number_of_platforms:num_entries); i++)
493 // platforms[i] = &your_platforms[i];
498 CL_API_ENTRY void * CL_API_CALL clGetExtensionFunctionAddress(
499 const char * func_name) CL_API_SUFFIX__VERSION_1_0 {
500 #error You have to fill this function with your extensions of incorporate these lines in your version
501 if( func_name != NULL && strcmp("clIcdGetPlatformIDsKHR", func_name) == 0 )
502 return (void *)clIcdGetPlatformIDsKHR;
505 CL_API_ENTRY cl_int CL_API_CALL clGetPlatformInfo(
506 cl_platform_id platform,
507 cl_platform_info param_name,
508 size_t param_value_size,
510 size_t * param_value_size_ret) CL_API_SUFFIX__VERSION_1_0 {
511 #error You ahve to fill this function with your information or assert that your version responds to CL_PLATFORM_ICD_SUFFIX_KHR
512 // char cl_platform_profile[] = "FULL_PROFILE";
513 // char cl_platform_version[] = "OpenCL 1.1";
514 // char cl_platform_name[] = "DummyCL";
515 // char cl_platform_vendor[] = "LIG";
516 // char cl_platform_extensions[] = "cl_khr_icd";
517 // char cl_platform_icd_suffix_khr[] = "DUMMY";
520 if( platform != NULL ) {
523 for(i=0; i<num_master_platforms; i++) {
524 if( platform == &master_platforms[i] )
528 return CL_INVALID_PLATFORM;
530 switch ( param_name ) {
531 case CL_PLATFORM_PROFILE:
532 string_p = cl_platform_profile;
533 size_string = sizeof(cl_platform_profile);
535 case CL_PLATFORM_VERSION:
536 string_p = cl_platform_version;
537 size_string = sizeof(cl_platform_version);
539 case CL_PLATFORM_NAME:
540 string_p = cl_platform_name;
541 size_string = sizeof(cl_platform_name);
543 case CL_PLATFORM_VENDOR:
544 string_p = cl_platform_vendor;
545 size_string = sizeof(cl_platform_vendor);
547 case CL_PLATFORM_EXTENSIONS:
548 string_p = cl_platform_extensions;
549 size_string = sizeof(cl_platform_extensions);
551 case CL_PLATFORM_ICD_SUFFIX_KHR:
552 string_p = cl_platform_icd_suffix_khr;
553 size_string = sizeof(cl_platform_icd_suffix_khr);
556 return CL_INVALID_VALUE;
559 if( param_value != NULL ) {
560 if( size_string > param_value_size )
561 return CL_INVALID_VALUE;
562 memcpy(param_value, string_p, size_string);
564 if( param_value_size_ret != NULL )
565 *param_value_size_ret = size_string;
569 return ocl_icd_bindings_source
572 def self.generate_ocl_icd_loader_gen_source
573 skip_funcs = $specific_loader_funcs
574 ocl_icd_loader_gen_source = "/**\n#{$license}\n*/\n"
575 ocl_icd_loader_gen_source += "#include \"ocl_icd_loader.h\"\n"
576 ocl_icd_loader_gen_source += "#define DEBUG_OCL_ICD_PROVIDE_DUMP_FIELD\n"
577 ocl_icd_loader_gen_source += "#include \"ocl_icd_debug.h\"\n"
578 $api_entries.each { |func_name, entry|
579 next if skip_funcs.include?(func_name)
580 clean_entry = entry.sub(/(.*\)).*/m,'\1').gsub("/*","").gsub("*/","").gsub("\r","") + "{\n"
581 return_type = entry.match(/CL_API_ENTRY (.*) CL_API_CALL/)[1]
582 parameters = clean_entry.match(/\(.*\)/m)[0][1..-2]
583 parameters.gsub!(/\[.*?\]/,"")
584 parameters.sub!(/\(.*?\*\s*(.*?)\)\s*\(.*?\)/m,'\1')
585 ocl_icd_loader_gen_source += clean_entry.gsub(/\*\[.*?\]/,"* ").gsub(/\[.+?\]/,"")
586 first_parameter = parameters.match(/.*?\,/m)
587 if not first_parameter then
588 first_parameter = parameters.match(/.*/m)[0]
590 first_parameter = first_parameter[0][0..-2]
592 fps = first_parameter.split
593 ocl_icd_loader_gen_source += " debug_trace();\n"
594 raise "Unsupported data_type #{fps[0]}" if not $cl_data_type_error[fps[0]]
595 ps = parameters.split(",")
596 ps = ps.collect { |p|
598 p = p[-1].gsub("*","")
600 error_handler = lambda {
601 if(ps.include?("errcode_ret")) then
602 ocl_icd_loader_gen_source += " if( errcode_ret != NULL ) {\n";
603 ocl_icd_loader_gen_source += " *errcode_ret = #{$cl_data_type_error[fps[0]]};\n"
604 ocl_icd_loader_gen_source += " }\n"
605 if return_type != "void" then
606 ocl_icd_loader_gen_source += " RETURN(NULL);\n"
608 ocl_icd_loader_gen_source += " return;\n"
610 elsif ($non_standard_error.include?(func_name)) then
611 if return_type != "void" then
612 ocl_icd_loader_gen_source += " RETURN(NULL);\n"
614 ocl_icd_loader_gen_source += " return;\n"
617 if return_type != "void" then
618 ocl_icd_loader_gen_source += " RETURN(#{$cl_data_type_error[fps[0]]});\n" if return_type != "void"
620 ocl_icd_loader_gen_source += " return;\n"
625 if(fps[0] == "cl_platform_id") then
626 ocl_icd_loader_gen_source += " #{fps[1]}=selectPlatformID(#{fps[1]});\n"
628 ocl_icd_loader_gen_source += " if( (struct _#{fps[0]} *)#{fps[1]} == NULL) {\n"
630 ocl_icd_loader_gen_source += " }\n"
631 if return_type != "void" then
632 return_debug="RETURN"
634 return_debug="return"
636 ocl_icd_loader_gen_source += " #{return_debug}(((struct _#{fps[0]} *)#{fps[1]})->dispatch->#{func_name}("
637 ocl_icd_loader_gen_source += ps.join(", ")
638 ocl_icd_loader_gen_source += "));\n"
639 ocl_icd_loader_gen_source += "}\n\n"
641 ocl_icd_loader_gen_source += "#pragma GCC visibility push(hidden)\n\n"
642 skip_funcs = $specific_loader_funcs
643 $api_entries.each { |func_name, entry|
644 #next if func_name.match(/EXT$/)
645 #next if func_name.match(/KHR$/)
646 if (skip_funcs.include?(func_name)) then
647 ocl_icd_loader_gen_source += "extern typeof(#{func_name}) #{func_name}_hid;\n"
649 ocl_icd_loader_gen_source += "typeof(#{func_name}) #{func_name}_hid __attribute__ ((alias (\"#{func_name}\"), visibility(\"hidden\")));\n"
652 ocl_icd_loader_gen_source += "\n\nstruct func_desc const function_description[]= {\n"
653 $api_entries.each { |func_name, entry|
654 #next if func_name.match(/EXT$/)
655 #next if func_name.match(/KHR$/)
656 ocl_icd_loader_gen_source += " {\"#{func_name}\", (void(* const)(void))&#{func_name}_hid },\n"
658 ocl_icd_loader_gen_source += <<EOF
663 void dump_platform(clGEFA_t f, cl_platform_id pid) {
664 debug(D_ALWAYS, "platform @%p: name=field_in_struct [clGetExtensionFunctionAddress(name)/clGetExtensionFunctionAddressForPlatform(name)]", pid);
666 $api_entries_array.each { |entry|
667 e = entry.gsub("\r"," ").gsub("\n"," ").gsub("\t"," ").
668 sub(/.*CL_API_CALL *([^ ()]*)[ ()].*$/m, '\1')
669 ocl_icd_loader_gen_source += " dump_field(pid, f, #{e});\n"
672 ocl_icd_loader_gen_source += <<EOF
676 #pragma GCC visibility pop
679 return ocl_icd_loader_gen_source;
682 def self.generate_from_database(yamlfile)
683 load_database(yamlfile)
684 File.open('ocl_icd.h','w') { |f|
685 f.puts generate_ocl_icd_header
687 File.open('ocl_icd_loader_gen.h','w') { |f|
688 f.puts generate_ocl_icd_loader_header
690 File.open('ocl_icd_loader_gen.map','w') { |f|
691 f.puts generate_ocl_icd_loader_map
693 File.open('ocl_icd_bindings.c','w') { |f|
694 f.puts generate_ocl_icd_bindings_source
696 File.open('ocl_icd_loader_gen.c','w') { |f|
697 f.puts generate_ocl_icd_loader_gen_source
701 ##########################################################
702 ##########################################################
703 # update-database mode
704 def self.savedb(yamlfile)
705 File::open(yamlfile,"w") { |f|
706 f.write($license.gsub(/^/,"# "))
709 # In Intel (OpenCL 1.1):
710 # * clSetCommandQueueProperty(13): nil (deprecated in 1.1)
711 # * clGetGLContextInfoKHR(74): function present with its symbol
713 # * 92: correspond to symbol clGetKernelArgInfo (first abandonned version?)
715 # In nvidia (OpenCL 1.1):
716 # * clGetGLContextInfoKHR(74): function present but no symbol
719 # * only two OpenCL symbols: clGetPlatformInfo(1) and clGetExtensionFunctionAddress(65)
720 # In AMD (OpenCL 1.2):
721 # * clGetPlatformIDs(0): nil (symbol present)
722 # * clGetGLContextInfoKHR(74): function present but no symbol
730 # Not using YAML::dump as:
731 # * keys are not ordered
732 # * strings are badly formatted in new YAML ruby implementation (psych)
733 # * it is very easy to do it ourself
734 #f.write(YAML::dump(api_db))
736 $known_entries.keys.sort.each { |k|
737 f.write("\n#{k}: |-\n ")
738 f.write($api_entries[$known_entries[k]].gsub("\n","\n "))
744 def self.updatedb_from_input(dbfile, inputfile)
746 load_database(dbfile, with_windows=true)
747 doc = YAML::load_file(inputfile)
750 next if $known_entries[i]
751 $known_entries[i]=doc[i]
758 ############################################################
759 ############################################################
760 ############################################################
767 OptionParser.new do |opts|
768 opts.banner = "Usage: cd_generator.rb [options] mode"
770 opts.on("-d", "--database FILE", String, "YAML file (default ocl_interface.yaml)") do |v|
771 options[:database] = v
773 opts.on("-i", "--input FILE", String,
774 "binding between OpenCL functions and entry number (required for update-database)") \
778 opts.on("-s", "--[no-]system-headers",
779 "Look for OpenCL functions in system header files") \
781 options[:"system-headers"] = v
783 opts.on("-m", "--mode [MODE]", [:database, :generate, :"update-database"],
784 "Select mode (database, generate, update-database)") do |m|
789 if !options[:database] then
790 options[:database] = "ocl_interface.yaml"
793 if !options[:mode] then
794 raise "--mode option required"
796 if options[:mode] == :generate then
797 if !options[:"system-headers"] then
798 IcdGenerator.generate_sources(from_headers=false, from_database=true, database=options[:database])
800 IcdGenerator.generate_sources(from_headers=true, from_database=false)
802 elsif options[:mode] == :"update-database" then
803 if !options[:input] then
804 raise "--input option required"
806 IcdGenerator.updatedb_from_input(options[:database], options[:input])
807 elsif options[:mode] == :database then
808 IcdGenerator.generate_from_database(options[:database])
810 raise "Mode must be one of generate, database or update-database not #{options[:mode]}"