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", 2 => "clGetDeviceIDs" }
34 $use_name_in_test = { 1 => "clGetPlatformInfo", 0 => "clGetPlatformIDs", 2 => "clGetDeviceIDs" }
35 # do not call these functions when trying to discover the mapping
36 $forbidden_funcs = ["clGetExtensionFunctionAddress", "clGetPlatformIDs",
37 "clGetPlatformInfo", "clGetGLContextInfoKHR", "clUnloadCompiler",
38 "clSetCommandQueueProperty", "clGetDeviceIDs"]
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"
247 elsif func_name == "clGetDeviceIDs" then
248 run_dummy_icd += " #{func_name}((cl_platform_id)chosen_platform,0,0,NULL,NULL);\n"
250 run_dummy_icd += " oclFuncPtr = (oclFuncPtr_fn)" + func_name + ";\n"
251 run_dummy_icd += " oclFuncPtr(chosen_platform);\n"
253 run_dummy_icd += " printf(\"%s\\n\", \"#{func_name}\");"
254 run_dummy_icd += " fflush(NULL);\n"
256 run_dummy_icd += " return;\n}\n"
260 def self.generate_run_dummy_icd_weak_source
261 run_dummy_icd_weak = "/**\n#{$license}\n*/\n"
262 run_dummy_icd_weak += <<EOF
263 #define _GNU_SOURCE 1
268 __attribute__((weak)) int f (void* arg, int arg2, int arg3, void* arg4, void* arg5) { \\
269 void (* p)(void*, int, int, void*, void*)=NULL; \\
270 p=dlsym(RTLD_NEXT, #f); \\
272 (*p)(arg, arg2, arg3, arg4, arg5); \\
280 $api_entries.each_key { |func_name|
281 next if $noweak_funcs.include?(func_name)
282 run_dummy_icd_weak += "F(#{func_name})\n"
284 return run_dummy_icd_weak
287 def self.generate_sources(from_headers=true, from_database=false, database=nil)
291 if from_database then
292 load_database(database)
294 File.open('libdummy_icd_gen.h','w') { |f|
295 f.puts generate_libdummy_icd_header
297 File.open('libdummy_icd_gen.c','w') { |f|
298 f.puts generate_libdummy_icd_source
300 File.open('run_dummy_icd_gen.c','w') { |f|
301 f.puts generate_run_dummy_icd_source
303 File.open('run_dummy_icd_weak_gen.c','w') { |f|
304 f.puts generate_run_dummy_icd_weak_source
308 ##########################################################
309 ##########################################################
311 def self.generate_ocl_icd_header
312 ocl_icd_header = "/**\n#{$license}\n*/\n\n"
313 ocl_icd_header += "#ifndef OCL_ICD_H\n"
314 ocl_icd_header += "#define OCL_ICD_H\n"
315 ocl_icd_header += "#pragma GCC diagnostic push\n"
316 ocl_icd_header += "# pragma GCC diagnostic ignored \"-Wcpp\"\n"
317 ocl_icd_header += "# define CL_USE_DEPRECATED_OPENCL_1_0_APIS\n"
318 ocl_icd_header += "# define CL_USE_DEPRECATED_OPENCL_1_1_APIS\n"
319 ocl_icd_header += "# define CL_USE_DEPRECATED_OPENCL_1_2_APIS\n"
320 ocl_icd_header += "# include <CL/opencl.h>\n"
321 ocl_icd_header += self.include_headers
322 ocl_icd_header += "#pragma GCC diagnostic pop\n"
323 ocl_icd_header += <<EOF
325 #define OCL_ICD_API_VERSION 1
326 #define OCL_ICD_IDENTIFIED_FUNCTIONS #{$known_entries.count}
328 struct _cl_icd_dispatch {
331 $api_entries_array.each { |entry|
332 version = entry.split("\n").
333 grep(/ CL_API_SUFFIX__(VERSION_[0-9_]+)[^0-9_]/).join('').
334 gsub(/.* CL_API_SUFFIX__(VERSION_[0-9_]+)[^0-9_].*$/, '\1')
335 if (version != '') then
336 ocl_icd_header += '#ifdef CL_'+version+"\n"
338 ocl_icd_header += entry.gsub("\r","").
339 sub(/CL_API_CALL\n?(.*?)\(/m,'(CL_API_CALL*\1)('+"\n ").
340 gsub(/\) (CL_API_SUFFIX__VERSION)/m,"\n) \\1").gsub(/\s*$/,'').
341 gsub(/^[\t ]+/," ").gsub(/^([^\t ])/, ' \1') + "\n"
342 if (version != '') then
343 ocl_icd_header += '#else'+"\n"
344 ocl_icd_header += ' CL_API_ENTRY cl_int (CL_API_CALL* clUnknown'+nb.to_s+")(void);\n"
345 ocl_icd_header += '#endif'+"\n"
347 ocl_icd_header += "\n"
350 ocl_icd_header += "};\n"
351 ocl_icd_header += "#endif\n\n"
352 return ocl_icd_header
355 def self.generate_ocl_icd_loader_header
356 ocl_icd_header = "/**\n#{$license}\n*/\n\n"
357 ocl_icd_header += "#include \"ocl_icd.h\"\n\n"
358 ocl_icd_header += <<EOF
362 void(*const addr)(void);
364 typedef __typeof__(clGetExtensionFunctionAddress) *clGetExtensionFunctionAddress_fn;
365 extern const struct func_desc function_description[];
367 cl_uint num_platforms;
369 clGetExtensionFunctionAddress_fn ext_fn_ptr;
372 struct platform_icd {
373 char * extension_suffix;
375 struct vendor_icd *vicd;
377 cl_uint ngpus; /* number of GPU devices */
378 cl_uint ncpus; /* number of CPU devices */
379 cl_uint ndevs; /* total number of devices, of all types */
383 ocl_icd_header += "extern struct _cl_icd_dispatch master_dispatch;\n"
384 $cl_objects.each { |o|
385 ocl_icd_header += "struct _cl_#{o} { struct _cl_icd_dispatch *dispatch; };\n"
387 return ocl_icd_header
390 def self.generate_ocl_icd_loader_map
391 ocl_icd_loader_map = "/**\n#{$license}\n*/\n\n"
393 $versions_entries.keys.sort.each { |version|
394 ocl_icd_loader_map += "OPENCL_#{version.sub('_','.')} {\n";
395 ocl_icd_loader_map += " global:\n";
396 $versions_entries[version].each { |symb|
397 ocl_icd_loader_map += " #{symb};\n"
399 if (prev_version == "") then
400 ocl_icd_loader_map += " local:\n";
401 ocl_icd_loader_map += " *;\n";
403 ocl_icd_loader_map += "} #{prev_version};\n\n";
404 prev_version="OPENCL_#{version.sub('_','.')}";
406 return ocl_icd_loader_map
409 def self.generate_ocl_icd_bindings_source
410 ocl_icd_bindings_source = "/**\n#{$license}\n*/\n"
411 ocl_icd_bindings_source += "#include \"ocl_icd.h\"\n"
412 ocl_icd_bindings_source += "struct _cl_icd_dispatch master_dispatch = {\n"
413 ($api_entries.length+$buff-1).times { |i|
414 if( $known_entries[i] ) then
415 ocl_icd_bindings_source += " #{$known_entries[i]},\n"
417 ocl_icd_bindings_source += " (void *) NULL,\n"
420 if( $known_entries[$api_entries.length+$buff-1] ) then
421 ocl_icd_bindings_source += " #{$known_entries[$api_entries.length+$buff-1]}\n"
423 ocl_icd_bindings_source += " (void *) NULL\n"
425 ocl_icd_bindings_source += "};\n"
426 ocl_icd_bindings_source += <<EOF
428 CL_API_ENTRY cl_int CL_API_CALL clIcdGetPlatformIDsKHR(
430 cl_platform_id *platforms,
431 cl_uint *num_platforms) {
432 if( platforms == NULL && num_platforms == NULL )
433 return CL_INVALID_VALUE;
434 if( num_entries == 0 && platforms != NULL )
435 return CL_INVALID_VALUE;
436 #error You have to fill the commented lines with corresponding variables from your library
437 // if( your_number_of_platforms == 0)
438 // return CL_PLATFORM_NOT_FOUND_KHR;
439 // if( num_platforms != NULL )
440 // *num_platforms = your_number_of_platforms;
441 if( platforms != NULL ) {
443 // for( i=0; i<(your_number_of_platforms<num_entries?your_number_of_platforms:num_entries); i++)
444 // platforms[i] = &your_platforms[i];
449 CL_API_ENTRY void * CL_API_CALL clGetExtensionFunctionAddress(
450 const char * func_name) CL_API_SUFFIX__VERSION_1_0 {
451 #error You have to fill this function with your extensions of incorporate these lines in your version
452 if( func_name != NULL && strcmp("clIcdGetPlatformIDsKHR", func_name) == 0 )
453 return (void *)clIcdGetPlatformIDsKHR;
456 CL_API_ENTRY cl_int CL_API_CALL clGetPlatformInfo(
457 cl_platform_id platform,
458 cl_platform_info param_name,
459 size_t param_value_size,
461 size_t * param_value_size_ret) CL_API_SUFFIX__VERSION_1_0 {
462 #error You ahve to fill this function with your information or assert that your version responds to CL_PLATFORM_ICD_SUFFIX_KHR
463 // char cl_platform_profile[] = "FULL_PROFILE";
464 // char cl_platform_version[] = "OpenCL 1.1";
465 // char cl_platform_name[] = "DummyCL";
466 // char cl_platform_vendor[] = "LIG";
467 // char cl_platform_extensions[] = "cl_khr_icd";
468 // char cl_platform_icd_suffix_khr[] = "DUMMY";
471 if( platform != NULL ) {
474 for(i=0; i<num_master_platforms; i++) {
475 if( platform == &master_platforms[i] )
479 return CL_INVALID_PLATFORM;
481 switch ( param_name ) {
482 case CL_PLATFORM_PROFILE:
483 string_p = cl_platform_profile;
484 size_string = sizeof(cl_platform_profile);
486 case CL_PLATFORM_VERSION:
487 string_p = cl_platform_version;
488 size_string = sizeof(cl_platform_version);
490 case CL_PLATFORM_NAME:
491 string_p = cl_platform_name;
492 size_string = sizeof(cl_platform_name);
494 case CL_PLATFORM_VENDOR:
495 string_p = cl_platform_vendor;
496 size_string = sizeof(cl_platform_vendor);
498 case CL_PLATFORM_EXTENSIONS:
499 string_p = cl_platform_extensions;
500 size_string = sizeof(cl_platform_extensions);
502 case CL_PLATFORM_ICD_SUFFIX_KHR:
503 string_p = cl_platform_icd_suffix_khr;
504 size_string = sizeof(cl_platform_icd_suffix_khr);
507 return CL_INVALID_VALUE;
510 if( param_value != NULL ) {
511 if( size_string > param_value_size )
512 return CL_INVALID_VALUE;
513 memcpy(param_value, string_p, size_string);
515 if( param_value_size_ret != NULL )
516 *param_value_size_ret = size_string;
520 return ocl_icd_bindings_source
523 def self.generate_ocl_icd_loader_gen_source
524 skip_funcs = $specific_loader_funcs
525 ocl_icd_loader_gen_source = "/**\n#{$license}\n*/\n"
526 ocl_icd_loader_gen_source += "#include \"ocl_icd_loader.h\"\n"
527 ocl_icd_loader_gen_source += "#define DEBUG_OCL_ICD_PROVIDE_DUMP_FIELD\n"
528 ocl_icd_loader_gen_source += "#include \"ocl_icd_debug.h\"\n"
529 $api_entries.each { |func_name, entry|
530 next if skip_funcs.include?(func_name)
531 clean_entry = entry.sub(/(.*\)).*/m,'\1').gsub("/*","").gsub("*/","").gsub("\r","") + "{\n"
532 return_type = entry.match(/CL_API_ENTRY (.*) CL_API_CALL/)[1]
533 parameters = clean_entry.match(/\(.*\)/m)[0][1..-2]
534 parameters.gsub!(/\[.*?\]/,"")
535 parameters.sub!(/\(.*?\*\s*(.*?)\)\s*\(.*?\)/m,'\1')
536 ocl_icd_loader_gen_source += clean_entry.gsub(/\*\[.*?\]/,"* ").gsub(/\[.+?\]/,"")
537 first_parameter = parameters.match(/.*?\,/m)
538 if not first_parameter then
539 first_parameter = parameters.match(/.*/m)[0]
541 first_parameter = first_parameter[0][0..-2]
543 fps = first_parameter.split
544 ocl_icd_loader_gen_source += " debug_trace();\n"
545 raise "Unsupported data_type #{fps[0]}" if not $cl_data_type_error[fps[0]]
546 ps = parameters.split(",")
547 ps = ps.collect { |p|
549 p = p[-1].gsub("*","")
551 error_handler = lambda {
552 if(ps.include?("errcode_ret")) then
553 ocl_icd_loader_gen_source += " if( errcode_ret != NULL ) {\n";
554 ocl_icd_loader_gen_source += " *errcode_ret = #{$cl_data_type_error[fps[0]]};\n"
555 ocl_icd_loader_gen_source += " }\n"
556 if return_type != "void" then
557 ocl_icd_loader_gen_source += " RETURN(NULL);\n"
559 ocl_icd_loader_gen_source += " return;\n"
561 elsif ($non_standard_error.include?(func_name)) then
562 if return_type != "void" then
563 ocl_icd_loader_gen_source += " RETURN(NULL);\n"
565 ocl_icd_loader_gen_source += " return;\n"
568 if return_type != "void" then
569 ocl_icd_loader_gen_source += " RETURN(#{$cl_data_type_error[fps[0]]});\n" if return_type != "void"
571 ocl_icd_loader_gen_source += " return;\n"
576 if(fps[0] == "cl_platform_id") then
577 ocl_icd_loader_gen_source += " #{fps[1]}=selectPlatformID(#{fps[1]});\n"
579 ocl_icd_loader_gen_source += " if( (struct _#{fps[0]} *)#{fps[1]} == NULL) {\n"
581 ocl_icd_loader_gen_source += " }\n"
582 if return_type != "void" then
583 return_debug="RETURN"
585 return_debug="return"
587 ocl_icd_loader_gen_source += " #{return_debug}(((struct _#{fps[0]} *)#{fps[1]})->dispatch->#{func_name}("
588 ocl_icd_loader_gen_source += ps.join(", ")
589 ocl_icd_loader_gen_source += "));\n"
590 ocl_icd_loader_gen_source += "}\n\n"
592 ocl_icd_loader_gen_source += "#pragma GCC visibility push(hidden)\n\n"
593 skip_funcs = $specific_loader_funcs
594 $api_entries.each { |func_name, entry|
595 #next if func_name.match(/EXT$/)
596 #next if func_name.match(/KHR$/)
597 if (skip_funcs.include?(func_name)) then
598 ocl_icd_loader_gen_source += "extern typeof(#{func_name}) #{func_name}_hid;\n"
600 ocl_icd_loader_gen_source += "typeof(#{func_name}) #{func_name}_hid __attribute__ ((alias (\"#{func_name}\"), visibility(\"hidden\")));\n"
603 ocl_icd_loader_gen_source += "\n\nstruct func_desc const function_description[]= {\n"
604 $api_entries.each { |func_name, entry|
605 #next if func_name.match(/EXT$/)
606 #next if func_name.match(/KHR$/)
607 ocl_icd_loader_gen_source += " {\"#{func_name}\", (void(* const)(void))&#{func_name}_hid },\n"
609 ocl_icd_loader_gen_source += <<EOF
614 void dump_platform(clGEFA_t f, cl_platform_id pid) {
615 debug(D_ALWAYS, "platform @%p: name=field_in_struct [clGetExtensionFunctionAddress(name)/clGetExtensionFunctionAddressForPlatform(name)]", pid);
617 $api_entries_array.each { |entry|
618 e = entry.gsub("\r"," ").gsub("\n"," ").gsub("\t"," ").
619 sub(/.*CL_API_CALL *([^ ()]*)[ ()].*$/m, '\1')
620 ocl_icd_loader_gen_source += " dump_field(pid, f, #{e});\n"
623 ocl_icd_loader_gen_source += <<EOF
627 #pragma GCC visibility pop
630 return ocl_icd_loader_gen_source;
633 def self.generate_from_database(yamlfile)
634 load_database(yamlfile)
635 File.open('ocl_icd.h','w') { |f|
636 f.puts generate_ocl_icd_header
638 File.open('ocl_icd_loader_gen.h','w') { |f|
639 f.puts generate_ocl_icd_loader_header
641 File.open('ocl_icd_loader_gen.map','w') { |f|
642 f.puts generate_ocl_icd_loader_map
644 File.open('ocl_icd_bindings.c','w') { |f|
645 f.puts generate_ocl_icd_bindings_source
647 File.open('ocl_icd_loader_gen.c','w') { |f|
648 f.puts generate_ocl_icd_loader_gen_source
652 ##########################################################
653 ##########################################################
654 # update-database mode
655 def self.savedb(yamlfile)
656 File::open(yamlfile,"w") { |f|
657 f.write($license.gsub(/^/,"# "))
660 # In Intel (OpenCL 1.1):
661 # * clSetCommandQueueProperty(13): nil (deprecated in 1.1)
662 # * clGetGLContextInfoKHR(74): function present with its symbol
664 # * 92: correspond to symbol clGetKernelArgInfo (first abandonned version?)
666 # In nvidia (OpenCL 1.1):
667 # * clGetGLContextInfoKHR(74): function present but no symbol
670 # * only two OpenCL symbols: clGetPlatformInfo(1) and clGetExtensionFunctionAddress(65)
671 # In AMD (OpenCL 1.2):
672 # * clGetPlatformIDs(0): nil (symbol present)
673 # * clGetGLContextInfoKHR(74): function present but no symbol
681 # Not using YAML::dump as:
682 # * keys are not ordered
683 # * strings are badly formatted in new YAML ruby implementation (psych)
684 # * it is very easy to do it ourself
685 #f.write(YAML::dump(api_db))
687 $known_entries.keys.sort.each { |k|
688 f.write("\n#{k}: |-\n ")
689 f.write($api_entries[$known_entries[k]].gsub("\n","\n "))
695 def self.updatedb_from_input(dbfile, inputfile)
697 load_database(dbfile, with_windows=true)
698 doc = YAML::load_file(inputfile)
701 next if $known_entries[i]
702 $known_entries[i]=doc[i]
709 ############################################################
710 ############################################################
711 ############################################################
718 OptionParser.new do |opts|
719 opts.banner = "Usage: cd_generator.rb [options] mode"
721 opts.on("-d", "--database FILE", String, "YAML file (default ocl_interface.yaml)") do |v|
722 options[:database] = v
724 opts.on("-i", "--input FILE", String,
725 "binding between OpenCL functions and entry number (required for update-database)") \
729 opts.on("-s", "--[no-]system-headers",
730 "Look for OpenCL functions in system header files") \
732 options[:"system-headers"] = v
734 opts.on("-m", "--mode [MODE]", [:database, :generate, :"update-database"],
735 "Select mode (database, generate, update-database)") do |m|
740 if !options[:database] then
741 options[:database] = "ocl_interface.yaml"
744 if !options[:mode] then
745 raise "--mode option required"
747 if options[:mode] == :generate then
748 if !options[:"system-headers"] then
749 IcdGenerator.generate_sources(from_headers=false, from_database=true, database=options[:database])
751 IcdGenerator.generate_sources(from_headers=true, from_database=false)
753 elsif options[:mode] == :"update-database" then
754 if !options[:input] then
755 raise "--input option required"
757 IcdGenerator.updatedb_from_input(options[:database], options[:input])
758 elsif options[:mode] == :database then
759 IcdGenerator.generate_from_database(options[:database])
761 raise "Mode must be one of generate, database or update-database not #{options[:mode]}"