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 __attribute__((weak)) int f (void* arg, int arg2, int arg3, void* arg4, void* arg5) { \\
293 void (* p)(void*, int, int, void*, void*)=NULL; \\
294 p=dlsym(RTLD_NEXT, #f); \\
296 (*p)(arg, arg2, arg3, arg4, arg5); \\
304 $api_entries.each_key { |func_name|
305 next if $noweak_funcs.include?(func_name)
306 run_dummy_icd_weak += "F(#{func_name})\n"
308 return run_dummy_icd_weak
311 def self.generate_sources(from_headers=true, from_database=false, database=nil)
315 if from_database then
316 load_database(database)
318 File.open('libdummy_icd_gen.h','w') { |f|
319 f.puts generate_libdummy_icd_header
321 File.open('libdummy_icd_gen.c','w') { |f|
322 f.puts generate_libdummy_icd_source
324 File.open('run_dummy_icd_gen.c','w') { |f|
325 f.puts generate_run_dummy_icd_source
327 File.open('run_dummy_icd_weak_gen.c','w') { |f|
328 f.puts generate_run_dummy_icd_weak_source
332 ##########################################################
333 ##########################################################
335 def self.generate_ocl_icd_header
336 ocl_icd_header = "/**\n#{$license}\n*/\n\n"
337 ocl_icd_header += "#ifndef OCL_ICD_H\n"
338 ocl_icd_header += "#define OCL_ICD_H\n"
339 ocl_icd_header += "#pragma GCC diagnostic push\n"
340 ocl_icd_header += "# pragma GCC diagnostic ignored \"-Wcpp\"\n"
341 ocl_icd_header += "# define CL_USE_DEPRECATED_OPENCL_1_0_APIS\n"
342 ocl_icd_header += "# define CL_USE_DEPRECATED_OPENCL_1_1_APIS\n"
343 ocl_icd_header += "# define CL_USE_DEPRECATED_OPENCL_1_2_APIS\n"
344 ocl_icd_header += "# include <CL/opencl.h>\n"
345 ocl_icd_header += self.include_headers
346 ocl_icd_header += "#pragma GCC diagnostic pop\n"
347 ocl_icd_header += <<EOF
349 #define OCL_ICD_API_VERSION 1
350 #define OCL_ICD_IDENTIFIED_FUNCTIONS #{$known_entries.count}
352 struct _cl_icd_dispatch {
355 $api_entries_array.each { |entry|
356 version = entry.split("\n").
357 grep(/ CL_API_SUFFIX__(VERSION_[0-9_]+)[^0-9_]/).join('').
358 gsub(/.* CL_API_SUFFIX__(VERSION_[0-9_]+)[^0-9_].*$/, '\1')
359 if (version != '') then
360 ocl_icd_header += '#ifdef CL_'+version+"\n"
362 ocl_icd_header += entry.gsub("\r","").
363 sub(/CL_API_CALL\n?(.*?)\(/m,'(CL_API_CALL*\1)('+"\n ").
364 gsub(/\) (CL_API_SUFFIX__VERSION)/m,"\n) \\1").gsub(/\s*$/,'').
365 gsub(/^[\t ]+/," ").gsub(/^([^\t ])/, ' \1') + "\n"
366 if (version != '') then
367 ocl_icd_header += '#else'+"\n"
368 ocl_icd_header += ' CL_API_ENTRY cl_int (CL_API_CALL* clUnknown'+nb.to_s+")(void);\n"
369 ocl_icd_header += '#endif'+"\n"
371 ocl_icd_header += "\n"
374 ocl_icd_header += "};\n"
375 ocl_icd_header += "#endif\n\n"
376 return ocl_icd_header
379 def self.generate_ocl_icd_loader_header
380 ocl_icd_header = "/**\n#{$license}\n*/\n\n"
381 ocl_icd_header += "#include \"ocl_icd.h\"\n\n"
382 ocl_icd_header += <<EOF
386 void(*const addr)(void);
388 typedef __typeof__(clGetExtensionFunctionAddress) *clGetExtensionFunctionAddress_fn;
389 extern const struct func_desc function_description[];
391 cl_uint num_platforms;
393 clGetExtensionFunctionAddress_fn ext_fn_ptr;
396 struct platform_icd {
397 char * extension_suffix;
399 struct vendor_icd *vicd;
401 cl_uint ngpus; /* number of GPU devices */
402 cl_uint ncpus; /* number of CPU devices */
403 cl_uint ndevs; /* total number of devices, of all types */
407 ocl_icd_header += "extern struct _cl_icd_dispatch master_dispatch;\n"
408 $cl_objects.each { |o|
409 ocl_icd_header += "struct _cl_#{o} { struct _cl_icd_dispatch *dispatch; };\n"
411 return ocl_icd_header
414 def self.generate_ocl_icd_loader_map
415 ocl_icd_loader_map = "/**\n#{$license}\n*/\n\n"
417 $versions_entries.keys.sort.each { |version|
418 ocl_icd_loader_map += "OPENCL_#{version.sub('_','.')} {\n";
419 ocl_icd_loader_map += " global:\n";
420 $versions_entries[version].each { |symb|
421 ocl_icd_loader_map += " #{symb};\n"
423 if (prev_version == "") then
424 ocl_icd_loader_map += " local:\n";
425 ocl_icd_loader_map += " *;\n";
427 ocl_icd_loader_map += "} #{prev_version};\n\n";
428 prev_version="OPENCL_#{version.sub('_','.')}";
430 return ocl_icd_loader_map
433 def self.generate_ocl_icd_bindings_source
434 ocl_icd_bindings_source = "/**\n#{$license}\n*/\n"
435 ocl_icd_bindings_source += "#include \"ocl_icd.h\"\n"
436 ocl_icd_bindings_source += "struct _cl_icd_dispatch master_dispatch = {\n"
437 ($api_entries.length+$buff-1).times { |i|
438 if( $known_entries[i] ) then
439 ocl_icd_bindings_source += " #{$known_entries[i]},\n"
441 ocl_icd_bindings_source += " (void *) NULL,\n"
444 if( $known_entries[$api_entries.length+$buff-1] ) then
445 ocl_icd_bindings_source += " #{$known_entries[$api_entries.length+$buff-1]}\n"
447 ocl_icd_bindings_source += " (void *) NULL\n"
449 ocl_icd_bindings_source += "};\n"
450 ocl_icd_bindings_source += <<EOF
452 CL_API_ENTRY cl_int CL_API_CALL clIcdGetPlatformIDsKHR(
454 cl_platform_id *platforms,
455 cl_uint *num_platforms) {
456 if( platforms == NULL && num_platforms == NULL )
457 return CL_INVALID_VALUE;
458 if( num_entries == 0 && platforms != NULL )
459 return CL_INVALID_VALUE;
460 #error You have to fill the commented lines with corresponding variables from your library
461 // if( your_number_of_platforms == 0)
462 // return CL_PLATFORM_NOT_FOUND_KHR;
463 // if( num_platforms != NULL )
464 // *num_platforms = your_number_of_platforms;
465 if( platforms != NULL ) {
467 // for( i=0; i<(your_number_of_platforms<num_entries?your_number_of_platforms:num_entries); i++)
468 // platforms[i] = &your_platforms[i];
473 CL_API_ENTRY void * CL_API_CALL clGetExtensionFunctionAddress(
474 const char * func_name) CL_API_SUFFIX__VERSION_1_0 {
475 #error You have to fill this function with your extensions of incorporate these lines in your version
476 if( func_name != NULL && strcmp("clIcdGetPlatformIDsKHR", func_name) == 0 )
477 return (void *)clIcdGetPlatformIDsKHR;
480 CL_API_ENTRY cl_int CL_API_CALL clGetPlatformInfo(
481 cl_platform_id platform,
482 cl_platform_info param_name,
483 size_t param_value_size,
485 size_t * param_value_size_ret) CL_API_SUFFIX__VERSION_1_0 {
486 #error You ahve to fill this function with your information or assert that your version responds to CL_PLATFORM_ICD_SUFFIX_KHR
487 // char cl_platform_profile[] = "FULL_PROFILE";
488 // char cl_platform_version[] = "OpenCL 1.1";
489 // char cl_platform_name[] = "DummyCL";
490 // char cl_platform_vendor[] = "LIG";
491 // char cl_platform_extensions[] = "cl_khr_icd";
492 // char cl_platform_icd_suffix_khr[] = "DUMMY";
495 if( platform != NULL ) {
498 for(i=0; i<num_master_platforms; i++) {
499 if( platform == &master_platforms[i] )
503 return CL_INVALID_PLATFORM;
505 switch ( param_name ) {
506 case CL_PLATFORM_PROFILE:
507 string_p = cl_platform_profile;
508 size_string = sizeof(cl_platform_profile);
510 case CL_PLATFORM_VERSION:
511 string_p = cl_platform_version;
512 size_string = sizeof(cl_platform_version);
514 case CL_PLATFORM_NAME:
515 string_p = cl_platform_name;
516 size_string = sizeof(cl_platform_name);
518 case CL_PLATFORM_VENDOR:
519 string_p = cl_platform_vendor;
520 size_string = sizeof(cl_platform_vendor);
522 case CL_PLATFORM_EXTENSIONS:
523 string_p = cl_platform_extensions;
524 size_string = sizeof(cl_platform_extensions);
526 case CL_PLATFORM_ICD_SUFFIX_KHR:
527 string_p = cl_platform_icd_suffix_khr;
528 size_string = sizeof(cl_platform_icd_suffix_khr);
531 return CL_INVALID_VALUE;
534 if( param_value != NULL ) {
535 if( size_string > param_value_size )
536 return CL_INVALID_VALUE;
537 memcpy(param_value, string_p, size_string);
539 if( param_value_size_ret != NULL )
540 *param_value_size_ret = size_string;
544 return ocl_icd_bindings_source
547 def self.generate_ocl_icd_loader_gen_source
548 skip_funcs = $specific_loader_funcs
549 ocl_icd_loader_gen_source = "/**\n#{$license}\n*/\n"
550 ocl_icd_loader_gen_source += "#include \"ocl_icd_loader.h\"\n"
551 ocl_icd_loader_gen_source += "#define DEBUG_OCL_ICD_PROVIDE_DUMP_FIELD\n"
552 ocl_icd_loader_gen_source += "#include \"ocl_icd_debug.h\"\n"
553 $api_entries.each { |func_name, entry|
554 next if skip_funcs.include?(func_name)
555 clean_entry = entry.sub(/(.*\)).*/m,'\1').gsub("/*","").gsub("*/","").gsub("\r","") + "{\n"
556 return_type = entry.match(/CL_API_ENTRY (.*) CL_API_CALL/)[1]
557 parameters = clean_entry.match(/\(.*\)/m)[0][1..-2]
558 parameters.gsub!(/\[.*?\]/,"")
559 parameters.sub!(/\(.*?\*\s*(.*?)\)\s*\(.*?\)/m,'\1')
560 ocl_icd_loader_gen_source += clean_entry.gsub(/\*\[.*?\]/,"* ").gsub(/\[.+?\]/,"")
561 first_parameter = parameters.match(/.*?\,/m)
562 if not first_parameter then
563 first_parameter = parameters.match(/.*/m)[0]
565 first_parameter = first_parameter[0][0..-2]
567 fps = first_parameter.split
568 ocl_icd_loader_gen_source += " debug_trace();\n"
569 raise "Unsupported data_type #{fps[0]}" if not $cl_data_type_error[fps[0]]
570 ps = parameters.split(",")
571 ps = ps.collect { |p|
573 p = p[-1].gsub("*","")
575 error_handler = lambda {
576 if(ps.include?("errcode_ret")) then
577 ocl_icd_loader_gen_source += " if( errcode_ret != NULL ) {\n";
578 ocl_icd_loader_gen_source += " *errcode_ret = #{$cl_data_type_error[fps[0]]};\n"
579 ocl_icd_loader_gen_source += " }\n"
580 if return_type != "void" then
581 ocl_icd_loader_gen_source += " RETURN(NULL);\n"
583 ocl_icd_loader_gen_source += " return;\n"
585 elsif ($non_standard_error.include?(func_name)) then
586 if return_type != "void" then
587 ocl_icd_loader_gen_source += " RETURN(NULL);\n"
589 ocl_icd_loader_gen_source += " return;\n"
592 if return_type != "void" then
593 ocl_icd_loader_gen_source += " RETURN(#{$cl_data_type_error[fps[0]]});\n" if return_type != "void"
595 ocl_icd_loader_gen_source += " return;\n"
600 if(fps[0] == "cl_platform_id") then
601 ocl_icd_loader_gen_source += " #{fps[1]}=selectPlatformID(#{fps[1]});\n"
603 ocl_icd_loader_gen_source += " if( (struct _#{fps[0]} *)#{fps[1]} == NULL) {\n"
605 ocl_icd_loader_gen_source += " }\n"
606 if return_type != "void" then
607 return_debug="RETURN"
609 return_debug="return"
611 ocl_icd_loader_gen_source += " #{return_debug}(((struct _#{fps[0]} *)#{fps[1]})->dispatch->#{func_name}("
612 ocl_icd_loader_gen_source += ps.join(", ")
613 ocl_icd_loader_gen_source += "));\n"
614 ocl_icd_loader_gen_source += "}\n\n"
616 ocl_icd_loader_gen_source += "#pragma GCC visibility push(hidden)\n\n"
617 skip_funcs = $specific_loader_funcs
618 $api_entries.each { |func_name, entry|
619 #next if func_name.match(/EXT$/)
620 #next if func_name.match(/KHR$/)
621 if (skip_funcs.include?(func_name)) then
622 ocl_icd_loader_gen_source += "extern typeof(#{func_name}) #{func_name}_hid;\n"
624 ocl_icd_loader_gen_source += "typeof(#{func_name}) #{func_name}_hid __attribute__ ((alias (\"#{func_name}\"), visibility(\"hidden\")));\n"
627 ocl_icd_loader_gen_source += "\n\nstruct func_desc const function_description[]= {\n"
628 $api_entries.each { |func_name, entry|
629 #next if func_name.match(/EXT$/)
630 #next if func_name.match(/KHR$/)
631 ocl_icd_loader_gen_source += " {\"#{func_name}\", (void(* const)(void))&#{func_name}_hid },\n"
633 ocl_icd_loader_gen_source += <<EOF
638 void dump_platform(clGEFA_t f, cl_platform_id pid) {
639 debug(D_ALWAYS, "platform @%p: name=field_in_struct [clGetExtensionFunctionAddress(name)/clGetExtensionFunctionAddressForPlatform(name)]", pid);
641 $api_entries_array.each { |entry|
642 e = entry.gsub("\r"," ").gsub("\n"," ").gsub("\t"," ").
643 sub(/.*CL_API_CALL *([^ ()]*)[ ()].*$/m, '\1')
644 ocl_icd_loader_gen_source += " dump_field(pid, f, #{e});\n"
647 ocl_icd_loader_gen_source += <<EOF
651 #pragma GCC visibility pop
654 return ocl_icd_loader_gen_source;
657 def self.generate_from_database(yamlfile)
658 load_database(yamlfile)
659 File.open('ocl_icd.h','w') { |f|
660 f.puts generate_ocl_icd_header
662 File.open('ocl_icd_loader_gen.h','w') { |f|
663 f.puts generate_ocl_icd_loader_header
665 File.open('ocl_icd_loader_gen.map','w') { |f|
666 f.puts generate_ocl_icd_loader_map
668 File.open('ocl_icd_bindings.c','w') { |f|
669 f.puts generate_ocl_icd_bindings_source
671 File.open('ocl_icd_loader_gen.c','w') { |f|
672 f.puts generate_ocl_icd_loader_gen_source
676 ##########################################################
677 ##########################################################
678 # update-database mode
679 def self.savedb(yamlfile)
680 File::open(yamlfile,"w") { |f|
681 f.write($license.gsub(/^/,"# "))
684 # In Intel (OpenCL 1.1):
685 # * clSetCommandQueueProperty(13): nil (deprecated in 1.1)
686 # * clGetGLContextInfoKHR(74): function present with its symbol
688 # * 92: correspond to symbol clGetKernelArgInfo (first abandonned version?)
690 # In nvidia (OpenCL 1.1):
691 # * clGetGLContextInfoKHR(74): function present but no symbol
694 # * only two OpenCL symbols: clGetPlatformInfo(1) and clGetExtensionFunctionAddress(65)
695 # In AMD (OpenCL 1.2):
696 # * clGetPlatformIDs(0): nil (symbol present)
697 # * clGetGLContextInfoKHR(74): function present but no symbol
705 # Not using YAML::dump as:
706 # * keys are not ordered
707 # * strings are badly formatted in new YAML ruby implementation (psych)
708 # * it is very easy to do it ourself
709 #f.write(YAML::dump(api_db))
711 $known_entries.keys.sort.each { |k|
712 f.write("\n#{k}: |-\n ")
713 f.write($api_entries[$known_entries[k]].gsub("\n","\n "))
719 def self.updatedb_from_input(dbfile, inputfile)
721 load_database(dbfile, with_windows=true)
722 doc = YAML::load_file(inputfile)
725 next if $known_entries[i]
726 $known_entries[i]=doc[i]
733 ############################################################
734 ############################################################
735 ############################################################
742 OptionParser.new do |opts|
743 opts.banner = "Usage: cd_generator.rb [options] mode"
745 opts.on("-d", "--database FILE", String, "YAML file (default ocl_interface.yaml)") do |v|
746 options[:database] = v
748 opts.on("-i", "--input FILE", String,
749 "binding between OpenCL functions and entry number (required for update-database)") \
753 opts.on("-s", "--[no-]system-headers",
754 "Look for OpenCL functions in system header files") \
756 options[:"system-headers"] = v
758 opts.on("-m", "--mode [MODE]", [:database, :generate, :"update-database"],
759 "Select mode (database, generate, update-database)") do |m|
764 if !options[:database] then
765 options[:database] = "ocl_interface.yaml"
768 if !options[:mode] then
769 raise "--mode option required"
771 if options[:mode] == :generate then
772 if !options[:"system-headers"] then
773 IcdGenerator.generate_sources(from_headers=false, from_database=true, database=options[:database])
775 IcdGenerator.generate_sources(from_headers=true, from_database=false)
777 elsif options[:mode] == :"update-database" then
778 if !options[:input] then
779 raise "--input option required"
781 IcdGenerator.updatedb_from_input(options[:database], options[:input])
782 elsif options[:mode] == :database then
783 IcdGenerator.generate_from_database(options[:database])
785 raise "Mode must be one of generate, database or update-database not #{options[:mode]}"