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" ]
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 += "# include <CL/opencl.h>\n"
227 run_dummy_icd += self.include_headers
228 run_dummy_icd += "#pragma GCC diagnostic pop\n"
229 run_dummy_icd += "\n\n"
230 run_dummy_icd += "typedef CL_API_ENTRY cl_int (CL_API_CALL* oclFuncPtr_fn)(cl_platform_id platform);\n\n"
231 run_dummy_icd += "void call_all_OpenCL_functions(cl_platform_id chosen_platform) {\n"
232 run_dummy_icd += " oclFuncPtr_fn oclFuncPtr;\n"
233 run_dummy_icd += " cl_context_properties properties[] = { CL_CONTEXT_PLATFORM, (cl_context_properties)chosen_platform, 0 };\n"
234 $api_entries.each_key { |func_name|
235 next if $forbidden_funcs.include?(func_name)
236 if func_name == "clCreateContext" then
237 run_dummy_icd += " #{func_name}(properties,1,(cl_device_id*)&chosen_platform,NULL,NULL,NULL);\n"
238 elsif func_name == "clGetGLContextInfoKHR" then
239 run_dummy_icd += " #{func_name}(properties,CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR, 0, NULL, NULL);\n"
240 elsif func_name == "clCreateContextFromType" then
241 run_dummy_icd += " #{func_name}(properties,CL_DEVICE_TYPE_CPU,NULL,NULL,NULL);\n"
242 elsif func_name == "clWaitForEvents" then
243 run_dummy_icd += " #{func_name}(1,(cl_event*)&chosen_platform);\n"
244 elsif func_name == "clGetExtensionFunctionAddressForPlatform" then
245 run_dummy_icd += " #{func_name}((cl_platform_id)chosen_platform, \"clIcdGetPlatformIDsKHR\");\n"
247 run_dummy_icd += " oclFuncPtr = (oclFuncPtr_fn)" + func_name + ";\n"
248 run_dummy_icd += " oclFuncPtr(chosen_platform);\n"
250 run_dummy_icd += " printf(\"%s\\n\", \"#{func_name}\");"
251 run_dummy_icd += " fflush(NULL);\n"
253 run_dummy_icd += " return;\n}\n"
257 def self.generate_run_dummy_icd_weak_source
258 run_dummy_icd_weak = "/**\n#{$license}\n*/\n"
259 run_dummy_icd_weak += <<EOF
260 #define _GNU_SOURCE 1
265 __attribute__((weak)) int f (void* arg, void* arg2) { \\
266 void (* p)(void*, void*)=NULL; \\
267 p=dlsym(RTLD_NEXT, #f); \\
277 $api_entries.each_key { |func_name|
278 next if $noweak_funcs.include?(func_name)
279 run_dummy_icd_weak += "F(#{func_name})\n"
281 return run_dummy_icd_weak
284 def self.generate_sources(from_headers=true, from_database=false, database=nil)
288 if from_database then
289 load_database(database)
291 File.open('libdummy_icd_gen.h','w') { |f|
292 f.puts generate_libdummy_icd_header
294 File.open('libdummy_icd_gen.c','w') { |f|
295 f.puts generate_libdummy_icd_source
297 File.open('run_dummy_icd_gen.c','w') { |f|
298 f.puts generate_run_dummy_icd_source
300 File.open('run_dummy_icd_weak.c','w') { |f|
301 f.puts generate_run_dummy_icd_weak_source
305 ##########################################################
306 ##########################################################
308 def self.generate_ocl_icd_header
309 ocl_icd_header = "/**\n#{$license}\n*/\n\n"
310 ocl_icd_header += "#ifndef OCL_ICD_H\n"
311 ocl_icd_header += "#define OCL_ICD_H\n"
312 ocl_icd_header += "#pragma GCC diagnostic push\n"
313 ocl_icd_header += "# pragma GCC diagnostic ignored \"-Wcpp\"\n"
314 ocl_icd_header += "# define CL_USE_DEPRECATED_OPENCL_1_0_APIS\n"
315 ocl_icd_header += "# define CL_USE_DEPRECATED_OPENCL_1_1_APIS\n"
316 ocl_icd_header += "# include <CL/opencl.h>\n"
317 ocl_icd_header += self.include_headers
318 ocl_icd_header += "#pragma GCC diagnostic pop\n"
319 ocl_icd_header += <<EOF
321 #define OCL_ICD_API_VERSION 1
322 #define OCL_ICD_IDENTIFIED_FUNCTIONS #{$known_entries.count}
324 struct _cl_icd_dispatch {
326 $api_entries_array.each { |entry|
327 ocl_icd_header += entry.gsub("\r","").
328 sub(/CL_API_CALL\n?(.*?)\(/m,'(CL_API_CALL*\1)('+"\n ").
329 gsub(/\) (CL_API_SUFFIX__VERSION)/m,"\n) \\1").gsub(/\s*$/,'').
330 gsub(/^[\t ]+/," ").gsub(/^([^\t ])/, ' \1') + "\n\n"
332 ocl_icd_header += "};\n"
333 ocl_icd_header += "#endif\n\n"
334 return ocl_icd_header
337 def self.generate_ocl_icd_loader_header
338 ocl_icd_header = "/**\n#{$license}\n*/\n\n"
339 ocl_icd_header += "#include \"ocl_icd.h\"\n\n"
340 ocl_icd_header += <<EOF
344 void(*const addr)(void);
346 typedef __typeof__(clGetExtensionFunctionAddress) *clGetExtensionFunctionAddress_fn;
347 extern const struct func_desc function_description[];
349 cl_uint num_platforms;
350 cl_uint first_platform;
352 clGetExtensionFunctionAddress_fn ext_fn_ptr;
354 struct platform_icd {
355 char * extension_suffix;
357 struct vendor_icd *vicd;
362 ocl_icd_header += "extern struct _cl_icd_dispatch master_dispatch;\n"
363 $cl_objects.each { |o|
364 ocl_icd_header += "struct _cl_#{o} { struct _cl_icd_dispatch *dispatch; };\n"
366 return ocl_icd_header
369 def self.generate_ocl_icd_loader_map
370 ocl_icd_loader_map = "/**\n#{$license}\n*/\n\n"
372 $versions_entries.keys.sort.each { |version|
373 ocl_icd_loader_map += "OPENCL_#{version.sub('_','.')} {\n";
374 ocl_icd_loader_map += " global:\n";
375 $versions_entries[version].each { |symb|
376 ocl_icd_loader_map += " #{symb};\n"
378 if (prev_version == "") then
379 ocl_icd_loader_map += " local:\n";
380 ocl_icd_loader_map += " *;\n";
382 ocl_icd_loader_map += "} #{prev_version};\n\n";
383 prev_version="OPENCL_#{version.sub('_','.')}";
385 return ocl_icd_loader_map
388 def self.generate_ocl_icd_bindings_source
389 ocl_icd_bindings_source = "/**\n#{$license}\n*/\n"
390 ocl_icd_bindings_source += "#include \"ocl_icd.h\"\n"
391 ocl_icd_bindings_source += "struct _cl_icd_dispatch master_dispatch = {\n"
392 ($api_entries.length+$buff-1).times { |i|
393 if( $known_entries[i] ) then
394 ocl_icd_bindings_source += " #{$known_entries[i]},\n"
396 ocl_icd_bindings_source += " (void *) NULL,\n"
399 if( $known_entries[$api_entries.length+$buff-1] ) then
400 ocl_icd_bindings_source += " #{$known_entries[i]}\n"
402 ocl_icd_bindings_source += " (void *) NULL\n"
404 ocl_icd_bindings_source += "};\n"
405 ocl_icd_bindings_source += <<EOF
407 CL_API_ENTRY cl_int CL_API_CALL clIcdGetPlatformIDsKHR(
409 cl_platform_id *platforms,
410 cl_uint *num_platforms) {
411 if( platforms == NULL && num_platforms == NULL )
412 return CL_INVALID_VALUE;
413 if( num_entries == 0 && platforms != NULL )
414 return CL_INVALID_VALUE;
415 #error You have to fill the commented lines with corresponding variables from your library
416 // if( your_number_of_platforms == 0)
417 // return CL_PLATFORM_NOT_FOUND_KHR;
418 // if( num_platforms != NULL )
419 // *num_platforms = your_number_of_platforms;
420 if( platforms != NULL ) {
422 // for( i=0; i<(your_number_of_platforms<num_entries?your_number_of_platforms:num_entries); i++)
423 // platforms[i] = &your_platforms[i];
428 CL_API_ENTRY void * CL_API_CALL clGetExtensionFunctionAddress(
429 const char * func_name) CL_API_SUFFIX__VERSION_1_0 {
430 #error You have to fill this function with your extensions of incorporate these lines in your version
431 if( func_name != NULL && strcmp("clIcdGetPlatformIDsKHR", func_name) == 0 )
432 return (void *)clIcdGetPlatformIDsKHR;
435 CL_API_ENTRY cl_int CL_API_CALL clGetPlatformInfo(
436 cl_platform_id platform,
437 cl_platform_info param_name,
438 size_t param_value_size,
440 size_t * param_value_size_ret) CL_API_SUFFIX__VERSION_1_0 {
441 #error You ahve to fill this function with your information or assert that your version responds to CL_PLATFORM_ICD_SUFFIX_KHR
442 // char cl_platform_profile[] = "FULL_PROFILE";
443 // char cl_platform_version[] = "OpenCL 1.1";
444 // char cl_platform_name[] = "DummyCL";
445 // char cl_platform_vendor[] = "LIG";
446 // char cl_platform_extensions[] = "cl_khr_icd";
447 // char cl_platform_icd_suffix_khr[] = "DUMMY";
450 if( platform != NULL ) {
453 for(i=0; i<num_master_platforms; i++) {
454 if( platform == &master_platforms[i] )
458 return CL_INVALID_PLATFORM;
460 switch ( param_name ) {
461 case CL_PLATFORM_PROFILE:
462 string_p = cl_platform_profile;
463 size_string = sizeof(cl_platform_profile);
465 case CL_PLATFORM_VERSION:
466 string_p = cl_platform_version;
467 size_string = sizeof(cl_platform_version);
469 case CL_PLATFORM_NAME:
470 string_p = cl_platform_name;
471 size_string = sizeof(cl_platform_name);
473 case CL_PLATFORM_VENDOR:
474 string_p = cl_platform_vendor;
475 size_string = sizeof(cl_platform_vendor);
477 case CL_PLATFORM_EXTENSIONS:
478 string_p = cl_platform_extensions;
479 size_string = sizeof(cl_platform_extensions);
481 case CL_PLATFORM_ICD_SUFFIX_KHR:
482 string_p = cl_platform_icd_suffix_khr;
483 size_string = sizeof(cl_platform_icd_suffix_khr);
486 return CL_INVALID_VALUE;
489 if( param_value != NULL ) {
490 if( size_string > param_value_size )
491 return CL_INVALID_VALUE;
492 memcpy(param_value, string_p, size_string);
494 if( param_value_size_ret != NULL )
495 *param_value_size_ret = size_string;
499 return ocl_icd_bindings_source
502 def self.generate_ocl_icd_loader_gen_source
503 skip_funcs = $specific_loader_funcs
504 ocl_icd_loader_gen_source = "/**\n#{$license}\n*/\n"
505 ocl_icd_loader_gen_source += "#include \"ocl_icd_loader.h\"\n"
506 ocl_icd_loader_gen_source += "#define DEBUG_OCL_ICD_PROVIDE_DUMP_FIELD\n"
507 ocl_icd_loader_gen_source += "#include \"ocl_icd_debug.h\"\n"
508 ocl_icd_loader_gen_source += "extern struct platform_icd *_picds;\n"
509 ocl_icd_loader_gen_source += "extern cl_uint _num_picds;\n"
510 $api_entries.each { |func_name, entry|
511 next if skip_funcs.include?(func_name)
512 clean_entry = entry.sub(/(.*\)).*/m,'\1').gsub("/*","").gsub("*/","").gsub("\r","") + "{\n"
513 parameters = clean_entry.match(/\(.*\)/m)[0][1..-2]
514 parameters.gsub!(/\[.*?\]/,"")
515 parameters.sub!(/\(.*?\*\s*(.*?)\)\s*\(.*?\)/,'\1')
516 ocl_icd_loader_gen_source += clean_entry.gsub(/\[.*?\]/,"")
517 first_parameter = parameters.match(/.*?\,/m)
518 if not first_parameter then
519 first_parameter = parameters.match(/.*/m)[0]
521 first_parameter = first_parameter[0][0..-2]
523 fps = first_parameter.split
524 ocl_icd_loader_gen_source += " debug_trace();\n"
525 raise "Unsupported data_type #{fps[0]}" if not $cl_data_type_error[fps[0]]
526 ps = parameters.split(",")
527 ps = ps.collect { |p|
529 p = p[-1].gsub("*","")
531 error_handler = lambda {
532 if(ps.include?("errcode_ret")) then
533 ocl_icd_loader_gen_source += " if( errcode_ret != NULL ) {\n";
534 ocl_icd_loader_gen_source += " *errcode_ret = #{$cl_data_type_error[fps[0]]};\n"
535 ocl_icd_loader_gen_source += " }\n"
536 ocl_icd_loader_gen_source += " RETURN(NULL);\n"
537 elsif ($non_standard_error.include?(func_name)) then
538 ocl_icd_loader_gen_source += " RETURN(NULL);\n"
540 ocl_icd_loader_gen_source += " RETURN(#{$cl_data_type_error[fps[0]]});\n"
543 if(fps[0] == "cl_platform_id") then
544 ocl_icd_loader_gen_source += " if(_num_picds == 0) {\n"
546 ocl_icd_loader_gen_source += " }\n"
549 ocl_icd_loader_gen_source += " if( (struct _#{fps[0]} *)#{fps[1]} == NULL) {\n"
550 if(fps[0] == "cl_platform_id") then
551 ocl_icd_loader_gen_source += " const char *default_platform = getenv(\"OPENCL_ICD_DEFAULT_PLATFORM\");\n"
552 ocl_icd_loader_gen_source += " int num_default_platform;\n"
553 ocl_icd_loader_gen_source += " char *end_scan;\n"
554 ocl_icd_loader_gen_source += " if (! default_platform) {\n"
555 ocl_icd_loader_gen_source += " num_default_platform = 0;\n"
556 ocl_icd_loader_gen_source += " } else {\n"
557 ocl_icd_loader_gen_source += " num_default_platform = strtol(default_platform, &end_scan, 10);\n"
558 ocl_icd_loader_gen_source += " if (*default_platform == '\\0' || *end_scan != '\\0') {\n"
560 ocl_icd_loader_gen_source += " }\n"
561 ocl_icd_loader_gen_source += " }\n"
562 ocl_icd_loader_gen_source += " if (num_default_platform < 0 || num_default_platform >= _num_picds) {\n"
564 ocl_icd_loader_gen_source += " }\n"
565 ocl_icd_loader_gen_source += " RETURN(_picds[num_default_platform].pid->dispatch->#{func_name}("
566 ocl_icd_loader_gen_source += ps.join(", ")
567 ocl_icd_loader_gen_source += "));\n"
571 ocl_icd_loader_gen_source += " }\n"
572 ocl_icd_loader_gen_source += " RETURN(((struct _#{fps[0]} *)#{fps[1]})->dispatch->#{func_name}("
573 ocl_icd_loader_gen_source += ps.join(", ")
574 ocl_icd_loader_gen_source += "));\n"
575 ocl_icd_loader_gen_source += "}\n\n"
577 ocl_icd_loader_gen_source += "#pragma GCC visibility push(hidden)\n\n"
578 skip_funcs = $specific_loader_funcs
579 $api_entries.each { |func_name, entry|
580 #next if func_name.match(/EXT$/)
581 #next if func_name.match(/KHR$/)
582 if (skip_funcs.include?(func_name)) then
583 ocl_icd_loader_gen_source += "extern typeof(#{func_name}) #{func_name}_hid;\n"
585 ocl_icd_loader_gen_source += "typeof(#{func_name}) #{func_name}_hid __attribute__ ((alias (\"#{func_name}\"), visibility(\"hidden\")));\n"
588 ocl_icd_loader_gen_source += "\n\nstruct func_desc const function_description[]= {\n"
589 $api_entries.each { |func_name, entry|
590 #next if func_name.match(/EXT$/)
591 #next if func_name.match(/KHR$/)
592 ocl_icd_loader_gen_source += " {\"#{func_name}\", (void(* const)(void))&#{func_name}_hid },\n"
594 ocl_icd_loader_gen_source += <<EOF
599 void dump_platform(clGEFA_t f, cl_platform_id pid) {
600 debug(D_ALWAYS, "platform @%p: name=field_in_struct [clGetExtensionFunctionAddress(name)/clGetExtensionFunctionAddressForPlatform(name)]", pid);
602 $api_entries_array.each { |entry|
603 e = entry.gsub("\r"," ").gsub("\n"," ").gsub("\t"," ").
604 sub(/.*CL_API_CALL *([^ ()]*)[ ()].*$/m, '\1')
605 ocl_icd_loader_gen_source += " dump_field(pid, f, #{e});\n"
608 ocl_icd_loader_gen_source += <<EOF
612 #pragma GCC visibility pop
615 return ocl_icd_loader_gen_source;
618 def self.generate_from_database(yamlfile)
619 load_database(yamlfile)
620 File.open('ocl_icd.h','w') { |f|
621 f.puts generate_ocl_icd_header
623 File.open('ocl_icd_loader.h','w') { |f|
624 f.puts generate_ocl_icd_loader_header
626 File.open('ocl_icd_loader.map','w') { |f|
627 f.puts generate_ocl_icd_loader_map
629 File.open('ocl_icd_bindings.c','w') { |f|
630 f.puts generate_ocl_icd_bindings_source
632 File.open('ocl_icd_loader_gen.c','w') { |f|
633 f.puts generate_ocl_icd_loader_gen_source
637 ##########################################################
638 ##########################################################
639 # update-database mode
640 def self.savedb(yamlfile)
641 File::open(yamlfile,"w") { |f|
642 f.write($license.gsub(/^/,"# "))
645 # In Intel (OpenCL 1.1):
646 # * clSetCommandQueueProperty(13): nil (deprecated in 1.1)
647 # * clGetGLContextInfoKHR(74): function present with its symbol
649 # * 92: correspond to symbol clGetKernelArgInfo (first abandonned version?)
651 # In nvidia (OpenCL 1.1):
652 # * clGetGLContextInfoKHR(74): function present but no symbol
655 # * only two OpenCL symbols: clGetPlatformInfo(1) and clGetExtensionFunctionAddress(65)
656 # In AMD (OpenCL 1.2):
657 # * clGetPlatformIDs(0): nil (symbol present)
658 # * clGetGLContextInfoKHR(74): function present but no symbol
666 # Not using YAML::dump as:
667 # * keys are not ordered
668 # * strings are badly formatted in new YAML ruby implementation (psych)
669 # * it is very easy to do it ourself
670 #f.write(YAML::dump(api_db))
672 $known_entries.keys.sort.each { |k|
673 f.write("\n#{k}: |-\n ")
674 f.write($api_entries[$known_entries[k]].gsub("\n","\n "))
680 def self.updatedb_from_input(dbfile, inputfile)
682 load_database(dbfile, with_windows=true)
683 doc = YAML::load_file(inputfile)
686 next if $known_entries[i]
687 $known_entries[i]=doc[i]
694 ############################################################
695 ############################################################
696 ############################################################
703 OptionParser.new do |opts|
704 opts.banner = "Usage: cd_generator.rb [options] mode"
706 opts.on("-d", "--database FILE", String, "YAML file (default ocl_interface.yaml)") do |v|
707 options[:database] = v
709 opts.on("-i", "--input FILE", String,
710 "binding between OpenCL functions and entry number (required for update-database)") \
714 opts.on("-s", "--[no-]system-headers",
715 "Look for OpenCL functions in system header files") \
717 options[:"system-headers"] = v
719 opts.on("-m", "--mode [MODE]", [:database, :generate, :"update-database"],
720 "Select mode (database, generate, update-database)") do |m|
725 if !options[:database] then
726 options[:database] = "ocl_interface.yaml"
729 if !options[:mode] then
730 raise "--mode option required"
732 if options[:mode] == :generate then
733 if !options[:"system-headers"] then
734 IcdGenerator.generate_sources(from_headers=false, from_database=true, database=options[:database])
736 IcdGenerator.generate_sources(from_headers=true, from_database=false)
738 elsif options[:mode] == :"update-database" then
739 if !options[:input] then
740 raise "--input option required"
742 IcdGenerator.updatedb_from_input(options[:database], options[:input])
743 elsif options[:mode] == :database then
744 IcdGenerator.generate_from_database(options[:database])
746 raise "Mode must be one of generate, database or update-database not #{options[:mode]}"