opencl_ruby_ffi 1.3.5 → 1.3.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,95 @@
1
+ if RUBY_VERSION.scan(/\d+/).collect(&:to_i).first >= 2
2
+ using OpenCLRefinements
3
+ end
4
+
5
+ module OpenCL
6
+
7
+ # Unofficial kernel profiling extension
8
+ CONTEXT_KERNEL_PROFILING_MODES_COUNT_INTEL = 0x407A
9
+ CONTEXT_KERNEL_PROFILING_MODE_INFO_INTEL = 0x407B
10
+ KERNEL_IL_SYMBOLS_INTEL = 0x407C
11
+ KERNEL_BINARY_PROGRAM_INTEL = 0x407D
12
+ # Unofficial VTune Debug Info extension
13
+ PROGRAM_DEBUG_INFO_INTEL = 0x4100
14
+ PROGRAM_DEBUG_INFO_SIZES_INTEL = 0x4101
15
+ KERNEL_BINARIES_INTEL = 0x4102
16
+ KERNEL_BINARY_SIZES_INTEL = 0x4103
17
+
18
+ class Kernel
19
+ IL_SYMBOLS_INTEL = 0x407C
20
+ BINARY_PROGRAM_INTEL = 0x407D
21
+ BINARIES_INTEL = 0x4102
22
+ BINARY_SIZES_INTEL = 0x4103
23
+
24
+ def binary_program_intel(device = program.devices.first)
25
+ sz = MemoryPointer::new( :size_t )
26
+ begin
27
+ error = OpenCL.clGetKernelWorkGroupInfo(self, device, BINARY_PROGRAM_INTEL, 0, nil, sz)
28
+ error_check(error)
29
+ sz = sz.read_size_t
30
+ bin = MemoryPointer::new(sz)
31
+ error = OpenCL.clGetKernelWorkGroupInfo(self, device, BINARY_PROGRAM_INTEL, sz, bin, nil)
32
+ error_check(error)
33
+ return bin.read_bytes(sz)
34
+ rescue
35
+ error = OpenCL.clGetKernelInfo(self, BINARY_PROGRAM_INTEL, 0, nil, sz)
36
+ error_check(error)
37
+ sz = sz.read_size_t
38
+ bin = MemoryPointer::new(sz)
39
+ error = OpenCL.clGetKernelInfo(self, BINARY_PROGRAM_INTEL, sz, bin, nil)
40
+ error_check(error)
41
+ return bin.read_bytes(sz)
42
+ end
43
+ end
44
+
45
+ get_info_array("Kernel", :size_t, "binary_sizes_intel")
46
+
47
+ def binaries_intel
48
+ sizes = self.binary_sizes_intel
49
+ bin_array = MemoryPointer::new( :pointer, sizes.length )
50
+ total_size = 0
51
+ pointers = []
52
+ sizes.each_with_index { |s, i|
53
+ total_size += s
54
+ pointers[i] = MemoryPointer::new(s)
55
+ bin_array[i].write_pointer(pointers[i])
56
+ }
57
+ error = OpenCL.clGetKernelInfo(self, BINARIES_INTEL, total_size, bin_array, nil)
58
+ error_check(error)
59
+ bins = []
60
+ devs = self.program.devices
61
+ sizes.each_with_index { |s, i|
62
+ bins.push [devs[i], pointers[i].read_bytes(s)]
63
+ }
64
+ return bins
65
+ end
66
+
67
+ end
68
+
69
+ class Program
70
+ DEBUG_INFO_INTEL = 0x4100
71
+ DEBUG_INFO_SIZES_INTEL = 0x4101
72
+
73
+ get_info_array("Program", :size_t, "debug_info_sizes_intel")
74
+
75
+ def debug_info_intel
76
+ sizes = self.debug_info_sizes_intel
77
+ bin_array = MemoryPointer::new( :pointer, sizes.length )
78
+ total_size = 0
79
+ sizes.each_with_index { |s, i|
80
+ total_size += s
81
+ pointers[i] = MemoryPointer::new(s)
82
+ bin_array[i].write_pointer(pointers[i])
83
+ }
84
+ error = OpenCL.clGetProgramInfo(self, DEBUG_INFO_INTEL, total_size, bin_array, nil)
85
+ error_check(error)
86
+ bins = []
87
+ devs = self.devices
88
+ sizes.each_with_index { |s, i|
89
+ bins.push [devs[i], pointers[i].read_bytes(s)]
90
+ }
91
+ return bins
92
+ end
93
+ end
94
+
95
+ end
@@ -0,0 +1,119 @@
1
+ using OpenCLRefinements if RUBY_VERSION.scan(/\d+/).collect(&:to_i).first >= 2
2
+
3
+ module OpenCL
4
+
5
+ UUID_SIZE_KHR = 16
6
+ LUID_SIZE_KHR = 8
7
+
8
+ DEVICE_UUID_KHR = 0x106A
9
+ DRIVER_UUID_KHR = 0x106B
10
+ DEVICE_LUID_VALID_KHR = 0x106C
11
+ DEVICE_LUID_KHR = 0x106D
12
+ DEVICE_NODE_MASK_KHR = 0x106E
13
+
14
+ class UUID < Struct
15
+ layout :id, [ OpenCL.find_type(:cl_uchar), UUID_SIZE_KHR ]
16
+ def to_s
17
+ a = self[:id].to_a
18
+ s = ""
19
+ s << "%02x" % a[15]
20
+ s << "%02x" % a[14]
21
+ s << "%02x" % a[13]
22
+ s << "%02x" % a[12]
23
+ s << "-"
24
+ s << "%02x" % a[11]
25
+ s << "%02x" % a[10]
26
+ s << "-"
27
+ s << "%02x" % a[9]
28
+ s << "%02x" % a[8]
29
+ s << "-"
30
+ s << "%02x" % a[7]
31
+ s << "%02x" % a[6]
32
+ s << "-"
33
+ s << "%02x" % a[5]
34
+ s << "%02x" % a[4]
35
+ s << "%02x" % a[3]
36
+ s << "%02x" % a[2]
37
+ s << "%02x" % a[1]
38
+ s << "%02x" % a[0]
39
+ end
40
+
41
+ def self.from_string(uuid)
42
+ new.from_string(uuid)
43
+ end
44
+
45
+ def from_string(uuid)
46
+ m = uuid.match(/(\h\h)(\h\h)(\h\h)(\h\h)-(\h\h)(\h\h)-(\h\h)(\h\h)-(\h\h)(\h\h)-(\h\h)(\h\h)(\h\h)(\h\h)(\h\h)(\h\h)/)
47
+ raise "invalid format" unless m
48
+ UUID_SIZE_KHR.times { |i|
49
+ self[:id][UUID_SIZE_KHR-1-i] = m[i+1].to_i(16)
50
+ }
51
+ self
52
+ end
53
+ end
54
+
55
+ class LUID < Struct
56
+ layout :id, [ OpenCL.find_type(:cl_uchar), LUID_SIZE_KHR ]
57
+ def to_s
58
+ a = self[:id].to_a
59
+ s = ""
60
+ s << "%02x" % a[7]
61
+ s << "%02x" % a[6]
62
+ s << "%02x" % a[5]
63
+ s << "%02x" % a[4]
64
+ s << "%02x" % a[3]
65
+ s << "%02x" % a[2]
66
+ s << "%02x" % a[1]
67
+ s << "%02x" % a[0]
68
+ end
69
+
70
+ def self.from_string(uuid)
71
+ new.from_string(uuid)
72
+ end
73
+
74
+ def from_string(uuid)
75
+ m = uuid.match(/(\h\h)(\h\h)(\h\h)(\h\h)(\h\h)(\h\h)(\h\h)(\h\h)/)
76
+ raise "invalid format" unless m
77
+ LUID_SIZE_KHR.times { |i|
78
+ self[:id][LUID_SIZE_KHR-1-i] = m[i+1].to_i(16)
79
+ }
80
+ self
81
+ end
82
+ end
83
+
84
+ class Device
85
+ UUID_KHR = 0x106A
86
+ LUID_VALID_KHR = 0x106C
87
+ LUID_KHR = 0x106D
88
+ NODE_MASK_KHR = 0x106E
89
+
90
+ module KHRDeviceUUID
91
+ extend InnerGenerator
92
+ get_info("Device", :cl_bool, "luid_valid_khr")
93
+ get_info("Device", :cl_uint, "node_mask_khr")
94
+
95
+ def uuid_khr
96
+ id = UUID.new
97
+ error = OpenCL.clGetDeviceInfo( self, UUID_KHR, UUID_SIZE_KHR, id, nil)
98
+ error_check(error)
99
+ return id
100
+ end
101
+
102
+ def driver_uuid_khr
103
+ id = UUID.new
104
+ error = OpenCL.clGetDeviceInfo( self, DRIVER_UUID_KHR, UUID_SIZE_KHR, id, nil)
105
+ error_check(error)
106
+ return id
107
+ end
108
+
109
+ def luid_khr
110
+ id = LUID.new
111
+ error = OpenCL.clGetDeviceInfo( self, LUID_KHR, LUID_SIZE_KHR, id, nil)
112
+ error_check(error)
113
+ return id
114
+ end
115
+ end
116
+ register_extension( :cl_khr_device_uuid, KHRDeviceUUID, "extensions.include?(\"cl_khr_device_uuid\")" )
117
+ end
118
+
119
+ end
@@ -35,7 +35,7 @@ module OpenCL
35
35
  class Union < FFI::Union
36
36
  end
37
37
 
38
- @@callbacks = []
38
+ @@callbacks = {}
39
39
 
40
40
  # Maps the :cl_image_fomat type of OpenCL
41
41
  class ImageFormat < Struct
@@ -47,13 +47,13 @@ module OpenCL
47
47
  end
48
48
 
49
49
  # Creates a new ImageFormat from an image channel order and data type
50
- def initialize( image_channel_order, image_channel_data_type = nil )
51
- if image_channel_order.is_a?(FFI::Pointer) and image_channel_data_type.nil? then
50
+ def initialize( image_channel_order = nil, image_channel_data_type = nil )
51
+ if image_channel_order.is_a?(FFI::Pointer) then
52
52
  super(image_channel_order)
53
53
  else
54
54
  super()
55
- self[:image_channel_order] = image_channel_order
56
- self[:image_channel_data_type] = image_channel_data_type
55
+ self[:image_channel_order] = image_channel_order if image_channel_order
56
+ self[:image_channel_data_type] = image_channel_data_type if image_channel_data_type
57
57
  end
58
58
  end
59
59
 
@@ -98,18 +98,22 @@ module OpenCL
98
98
  :buffer, Mem.ptr
99
99
 
100
100
  # Creates anew ImageDesc using the values provided by the user
101
- def initialize( image_type, image_width, image_height, image_depth, image_array_size, image_row_pitch, image_slice_pitch, num_mip_levels, num_samples, buffer )
102
- super()
103
- self[:image_type] = image_type
104
- self[:image_width] = image_width
105
- self[:image_height] = image_height
106
- self[:image_depth] = image_depth
107
- self[:image_array_size] = image_array_size
108
- self[:image_row_pitch] = image_row_pitch
109
- self[:image_slice_pitch] = image_slice_pitch
110
- self[:num_mip_levels] = num_mip_levels
111
- self[:num_samples] = num_samples
112
- self[:buffer] = buffer
101
+ def initialize( image_type = nil, image_width = nil, image_height = nil, image_depth = nil, image_array_size = nil, image_row_pitch = nil, image_slice_pitch = nil, num_mip_levels = nil, num_samples = nil, buffer = nil )
102
+ if (image_type.is_a?(FFI::Pointer))
103
+ super(image_type)
104
+ else
105
+ super()
106
+ self[:image_type] = image_type if image_type
107
+ self[:image_width] = image_width if image_width
108
+ self[:image_height] = image_height if image_height
109
+ self[:image_depth] = image_depth if image_depth
110
+ self[:image_array_size] = image_array_size if image_array_size
111
+ self[:image_row_pitch] = image_row_pitch if image_row_pitch
112
+ self[:image_slice_pitch] = image_slice_pitch if image_slice_pitch
113
+ self[:num_mip_levels] = num_mip_levels if num_mip_levels
114
+ self[:num_samples] = num_samples if num_samples
115
+ self[:buffer] = buffer if buffer
116
+ end
113
117
  end
114
118
  end
115
119
 
@@ -119,10 +123,84 @@ module OpenCL
119
123
  :size, :size_t
120
124
 
121
125
  # Creates a new BufferRegion using the value provided by the user
122
- def initialize( origin, sz )
123
- super()
124
- self[:origin] = origin
125
- self[:size] = sz
126
+ def initialize( origin = nil, sz = nil )
127
+ if (origin.is_a?(FFI::Pointer))
128
+ super(origin)
129
+ else
130
+ super()
131
+ self[:origin] = origin if origin
132
+ self[:size] = sz if sz
133
+ end
134
+ end
135
+ end
136
+
137
+ class Version
138
+ include Comparable
139
+ MAJOR_BITS = 10
140
+ MINOR_BITS = 10
141
+ PATCH_BITS = 12
142
+ MAJOR_MASK = (1 << MAJOR_BITS) - 1
143
+ MINOR_MASK = (1 << MINOR_BITS) - 1
144
+ PATCH_MASK = (1 << PATCH_BITS) - 1
145
+
146
+ attr_reader :major, :minor, :patch
147
+ def initialize(major, minor = 0, patch = 0)
148
+ @major = major
149
+ @minor = minor
150
+ @patch = patch
151
+ end
152
+
153
+ def to_int
154
+ Version.make(@major, @minor, @patch)
155
+ end
156
+ alias to_i to_int
157
+
158
+ def <=>(other)
159
+ res = (@major <=> other.major)
160
+ res = (@minor <=> other.minor) if res == 0
161
+ res = (@patch <=> other.patch) if res == 0
162
+ res
163
+ end
164
+
165
+ def to_s
166
+ "#{@major}.#{@minor}.#{@patch}"
167
+ end
168
+
169
+ def self.major(v)
170
+ v >> (MINOR_BITS + PATCH_BITS)
171
+ end
172
+
173
+ def self.minor(v)
174
+ (v >> (PATCH_BITS)) & MINOR_MASK
175
+ end
176
+
177
+ def self.patch(v)
178
+ v & PATCH_MASK
179
+ end
180
+
181
+ def self.make(major, minor = 0, patch = 0)
182
+ ((major & MAJOR_MASK) << (MINOR_BITS + PATCH_BITS)) +
183
+ ((minor & MINOR_MASK) << PATCH_BITS) +
184
+ (patch & PATCH_MASK)
185
+ end
186
+
187
+ def self.from_int(v)
188
+ self.new(major(v), minor(v), patch(v))
189
+ end
190
+ end
191
+
192
+ # Maps the :cl_name_version type of OpenCL
193
+ class NameVersion < Struct
194
+ MAX_NAME_SIZE = 64
195
+ layout :version, :cl_version,
196
+ :name, [:char, MAX_NAME_SIZE]
197
+
198
+ def version
199
+ Version.from_int(self[:version])
200
+ end
201
+
202
+ def name
203
+ self[:name].to_s
126
204
  end
127
205
  end
128
206
 
@@ -169,7 +247,7 @@ module OpenCL
169
247
  end
170
248
  return properties
171
249
  end
172
-
250
+
173
251
  # Extracts the origin_symbol and region_symbol named options for image from the given hash. Returns the read (or detemined suitable) origin and region in a tuple
174
252
  def get_origin_region( image, options, origin_symbol, region_symbol )
175
253
  origin = MemoryPointer::new( :size_t, 3 )
@@ -214,6 +292,19 @@ module OpenCL
214
292
  return properties
215
293
  end
216
294
 
295
+ # EXtracts the :properties named option (for a Mem) from the hash given and returns the properties values
296
+ def get_mem_properties( options )
297
+ properties = nil
298
+ if options[:properties] then
299
+ properties = MemoryPointer::new( :cl_mem_properties, options[:properties].length + 1 )
300
+ options[:properties].each_with_index { |e,i|
301
+ properties[i].write_cl_mem_properties(e.respond_to?(:to_ptr) ? e : e.to_i)
302
+ }
303
+ properties[options[:properties].length].write_cl_mem_properties(0)
304
+ end
305
+ return properties
306
+ end
307
+
217
308
  # Extracts the :device_list named option from the hash given and returns [ number of devices, an Pointer to the list of Device or nil ]
218
309
  def get_device_list( options )
219
310
  devices = options[:device_list]
@@ -248,6 +339,7 @@ module OpenCL
248
339
  :cl_command_queue_properties => CommandQueue::Properties,
249
340
  :cl_device_affinity_domain => Device::AffinityDomain,
250
341
  :cl_device_svm_capabilities => Device::SVMCapabilities,
342
+ :cl_device_atomic_capabilities => Device::AtomicCapabilities,
251
343
  :cl_channel_order => ChannelOrder,
252
344
  :cl_channel_type => ChannelType,
253
345
  :cl_mem_flags => Mem::Flags,
@@ -287,26 +379,43 @@ module OpenCL
287
379
  module ExtensionInnerGenerator
288
380
 
289
381
  private
290
- # Generates a new method for klass that use the given clGetKlassInfo on the object platform, to read an info of the given type. The info queried is specified by name.
291
- # @param [String] klass the property is to be found
292
- # @param [Symbol] type of the property
293
- # @param [String] name of the property
294
- # @!macro [attach] get_info
382
+
383
+ # @!macro [attach] get_info_ext
295
384
  # @!method $3
296
385
  # Returns the OpenCL::$1::$3 info
297
386
  # @return $2
298
- def get_info_ext(klass, type, name, function)
299
- klass_name = klass
300
- klass_name = "MemObject" if klass == "Mem"
387
+ def get_info_ext(klass, type, name, function, memoizable = false)
388
+ if memoizable
301
389
  s = <<EOF
302
390
  def #{name.downcase}
303
- f = platform.get_extension_function("#{function}", :cl_int, [#{klass_name}, :cl_uint, :size_t, :pointer, :pointer])
391
+ @_#{name.downcase} ||= begin
392
+ f = platform.get_extension_function("#{function}", :cl_int, [#{klass}, :cl_uint, :size_t, :pointer, :pointer])
393
+ error_check(OpenCL::INVALID_OPERATION) unless f
394
+
395
+ ptr1 = MemoryPointer::new(:size_t, 1)
396
+ error = f.call(self, #{klass}::#{name.upcase}, 0, nil, ptr1)
397
+ error_check(error)
398
+ ptr2 = MemoryPointer::new(ptr1.read_size_t)
399
+ error = f.call(self, #{klass}::#{name.upcase}, ptr1.read_size_t, ptr2, nil)
400
+ error_check(error)
401
+ if(convert_type(:#{type})) then
402
+ convert_type(:#{type})::new(ptr2.read_#{type})
403
+ else
404
+ ptr2.read_#{type}
405
+ end
406
+ end
407
+ end
408
+ EOF
409
+ else
410
+ s = <<EOF
411
+ def #{name.downcase}
412
+ f = platform.get_extension_function("#{function}", :cl_int, [#{klass}, :cl_uint, :size_t, :pointer, :pointer])
304
413
  error_check(OpenCL::INVALID_OPERATION) unless f
305
414
 
306
- ptr1 = MemoryPointer::new( :size_t, 1)
415
+ ptr1 = MemoryPointer::new(:size_t, 1)
307
416
  error = f.call(self, #{klass}::#{name.upcase}, 0, nil, ptr1)
308
417
  error_check(error)
309
- ptr2 = MemoryPointer::new( ptr1.read_size_t )
418
+ ptr2 = MemoryPointer::new(ptr1.read_size_t)
310
419
  error = f.call(self, #{klass}::#{name.upcase}, ptr1.read_size_t, ptr2, nil)
311
420
  error_check(error)
312
421
  if(convert_type(:#{type})) then
@@ -316,6 +425,7 @@ module OpenCL
316
425
  end
317
426
  end
318
427
  EOF
428
+ end
319
429
  if type == :cl_bool then
320
430
  s += <<EOF
321
431
  def #{name.downcase}?
@@ -326,29 +436,46 @@ EOF
326
436
  module_eval s
327
437
  end
328
438
 
329
- # Generates a new method for klass that use the apropriate clGetKlassInfo, to read an Array of element of the given type. The info queried is specified by name.
330
- # @param [String] klass the property is to be found
331
- # @param [Symbol] type of the property
332
- # @param [String] name of the property
333
- # @!macro [attach] get_info_array
439
+ # @!macro [attach] get_info_array_ext
334
440
  # @!method $3
335
441
  # Returns the OpenCL::$1::$3 info
336
442
  # @return an Array of $2
337
- def get_info_array_ext(klass, type, name, function)
338
- klass_name = klass
339
- klass_name = "MemObject" if klass == "Mem"
443
+ def get_info_array_ext(klass, type, name, function, memoizable = false)
444
+ if memoizable
340
445
  s = <<EOF
341
446
  def #{name.downcase}
342
- f = platform.get_extension_function("#{function}", :cl_int, [:cl_uint, :size_t, :pointer, :pointer])
447
+ @_#{name.downcase} ||= begin
448
+ f = platform.get_extension_function("#{function}", :cl_int, [#{klass}, :cl_uint, :size_t, :pointer, :pointer])
449
+ error_check(OpenCL::INVALID_OPERATION) unless f
450
+
451
+ ptr1 = MemoryPointer::new(:size_t, 1)
452
+ error = f.call(self, #{klass}::#{name.upcase}, 0, nil, ptr1)
453
+ error_check(error)
454
+ ptr2 = MemoryPointer::new(ptr1.read_size_t)
455
+ error = f.call(self, #{klass}::#{name.upcase}, ptr1.read_size_t, ptr2, nil)
456
+ error_check(error)
457
+ arr = ptr2.get_array_of_#{type}(0, ptr1.read_size_t / OpenCL.find_type(:#{type}).size)
458
+ if(convert_type(:#{type})) then
459
+ arr.collect { |e| convert_type(:#{type})::new(e) }
460
+ else
461
+ arr
462
+ end
463
+ end
464
+ end
465
+ EOF
466
+ else
467
+ s = <<EOF
468
+ def #{name.downcase}
469
+ f = platform.get_extension_function("#{function}", :cl_int, [#{klass}, :cl_uint, :size_t, :pointer, :pointer])
343
470
  error_check(OpenCL::INVALID_OPERATION) unless f
344
471
 
345
- ptr1 = MemoryPointer::new( :size_t, 1)
472
+ ptr1 = MemoryPointer::new(:size_t, 1)
346
473
  error = f.call(self, #{klass}::#{name.upcase}, 0, nil, ptr1)
347
474
  error_check(error)
348
- ptr2 = MemoryPointer::new( ptr1.read_size_t )
475
+ ptr2 = MemoryPointer::new(ptr1.read_size_t)
349
476
  error = f.call(self, #{klass}::#{name.upcase}, ptr1.read_size_t, ptr2, nil)
350
477
  error_check(error)
351
- arr = ptr2.get_array_of_#{type}(0, ptr1.read_size_t/ OpenCL.find_type(:#{type}).size)
478
+ arr = ptr2.get_array_of_#{type}(0, ptr1.read_size_t / OpenCL.find_type(:#{type}).size)
352
479
  if(convert_type(:#{type})) then
353
480
  return arr.collect { |e| convert_type(:#{type})::new(e) }
354
481
  else
@@ -356,6 +483,7 @@ EOF
356
483
  end
357
484
  end
358
485
  EOF
486
+ end
359
487
  module_eval s
360
488
  end
361
489
 
@@ -366,23 +494,38 @@ EOF
366
494
 
367
495
  private
368
496
 
369
- # Generates a new method for klass that use the apropriate clGetKlassInfo, to read an info of the given type. The info queried is specified by name.
370
- # @param [String] klass the property is to be found
371
- # @param [Symbol] type of the property
372
- # @param [String] name of the property
373
497
  # @!macro [attach] get_info
374
498
  # @!method $3
375
499
  # Returns the OpenCL::$1::$3 info
376
500
  # @return $2
377
- def get_info(klass, type, name)
501
+ def get_info(klass, type, name, memoizable = false)
378
502
  klass_name = klass
379
503
  klass_name = "MemObject" if klass == "Mem"
504
+ if memoizable
505
+ s = <<EOF
506
+ def #{name.downcase}
507
+ @_#{name.downcase} ||= begin
508
+ ptr1 = MemoryPointer::new(:size_t, 1)
509
+ error = OpenCL.clGet#{klass_name}Info(self, #{klass}::#{name.upcase}, 0, nil, ptr1)
510
+ error_check(error)
511
+ ptr2 = MemoryPointer::new(ptr1.read_size_t)
512
+ error = OpenCL.clGet#{klass_name}Info(self, #{klass}::#{name.upcase}, ptr1.read_size_t, ptr2, nil)
513
+ error_check(error)
514
+ if(convert_type(:#{type})) then
515
+ convert_type(:#{type})::new(ptr2.read_#{type})
516
+ else
517
+ ptr2.read_#{type}
518
+ end
519
+ end
520
+ end
521
+ EOF
522
+ else
380
523
  s = <<EOF
381
524
  def #{name.downcase}
382
- ptr1 = MemoryPointer::new( :size_t, 1)
525
+ ptr1 = MemoryPointer::new(:size_t, 1)
383
526
  error = OpenCL.clGet#{klass_name}Info(self, #{klass}::#{name.upcase}, 0, nil, ptr1)
384
527
  error_check(error)
385
- ptr2 = MemoryPointer::new( ptr1.read_size_t )
528
+ ptr2 = MemoryPointer::new(ptr1.read_size_t)
386
529
  error = OpenCL.clGet#{klass_name}Info(self, #{klass}::#{name.upcase}, ptr1.read_size_t, ptr2, nil)
387
530
  error_check(error)
388
531
  if(convert_type(:#{type})) then
@@ -392,6 +535,7 @@ EOF
392
535
  end
393
536
  end
394
537
  EOF
538
+ end
395
539
  if type == :cl_bool then
396
540
  s += <<EOF
397
541
  def #{name.downcase}?
@@ -402,26 +546,42 @@ EOF
402
546
  module_eval s
403
547
  end
404
548
 
405
- # Generates a new method for klass that use the apropriate clGetKlassInfo, to read an Array of element of the given type. The info queried is specified by name.
406
- # @param [String] klass the property is to be found
407
- # @param [Symbol] type of the property
408
- # @param [String] name of the property
409
549
  # @!macro [attach] get_info_array
410
550
  # @!method $3
411
551
  # Returns the OpenCL::$1::$3 info
412
552
  # @return an Array of $2
413
- def get_info_array(klass, type, name)
553
+ def get_info_array(klass, type, name, memoizable = false)
414
554
  klass_name = klass
415
555
  klass_name = "MemObject" if klass == "Mem"
416
- s = <<EOF
556
+ if memoizable
557
+ s = <<EOF
417
558
  def #{name.downcase}
418
- ptr1 = MemoryPointer::new( :size_t, 1)
559
+ @_#{name.downcase} ||= begin
560
+ ptr1 = MemoryPointer::new(:size_t, 1)
561
+ error = OpenCL.clGet#{klass_name}Info(self, #{klass}::#{name.upcase}, 0, nil, ptr1)
562
+ error_check(error)
563
+ ptr2 = MemoryPointer::new(ptr1.read_size_t)
564
+ error = OpenCL.clGet#{klass_name}Info(self, #{klass}::#{name.upcase}, ptr1.read_size_t, ptr2, nil)
565
+ error_check(error)
566
+ arr = ptr2.get_array_of_#{type}(0, ptr1.read_size_t / OpenCL.find_type(:#{type}).size)
567
+ if(convert_type(:#{type})) then
568
+ arr.collect { |e| convert_type(:#{type})::new(e) }
569
+ else
570
+ arr
571
+ end
572
+ end
573
+ end
574
+ EOF
575
+ else
576
+ s = <<EOF
577
+ def #{name.downcase}
578
+ ptr1 = MemoryPointer::new(:size_t, 1)
419
579
  error = OpenCL.clGet#{klass_name}Info(self, #{klass}::#{name.upcase}, 0, nil, ptr1)
420
580
  error_check(error)
421
- ptr2 = MemoryPointer::new( ptr1.read_size_t )
581
+ ptr2 = MemoryPointer::new(ptr1.read_size_t)
422
582
  error = OpenCL.clGet#{klass_name}Info(self, #{klass}::#{name.upcase}, ptr1.read_size_t, ptr2, nil)
423
583
  error_check(error)
424
- arr = ptr2.get_array_of_#{type}(0, ptr1.read_size_t/ OpenCL.find_type(:#{type}).size)
584
+ arr = ptr2.get_array_of_#{type}(0, ptr1.read_size_t / OpenCL.find_type(:#{type}).size)
425
585
  if(convert_type(:#{type})) then
426
586
  return arr.collect { |e| convert_type(:#{type})::new(e) }
427
587
  else
@@ -429,6 +589,7 @@ EOF
429
589
  end
430
590
  end
431
591
  EOF
592
+ end
432
593
  module_eval s
433
594
  end
434
595