2 Copyright (c) 2012-2015, Brice Videau <brice.videau@imag.fr>
3 Copyright (c) 2012-2015, 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", "/usr/include/CL/cl_egl.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-2015, Brice Videau <brice.videau@imag.fr>
75 Copyright (c) 2012-2015, 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 == "clGetExtensionFunctionAddressForPlatform" then
255 run_dummy_icd += " #{func_name}((cl_platform_id )chosen_platform,\"extLIG\");\n"
256 elsif func_name == "clUnloadCompiler" then
257 run_dummy_icd += " #{func_name}();\n"
259 params = $api_entries[func_name].gsub(/[[:space:]]+/, ' ')
260 params.gsub!(/[\/][*](([^*]*)[*][^\/])*[^*]*[*][\/]/,'')
261 params.gsub!(/^[^(]*[(] *(.*[^ ]) *[)][^)]*$/, '\1')
262 params = params.gsub(/[^,(]+([(][^)]*[)])*[^,]*/) { |p|
264 p.gsub!("user_func", "")
265 if false && p.match(/[*]/) then
271 if func_name != "clGetPlatformIDs" then
272 params.gsub!(/^([^0]*)0/, '\1chosen_platform')
274 run_dummy_icd += " #{func_name}(#{params});\n"
276 run_dummy_icd += " printf(\"%s\\n\", \"#{func_name}\");\n"
277 run_dummy_icd += "#ifdef OCL_ICD_PRINT_EXPECTED\n"
278 run_dummy_icd += " printf(\"#{$key_entries[func_name]} : %s (expected)\\n\", \"#{func_name}\");\n"
279 run_dummy_icd += "#endif\n"
280 run_dummy_icd += " fflush(NULL);\n"
282 run_dummy_icd += " return;\n}\n"
286 def self.generate_run_dummy_icd_weak_source
287 run_dummy_icd_weak = "/**\n#{$license}\n*/\n"
288 run_dummy_icd_weak += <<EOF
289 #define _GNU_SOURCE 1
294 run_dummy_icd_weak += "#pragma GCC diagnostic push\n"
295 run_dummy_icd_weak += "# pragma GCC diagnostic ignored \"-Wcpp\"\n"
296 run_dummy_icd_weak += "# define CL_USE_DEPRECATED_OPENCL_1_0_APIS\n"
297 run_dummy_icd_weak += "# define CL_USE_DEPRECATED_OPENCL_1_1_APIS\n"
298 run_dummy_icd_weak += "# define CL_USE_DEPRECATED_OPENCL_1_2_APIS\n"
299 run_dummy_icd_weak += "# include <CL/opencl.h>\n"
300 run_dummy_icd_weak += self.include_headers
301 run_dummy_icd_weak += "#pragma GCC diagnostic pop\n"
303 $api_entries.each { |func_name, entry|
304 next if $noweak_funcs.include?(func_name)
305 clean_entry = entry.sub(/(.*\)).*/m,'\1').gsub("/*","").gsub("*/","").gsub("\r","") + "{\n"
306 return_type = entry.match(/CL_API_ENTRY (.*) CL_API_CALL/)[1]
307 parameters = clean_entry.match(/\(.*\)/m)[0][1..-2]
308 parameters.gsub!(/\[.*?\]/,"")
309 parameters.sub!(/\(.*?\*\s*(.*?)\)\s*\(.*?\)/m,'\1')
310 run_dummy_icd_weak += clean_entry.gsub(/\*\[.*?\]/,"* ").gsub(/\[.+?\]/,"")
311 first_parameter = parameters.match(/.*?\,/m)
312 if not first_parameter then
313 first_parameter = parameters.match(/.*/m)[0]
315 first_parameter = first_parameter[0][0..-2]
317 fps = first_parameter.split
318 run_dummy_icd_weak += " void (*p)()=dlsym(RTLD_NEXT, \"#{func_name}\");\n"
319 ps = parameters.split(",")
320 ps = ps.collect { |p|
322 p = p[-1].gsub("*","")
325 run_dummy_icd_weak += " if(p) {\n"
326 run_dummy_icd_weak += " return((*(typeof(#{func_name})*)p)("
327 run_dummy_icd_weak += ps.join(", ")
328 run_dummy_icd_weak += "));\n"
329 run_dummy_icd_weak += " } else {\n"
330 run_dummy_icd_weak += " printf(\"-1 : \");\n"
331 run_dummy_icd_weak += " return (#{return_type})0;\n"
332 run_dummy_icd_weak += " }\n"
333 run_dummy_icd_weak += "}\n\n"
335 return run_dummy_icd_weak
338 def self.generate_sources(from_headers=true, from_database=false, database=nil)
342 if from_database then
343 load_database(database)
345 File.open('libdummy_icd_gen.h','w') { |f|
346 f.puts generate_libdummy_icd_header
348 File.open('libdummy_icd_gen.c','w') { |f|
349 f.puts generate_libdummy_icd_source
351 File.open('run_dummy_icd_gen.c','w') { |f|
352 f.puts generate_run_dummy_icd_source
354 File.open('run_dummy_icd_weak_gen.c','w') { |f|
355 f.puts generate_run_dummy_icd_weak_source
359 ##########################################################
360 ##########################################################
362 def self.generate_ocl_icd_header
363 ocl_icd_header = "/**\n#{$license}\n*/\n\n"
364 ocl_icd_header += "#ifndef OCL_ICD_H\n"
365 ocl_icd_header += "#define OCL_ICD_H\n"
366 ocl_icd_header += "#pragma GCC diagnostic push\n"
367 ocl_icd_header += "# pragma GCC diagnostic ignored \"-Wcpp\"\n"
368 ocl_icd_header += "# define CL_USE_DEPRECATED_OPENCL_1_0_APIS\n"
369 ocl_icd_header += "# define CL_USE_DEPRECATED_OPENCL_1_1_APIS\n"
370 ocl_icd_header += "# define CL_USE_DEPRECATED_OPENCL_1_2_APIS\n"
371 ocl_icd_header += "# include <CL/opencl.h>\n"
372 ocl_icd_header += self.include_headers
373 ocl_icd_header += "#pragma GCC diagnostic pop\n"
374 ocl_icd_header += <<EOF
376 #define OCL_ICD_API_VERSION 1
377 #define OCL_ICD_IDENTIFIED_FUNCTIONS #{$known_entries.count}
379 struct _cl_icd_dispatch {
382 $api_entries_array.each { |entry|
383 version = entry.split("\n").
384 grep(/ CL_(API|EXT)_SUFFIX__(VERSION_[0-9_]+)[^0-9_]/).join('').
385 gsub(/.* CL_(API|EXT)_SUFFIX__(VERSION_[0-9_]*[0-9])_*[^0-9_].*$/, '\2')
386 if (version != '') then
387 ocl_icd_header += '#ifdef CL_'+version+"\n"
388 elsif not entry =~ / clUnknown/
389 ocl_icd_header += "#warning no version\n"
391 ocl_icd_header += entry.gsub("\r","").
392 sub(/CL_API_CALL\n?(.*?)\(/m,'(CL_API_CALL*\1)('+"\n ").
393 gsub(/\) (CL_API_SUFFIX__VERSION)/m,"\n) \\1").gsub(/\s*$/,'').
394 gsub(/^[\t ]+/," ").gsub(/^([^\t ])/, ' \1') + "\n"
395 if (version != '') then
396 ocl_icd_header += '#else'+"\n"
397 ocl_icd_header += ' CL_API_ENTRY cl_int (CL_API_CALL* clUnknown'+nb.to_s+")(void);\n"
398 ocl_icd_header += '#endif'+"\n"
400 ocl_icd_header += "\n"
403 ocl_icd_header += "};\n"
404 ocl_icd_header += "#endif\n\n"
405 return ocl_icd_header
408 def self.generate_ocl_icd_loader_header
409 ocl_icd_header = "/**\n#{$license}\n*/\n\n"
410 ocl_icd_header += "#include \"ocl_icd.h\"\n\n"
411 ocl_icd_header += <<EOF
415 void(*const addr)(void);
417 typedef __typeof__(clGetExtensionFunctionAddress) *clGetExtensionFunctionAddress_fn;
418 extern const struct func_desc function_description[];
420 cl_uint num_platforms;
422 clGetExtensionFunctionAddress_fn ext_fn_ptr;
425 struct platform_icd {
426 char * extension_suffix;
428 struct vendor_icd *vicd;
430 cl_uint ngpus; /* number of GPU devices */
431 cl_uint ncpus; /* number of CPU devices */
432 cl_uint ndevs; /* total number of devices, of all types */
436 ocl_icd_header += "extern struct _cl_icd_dispatch master_dispatch;\n"
437 $cl_objects.each { |o|
438 ocl_icd_header += "struct _cl_#{o} { struct _cl_icd_dispatch *dispatch; };\n"
440 return ocl_icd_header
443 def self.generate_ocl_icd_loader_map
444 ocl_icd_loader_map = "/**\n#{$license}\n*/\n\n"
446 $versions_entries.keys.sort.each { |version|
447 ocl_icd_loader_map += "OPENCL_#{version.sub('_','.')} {\n";
448 ocl_icd_loader_map += " global:\n";
449 $versions_entries[version].each { |symb|
450 ocl_icd_loader_map += " #{symb};\n"
452 if (prev_version == "") then
453 ocl_icd_loader_map += " local:\n";
454 ocl_icd_loader_map += " *;\n";
456 ocl_icd_loader_map += "} #{prev_version};\n\n";
457 prev_version="OPENCL_#{version.sub('_','.')}";
459 return ocl_icd_loader_map
462 def self.generate_ocl_icd_bindings_source
463 ocl_icd_bindings_source = "/**\n#{$license}\n*/\n"
464 ocl_icd_bindings_source += "#include \"ocl_icd.h\"\n"
465 ocl_icd_bindings_source += "struct _cl_icd_dispatch master_dispatch = {\n"
466 ($api_entries.length+$buff-1).times { |i|
467 if( $known_entries[i] ) then
468 ocl_icd_bindings_source += " #{$known_entries[i]},\n"
470 ocl_icd_bindings_source += " (void *) NULL,\n"
473 if( $known_entries[$api_entries.length+$buff-1] ) then
474 ocl_icd_bindings_source += " #{$known_entries[$api_entries.length+$buff-1]}\n"
476 ocl_icd_bindings_source += " (void *) NULL\n"
478 ocl_icd_bindings_source += "};\n"
479 ocl_icd_bindings_source += <<EOF
481 CL_API_ENTRY cl_int CL_API_CALL clIcdGetPlatformIDsKHR(
483 cl_platform_id *platforms,
484 cl_uint *num_platforms) {
485 if( platforms == NULL && num_platforms == NULL )
486 return CL_INVALID_VALUE;
487 if( num_entries == 0 && platforms != NULL )
488 return CL_INVALID_VALUE;
489 #error You have to fill the commented lines with corresponding variables from your library
490 // if( your_number_of_platforms == 0)
491 // return CL_PLATFORM_NOT_FOUND_KHR;
492 // if( num_platforms != NULL )
493 // *num_platforms = your_number_of_platforms;
494 if( platforms != NULL ) {
496 // for( i=0; i<(your_number_of_platforms<num_entries?your_number_of_platforms:num_entries); i++)
497 // platforms[i] = &your_platforms[i];
502 CL_API_ENTRY void * CL_API_CALL clGetExtensionFunctionAddress(
503 const char * func_name) CL_API_SUFFIX__VERSION_1_0 {
504 #error You have to fill this function with your extensions of incorporate these lines in your version
505 if( func_name != NULL && strcmp("clIcdGetPlatformIDsKHR", func_name) == 0 )
506 return (void *)clIcdGetPlatformIDsKHR;
509 CL_API_ENTRY cl_int CL_API_CALL clGetPlatformInfo(
510 cl_platform_id platform,
511 cl_platform_info param_name,
512 size_t param_value_size,
514 size_t * param_value_size_ret) CL_API_SUFFIX__VERSION_1_0 {
515 #error You ahve to fill this function with your information or assert that your version responds to CL_PLATFORM_ICD_SUFFIX_KHR
516 // char cl_platform_profile[] = "FULL_PROFILE";
517 // char cl_platform_version[] = "OpenCL 1.1";
518 // char cl_platform_name[] = "DummyCL";
519 // char cl_platform_vendor[] = "LIG";
520 // char cl_platform_extensions[] = "cl_khr_icd";
521 // char cl_platform_icd_suffix_khr[] = "DUMMY";
524 if( platform != NULL ) {
527 for(i=0; i<num_master_platforms; i++) {
528 if( platform == &master_platforms[i] )
532 return CL_INVALID_PLATFORM;
534 switch ( param_name ) {
535 case CL_PLATFORM_PROFILE:
536 string_p = cl_platform_profile;
537 size_string = sizeof(cl_platform_profile);
539 case CL_PLATFORM_VERSION:
540 string_p = cl_platform_version;
541 size_string = sizeof(cl_platform_version);
543 case CL_PLATFORM_NAME:
544 string_p = cl_platform_name;
545 size_string = sizeof(cl_platform_name);
547 case CL_PLATFORM_VENDOR:
548 string_p = cl_platform_vendor;
549 size_string = sizeof(cl_platform_vendor);
551 case CL_PLATFORM_EXTENSIONS:
552 string_p = cl_platform_extensions;
553 size_string = sizeof(cl_platform_extensions);
555 case CL_PLATFORM_ICD_SUFFIX_KHR:
556 string_p = cl_platform_icd_suffix_khr;
557 size_string = sizeof(cl_platform_icd_suffix_khr);
560 return CL_INVALID_VALUE;
563 if( param_value != NULL ) {
564 if( size_string > param_value_size )
565 return CL_INVALID_VALUE;
566 memcpy(param_value, string_p, size_string);
568 if( param_value_size_ret != NULL )
569 *param_value_size_ret = size_string;
573 return ocl_icd_bindings_source
576 def self.generate_get_extension_address_for_platform
578 if( func_name == NULL )
580 struct func_desc const * fn=&function_description[0];
581 int lenfn=strlen(func_name);
583 (strcmp(func_name+lenfn-3, "KHR")==0 || strcmp(func_name+lenfn-3, "EXT")==0)) {
584 while (fn->name != NULL) {
585 if (strcmp(func_name, fn->name)==0)
594 def self.generate_ocl_icd_loader_gen_source
595 skip_funcs = $specific_loader_funcs
596 ocl_icd_loader_gen_source = "/**\n#{$license}\n*/\n"
597 ocl_icd_loader_gen_source += "#include <string.h>\n"
598 ocl_icd_loader_gen_source += "#include \"ocl_icd_loader.h\"\n"
599 ocl_icd_loader_gen_source += "#define DEBUG_OCL_ICD_PROVIDE_DUMP_FIELD\n"
600 ocl_icd_loader_gen_source += "#include \"ocl_icd_debug.h\"\n"
601 $api_entries.each { |func_name, entry|
602 next if skip_funcs.include?(func_name)
603 clean_entry = entry.sub(/(.*\)).*/m,'\1').gsub("/*","").gsub("*/","").gsub("\r","") + "{\n"
604 return_type = entry.match(/CL_API_ENTRY (.*) CL_API_CALL/)[1]
605 parameters = clean_entry.match(/\(.*\)/m)[0][1..-2]
606 parameters.gsub!(/\[.*?\]/,"")
607 parameters.sub!(/\(.*?\*\s*(.*?)\)\s*\(.*?\)/m,'\1')
608 ocl_icd_loader_gen_source += clean_entry.gsub(/\*\[.*?\]/,"* ").gsub(/\[.+?\]/,"")
609 first_parameter = parameters.match(/.*?\,/m)
610 if not first_parameter then
611 first_parameter = parameters.match(/.*/m)[0]
613 first_parameter = first_parameter[0][0..-2]
615 fps = first_parameter.split
616 ocl_icd_loader_gen_source += " debug_trace();\n"
617 ocl_icd_loader_gen_source += generate_get_extension_address_for_platform if func_name == "clGetExtensionFunctionAddressForPlatform"
618 raise "Unsupported data_type #{fps[0]}" if not $cl_data_type_error[fps[0]]
619 ps = parameters.split(",")
620 ps = ps.collect { |p|
622 p = p[-1].gsub("*","")
624 error_handler = lambda {
625 if(ps.include?("errcode_ret")) then
626 ocl_icd_loader_gen_source += " if( errcode_ret != NULL ) {\n";
627 ocl_icd_loader_gen_source += " *errcode_ret = #{$cl_data_type_error[fps[0]]};\n"
628 ocl_icd_loader_gen_source += " }\n"
629 if return_type != "void" then
630 ocl_icd_loader_gen_source += " RETURN(NULL);\n"
632 ocl_icd_loader_gen_source += " return;\n"
634 elsif ($non_standard_error.include?(func_name)) then
635 if return_type != "void" then
636 ocl_icd_loader_gen_source += " RETURN(NULL);\n"
638 ocl_icd_loader_gen_source += " return;\n"
641 if return_type != "void" then
642 ocl_icd_loader_gen_source += " RETURN(#{$cl_data_type_error[fps[0]]});\n" if return_type != "void"
644 ocl_icd_loader_gen_source += " return;\n"
649 if(fps[0] == "cl_platform_id") then
650 ocl_icd_loader_gen_source += " #{fps[1]}=selectPlatformID(#{fps[1]});\n"
652 ocl_icd_loader_gen_source += " if( (struct _#{fps[0]} *)#{fps[1]} == NULL) {\n"
654 ocl_icd_loader_gen_source += " }\n"
655 if return_type != "void" then
656 return_debug="RETURN"
658 return_debug="return"
660 ocl_icd_loader_gen_source += " #{return_debug}(((struct _#{fps[0]} *)#{fps[1]})->dispatch->#{func_name}("
661 ocl_icd_loader_gen_source += ps.join(", ")
662 ocl_icd_loader_gen_source += "));\n"
663 ocl_icd_loader_gen_source += "}\n\n"
665 ocl_icd_loader_gen_source += "#pragma GCC visibility push(hidden)\n\n"
666 skip_funcs = $specific_loader_funcs
667 $api_entries.each { |func_name, entry|
668 #next if func_name.match(/EXT$/)
669 #next if func_name.match(/KHR$/)
670 if (skip_funcs.include?(func_name)) then
671 ocl_icd_loader_gen_source += "extern typeof(#{func_name}) #{func_name}_hid;\n"
673 ocl_icd_loader_gen_source += "typeof(#{func_name}) #{func_name}_hid __attribute__ ((alias (\"#{func_name}\"), visibility(\"hidden\")));\n"
676 ocl_icd_loader_gen_source += "\n\nstruct func_desc const function_description[]= {\n"
677 $api_entries.each { |func_name, entry|
678 #next if func_name.match(/EXT$/)
679 #next if func_name.match(/KHR$/)
680 ocl_icd_loader_gen_source += " {\"#{func_name}\", (void(* const)(void))&#{func_name}_hid },\n"
682 ocl_icd_loader_gen_source += <<EOF
687 void dump_platform(clGEFA_t f, cl_platform_id pid) {
688 debug(D_ALWAYS, "platform @%p: name=field_in_struct [clGetExtensionFunctionAddress(name)/clGetExtensionFunctionAddressForPlatform(name)]", pid);
690 $api_entries_array.each { |entry|
691 e = entry.gsub("\r"," ").gsub("\n"," ").gsub("\t"," ").
692 sub(/.*CL_API_CALL *([^ ()]*)[ ()].*$/m, '\1')
693 ocl_icd_loader_gen_source += " dump_field(pid, f, #{e});\n"
696 ocl_icd_loader_gen_source += <<EOF
700 #pragma GCC visibility pop
703 return ocl_icd_loader_gen_source;
706 def self.generate_from_database(yamlfile)
707 load_database(yamlfile)
708 File.open('ocl_icd.h','w') { |f|
709 f.puts generate_ocl_icd_header
711 File.open('ocl_icd_loader_gen.h','w') { |f|
712 f.puts generate_ocl_icd_loader_header
714 File.open('ocl_icd_loader_gen.map','w') { |f|
715 f.puts generate_ocl_icd_loader_map
717 File.open('ocl_icd_bindings.c','w') { |f|
718 f.puts generate_ocl_icd_bindings_source
720 File.open('ocl_icd_loader_gen.c','w') { |f|
721 f.puts generate_ocl_icd_loader_gen_source
725 ##########################################################
726 ##########################################################
727 # update-database mode
728 def self.savedb(yamlfile)
729 File::open(yamlfile,"w") { |f|
730 f.write($license.gsub(/^/,"# "))
733 # In Intel (OpenCL 1.1):
734 # * clSetCommandQueueProperty(13): nil (deprecated in 1.1)
735 # * clGetGLContextInfoKHR(74): function present with its symbol
737 # * 92: correspond to symbol clGetKernelArgInfo (first abandonned version?)
739 # In nvidia (OpenCL 1.1):
740 # * clGetGLContextInfoKHR(74): function present but no symbol
743 # * only two OpenCL symbols: clGetPlatformInfo(1) and clGetExtensionFunctionAddress(65)
744 # In AMD (OpenCL 1.2):
745 # * clGetPlatformIDs(0): nil (symbol present)
746 # * clGetGLContextInfoKHR(74): function present but no symbol
754 # Not using YAML::dump as:
755 # * keys are not ordered
756 # * strings are badly formatted in new YAML ruby implementation (psych)
757 # * it is very easy to do it ourself
758 #f.write(YAML::dump(api_db))
760 $known_entries.keys.sort.each { |k|
761 f.write("\n#{k}: |-\n ")
762 f.write($api_entries[$known_entries[k]].gsub("\n","\n "))
768 def self.updatedb_from_input(dbfile, inputfile)
770 load_database(dbfile, with_windows=true)
771 doc = YAML::load_file(inputfile)
774 next if $known_entries[i]
775 $known_entries[i]=doc[i]
782 ############################################################
783 ############################################################
784 ############################################################
791 OptionParser.new do |opts|
792 opts.banner = "Usage: cd_generator.rb [options] mode"
794 opts.on("-d", "--database FILE", String, "YAML file (default ocl_interface.yaml)") do |v|
795 options[:database] = v
797 opts.on("-i", "--input FILE", String,
798 "binding between OpenCL functions and entry number (required for update-database)") \
802 opts.on("-s", "--[no-]system-headers",
803 "Look for OpenCL functions in system header files") \
805 options[:"system-headers"] = v
807 opts.on("-m", "--mode [MODE]", [:database, :generate, :"update-database"],
808 "Select mode (database, generate, update-database)") do |m|
813 if !options[:database] then
814 options[:database] = "ocl_interface.yaml"
817 if !options[:mode] then
818 raise "--mode option required"
820 if options[:mode] == :generate then
821 if !options[:"system-headers"] then
822 IcdGenerator.generate_sources(from_headers=false, from_database=true, database=options[:database])
824 IcdGenerator.generate_sources(from_headers=true, from_database=false)
826 elsif options[:mode] == :"update-database" then
827 if !options[:input] then
828 raise "--input option required"
830 IcdGenerator.updatedb_from_input(options[:database], options[:input])
831 elsif options[:mode] == :database then
832 IcdGenerator.generate_from_database(options[:database])
834 raise "Mode must be one of generate, database or update-database not #{options[:mode]}"