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.
31 $api_entries_array = []
32 $cl_objects = ["platform_id", "device_id", "context", "command_queue", "mem", "program", "kernel", "event", "sampler"]
33 $know_entries = { 1 => "clGetPlatformInfo", 0 => "clGetPlatformIDs" }
34 $use_name_in_test = { 1 => "clGetPlatformInfo", 0 => "clGetPlatformIDs" }
35 # do not call these functions when trying to discover the mapping
36 $forbidden_funcs = ["clGetExtensionFunctionAddress", "clGetPlatformIDs",
37 "clGetPlatformInfo", "clGetGLContextInfoKHR", "clUnloadCompiler",
38 "clSetCommandQueueProperty"]
39 $windows_funcs = ["clGetDeviceIDsFromD3D10KHR", "clCreateFromD3D10BufferKHR",
40 "clCreateFromD3D10Texture2DKHR", "clCreateFromD3D10Texture3DKHR",
41 "clEnqueueAcquireD3D10ObjectsKHR", "clEnqueueReleaseD3D10ObjectsKHR",
42 "clGetDeviceIDsFromD3D11KHR", "clCreateFromD3D11BufferKHR",
43 "clCreateFromD3D11Texture2DKHR", "clCreateFromD3D11Texture3DKHR",
44 "clEnqueueAcquireD3D11ObjectsKHR", "clEnqueueReleaseD3D11ObjectsKHR",
45 "clGetDeviceIDsFromDX9MediaAdapterKHR", "clCreateFromDX9MediaSurfaceKHR",
46 "clEnqueueAcquireDX9MediaSurfacesKHR", "clEnqueueReleaseDX9MediaSurfacesKHR"]
47 # do not create weak functions for these ones in the discovering program
48 $noweak_funcs = ["clGetExtensionFunctionAddress", "clGetPlatformIDs",
49 "clGetPlatformInfo", "clGetGLContextInfoKHR", "clUnloadCompiler",
50 "clCreateContext", "clCreateContextFromType", "clWaitForEvents"]
51 # functions written specifically in the loader
52 $specific_loader_funcs = ["clGetExtensionFunctionAddress","clGetPlatformIDs",
53 "clGetGLContextInfoKHR", "clUnloadCompiler",
54 "clCreateContext", "clCreateContextFromType", "clWaitForEvents"]
55 $header_files = ["/usr/include/CL/cl.h", "/usr/include/CL/cl_gl.h",
56 "/usr/include/CL/cl_ext.h", "/usr/include/CL/cl_gl_ext.h"]
57 $windows_header_files = ["/usr/include/CL/cl_dx9_media_sharing.h", "/usr/include/CL/cl_d3d11.h", "/usr/include/CL/cl_d3d10.h"]
58 $cl_data_type_error = { "cl_platform_id" => "CL_INVALID_PLATFORM",
59 "cl_device_id" => "CL_INVALID_DEVICE",
60 "cl_context" => "CL_INVALID_CONTEXT",
61 "cl_command_queue" => "CL_INVALID_COMMAND_QUEUE",
62 "cl_mem" => "CL_INVALID_MEM_OBJECT",
63 "cl_program" => "CL_INVALID_PROGRAM",
64 "cl_kernel" => "CL_INVALID_KERNEL",
65 "cl_event" => "CL_INVALID_EVENT",
66 "cl_sampler" => "CL_INVALID_SAMPLER"}
67 $non_standard_error = [ "clGetExtensionFunctionAddressForPlatform", "clSVMAlloc" ]
68 $versions_entries = []
71 Copyright (c) 2012, Brice Videau <brice.videau@imag.fr>
72 Copyright (c) 2012, Vincent Danjean <Vincent.Danjean@ens-lyon.org>
75 Redistribution and use in source and binary forms, with or without
76 modification, are permitted provided that the following conditions are met:
78 1. Redistributions of source code must retain the above copyright notice, this
79 list of conditions and the following disclaimer.
80 2. Redistributions in binary form must reproduce the above copyright notice,
81 this list of conditions and the following disclaimer in the documentation
82 and/or other materials provided with the distribution.
84 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
85 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
86 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
87 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
88 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
89 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
90 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
91 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
92 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
93 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
95 Do not edit this file. It is automatically generated.
98 ##########################################################
99 ##########################################################
101 def self.parse_headers
103 $header_files.each{ |fname|
104 f = File::open(fname)
106 api_entries += doc.scan(/CL_API_ENTRY.*?;/m)
109 api_entries.each{ |entry|
112 entry_name = entry.match(/CL_API_CALL(.*?)\(/m)[1].strip
114 entry_name = entry.match(/(\S*?)\(/m)[1].strip
116 next if entry_name.match('\*')
117 next if entry_name.match("INTEL")
118 next if entry_name.match("APPLE")
119 $api_entries[entry_name] = entry.gsub("\r","")
121 # $api_entries.each{ |key, value|
122 # puts "#{key}: #{value}"
126 def self.load_database(yamlfile, with_windows=false)
127 doc = YAML::load_file(yamlfile)
130 $versions_entries = Hash::new { |hash,key| hash[key]=[] }
133 doc.each { |key, value|
134 #puts (key.to_s+":: "+value)
136 entry_name = value.match(/CL_API_CALL(.*?)\(/m)[1].strip
138 entry_name = value.match(/(\S*?)\(/m)[1].strip
140 next if (!with_windows) && $windows_funcs.include?(entry_name)
141 version = value.match(/SUFFIX__VERSION_(\d_\d)/m)[1]
142 $versions_entries[version].push(entry_name)
143 $known_entries[key] = entry_name
144 $api_entries[entry_name] = value
146 $api_entries_array = []
147 ($known_entries.length+$buff).times { |i|
148 #puts (i.to_s+": "+$known_entries[i])
149 if $known_entries[i] then
150 $api_entries_array.push( $api_entries[$known_entries[i]] )
152 $api_entries_array.push( "CL_API_ENTRY cl_int CL_API_CALL clUnknown#{i}(void);" )
157 def self.include_headers
159 $header_files.each { |h|
160 if h.match('^/usr/include/') then
161 headers += "#include <#{h[13..-1]}>\n"
163 headers += "#include \"#{h}\"\n"
169 ##########################################################
170 ##########################################################
172 def self.generate_libdummy_icd_header
173 libdummy_icd_structures = "/**\n#{$license}\n*/\n"
174 libdummy_icd_structures += "#include <CL/opencl.h>\n"
175 libdummy_icd_structures += self.include_headers
176 libdummy_icd_structures += "\n\nstruct _cl_icd_dispatch;\n"
177 libdummy_icd_structures += "struct _cl_platform_id { struct _cl_icd_dispatch *dispatch; };\n\n"
178 libdummy_icd_structures += "struct _cl_icd_dispatch {\n"
179 ($api_entries.length+$buff).times { |i|
180 if( $known_entries[i] ) then
181 libdummy_icd_structures += " void(*known#{i})(void);\n"
183 libdummy_icd_structures += " void(*unknown#{i})(void);\n"
186 libdummy_icd_structures += "};\n\n"
187 libdummy_icd_structures += "#pragma GCC visibility push(hidden)\n\n"
188 libdummy_icd_structures += "struct _cl_icd_dispatch master_dispatch; \n\n"
189 $use_name_in_test.each { |k, f|
190 libdummy_icd_structures += "typeof(#{f}) INT#{f};\n"
192 libdummy_icd_structures += "#pragma GCC visibility pop\n\n"
193 return libdummy_icd_structures
196 def self.generate_libdummy_icd_source
197 libdummy_icd_source = "/**\n#{$license}\n*/\n\n"
198 libdummy_icd_source += "#include <stdio.h>\n\n"
199 libdummy_icd_source += "#include \"libdummy_icd_gen.h\"\n\n"
200 libdummy_icd_source += "#include \"libdummy_icd.h\"\n\n"
201 (0...$api_entries.length+$buff).each { |i|
202 libdummy_icd_source += "void dummyFunc#{i}(void){ printf(\"#{i} : \"); fflush(NULL); }\n"
204 libdummy_icd_source += "\nstruct _cl_icd_dispatch master_dispatch = {\n"
206 ($api_entries.length+$buff).times { |i|
207 comma="" if (i == $api_entries.length+$buff-1)
208 if( $use_name_in_test[i] ) then
209 libdummy_icd_source += " (void(*)(void))& INT#{$known_entries[i]}#{comma}\n"
211 libdummy_icd_source += " (void(*)(void))& dummyFunc#{i}#{comma}\n"
214 libdummy_icd_source += "};\n"
215 return libdummy_icd_source
218 def self.generate_run_dummy_icd_source
219 run_dummy_icd = "/**\n#{$license}\n*/\n"
220 run_dummy_icd += "#include <stdlib.h>\n"
221 run_dummy_icd += "#include <stdio.h>\n"
222 run_dummy_icd += "#pragma GCC diagnostic push\n"
223 run_dummy_icd += "# pragma GCC diagnostic ignored \"-Wcpp\"\n"
224 run_dummy_icd += "# define CL_USE_DEPRECATED_OPENCL_1_0_APIS\n"
225 run_dummy_icd += "# define CL_USE_DEPRECATED_OPENCL_1_1_APIS\n"
226 run_dummy_icd += "# define CL_USE_DEPRECATED_OPENCL_1_2_APIS\n"
227 run_dummy_icd += "# include <CL/opencl.h>\n"
228 run_dummy_icd += self.include_headers
229 run_dummy_icd += "#pragma GCC diagnostic pop\n"
230 run_dummy_icd += "\n\n"
231 run_dummy_icd += "typedef CL_API_ENTRY cl_int (CL_API_CALL* oclFuncPtr_fn)(cl_platform_id platform);\n\n"
232 run_dummy_icd += "void call_all_OpenCL_functions(cl_platform_id chosen_platform) {\n"
233 run_dummy_icd += " oclFuncPtr_fn oclFuncPtr;\n"
234 run_dummy_icd += " cl_context_properties properties[] = { CL_CONTEXT_PLATFORM, (cl_context_properties)chosen_platform, 0 };\n"
235 $api_entries.each_key { |func_name|
236 next if $forbidden_funcs.include?(func_name)
237 if func_name == "clCreateContext" then
238 run_dummy_icd += " #{func_name}(properties,1,(cl_device_id*)&chosen_platform,NULL,NULL,NULL);\n"
239 elsif func_name == "clGetGLContextInfoKHR" then
240 run_dummy_icd += " #{func_name}(properties,CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR, 0, NULL, NULL);\n"
241 elsif func_name == "clCreateContextFromType" then
242 run_dummy_icd += " #{func_name}(properties,CL_DEVICE_TYPE_CPU,NULL,NULL,NULL);\n"
243 elsif func_name == "clWaitForEvents" then
244 run_dummy_icd += " #{func_name}(1,(cl_event*)&chosen_platform);\n"
245 elsif func_name == "clGetExtensionFunctionAddressForPlatform" then
246 run_dummy_icd += " #{func_name}((cl_platform_id)chosen_platform, \"clIcdGetPlatformIDsKHR\");\n"
248 run_dummy_icd += " oclFuncPtr = (oclFuncPtr_fn)" + func_name + ";\n"
249 run_dummy_icd += " oclFuncPtr(chosen_platform);\n"
251 run_dummy_icd += " printf(\"%s\\n\", \"#{func_name}\");"
252 run_dummy_icd += " fflush(NULL);\n"
254 run_dummy_icd += " return;\n}\n"
258 def self.generate_run_dummy_icd_weak_source
259 run_dummy_icd_weak = "/**\n#{$license}\n*/\n"
260 run_dummy_icd_weak += <<EOF
261 #define _GNU_SOURCE 1
266 __attribute__((weak)) int f (void* arg, void* arg2) { \\
267 void (* p)(void*, void*)=NULL; \\
268 p=dlsym(RTLD_NEXT, #f); \\
278 $api_entries.each_key { |func_name|
279 next if $noweak_funcs.include?(func_name)
280 run_dummy_icd_weak += "F(#{func_name})\n"
282 return run_dummy_icd_weak
285 def self.generate_sources(from_headers=true, from_database=false, database=nil)
289 if from_database then
290 load_database(database)
292 File.open('libdummy_icd_gen.h','w') { |f|
293 f.puts generate_libdummy_icd_header
295 File.open('libdummy_icd_gen.c','w') { |f|
296 f.puts generate_libdummy_icd_source
298 File.open('run_dummy_icd_gen.c','w') { |f|
299 f.puts generate_run_dummy_icd_source
301 File.open('run_dummy_icd_weak_gen.c','w') { |f|
302 f.puts generate_run_dummy_icd_weak_source
306 ##########################################################
307 ##########################################################
309 def self.generate_ocl_icd_header
310 ocl_icd_header = "/**\n#{$license}\n*/\n\n"
311 ocl_icd_header += "#ifndef OCL_ICD_H\n"
312 ocl_icd_header += "#define OCL_ICD_H\n"
313 ocl_icd_header += "#pragma GCC diagnostic push\n"
314 ocl_icd_header += "# pragma GCC diagnostic ignored \"-Wcpp\"\n"
315 ocl_icd_header += "# define CL_USE_DEPRECATED_OPENCL_1_0_APIS\n"
316 ocl_icd_header += "# define CL_USE_DEPRECATED_OPENCL_1_1_APIS\n"
317 ocl_icd_header += "# define CL_USE_DEPRECATED_OPENCL_1_2_APIS\n"
318 ocl_icd_header += "# include <CL/opencl.h>\n"
319 ocl_icd_header += self.include_headers
320 ocl_icd_header += "#pragma GCC diagnostic pop\n"
321 ocl_icd_header += <<EOF
323 #define OCL_ICD_API_VERSION 1
324 #define OCL_ICD_IDENTIFIED_FUNCTIONS #{$known_entries.count}
326 struct _cl_icd_dispatch {
329 $api_entries_array.each { |entry|
330 version = entry.split("\n").
331 grep(/ CL_API_SUFFIX__(VERSION_[0-9_]+)[^0-9_]/).join('').
332 gsub(/.* CL_API_SUFFIX__(VERSION_[0-9_]+)[^0-9_].*$/, '\1')
333 if (version != '') then
334 ocl_icd_header += '#ifdef CL_'+version+"\n"
336 ocl_icd_header += entry.gsub("\r","").
337 sub(/CL_API_CALL\n?(.*?)\(/m,'(CL_API_CALL*\1)('+"\n ").
338 gsub(/\) (CL_API_SUFFIX__VERSION)/m,"\n) \\1").gsub(/\s*$/,'').
339 gsub(/^[\t ]+/," ").gsub(/^([^\t ])/, ' \1') + "\n"
340 if (version != '') then
341 ocl_icd_header += '#else'+"\n"
342 ocl_icd_header += ' CL_API_ENTRY cl_int (CL_API_CALL* clUnknown'+nb.to_s+")(void);\n"
343 ocl_icd_header += '#endif'+"\n"
345 ocl_icd_header += "\n"
348 ocl_icd_header += "};\n"
349 ocl_icd_header += "#endif\n\n"
350 return ocl_icd_header
353 def self.generate_ocl_icd_loader_header
354 ocl_icd_header = "/**\n#{$license}\n*/\n\n"
355 ocl_icd_header += "#include \"ocl_icd.h\"\n\n"
356 ocl_icd_header += <<EOF
360 void(*const addr)(void);
362 typedef __typeof__(clGetExtensionFunctionAddress) *clGetExtensionFunctionAddress_fn;
363 extern const struct func_desc function_description[];
365 cl_uint num_platforms;
366 cl_uint first_platform;
368 clGetExtensionFunctionAddress_fn ext_fn_ptr;
370 struct platform_icd {
371 char * extension_suffix;
373 struct vendor_icd *vicd;
378 ocl_icd_header += "extern struct _cl_icd_dispatch master_dispatch;\n"
379 $cl_objects.each { |o|
380 ocl_icd_header += "struct _cl_#{o} { struct _cl_icd_dispatch *dispatch; };\n"
382 return ocl_icd_header
385 def self.generate_ocl_icd_loader_map
386 ocl_icd_loader_map = "/**\n#{$license}\n*/\n\n"
388 $versions_entries.keys.sort.each { |version|
389 ocl_icd_loader_map += "OPENCL_#{version.sub('_','.')} {\n";
390 ocl_icd_loader_map += " global:\n";
391 $versions_entries[version].each { |symb|
392 ocl_icd_loader_map += " #{symb};\n"
394 if (prev_version == "") then
395 ocl_icd_loader_map += " local:\n";
396 ocl_icd_loader_map += " *;\n";
398 ocl_icd_loader_map += "} #{prev_version};\n\n";
399 prev_version="OPENCL_#{version.sub('_','.')}";
401 return ocl_icd_loader_map
404 def self.generate_ocl_icd_bindings_source
405 ocl_icd_bindings_source = "/**\n#{$license}\n*/\n"
406 ocl_icd_bindings_source += "#include \"ocl_icd.h\"\n"
407 ocl_icd_bindings_source += "struct _cl_icd_dispatch master_dispatch = {\n"
408 ($api_entries.length+$buff-1).times { |i|
409 if( $known_entries[i] ) then
410 ocl_icd_bindings_source += " #{$known_entries[i]},\n"
412 ocl_icd_bindings_source += " (void *) NULL,\n"
415 if( $known_entries[$api_entries.length+$buff-1] ) then
416 ocl_icd_bindings_source += " #{$known_entries[$api_entries.length+$buff-1]}\n"
418 ocl_icd_bindings_source += " (void *) NULL\n"
420 ocl_icd_bindings_source += "};\n"
421 ocl_icd_bindings_source += <<EOF
423 CL_API_ENTRY cl_int CL_API_CALL clIcdGetPlatformIDsKHR(
425 cl_platform_id *platforms,
426 cl_uint *num_platforms) {
427 if( platforms == NULL && num_platforms == NULL )
428 return CL_INVALID_VALUE;
429 if( num_entries == 0 && platforms != NULL )
430 return CL_INVALID_VALUE;
431 #error You have to fill the commented lines with corresponding variables from your library
432 // if( your_number_of_platforms == 0)
433 // return CL_PLATFORM_NOT_FOUND_KHR;
434 // if( num_platforms != NULL )
435 // *num_platforms = your_number_of_platforms;
436 if( platforms != NULL ) {
438 // for( i=0; i<(your_number_of_platforms<num_entries?your_number_of_platforms:num_entries); i++)
439 // platforms[i] = &your_platforms[i];
444 CL_API_ENTRY void * CL_API_CALL clGetExtensionFunctionAddress(
445 const char * func_name) CL_API_SUFFIX__VERSION_1_0 {
446 #error You have to fill this function with your extensions of incorporate these lines in your version
447 if( func_name != NULL && strcmp("clIcdGetPlatformIDsKHR", func_name) == 0 )
448 return (void *)clIcdGetPlatformIDsKHR;
451 CL_API_ENTRY cl_int CL_API_CALL clGetPlatformInfo(
452 cl_platform_id platform,
453 cl_platform_info param_name,
454 size_t param_value_size,
456 size_t * param_value_size_ret) CL_API_SUFFIX__VERSION_1_0 {
457 #error You ahve to fill this function with your information or assert that your version responds to CL_PLATFORM_ICD_SUFFIX_KHR
458 // char cl_platform_profile[] = "FULL_PROFILE";
459 // char cl_platform_version[] = "OpenCL 1.1";
460 // char cl_platform_name[] = "DummyCL";
461 // char cl_platform_vendor[] = "LIG";
462 // char cl_platform_extensions[] = "cl_khr_icd";
463 // char cl_platform_icd_suffix_khr[] = "DUMMY";
466 if( platform != NULL ) {
469 for(i=0; i<num_master_platforms; i++) {
470 if( platform == &master_platforms[i] )
474 return CL_INVALID_PLATFORM;
476 switch ( param_name ) {
477 case CL_PLATFORM_PROFILE:
478 string_p = cl_platform_profile;
479 size_string = sizeof(cl_platform_profile);
481 case CL_PLATFORM_VERSION:
482 string_p = cl_platform_version;
483 size_string = sizeof(cl_platform_version);
485 case CL_PLATFORM_NAME:
486 string_p = cl_platform_name;
487 size_string = sizeof(cl_platform_name);
489 case CL_PLATFORM_VENDOR:
490 string_p = cl_platform_vendor;
491 size_string = sizeof(cl_platform_vendor);
493 case CL_PLATFORM_EXTENSIONS:
494 string_p = cl_platform_extensions;
495 size_string = sizeof(cl_platform_extensions);
497 case CL_PLATFORM_ICD_SUFFIX_KHR:
498 string_p = cl_platform_icd_suffix_khr;
499 size_string = sizeof(cl_platform_icd_suffix_khr);
502 return CL_INVALID_VALUE;
505 if( param_value != NULL ) {
506 if( size_string > param_value_size )
507 return CL_INVALID_VALUE;
508 memcpy(param_value, string_p, size_string);
510 if( param_value_size_ret != NULL )
511 *param_value_size_ret = size_string;
515 return ocl_icd_bindings_source
518 def self.generate_ocl_icd_loader_gen_source
519 skip_funcs = $specific_loader_funcs
520 ocl_icd_loader_gen_source = "/**\n#{$license}\n*/\n"
521 ocl_icd_loader_gen_source += "#include \"ocl_icd_loader.h\"\n"
522 ocl_icd_loader_gen_source += "#define DEBUG_OCL_ICD_PROVIDE_DUMP_FIELD\n"
523 ocl_icd_loader_gen_source += "#include \"ocl_icd_debug.h\"\n"
524 $api_entries.each { |func_name, entry|
525 next if skip_funcs.include?(func_name)
526 clean_entry = entry.sub(/(.*\)).*/m,'\1').gsub("/*","").gsub("*/","").gsub("\r","") + "{\n"
527 return_type = entry.match(/CL_API_ENTRY (.*) CL_API_CALL/)[1]
528 parameters = clean_entry.match(/\(.*\)/m)[0][1..-2]
529 parameters.gsub!(/\[.*?\]/,"")
530 parameters.sub!(/\(.*?\*\s*(.*?)\)\s*\(.*?\)/m,'\1')
531 ocl_icd_loader_gen_source += clean_entry.gsub(/\*\[.*?\]/,"* ").gsub(/\[.+?\]/,"")
532 first_parameter = parameters.match(/.*?\,/m)
533 if not first_parameter then
534 first_parameter = parameters.match(/.*/m)[0]
536 first_parameter = first_parameter[0][0..-2]
538 fps = first_parameter.split
539 ocl_icd_loader_gen_source += " debug_trace();\n"
540 raise "Unsupported data_type #{fps[0]}" if not $cl_data_type_error[fps[0]]
541 ps = parameters.split(",")
542 ps = ps.collect { |p|
544 p = p[-1].gsub("*","")
546 error_handler = lambda {
547 if(ps.include?("errcode_ret")) then
548 ocl_icd_loader_gen_source += " if( errcode_ret != NULL ) {\n";
549 ocl_icd_loader_gen_source += " *errcode_ret = #{$cl_data_type_error[fps[0]]};\n"
550 ocl_icd_loader_gen_source += " }\n"
551 if return_type != "void" then
552 ocl_icd_loader_gen_source += " RETURN(NULL);\n"
554 ocl_icd_loader_gen_source += " return;\n"
556 elsif ($non_standard_error.include?(func_name)) then
557 if return_type != "void" then
558 ocl_icd_loader_gen_source += " RETURN(NULL);\n"
560 ocl_icd_loader_gen_source += " return;\n"
563 if return_type != "void" then
564 ocl_icd_loader_gen_source += " RETURN(#{$cl_data_type_error[fps[0]]});\n" if return_type != "void"
566 ocl_icd_loader_gen_source += " return;\n"
571 if(fps[0] == "cl_platform_id") then
572 ocl_icd_loader_gen_source += " #{fps[1]}=selectPlatformID(#{fps[1]});\n"
574 ocl_icd_loader_gen_source += " if( (struct _#{fps[0]} *)#{fps[1]} == NULL) {\n"
576 ocl_icd_loader_gen_source += " }\n"
577 if return_type != "void" then
578 ocl_icd_loader_gen_source += " RETURN(((struct _#{fps[0]} *)#{fps[1]})->dispatch->#{func_name}("
579 ocl_icd_loader_gen_source += ps.join(", ")
580 ocl_icd_loader_gen_source += "));\n"
582 ocl_icd_loader_gen_source += " return;"
584 ocl_icd_loader_gen_source += "}\n\n"
586 ocl_icd_loader_gen_source += "#pragma GCC visibility push(hidden)\n\n"
587 skip_funcs = $specific_loader_funcs
588 $api_entries.each { |func_name, entry|
589 #next if func_name.match(/EXT$/)
590 #next if func_name.match(/KHR$/)
591 if (skip_funcs.include?(func_name)) then
592 ocl_icd_loader_gen_source += "extern typeof(#{func_name}) #{func_name}_hid;\n"
594 ocl_icd_loader_gen_source += "typeof(#{func_name}) #{func_name}_hid __attribute__ ((alias (\"#{func_name}\"), visibility(\"hidden\")));\n"
597 ocl_icd_loader_gen_source += "\n\nstruct func_desc const function_description[]= {\n"
598 $api_entries.each { |func_name, entry|
599 #next if func_name.match(/EXT$/)
600 #next if func_name.match(/KHR$/)
601 ocl_icd_loader_gen_source += " {\"#{func_name}\", (void(* const)(void))&#{func_name}_hid },\n"
603 ocl_icd_loader_gen_source += <<EOF
608 void dump_platform(clGEFA_t f, cl_platform_id pid) {
609 debug(D_ALWAYS, "platform @%p: name=field_in_struct [clGetExtensionFunctionAddress(name)/clGetExtensionFunctionAddressForPlatform(name)]", pid);
611 $api_entries_array.each { |entry|
612 e = entry.gsub("\r"," ").gsub("\n"," ").gsub("\t"," ").
613 sub(/.*CL_API_CALL *([^ ()]*)[ ()].*$/m, '\1')
614 ocl_icd_loader_gen_source += " dump_field(pid, f, #{e});\n"
617 ocl_icd_loader_gen_source += <<EOF
621 #pragma GCC visibility pop
624 return ocl_icd_loader_gen_source;
627 def self.generate_from_database(yamlfile)
628 load_database(yamlfile)
629 File.open('ocl_icd.h','w') { |f|
630 f.puts generate_ocl_icd_header
632 File.open('ocl_icd_loader_gen.h','w') { |f|
633 f.puts generate_ocl_icd_loader_header
635 File.open('ocl_icd_loader_gen.map','w') { |f|
636 f.puts generate_ocl_icd_loader_map
638 File.open('ocl_icd_bindings.c','w') { |f|
639 f.puts generate_ocl_icd_bindings_source
641 File.open('ocl_icd_loader_gen.c','w') { |f|
642 f.puts generate_ocl_icd_loader_gen_source
646 ##########################################################
647 ##########################################################
648 # update-database mode
649 def self.savedb(yamlfile)
650 File::open(yamlfile,"w") { |f|
651 f.write($license.gsub(/^/,"# "))
654 # In Intel (OpenCL 1.1):
655 # * clSetCommandQueueProperty(13): nil (deprecated in 1.1)
656 # * clGetGLContextInfoKHR(74): function present with its symbol
658 # * 92: correspond to symbol clGetKernelArgInfo (first abandonned version?)
660 # In nvidia (OpenCL 1.1):
661 # * clGetGLContextInfoKHR(74): function present but no symbol
664 # * only two OpenCL symbols: clGetPlatformInfo(1) and clGetExtensionFunctionAddress(65)
665 # In AMD (OpenCL 1.2):
666 # * clGetPlatformIDs(0): nil (symbol present)
667 # * clGetGLContextInfoKHR(74): function present but no symbol
675 # Not using YAML::dump as:
676 # * keys are not ordered
677 # * strings are badly formatted in new YAML ruby implementation (psych)
678 # * it is very easy to do it ourself
679 #f.write(YAML::dump(api_db))
681 $known_entries.keys.sort.each { |k|
682 f.write("\n#{k}: |-\n ")
683 f.write($api_entries[$known_entries[k]].gsub("\n","\n "))
689 def self.updatedb_from_input(dbfile, inputfile)
691 load_database(dbfile, with_windows=true)
692 doc = YAML::load_file(inputfile)
695 next if $known_entries[i]
696 $known_entries[i]=doc[i]
703 ############################################################
704 ############################################################
705 ############################################################
712 OptionParser.new do |opts|
713 opts.banner = "Usage: cd_generator.rb [options] mode"
715 opts.on("-d", "--database FILE", String, "YAML file (default ocl_interface.yaml)") do |v|
716 options[:database] = v
718 opts.on("-i", "--input FILE", String,
719 "binding between OpenCL functions and entry number (required for update-database)") \
723 opts.on("-s", "--[no-]system-headers",
724 "Look for OpenCL functions in system header files") \
726 options[:"system-headers"] = v
728 opts.on("-m", "--mode [MODE]", [:database, :generate, :"update-database"],
729 "Select mode (database, generate, update-database)") do |m|
734 if !options[:database] then
735 options[:database] = "ocl_interface.yaml"
738 if !options[:mode] then
739 raise "--mode option required"
741 if options[:mode] == :generate then
742 if !options[:"system-headers"] then
743 IcdGenerator.generate_sources(from_headers=false, from_database=true, database=options[:database])
745 IcdGenerator.generate_sources(from_headers=true, from_database=false)
747 elsif options[:mode] == :"update-database" then
748 if !options[:input] then
749 raise "--input option required"
751 IcdGenerator.updatedb_from_input(options[:database], options[:input])
752 elsif options[:mode] == :database then
753 IcdGenerator.generate_from_database(options[:database])
755 raise "Mode must be one of generate, database or update-database not #{options[:mode]}"