opencl-bindings 1.0.0pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ChangeLog +43 -0
- data/LICENSE.txt +21 -0
- data/README.md +84 -0
- data/lib/opencl.rb +1347 -0
- data/lib/opencl_ext.rb +311 -0
- data/lib/opencl_gl.rb +119 -0
- data/lib/opencl_gl_ext.rb +115 -0
- data/sample/hello.cl +19 -0
- data/sample/hello.rb +69 -0
- data/sample/hello_clu.rb +59 -0
- data/sample/util/clu.rb +1470 -0
- metadata +56 -0
data/sample/hello.cl
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#pragma OPENCL EXTENSION cl_khr_byte_addressable_store : enable
|
2
|
+
/* Ref.: http://www.fixstars.com/en/opencl/book/sample/ */
|
3
|
+
__kernel void hello(__global char* string)
|
4
|
+
{
|
5
|
+
string[0] = 'H';
|
6
|
+
string[1] = 'e';
|
7
|
+
string[2] = 'l';
|
8
|
+
string[3] = 'l';
|
9
|
+
string[4] = 'o';
|
10
|
+
string[5] = ',';
|
11
|
+
string[6] = ' ';
|
12
|
+
string[7] = 'W';
|
13
|
+
string[8] = 'o';
|
14
|
+
string[9] = 'r';
|
15
|
+
string[10] = 'l';
|
16
|
+
string[11] = 'd';
|
17
|
+
string[12] = '!';
|
18
|
+
string[13] = '\0';
|
19
|
+
}
|
data/sample/hello.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# An example using raw OpenCL API.
|
2
|
+
# For more samples, visit https://github.com/vaiorabbit/ruby-opencl/tree/master/sample .
|
3
|
+
#
|
4
|
+
# Usage : $ ruby hello.rb
|
5
|
+
# Hello, World!
|
6
|
+
#
|
7
|
+
# Ref.: http://www.fixstars.com/en/opencl/book/sample/
|
8
|
+
|
9
|
+
require_relative '../lib/opencl'
|
10
|
+
|
11
|
+
# Load DLL
|
12
|
+
begin
|
13
|
+
OpenCL.load_lib('c:/Windows/System32/OpenCL.dll') # For Windows
|
14
|
+
rescue
|
15
|
+
OpenCL.load_lib('/System/Library/Frameworks/OpenCL.framework/OpenCL') # For Mac OS X
|
16
|
+
end
|
17
|
+
include OpenCL
|
18
|
+
|
19
|
+
# Platform
|
20
|
+
cl_platforms_buf = ' ' * 4
|
21
|
+
cl_platforms_count_buf = ' ' * 4
|
22
|
+
clGetPlatformIDs(1, cl_platforms_buf, cl_platforms_count_buf)
|
23
|
+
cl_platform = cl_platforms_buf.unpack("L")[0]
|
24
|
+
|
25
|
+
# Devices
|
26
|
+
cl_devices_buf_writable_count = 32
|
27
|
+
cl_devices_buf = ' ' * 4 * cl_devices_buf_writable_count
|
28
|
+
cl_devices_entry_count_buf = ' ' * 4
|
29
|
+
|
30
|
+
clGetDeviceIDs(cl_platform, CL_DEVICE_TYPE_DEFAULT, cl_devices_buf_writable_count, cl_devices_buf, cl_devices_entry_count_buf)
|
31
|
+
cl_devices_entry_count = cl_devices_entry_count_buf.unpack("L")[0]
|
32
|
+
cl_device_ids = cl_devices_buf.unpack("Q#{cl_devices_entry_count}")
|
33
|
+
|
34
|
+
# Context
|
35
|
+
errcode_ret_buf = ' ' * 4
|
36
|
+
cl_ctx = OpenCL.clCreateContext(nil, 1, cl_devices_buf, nil, nil, errcode_ret_buf)
|
37
|
+
|
38
|
+
# Command Queues
|
39
|
+
cl_cq = clCreateCommandQueue(cl_ctx, cl_device_ids[0], 0, errcode_ret_buf)
|
40
|
+
|
41
|
+
# Memory Buffer
|
42
|
+
MEM_SIZE = 128
|
43
|
+
cl_memobj = clCreateBuffer(cl_ctx, CL_MEM_READ_WRITE, MEM_SIZE * Fiddle:: SIZEOF_CHAR, nil, errcode_ret_buf)
|
44
|
+
|
45
|
+
# Program
|
46
|
+
source_str = File.read("hello.cl")
|
47
|
+
cl_prog = clCreateProgramWithSource(cl_ctx, 1, [source_str].pack("p"), [source_str.bytesize].pack("Q"), errcode_ret_buf)
|
48
|
+
clBuildProgram(cl_prog, 1, [cl_device_ids[0]].pack("Q"), nil, nil, nil)
|
49
|
+
|
50
|
+
# Kernel
|
51
|
+
cl_kern = clCreateKernel(cl_prog, "hello", errcode_ret_buf)
|
52
|
+
|
53
|
+
# Execute
|
54
|
+
clSetKernelArg(cl_kern, 0, Fiddle::SIZEOF_VOIDP, [cl_memobj.to_i].pack("Q"))
|
55
|
+
clEnqueueTask(cl_cq, cl_kern, 0, nil, nil)
|
56
|
+
|
57
|
+
# Result
|
58
|
+
result_buf = ' ' * MEM_SIZE
|
59
|
+
clEnqueueReadBuffer(cl_cq, cl_memobj, CL_TRUE, 0, MEM_SIZE * Fiddle::SIZEOF_CHAR, result_buf, 0, nil, nil)
|
60
|
+
puts result_buf # => Hello, World!
|
61
|
+
|
62
|
+
# End
|
63
|
+
clFlush(cl_cq)
|
64
|
+
clFinish(cl_cq)
|
65
|
+
clReleaseKernel(cl_kern)
|
66
|
+
clReleaseProgram(cl_prog)
|
67
|
+
clReleaseMemObject(cl_memobj)
|
68
|
+
clReleaseCommandQueue(cl_cq)
|
69
|
+
clReleaseContext(cl_ctx)
|
data/sample/hello_clu.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# An example using simple wrapper.
|
2
|
+
# For more samples, visit https://github.com/vaiorabbit/ruby-opencl/tree/master/sample .
|
3
|
+
#
|
4
|
+
# Usage : $ ruby hello_clu.rb
|
5
|
+
# Hello, World!
|
6
|
+
#
|
7
|
+
# Ref.: http://www.fixstars.com/en/opencl/book/sample/
|
8
|
+
|
9
|
+
require_relative 'util/clu'
|
10
|
+
|
11
|
+
# Load DLL
|
12
|
+
begin
|
13
|
+
OpenCL.load_lib('c:/Windows/System32/OpenCL.dll') # For Windows
|
14
|
+
rescue
|
15
|
+
OpenCL.load_lib('/System/Library/Frameworks/OpenCL.framework/OpenCL') # For Mac OS X
|
16
|
+
end
|
17
|
+
include OpenCL
|
18
|
+
|
19
|
+
# Platform
|
20
|
+
clu_platform = CLUPlatform.new
|
21
|
+
|
22
|
+
# Devices
|
23
|
+
clu_device = CLUDevice.new(clu_platform.platforms[0], CL_DEVICE_TYPE_DEFAULT)
|
24
|
+
|
25
|
+
# Context
|
26
|
+
clu_ctx = CLUContext.newContext(nil, clu_device.devices)
|
27
|
+
|
28
|
+
# Command Queues
|
29
|
+
clu_cq = CLUCommandQueue.newCommandQueue(clu_ctx.context, clu_device.devices[0])
|
30
|
+
|
31
|
+
# Memory Buffer
|
32
|
+
MEM_SIZE = 128
|
33
|
+
clu_memobj = CLUMemory.newBuffer(clu_ctx.context, CL_MEM_READ_WRITE, MEM_SIZE * Fiddle:: SIZEOF_CHAR)
|
34
|
+
|
35
|
+
# Program
|
36
|
+
source_str = File.read("hello.cl")
|
37
|
+
clu_prog = CLUProgram.newProgramWithSource(clu_ctx.context, [source_str])
|
38
|
+
clu_prog.buildProgram(clu_device.devices)
|
39
|
+
|
40
|
+
# Kernel
|
41
|
+
clu_kern = CLUKernel.newKernel(clu_prog.program, "hello")
|
42
|
+
|
43
|
+
# Execute
|
44
|
+
clu_kern.setKernelArg(0, Fiddle::TYPE_VOIDP, [clu_memobj.mem.to_i])
|
45
|
+
clu_cq.enqueueTask(clu_kern.kernel)
|
46
|
+
|
47
|
+
# Result
|
48
|
+
result_buf = ' ' * MEM_SIZE
|
49
|
+
clu_cq.enqueueReadBuffer(clu_memobj.mem, CL_TRUE, 0, MEM_SIZE * Fiddle::SIZEOF_CHAR, result_buf)
|
50
|
+
puts result_buf # => Hello, World!
|
51
|
+
|
52
|
+
# End
|
53
|
+
clu_cq.flush
|
54
|
+
clu_cq.finish
|
55
|
+
clu_kern.releaseKernel
|
56
|
+
clu_prog.releaseProgram
|
57
|
+
clu_memobj.releaseMemObject
|
58
|
+
clu_cq.releaseCommandQueue
|
59
|
+
clu_ctx.releaseContext
|
data/sample/util/clu.rb
ADDED
@@ -0,0 +1,1470 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
require_relative '../../lib/opencl'
|
3
|
+
require_relative '../../lib/opencl_ext'
|
4
|
+
require_relative '../../lib/opencl_gl'
|
5
|
+
require_relative '../../lib/opencl_gl_ext'
|
6
|
+
|
7
|
+
################################################################################
|
8
|
+
|
9
|
+
class CLUPlatform
|
10
|
+
def initialize
|
11
|
+
@platforms = nil # Array of cl_platform_id
|
12
|
+
end
|
13
|
+
|
14
|
+
def platforms
|
15
|
+
if @platforms == nil
|
16
|
+
getPlatformIDs()
|
17
|
+
end
|
18
|
+
return @platforms
|
19
|
+
end
|
20
|
+
|
21
|
+
def getPlatformIDs(error_info: nil)
|
22
|
+
# cl_uint : num_entries
|
23
|
+
# cl_platform_id* : platforms
|
24
|
+
# cl_uint* : num_platforms
|
25
|
+
num_entries = 32
|
26
|
+
platforms_buf = ' ' * 8 * num_entries
|
27
|
+
platforms_count_buf = ' ' * 4
|
28
|
+
|
29
|
+
err = OpenCL.clGetPlatformIDs(num_entries, platforms_buf, platforms_count_buf)
|
30
|
+
error_info << err if error_info != nil
|
31
|
+
|
32
|
+
num_platforms = platforms_count_buf.unpack("L")[0]
|
33
|
+
@platforms = platforms_buf.unpack("Q#{num_platforms}")
|
34
|
+
|
35
|
+
return @platforms
|
36
|
+
end
|
37
|
+
|
38
|
+
# cl_platform_id : platform
|
39
|
+
# cl_platform_info : param_name
|
40
|
+
def getPlatformInfo(param_name, platform: @platforms[0], error_info: nil)
|
41
|
+
param_value_buf_size = 1024
|
42
|
+
param_value_buf = ' ' * param_value_buf_size
|
43
|
+
param_value_size_ret_buf = ' ' * 4
|
44
|
+
|
45
|
+
err = OpenCL.clGetPlatformInfo(platform, param_name, param_value_buf_size, param_value_buf, param_value_size_ret_buf)
|
46
|
+
error_info << err if error_info != nil
|
47
|
+
|
48
|
+
param_value_size_ret = param_value_size_ret_buf.unpack("L")[0]
|
49
|
+
|
50
|
+
return param_value_buf[0...(param_value_size_ret-1)]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
################################################################################
|
55
|
+
|
56
|
+
class CLUDevice
|
57
|
+
attr_reader :devices # Array of cl_device_id
|
58
|
+
|
59
|
+
# cl_platform_id : platform
|
60
|
+
# cl_device_type : device_type
|
61
|
+
def initialize(platform = nil, device_type = OpenCL::CL_DEVICE_TYPE_DEFAULT)
|
62
|
+
@devices = nil
|
63
|
+
if platform != nil
|
64
|
+
getDeviceIDs(platform, device_type)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# cl_platform_id : platform
|
69
|
+
# cl_device_type : device_type
|
70
|
+
def getDeviceIDs(platform, device_type, error_info: nil)
|
71
|
+
# cl_uint : num_entries
|
72
|
+
# cl_device_id * : devices
|
73
|
+
# cl_uint * : num_devices
|
74
|
+
num_entries = 32
|
75
|
+
devices_buf = ' ' * 4 * num_entries
|
76
|
+
num_devices_buf = ' ' * 4
|
77
|
+
|
78
|
+
err = OpenCL.clGetDeviceIDs(platform, device_type, num_entries, devices_buf, num_devices_buf)
|
79
|
+
error_info << err if error_info != nil
|
80
|
+
|
81
|
+
num_devices = num_devices_buf.unpack("L")[0]
|
82
|
+
@devices = devices_buf.unpack("Q#{num_devices}")
|
83
|
+
|
84
|
+
return @devices
|
85
|
+
end
|
86
|
+
|
87
|
+
# cl_device_id : device
|
88
|
+
def retainDevice(device: @devices[0], error_info: nil)
|
89
|
+
return OpenCL.clRetainDevice(device)
|
90
|
+
end
|
91
|
+
|
92
|
+
def retainDevices(error_info: nil)
|
93
|
+
@devices.each do |device|
|
94
|
+
err = OpenCL.clRetainDevice(device)
|
95
|
+
error_info << err if error_info != nil
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# cl_device_id : device
|
100
|
+
def releaseDevice(device: @devices[0], error_info: nil)
|
101
|
+
return OpenCL.clReleaseDevice(device)
|
102
|
+
end
|
103
|
+
|
104
|
+
def releaseDevices(error_info: nil)
|
105
|
+
@devices.each do |device|
|
106
|
+
err = OpenCL.clReleaseDevice(device)
|
107
|
+
error_info << err if error_info != nil
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# cl_device_id : device
|
112
|
+
# cl_device_info : param_name
|
113
|
+
def getDeviceInfo(param_name, device: @devices[0], error_info: nil)
|
114
|
+
# size_t : param_value_size
|
115
|
+
# void * : param_value
|
116
|
+
# size_t * : param_value_size_ret
|
117
|
+
param_value_buf_length = 1024
|
118
|
+
param_value_buf = ' ' * param_value_buf_length
|
119
|
+
param_value_size_ret_buf = ' ' * 4
|
120
|
+
|
121
|
+
err = OpenCL.clGetDeviceInfo(device, param_name, param_value_buf_length, param_value_buf, param_value_size_ret_buf)
|
122
|
+
error_info << err if error_info != nil
|
123
|
+
|
124
|
+
param_value_size_ret = param_value_size_ret_buf.unpack("L")[0]
|
125
|
+
|
126
|
+
if param_name == OpenCL::CL_DEVICE_MAX_WORK_ITEM_SIZES
|
127
|
+
# Ref.: https://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clGetDeviceInfo.html
|
128
|
+
# CL_DEVICE_MAX_WORK_ITEM_SIZES returns n size_t entries, where n is the value returned by the query for CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS.
|
129
|
+
work_item_dimensions_buf = ' ' * 4
|
130
|
+
err = OpenCL.clGetDeviceInfo(device, OpenCL::CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, 4, work_item_dimensions_buf, nil)
|
131
|
+
error_info << err if error_info != nil
|
132
|
+
work_item_dimensions = work_item_dimensions_buf.unpack("L")[0]
|
133
|
+
end
|
134
|
+
|
135
|
+
unpack_format = @@param2unpack[param_name]
|
136
|
+
case unpack_format
|
137
|
+
when "char[]"
|
138
|
+
return param_value_buf[0...(param_value_size_ret-1)]
|
139
|
+
when "cl_bool"
|
140
|
+
return param_value_buf.unpack("L")[0] == 0 ? false : true
|
141
|
+
when "size_t[]"
|
142
|
+
if param_name == OpenCL::CL_DEVICE_MAX_WORK_ITEM_SIZES
|
143
|
+
return param_value_buf.unpack("Q#{work_item_dimensions}")
|
144
|
+
else
|
145
|
+
return param_value_buf.unpack("Q")
|
146
|
+
end
|
147
|
+
when "intptr_t[]"
|
148
|
+
if param_name == OpenCL::CL_DEVICE_PARTITION_PROPERTIES
|
149
|
+
# This is an array of cl_device_partition_property values...
|
150
|
+
# If the device does not support any partition types, a value of 0 will be returned.
|
151
|
+
return param_value_buf.unpack("Q#{param_value_size_ret / 8}")
|
152
|
+
else
|
153
|
+
return param_value_buf.unpack("Q")
|
154
|
+
end
|
155
|
+
when "cl_bitfield"
|
156
|
+
return param_value_buf.unpack("L")[0]
|
157
|
+
else
|
158
|
+
return param_value_buf.unpack(unpack_format)[0]
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
@@param2unpack = {
|
163
|
+
OpenCL::CL_DEVICE_TYPE => "L",
|
164
|
+
OpenCL::CL_DEVICE_VENDOR_ID => "L",
|
165
|
+
OpenCL::CL_DEVICE_MAX_COMPUTE_UNITS => "L",
|
166
|
+
OpenCL::CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS => "L",
|
167
|
+
OpenCL::CL_DEVICE_MAX_WORK_GROUP_SIZE => "Q",
|
168
|
+
OpenCL::CL_DEVICE_MAX_WORK_ITEM_SIZES => "size_t[]",
|
169
|
+
OpenCL::CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR => "L",
|
170
|
+
OpenCL::CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT => "L",
|
171
|
+
OpenCL::CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT => "L",
|
172
|
+
OpenCL::CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG => "L",
|
173
|
+
OpenCL::CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT => "L",
|
174
|
+
OpenCL::CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE => "L",
|
175
|
+
OpenCL::CL_DEVICE_MAX_CLOCK_FREQUENCY => "L",
|
176
|
+
OpenCL::CL_DEVICE_ADDRESS_BITS => "L",
|
177
|
+
OpenCL::CL_DEVICE_MAX_READ_IMAGE_ARGS => "L",
|
178
|
+
OpenCL::CL_DEVICE_MAX_WRITE_IMAGE_ARGS => "L",
|
179
|
+
OpenCL::CL_DEVICE_MAX_MEM_ALLOC_SIZE => "Q",
|
180
|
+
OpenCL::CL_DEVICE_IMAGE2D_MAX_WIDTH => "L",
|
181
|
+
OpenCL::CL_DEVICE_IMAGE2D_MAX_HEIGHT => "L",
|
182
|
+
OpenCL::CL_DEVICE_IMAGE3D_MAX_WIDTH => "L",
|
183
|
+
OpenCL::CL_DEVICE_IMAGE3D_MAX_HEIGHT => "L",
|
184
|
+
OpenCL::CL_DEVICE_IMAGE3D_MAX_DEPTH => "L",
|
185
|
+
OpenCL::CL_DEVICE_IMAGE_SUPPORT => "cl_bool",
|
186
|
+
OpenCL::CL_DEVICE_MAX_PARAMETER_SIZE => "L",
|
187
|
+
OpenCL::CL_DEVICE_MAX_SAMPLERS => "L",
|
188
|
+
OpenCL::CL_DEVICE_MEM_BASE_ADDR_ALIGN => "L",
|
189
|
+
OpenCL::CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE => "L",
|
190
|
+
OpenCL::CL_DEVICE_SINGLE_FP_CONFIG => "cl_bitfield",
|
191
|
+
OpenCL::CL_DEVICE_GLOBAL_MEM_CACHE_TYPE => "L",
|
192
|
+
OpenCL::CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE => "L",
|
193
|
+
OpenCL::CL_DEVICE_GLOBAL_MEM_CACHE_SIZE => "L",
|
194
|
+
OpenCL::CL_DEVICE_GLOBAL_MEM_SIZE => "Q",
|
195
|
+
OpenCL::CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE => "Q",
|
196
|
+
OpenCL::CL_DEVICE_MAX_CONSTANT_ARGS => "L",
|
197
|
+
OpenCL::CL_DEVICE_LOCAL_MEM_TYPE => "L",
|
198
|
+
OpenCL::CL_DEVICE_LOCAL_MEM_SIZE => "Q",
|
199
|
+
OpenCL::CL_DEVICE_ERROR_CORRECTION_SUPPORT => "cl_bool",
|
200
|
+
OpenCL::CL_DEVICE_PROFILING_TIMER_RESOLUTION => "L",
|
201
|
+
OpenCL::CL_DEVICE_ENDIAN_LITTLE => "cl_bool",
|
202
|
+
OpenCL::CL_DEVICE_AVAILABLE => "cl_bool",
|
203
|
+
OpenCL::CL_DEVICE_COMPILER_AVAILABLE => "cl_bool",
|
204
|
+
OpenCL::CL_DEVICE_EXECUTION_CAPABILITIES => "L",
|
205
|
+
OpenCL::CL_DEVICE_QUEUE_PROPERTIES => "cl_bitfield",
|
206
|
+
OpenCL::CL_DEVICE_NAME => "char[]",
|
207
|
+
OpenCL::CL_DEVICE_VENDOR => "char[]",
|
208
|
+
OpenCL::CL_DRIVER_VERSION => "char[]",
|
209
|
+
OpenCL::CL_DEVICE_PROFILE => "char[]",
|
210
|
+
OpenCL::CL_DEVICE_VERSION => "char[]",
|
211
|
+
OpenCL::CL_DEVICE_EXTENSIONS => "char[]",
|
212
|
+
OpenCL::CL_DEVICE_PLATFORM => "Q",
|
213
|
+
OpenCL::CL_DEVICE_DOUBLE_FP_CONFIG => "cl_bitfield",
|
214
|
+
OpenCL::CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF => "L",
|
215
|
+
OpenCL::CL_DEVICE_HOST_UNIFIED_MEMORY => "cl_bool",
|
216
|
+
OpenCL::CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR => "L",
|
217
|
+
OpenCL::CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT => "L",
|
218
|
+
OpenCL::CL_DEVICE_NATIVE_VECTOR_WIDTH_INT => "L",
|
219
|
+
OpenCL::CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG => "L",
|
220
|
+
OpenCL::CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT => "L",
|
221
|
+
OpenCL::CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE => "L",
|
222
|
+
OpenCL::CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF => "L",
|
223
|
+
OpenCL::CL_DEVICE_OPENCL_C_VERSION => "L",
|
224
|
+
OpenCL::CL_DEVICE_LINKER_AVAILABLE => "cl_bool",
|
225
|
+
OpenCL::CL_DEVICE_BUILT_IN_KERNELS => "char[]",
|
226
|
+
OpenCL::CL_DEVICE_IMAGE_MAX_BUFFER_SIZE => "L",
|
227
|
+
OpenCL::CL_DEVICE_IMAGE_MAX_ARRAY_SIZE => "L",
|
228
|
+
OpenCL::CL_DEVICE_PARENT_DEVICE => "Q",
|
229
|
+
OpenCL::CL_DEVICE_PARTITION_MAX_SUB_DEVICES => "L",
|
230
|
+
OpenCL::CL_DEVICE_PARTITION_PROPERTIES => "intptr_t[]",
|
231
|
+
OpenCL::CL_DEVICE_PARTITION_AFFINITY_DOMAIN => "cl_bitfield",
|
232
|
+
OpenCL::CL_DEVICE_PARTITION_TYPE => "L",
|
233
|
+
OpenCL::CL_DEVICE_REFERENCE_COUNT => "L",
|
234
|
+
OpenCL::CL_DEVICE_PREFERRED_INTEROP_USER_SYNC => "L",
|
235
|
+
OpenCL::CL_DEVICE_PRINTF_BUFFER_SIZE => "L",
|
236
|
+
OpenCL::CL_DEVICE_IMAGE_PITCH_ALIGNMENT => "L",
|
237
|
+
OpenCL::CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT => "L"
|
238
|
+
}
|
239
|
+
end
|
240
|
+
|
241
|
+
################################################################################
|
242
|
+
|
243
|
+
class CLUContext
|
244
|
+
attr_reader :context
|
245
|
+
|
246
|
+
def initialize
|
247
|
+
@context = nil # cl_context
|
248
|
+
end
|
249
|
+
|
250
|
+
# cl_context_properties * : properties
|
251
|
+
# cl_device_id * : devices
|
252
|
+
# void * : pfn_notify(char *, void *, size_t, void *),
|
253
|
+
# void * : user_data
|
254
|
+
def createContext(properties, devices, pfn_notify: nil, user_data: nil, error_info: nil)
|
255
|
+
packed_properties = properties == nil ? nil : properties.pack("Q*")
|
256
|
+
num_devices = devices.length
|
257
|
+
errcode_ret_buf = ' ' * 4
|
258
|
+
|
259
|
+
cl_ctx = OpenCL.clCreateContext(packed_properties, num_devices, devices.pack("Q*"), pfn_notify, user_data, errcode_ret_buf)
|
260
|
+
errcode_ret = errcode_ret_buf.unpack("l")[0]
|
261
|
+
error_info << errcode_ret if error_info != nil
|
262
|
+
|
263
|
+
if errcode_ret == OpenCL::CL_SUCCESS
|
264
|
+
@context = cl_ctx
|
265
|
+
return @context
|
266
|
+
else
|
267
|
+
return nil
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
def self.newContext(properties, devices, pfn_notify: nil, user_data: nil, error_info: nil)
|
272
|
+
obj = CLUContext.new
|
273
|
+
ret = obj.createContext(properties, devices, pfn_notify: pfn_notify, user_data: user_data, error_info: error_info)
|
274
|
+
return ret == nil ? nil : obj
|
275
|
+
end
|
276
|
+
|
277
|
+
# Prerequisite : opengl-bindings 1.5.2 or later ( https://github.com/vaiorabbit/ruby-opengl )
|
278
|
+
# You need to "require 'opengl'" before using this method.
|
279
|
+
def createContextWithGLInterop(properties, devices, platform, pfn_notify: nil, user_data: nil, error_info: nil)
|
280
|
+
|
281
|
+
properties.pop if properties.last == 0
|
282
|
+
|
283
|
+
case RbConfig::CONFIG['host_os']
|
284
|
+
|
285
|
+
when /mswin|msys|mingw|cygwin/
|
286
|
+
# for Windows
|
287
|
+
hGLRC = wglGetCurrentContext()
|
288
|
+
hDC = wglGetCurrentDC()
|
289
|
+
props = [ OpenCL::CL_GL_CONTEXT_KHR, hGLRC,
|
290
|
+
OpenCL::CL_WGL_HDC_KHR, hDC,
|
291
|
+
OpenCL::CL_CONTEXT_PLATFORM, platform,
|
292
|
+
0 ]
|
293
|
+
properties.concat(props)
|
294
|
+
|
295
|
+
when /darwin/
|
296
|
+
# for Mac OS X
|
297
|
+
hCGLContext = CGLGetCurrentContext()
|
298
|
+
hCGLShareGroup = CGLGetShareGroup(hCGLContext)
|
299
|
+
props = [ OpenCL::CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, hCGLShareGroup,
|
300
|
+
0 ]
|
301
|
+
properties.concat(props)
|
302
|
+
|
303
|
+
when /linux/
|
304
|
+
# for Linux (X Window)
|
305
|
+
hGLXContext = glXGetCurrentContext()
|
306
|
+
hDisplay = glXGetCurrentDisplay()
|
307
|
+
props = [ OpenCL::CL_GL_CONTEXT_KHR, hGLXContext,
|
308
|
+
OpenCL::CL_GLX_DISPLAY_KHR, hDisplay,
|
309
|
+
OpenCL::CL_CONTEXT_PLATFORM, platform,
|
310
|
+
0 ]
|
311
|
+
properties.concat(props)
|
312
|
+
|
313
|
+
else
|
314
|
+
raise RuntimeError, "OpenCL : Unknown OS: #{host_os.inspect}"
|
315
|
+
end
|
316
|
+
|
317
|
+
return createContext(properties, devices, pfn_notify: pfn_notify, user_data: user_data, error_info: error_info)
|
318
|
+
end
|
319
|
+
|
320
|
+
def self.newContextWithGLInterop(properties, devices, platform, pfn_notify: nil, user_data: nil, error_info: nil)
|
321
|
+
obj = CLUContext.new
|
322
|
+
ret = obj.createContextWithGLInterop(properties, devices, platform, pfn_notify: pfn_notify, user_data: user_data, error_info: error_info)
|
323
|
+
return ret == nil ? nil : obj
|
324
|
+
end
|
325
|
+
|
326
|
+
# cl_context : context
|
327
|
+
def retainContext(context: @context)
|
328
|
+
return OpenCL.clRetainContext(context)
|
329
|
+
end
|
330
|
+
|
331
|
+
# cl_context : context
|
332
|
+
def releaseContext(context: @context)
|
333
|
+
return OpenCL.clReleaseContext(context)
|
334
|
+
end
|
335
|
+
|
336
|
+
# cl_context : context
|
337
|
+
# cl_context_info : param_name
|
338
|
+
def getContextInfo(param_name, context: @context, error_info: nil)
|
339
|
+
# size_t : param_value_size
|
340
|
+
# void * : param_value
|
341
|
+
# size_t * : param_value_size_ret
|
342
|
+
param_value_buf_length = 1024
|
343
|
+
param_value_buf = ' ' * param_value_buf_length
|
344
|
+
param_value_size_ret_buf = ' ' * 4
|
345
|
+
|
346
|
+
err = OpenCL.clGetContextInfo(context, param_name, param_value_buf_length, param_value_buf, param_value_size_ret_buf)
|
347
|
+
error_info << err if error_info != nil
|
348
|
+
|
349
|
+
param_value_size_ret = param_value_size_ret_buf.unpack("L")[0]
|
350
|
+
|
351
|
+
unpack_format = @@param2unpack[param_name]
|
352
|
+
return param_value_buf.unpack(unpack_format)[0]
|
353
|
+
end
|
354
|
+
|
355
|
+
@@param2unpack = {
|
356
|
+
OpenCL::CL_CONTEXT_REFERENCE_COUNT => "L",
|
357
|
+
OpenCL::CL_CONTEXT_DEVICES => "Q",
|
358
|
+
OpenCL::CL_CONTEXT_PROPERTIES => "Q",
|
359
|
+
OpenCL::CL_CONTEXT_NUM_DEVICES => "L",
|
360
|
+
}
|
361
|
+
|
362
|
+
# cl_context : context
|
363
|
+
# cl_mem_flags : flags
|
364
|
+
# cl_mem_object_type : image_type
|
365
|
+
def getSupportedImageFormats(flags, image_type, context: @context, error_info: nil)
|
366
|
+
# cl_uint : num_entries
|
367
|
+
# cl_image_format * : image_formats
|
368
|
+
# cl_uint * : num_image_formats
|
369
|
+
|
370
|
+
num_image_formamts_buf = ' ' * 4
|
371
|
+
err = OpenCL.clGetSupportedImageFormats(context, flags, image_type, 0, nil, num_image_formamts_buf)
|
372
|
+
error_info << err if error_info != nil
|
373
|
+
num_image_formamts = num_image_formamts_buf.unpack("L")[0]
|
374
|
+
|
375
|
+
image_formats_buf = Fiddle::Pointer.malloc(num_image_formamts * OpenCL::CL_STRUCT_IMAGE_FORMAT.size)
|
376
|
+
err = OpenCL.clGetSupportedImageFormats(context, flags, image_type, num_image_formamts, image_formats_buf, nil)
|
377
|
+
error_info << err if error_info != nil
|
378
|
+
|
379
|
+
image_formats = []
|
380
|
+
num_image_formamts.times do |i|
|
381
|
+
fmt = OpenCL::CL_STRUCT_IMAGE_FORMAT.new(image_formats_buf.to_i + i * OpenCL::CL_STRUCT_IMAGE_FORMAT.size)
|
382
|
+
image_formats << fmt
|
383
|
+
end
|
384
|
+
return image_formats
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
################################################################################
|
389
|
+
|
390
|
+
class CLUMemory
|
391
|
+
attr_reader :mem # cl_mem
|
392
|
+
|
393
|
+
def initialize
|
394
|
+
@mem = nil
|
395
|
+
end
|
396
|
+
|
397
|
+
# cl_context : context
|
398
|
+
# cl_mem_flags : flags
|
399
|
+
# size_t : size
|
400
|
+
# void * : host_ptr
|
401
|
+
def createBuffer(context, flags, size, host_ptr = nil, error_info: nil)
|
402
|
+
errcode_ret_buf = ' ' * 4
|
403
|
+
|
404
|
+
mem = OpenCL.clCreateBuffer(context, flags, size, host_ptr, errcode_ret_buf)
|
405
|
+
errcode_ret = errcode_ret_buf.unpack("l")[0]
|
406
|
+
error_info << errcode_ret if error_info != nil
|
407
|
+
|
408
|
+
if errcode_ret == OpenCL::CL_SUCCESS
|
409
|
+
@mem = mem
|
410
|
+
return @mem
|
411
|
+
else
|
412
|
+
return nil
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
def self.newBuffer(context, flags, size, host_ptr = nil, error_info: nil)
|
417
|
+
obj = CLUMemory.new
|
418
|
+
ret = obj.createBuffer(context, flags, size, host_ptr, error_info: error_info)
|
419
|
+
return ret == nil ? nil : obj
|
420
|
+
end
|
421
|
+
|
422
|
+
# cl_context : context
|
423
|
+
# cl_mem_flags : flags
|
424
|
+
# const cl_image_format * : image_format
|
425
|
+
# const cl_image_desc * : image_desc
|
426
|
+
# void * : host_ptr
|
427
|
+
def createImage(context, flags, image_format, image_desc, host_ptr = nil, error_info: nil)
|
428
|
+
errcode_ret_buf = ' ' * 4
|
429
|
+
|
430
|
+
mem = OpenCL.clCreateImage(context, flags, image_format, image_desc, host_ptr, errcode_ret_buf)
|
431
|
+
errcode_ret = errcode_ret_buf.unpack("l")[0]
|
432
|
+
error_info << errcode_ret if error_info != nil
|
433
|
+
|
434
|
+
if errcode_ret == OpenCL::CL_SUCCESS
|
435
|
+
@mem = mem
|
436
|
+
return @mem
|
437
|
+
else
|
438
|
+
return nil
|
439
|
+
end
|
440
|
+
end
|
441
|
+
|
442
|
+
def self.newImage(context, flags, image_format, image_desc, host_ptr = nil, error_info: nil)
|
443
|
+
obj = CLUMemory.new
|
444
|
+
ret = obj.createImage(context, flags, image_format, image_desc, host_ptr, error_info: error_info)
|
445
|
+
return ret == nil ? nil : obj
|
446
|
+
end
|
447
|
+
|
448
|
+
# cl_context : context
|
449
|
+
# cl_mem_flags : flags
|
450
|
+
# cl_GLuint : bufobj
|
451
|
+
def createFromGLBuffer(context, flags, bufobj, error_info: nil)
|
452
|
+
errcode_ret_buf = ' ' * 4
|
453
|
+
|
454
|
+
mem = OpenCL.clCreateFromGLBuffer(context, flags, bufobj, errcode_ret_buf)
|
455
|
+
errcode_ret = errcode_ret_buf.unpack("l")[0]
|
456
|
+
error_info << errcode_ret if error_info != nil
|
457
|
+
|
458
|
+
if errcode_ret == OpenCL::CL_SUCCESS
|
459
|
+
@mem = mem
|
460
|
+
return @mem
|
461
|
+
else
|
462
|
+
return nil
|
463
|
+
end
|
464
|
+
end
|
465
|
+
|
466
|
+
def self.newFromGLBuffer(context, flags, bufobj, error_info: nil)
|
467
|
+
obj = CLUMemory.new
|
468
|
+
ret = obj.createFromGLBuffer(context, flags, bufobj, error_info: error_info)
|
469
|
+
return ret == nil ? nil : obj
|
470
|
+
end
|
471
|
+
|
472
|
+
# cl_context : context
|
473
|
+
# cl_mem_flags : flags
|
474
|
+
# cl_GLenum : target
|
475
|
+
# cl_GLint : miplevel
|
476
|
+
# cl_GLuint : texture
|
477
|
+
def createFromGLTexture(context, flags, target, miplevel, texture, error_info: nil)
|
478
|
+
errcode_ret_buf = ' ' * 4
|
479
|
+
|
480
|
+
mem = OpenCL.clCreateFromGLTexture(context, flags, target, miplevel, texture, errcode_ret_buf)
|
481
|
+
errcode_ret = errcode_ret_buf.unpack("l")[0]
|
482
|
+
error_info << errcode_ret if error_info != nil
|
483
|
+
|
484
|
+
if errcode_ret == OpenCL::CL_SUCCESS
|
485
|
+
@mem = mem
|
486
|
+
return @mem
|
487
|
+
else
|
488
|
+
return nil
|
489
|
+
end
|
490
|
+
end
|
491
|
+
|
492
|
+
def self.newFromGLTexture(context, flags, target, miplevel, texture, error_info: nil)
|
493
|
+
obj = CLUMemory.new
|
494
|
+
ret = obj.createFromGLTexture(context, flags, target, miplevel, texture, error_info: error_info)
|
495
|
+
return ret == nil ? nil : obj
|
496
|
+
end
|
497
|
+
|
498
|
+
# cl_context : context
|
499
|
+
# cl_mem_flags : flags
|
500
|
+
# cl_GLuint : renderbuffer
|
501
|
+
def createFromGLRenderBuffer(context, flags, renderbuffer, error_info: nil)
|
502
|
+
errcode_ret_buf = ' ' * 4
|
503
|
+
|
504
|
+
mem = OpenCL.clCreateFromGLRenderBuffer(context, flags, renderbuffer, errcode_ret_buf)
|
505
|
+
errcode_ret = errcode_ret_buf.unpack("l")[0]
|
506
|
+
error_info << errcode_ret if error_info != nil
|
507
|
+
|
508
|
+
if errcode_ret == OpenCL::CL_SUCCESS
|
509
|
+
@mem = mem
|
510
|
+
return @mem
|
511
|
+
else
|
512
|
+
return nil
|
513
|
+
end
|
514
|
+
end
|
515
|
+
|
516
|
+
def self.newFromGLRenderBuffer(context, flags, renderbuffer, error_info: nil)
|
517
|
+
obj = CLUMemory.new
|
518
|
+
ret = obj.createFromGLRenderBuffer(context, flags, renderbuffer, error_info: error_info)
|
519
|
+
return ret == nil ? nil : obj
|
520
|
+
end
|
521
|
+
|
522
|
+
# cl_mem : mem
|
523
|
+
def retainMemObject(mem: @mem)
|
524
|
+
return OpenCL.clRetainMemObject(mem)
|
525
|
+
end
|
526
|
+
|
527
|
+
# cl_mem : mem
|
528
|
+
def releaseMemObject(mem: @mem)
|
529
|
+
return OpenCL.clReleaseMemObject(mem)
|
530
|
+
end
|
531
|
+
|
532
|
+
# cl_mem : memobj
|
533
|
+
# cl_mem_info : param_name
|
534
|
+
def getMemObjectInfo(param_name, memobj: @mem, error_info: nil)
|
535
|
+
# size_t : param_value_size
|
536
|
+
# void * : param_value
|
537
|
+
# size_t * : param_value_size_ret
|
538
|
+
param_value_buf_length = 1024
|
539
|
+
param_value_buf = ' ' * param_value_buf_length
|
540
|
+
param_value_size_ret_buf = ' ' * 4
|
541
|
+
|
542
|
+
err = OpenCL.clGetMemObjectInfo(memobj, param_name, param_value_buf_length, param_value_buf, param_value_size_ret_buf)
|
543
|
+
error_info << err if error_info != nil
|
544
|
+
|
545
|
+
param_value_size_ret = param_value_size_ret_buf.unpack("L")[0]
|
546
|
+
|
547
|
+
unpack_format = @@mem_objinfo_param2unpack[param_name]
|
548
|
+
case unpack_format
|
549
|
+
when "void*" # param_name == OpenCL::CL_MEM_HOST_PTR
|
550
|
+
addr = param_value_buf.unpack("Q")[0]
|
551
|
+
# OS X (El Capitan) : Quering CL_MEM_HOST_PTR to memobj created without
|
552
|
+
# CL_MEM_USE_HOST_PTR does not return NULL, but keeps param_value_buf untouched.
|
553
|
+
if addr == 0 || param_value_buf[0, 8] == ' '
|
554
|
+
return nil
|
555
|
+
else
|
556
|
+
return Fiddle::Pointer.new(addr)
|
557
|
+
end
|
558
|
+
else
|
559
|
+
return param_value_buf.unpack(unpack_format)[0]
|
560
|
+
end
|
561
|
+
end
|
562
|
+
|
563
|
+
@@mem_objinfo_param2unpack = {
|
564
|
+
OpenCL::CL_MEM_TYPE => "L",
|
565
|
+
OpenCL::CL_MEM_FLAGS => "Q",
|
566
|
+
OpenCL::CL_MEM_SIZE => "Q",
|
567
|
+
OpenCL::CL_MEM_HOST_PTR => "void*",
|
568
|
+
OpenCL::CL_MEM_MAP_COUNT => "L",
|
569
|
+
OpenCL::CL_MEM_REFERENCE_COUNT => "L",
|
570
|
+
OpenCL::CL_MEM_CONTEXT => "Q",
|
571
|
+
OpenCL::CL_MEM_ASSOCIATED_MEMOBJECT => "Q",
|
572
|
+
OpenCL::CL_MEM_OFFSET => "Q",
|
573
|
+
}
|
574
|
+
|
575
|
+
# cl_mem : memobj
|
576
|
+
# cl_image_info : param_name
|
577
|
+
def getImageInfo(param_name, memobj: @mem, error_info: nil)
|
578
|
+
# size_t : param_value_size
|
579
|
+
# void * : param_value
|
580
|
+
# size_t * : param_value_size_ret
|
581
|
+
param_value_buf_length = 1024
|
582
|
+
param_value_buf = ' ' * param_value_buf_length
|
583
|
+
param_value_size_ret_buf = ' ' * 4
|
584
|
+
|
585
|
+
err = OpenCL.clGetImageInfo(memobj, param_name, param_value_buf_length, param_value_buf, param_value_size_ret_buf)
|
586
|
+
error_info << err if error_info != nil
|
587
|
+
|
588
|
+
param_value_size_ret = param_value_size_ret_buf.unpack("L")[0]
|
589
|
+
|
590
|
+
unpack_format = @@mem_imageinfo_param2unpack[param_name]
|
591
|
+
case unpack_format
|
592
|
+
when "cl_image_format" # param_name == OpenCL::CL_IMAGE_FORMAT
|
593
|
+
values = param_value_buf.unpack("L2") # instance of cl_image_format
|
594
|
+
fmt = OpenCL::CL_STRUCT_IMAGE_FORMAT.malloc
|
595
|
+
fmt.image_channel_order = values[0]
|
596
|
+
fmt.image_channel_data_type = values[1]
|
597
|
+
return fmt
|
598
|
+
else
|
599
|
+
return param_value_buf.unpack(unpack_format)[0]
|
600
|
+
end
|
601
|
+
end
|
602
|
+
|
603
|
+
@@mem_imageinfo_param2unpack = {
|
604
|
+
OpenCL::CL_IMAGE_FORMAT => "cl_image_format",
|
605
|
+
OpenCL::CL_IMAGE_ELEMENT_SIZE => "Q",
|
606
|
+
OpenCL::CL_IMAGE_ROW_PITCH => "Q",
|
607
|
+
OpenCL::CL_IMAGE_SLICE_PITCH => "Q",
|
608
|
+
OpenCL::CL_IMAGE_WIDTH => "Q",
|
609
|
+
OpenCL::CL_IMAGE_HEIGHT => "Q",
|
610
|
+
OpenCL::CL_IMAGE_DEPTH => "Q",
|
611
|
+
OpenCL::CL_IMAGE_ARRAY_SIZE => "Q",
|
612
|
+
OpenCL::CL_IMAGE_BUFFER => "Q",
|
613
|
+
OpenCL::CL_IMAGE_NUM_MIP_LEVELS => "L",
|
614
|
+
OpenCL::CL_IMAGE_NUM_SAMPLES => "L",
|
615
|
+
}
|
616
|
+
|
617
|
+
# cl_mem : memobj
|
618
|
+
def getGLObjectInfo(memobj: @mem, error_info: nil)
|
619
|
+
# cl_gl_object_type * : gl_object_type
|
620
|
+
# cl_GLuint * : gl_object_name
|
621
|
+
gl_object_type_buf = ' ' * 8
|
622
|
+
gl_object_name_buf = ' ' * 4
|
623
|
+
|
624
|
+
err = OpenCL.clGetGLObjectInfo(memobj, gl_object_type_buf, gl_object_name_buf)
|
625
|
+
error_info << err if error_info != nil
|
626
|
+
|
627
|
+
return gl_object_type_buf.unpack("L")[0], gl_object_name_buf.unpack("L")[0]
|
628
|
+
end
|
629
|
+
|
630
|
+
# cl_mem : memobj
|
631
|
+
# cl_image_info : param_name
|
632
|
+
def getGLTextureInfo(param_name, memobj: @mem, error_info: nil)
|
633
|
+
# size_t : param_value_size
|
634
|
+
# void * : param_value
|
635
|
+
# size_t * : param_value_size_ret
|
636
|
+
param_value_buf_length = 1024
|
637
|
+
param_value_buf = ' ' * param_value_buf_length
|
638
|
+
param_value_size_ret_buf = ' ' * 4
|
639
|
+
|
640
|
+
err = OpenCL.clGetGLTextureInfo(memobj, param_name, param_value_buf_length, param_value_buf, param_value_size_ret_buf)
|
641
|
+
error_info << err if error_info != nil
|
642
|
+
|
643
|
+
param_value_size_ret = param_value_size_ret_buf.unpack("L")[0]
|
644
|
+
|
645
|
+
unpack_format = @@mem_gltextureinfo_param2unpack[param_name]
|
646
|
+
return param_value_buf.unpack(unpack_format)[0]
|
647
|
+
end
|
648
|
+
|
649
|
+
@@mem_gltextureinfo_param2unpack = {
|
650
|
+
OpenCL::CL_GL_TEXTURE_TARGET => "L",
|
651
|
+
OpenCL::CL_GL_MIPMAP_LEVEL => "l",
|
652
|
+
}
|
653
|
+
end
|
654
|
+
|
655
|
+
################################################################################
|
656
|
+
|
657
|
+
class CLUCommandQueue
|
658
|
+
attr_reader :command_queue # cl_command_queue
|
659
|
+
|
660
|
+
def initialize
|
661
|
+
@command_queue = nil # cl_command_queue
|
662
|
+
end
|
663
|
+
|
664
|
+
# cl_context : context
|
665
|
+
# cl_device_id : device
|
666
|
+
# cl_command_queue_properties : properties
|
667
|
+
def createCommandQueue(context, device, properties = 0, error_info: nil)
|
668
|
+
errcode_ret_buf = ' ' * 4
|
669
|
+
|
670
|
+
cl_cq = OpenCL.clCreateCommandQueue(context, device, properties, errcode_ret_buf)
|
671
|
+
errcode_ret = errcode_ret_buf.unpack("l")[0]
|
672
|
+
error_info << errcode_ret if error_info != nil
|
673
|
+
|
674
|
+
if errcode_ret == OpenCL::CL_SUCCESS
|
675
|
+
@command_queue = cl_cq
|
676
|
+
return @command_queue
|
677
|
+
else
|
678
|
+
return nil
|
679
|
+
end
|
680
|
+
end
|
681
|
+
|
682
|
+
def self.newCommandQueue(context, device, properties = 0, error_info: nil)
|
683
|
+
obj = CLUCommandQueue.new
|
684
|
+
ret = obj.createCommandQueue(context, device, 0, error_info: error_info)
|
685
|
+
return ret == nil ? nil : obj
|
686
|
+
end
|
687
|
+
|
688
|
+
# cl_command_queue : command_queue
|
689
|
+
def retainCommandQueue(command_queue: @command_queue)
|
690
|
+
return OpenCL.clRetainCommandQueue(command_queue)
|
691
|
+
end
|
692
|
+
|
693
|
+
# cl_command_queue : command_queue
|
694
|
+
def releaseCommandQueue(command_queue: @command_queue)
|
695
|
+
return OpenCL.clReleaseCommandQueue(command_queue)
|
696
|
+
end
|
697
|
+
|
698
|
+
# cl_command_queue : command_queue
|
699
|
+
def flush(command_queue: @command_queue)
|
700
|
+
return OpenCL.clFlush(command_queue)
|
701
|
+
end
|
702
|
+
|
703
|
+
# cl_command_queue : command_queue
|
704
|
+
def finish(command_queue: @command_queue)
|
705
|
+
return OpenCL.clFinish(command_queue)
|
706
|
+
end
|
707
|
+
|
708
|
+
# cl_command_queue : command_queue
|
709
|
+
# cl_command_queue_info : param_name
|
710
|
+
def getCommandQueueInfo(param_name, command_queue: @command_queue, error_info: nil)
|
711
|
+
# size_t : param_value_size
|
712
|
+
# void * : param_value
|
713
|
+
# size_t * : param_value_size_ret
|
714
|
+
param_value_buf_length = 1024
|
715
|
+
param_value_buf = ' ' * param_value_buf_length
|
716
|
+
param_value_size_ret_buf = ' ' * 4
|
717
|
+
|
718
|
+
err = OpenCL.clGetCommandQueueInfo(command_queue, param_name, param_value_buf_length, param_value_buf, param_value_size_ret_buf)
|
719
|
+
error_info << err if error_info != nil
|
720
|
+
|
721
|
+
param_value_size_ret = param_value_size_ret_buf.unpack("L")[0]
|
722
|
+
|
723
|
+
unpack_format = @@param2unpack[param_name]
|
724
|
+
return param_value_buf.unpack(unpack_format)[0]
|
725
|
+
end
|
726
|
+
|
727
|
+
@@param2unpack = {
|
728
|
+
OpenCL::CL_QUEUE_CONTEXT => "Q",
|
729
|
+
OpenCL::CL_QUEUE_DEVICE => "Q",
|
730
|
+
OpenCL::CL_QUEUE_REFERENCE_COUNT => "L",
|
731
|
+
OpenCL::CL_QUEUE_PROPERTIES => "L",
|
732
|
+
}
|
733
|
+
|
734
|
+
# cl_command_queue : command_queue
|
735
|
+
# cl_mem : buffer
|
736
|
+
# cl_bool : blocking_read
|
737
|
+
# size_t : offset
|
738
|
+
# size_t : size
|
739
|
+
# void * : ptr
|
740
|
+
# const cl_event * : event_wait_list
|
741
|
+
# cl_event * : event
|
742
|
+
def enqueueReadBuffer(buffer, blocking_read, offset, size, ptr, command_queue: @command_queue, event_wait_list: nil, event: nil, error_info: nil)
|
743
|
+
event_buf = event == nil ? nil : ' ' * 8
|
744
|
+
num_events_in_wait_list = event_wait_list == nil ? 0 : event_wait_list.length
|
745
|
+
|
746
|
+
err = OpenCL.clEnqueueReadBuffer(command_queue, buffer, blocking_read, offset, size, ptr, num_events_in_wait_list, event_wait_list == nil ? nil : event_wait_list.pack("Q"), event_buf)
|
747
|
+
error_info << err if error_info != nil
|
748
|
+
|
749
|
+
event << event_buf.unpack("Q")[0] if event != nil
|
750
|
+
return err
|
751
|
+
end
|
752
|
+
|
753
|
+
# cl_command_queue : command_queue
|
754
|
+
# cl_mem : buffer
|
755
|
+
# cl_bool : blocking_write
|
756
|
+
# size_t : offset
|
757
|
+
# size_t : size
|
758
|
+
# const void * : ptr
|
759
|
+
# const cl_event * : event_wait_list
|
760
|
+
# cl_event * : event
|
761
|
+
def enqueueWriteBuffer(buffer, blocking_write, offset, size, ptr, command_queue: @command_queue, event_wait_list: nil, event: nil, error_info: nil)
|
762
|
+
event_buf = event == nil ? nil : ' ' * 8
|
763
|
+
num_events_in_wait_list = event_wait_list == nil ? 0 : event_wait_list.length
|
764
|
+
|
765
|
+
err = OpenCL.clEnqueueWriteBuffer(command_queue, buffer, blocking_write, offset, size, ptr, num_events_in_wait_list, event_wait_list == nil ? nil : event_wait_list.pack("Q"), event_buf)
|
766
|
+
error_info << err if error_info != nil
|
767
|
+
|
768
|
+
event << event_buf.unpack("Q")[0] if event != nil
|
769
|
+
return err
|
770
|
+
end
|
771
|
+
|
772
|
+
# cl_command_queue : command_queue
|
773
|
+
# cl_mem : buffer
|
774
|
+
# const void * : pattern
|
775
|
+
# size_t : offset
|
776
|
+
# size_t : size
|
777
|
+
# const cl_event * : event_wait_list
|
778
|
+
# cl_event * : event
|
779
|
+
def enqueueFillBuffer(buffer, pattern, offset, size, command_queue: @command_queue, event_wait_list: nil, event: nil, error_info: nil)
|
780
|
+
event_buf = event == nil ? nil : ' ' * 8
|
781
|
+
num_events_in_wait_list = event_wait_list == nil ? 0 : event_wait_list.length
|
782
|
+
# size_t : pattern_size
|
783
|
+
pattern_size = pattern.size
|
784
|
+
|
785
|
+
err = OpenCL.clEnqueueFillBuffer(command_queue, buffer, pattern, pattern_size, offset, size, num_events_in_wait_list, event_wait_list == nil ? nil : event_wait_list.pack("Q"), event_buf)
|
786
|
+
error_info << err if error_info != nil
|
787
|
+
|
788
|
+
event << event_buf.unpack("Q")[0] if event != nil
|
789
|
+
return err
|
790
|
+
end
|
791
|
+
|
792
|
+
# cl_command_queue : command_queue
|
793
|
+
# cl_mem : src_buffer
|
794
|
+
# cl_mem : dst_buffer
|
795
|
+
# size_t : src_offset
|
796
|
+
# size_t : dst_offset
|
797
|
+
# size_t : size
|
798
|
+
# const cl_event * : event_wait_list
|
799
|
+
# cl_event * : event
|
800
|
+
def enqueueCopyBuffer(src_buffer, dst_buffer, src_offset, dst_offset, size, command_queue: @command_queue, event_wait_list: nil, event: nil, error_info: nil)
|
801
|
+
event_buf = event == nil ? nil : ' ' * 8
|
802
|
+
num_events_in_wait_list = event_wait_list == nil ? 0 : event_wait_list.length
|
803
|
+
|
804
|
+
err = OpenCL.clEnqueueCopyBuffer(command_queue, src_buffer, dst_buffer, src_offset, dst_offset, size, num_events_in_wait_list, event_wait_list == nil ? nil : event_wait_list.pack("Q"), event_buf)
|
805
|
+
error_info << err if error_info != nil
|
806
|
+
|
807
|
+
event << event_buf.unpack("Q")[0] if event != nil
|
808
|
+
return err
|
809
|
+
end
|
810
|
+
|
811
|
+
# cl_command_queue : command_queue
|
812
|
+
# cl_mem : image
|
813
|
+
# cl_bool : blocking_read
|
814
|
+
# const size_t * : origin[3]
|
815
|
+
# const size_t * : region[3]
|
816
|
+
# size_t : row_pitch
|
817
|
+
# size_t : slice_pitch
|
818
|
+
# void * : ptr
|
819
|
+
# const cl_event * : event_wait_list
|
820
|
+
# cl_event * : event
|
821
|
+
def enqueueReadImage(image, blocking_read, origin, region, row_pitch, slice_pitch, ptr, command_queue: @command_queue, event_wait_list: nil, event: nil, error_info: nil)
|
822
|
+
event_buf = event == nil ? nil : ' ' * 8
|
823
|
+
num_events_in_wait_list = event_wait_list == nil ? 0 : event_wait_list.length
|
824
|
+
|
825
|
+
err = OpenCL.clEnqueueReadImage(command_queue, image, blocking_read, origin.pack("Q3"), region.pack("Q3"), row_pitch, slice_pitch, ptr, num_events_in_wait_list, event_wait_list == nil ? nil : event_wait_list.pack("Q"), event_buf)
|
826
|
+
error_info << err if error_info != nil
|
827
|
+
|
828
|
+
event << event_buf.unpack("Q")[0] if event != nil
|
829
|
+
return err
|
830
|
+
end
|
831
|
+
|
832
|
+
# cl_command_queue : command_queue
|
833
|
+
# cl_mem : image
|
834
|
+
# cl_bool : blocking_write
|
835
|
+
# const size_t * : origin[3]
|
836
|
+
# const size_t * : region[3]
|
837
|
+
# size_t : row_pitch
|
838
|
+
# size_t : slice_pitch
|
839
|
+
# void * : ptr
|
840
|
+
# const cl_event * : event_wait_list
|
841
|
+
# cl_event * : event
|
842
|
+
def enqueueWriteImage(image, blocking_write, origin, region, row_pitch, slice_pitch, ptr, command_queue: @command_queue, event_wait_list: nil, event: nil, error_info: nil)
|
843
|
+
event_buf = event == nil ? nil : ' ' * 8
|
844
|
+
num_events_in_wait_list = event_wait_list == nil ? 0 : event_wait_list.length
|
845
|
+
|
846
|
+
err = OpenCL.clEnqueueWriteImage(command_queue, image, blocking_write, origin.pack("Q3"), region.pack("Q3"), row_pitch, slice_pitch, ptr, num_events_in_wait_list, event_wait_list == nil ? nil : event_wait_list.pack("Q"), event_buf)
|
847
|
+
error_info << err if error_info != nil
|
848
|
+
|
849
|
+
event << event_buf.unpack("Q")[0] if event != nil
|
850
|
+
return err
|
851
|
+
end
|
852
|
+
|
853
|
+
# cl_command_queue : command_queue
|
854
|
+
# cl_mem : image
|
855
|
+
# const void * : fill_color
|
856
|
+
# const size_t * : origin[3]
|
857
|
+
# const size_t * : region[3]
|
858
|
+
# const cl_event * : event_wait_list
|
859
|
+
# cl_event * : event
|
860
|
+
def enqueueFillImage(image, fill_color, origin, region, command_queue: @command_queue, event_wait_list: nil, event: nil, error_info: nil)
|
861
|
+
event_buf = event == nil ? nil : ' ' * 8
|
862
|
+
num_events_in_wait_list = event_wait_list == nil ? 0 : event_wait_list.length
|
863
|
+
|
864
|
+
err = OpenCL.clEnqueueFillImage(command_queue, image, fill_color, origin.pack("Q3"), region.pack("Q3"), num_events_in_wait_list, event_wait_list == nil ? nil : event_wait_list.pack("Q"), event_buf)
|
865
|
+
error_info << err if error_info != nil
|
866
|
+
|
867
|
+
event << event_buf.unpack("Q")[0] if event != nil
|
868
|
+
return err
|
869
|
+
end
|
870
|
+
|
871
|
+
# cl_command_queue : command_queue
|
872
|
+
# cl_mem : src_image
|
873
|
+
# cl_mem : dst_image
|
874
|
+
# const size_t * : src_origin[3]
|
875
|
+
# const size_t * : dst_origin[3]
|
876
|
+
# const size_t * : region[3]
|
877
|
+
# const cl_event * : event_wait_list
|
878
|
+
# cl_event * : event
|
879
|
+
def enqueueCopyImage(src_image, dst_image, src_origin, dst_origin, region, command_queue: @command_queue, event_wait_list: nil, event: nil, error_info: nil)
|
880
|
+
event_buf = event == nil ? nil : ' ' * 8
|
881
|
+
num_events_in_wait_list = event_wait_list == nil ? 0 : event_wait_list.length
|
882
|
+
|
883
|
+
err = OpenCL.clEnqueueCopyImage(command_queue, src_image, dst_image, src_origin.pack("Q3"), dst_origin.pack("Q3"), region.pack("Q3"), num_events_in_wait_list, event_wait_list == nil ? nil : event_wait_list.pack("Q"), event_buf)
|
884
|
+
error_info << err if error_info != nil
|
885
|
+
|
886
|
+
event << event_buf.unpack("Q")[0] if event != nil
|
887
|
+
return err
|
888
|
+
end
|
889
|
+
|
890
|
+
# cl_command_queue : command_queue
|
891
|
+
# cl_mem : src_image
|
892
|
+
# cl_mem : dst_buffer
|
893
|
+
# const size_t * : src_origin[3]
|
894
|
+
# const size_t * : region[3]
|
895
|
+
# size_t : dst_offset
|
896
|
+
# const cl_event * : event_wait_list
|
897
|
+
# cl_event * : event
|
898
|
+
def enqueueCopyImageToBuffer(src_image, dst_buffer, src_origin, region, dst_offset, command_queue: @command_queue, event_wait_list: nil, event: nil, error_info: nil)
|
899
|
+
event_buf = event == nil ? nil : ' ' * 8
|
900
|
+
num_events_in_wait_list = event_wait_list == nil ? 0 : event_wait_list.length
|
901
|
+
|
902
|
+
err = OpenCL.clEnqueueCopyImageToBuffer(command_queue, src_image, dst_buffer, src_origin.pack("Q3"), region.pack("Q3"), dst_offset, num_events_in_wait_list, event_wait_list == nil ? nil : event_wait_list.pack("Q"), event_buf)
|
903
|
+
error_info << err if error_info != nil
|
904
|
+
|
905
|
+
event << event_buf.unpack("Q")[0] if event != nil
|
906
|
+
return err
|
907
|
+
end
|
908
|
+
|
909
|
+
# cl_command_queue : command_queue
|
910
|
+
# cl_mem : src_buffer
|
911
|
+
# cl_mem : dst_image
|
912
|
+
# size_t : src_offset
|
913
|
+
# const size_t * : dst_origin[3]
|
914
|
+
# const size_t * : region[3]
|
915
|
+
# const cl_event * : event_wait_list
|
916
|
+
# cl_event * : event
|
917
|
+
def enqueueCopyBufferToImage(src_buffer, dst_image, src_offset, dst_origin, region, command_queue: @command_queue, event_wait_list: nil, event: nil, error_info: nil)
|
918
|
+
event_buf = event == nil ? nil : ' ' * 8
|
919
|
+
num_events_in_wait_list = event_wait_list == nil ? 0 : event_wait_list.length
|
920
|
+
|
921
|
+
err = OpenCL.clEnqueueCopyBufferToImage(command_queue, src_buffer, dst_image, src_offset, dst_origin.pack("Q3"), region.pack("Q3"), num_events_in_wait_list, event_wait_list == nil ? nil : event_wait_list.pack("Q"), event_buf)
|
922
|
+
error_info << err if error_info != nil
|
923
|
+
|
924
|
+
event << event_buf.unpack("Q")[0] if event != nil
|
925
|
+
return err
|
926
|
+
end
|
927
|
+
|
928
|
+
# cl_command_queue : command_queue
|
929
|
+
# cl_mem : buffer
|
930
|
+
# cl_bool : blocking_map
|
931
|
+
# cl_map_flags : map_flags
|
932
|
+
# size_t : offset
|
933
|
+
# size_t : size
|
934
|
+
# const cl_event * : event_wait_list
|
935
|
+
# cl_event * : event
|
936
|
+
def enqueueMapBuffer(buffer, blocking_map, map_flags, offset, size, command_queue: @command_queue, event_wait_list: nil, event: nil, error_info: nil)
|
937
|
+
event_buf = event == nil ? nil : ' ' * 8
|
938
|
+
num_events_in_wait_list = event_wait_list == nil ? 0 : event_wait_list.length
|
939
|
+
errcode_ret_buf = ' ' * 4
|
940
|
+
|
941
|
+
mapped_ptr = OpenCL.clEnqueueMapBuffer(command_queue, buffer, blocking_map, map_flags, offset, size, num_events_in_wait_list, event_wait_list == nil ? nil : event_wait_list.pack("Q"), event_buf, errcode_ret_buf)
|
942
|
+
errcode_ret = errcode_ret_buf.unpack("l")[0]
|
943
|
+
error_info << errcode_ret if error_info != nil
|
944
|
+
|
945
|
+
event << event_buf.unpack("Q")[0] if event != nil
|
946
|
+
if errcode_ret == OpenCL::CL_SUCCESS
|
947
|
+
return mapped_ptr
|
948
|
+
else
|
949
|
+
return nil
|
950
|
+
end
|
951
|
+
end
|
952
|
+
|
953
|
+
# cl_command_queue : command_queue
|
954
|
+
# cl_mem : image
|
955
|
+
# cl_bool : blocking_map
|
956
|
+
# cl_map_flags : map_flags
|
957
|
+
# const size_t * : origin[3]
|
958
|
+
# const size_t * : region[3]
|
959
|
+
# const cl_event * : event_wait_list
|
960
|
+
# cl_event * : event
|
961
|
+
def enqueueMapImage(buffer, blocking_map, map_flags, origin, region, command_queue: @command_queue, event_wait_list: nil, event: nil, error_info: nil)
|
962
|
+
event_buf = event == nil ? nil : ' ' * 8
|
963
|
+
num_events_in_wait_list = event_wait_list == nil ? 0 : event_wait_list.length
|
964
|
+
errcode_ret_buf = ' ' * 4
|
965
|
+
|
966
|
+
image_row_pitch_buf = ' ' * 8
|
967
|
+
image_slice_pitch_buf = ' ' * 8
|
968
|
+
|
969
|
+
mapped_ptr = OpenCL.clEnqueueMapImage(command_queue, buffer, blocking_map, map_flags, origin.pack("Q3"), region.pack("Q3"), image_row_pitch_buf, image_slice_pitch_buf, num_events_in_wait_list, event_wait_list == nil ? nil : event_wait_list.pack("Q"), event_buf, errcode_ret_buf)
|
970
|
+
errcode_ret = errcode_ret_buf.unpack("l")[0]
|
971
|
+
error_info << errcode_ret if error_info != nil
|
972
|
+
|
973
|
+
image_row_pitch = image_row_pitch_buf.unpack("Q")[0]
|
974
|
+
image_slice_pitch = image_slice_pitch_buf.unpack("Q")[0]
|
975
|
+
|
976
|
+
event << event_buf.unpack("Q")[0] if event != nil
|
977
|
+
if errcode_ret == OpenCL::CL_SUCCESS
|
978
|
+
return mapped_ptr, image_row_pitch, image_slice_pitch
|
979
|
+
else
|
980
|
+
return nil, image_row_pitch, image_slice_pitch
|
981
|
+
end
|
982
|
+
end
|
983
|
+
|
984
|
+
# cl_command_queue : command_queue
|
985
|
+
# cl_mem : memobj
|
986
|
+
# void * : mapped_ptr
|
987
|
+
# const cl_event * : event_wait_list
|
988
|
+
# cl_event * : event
|
989
|
+
def enqueueUnmapMemObject(memobj, mapped_ptr, command_queue: @command_queue, event_wait_list: nil, event: nil, error_info: nil)
|
990
|
+
event_buf = event == nil ? nil : ' ' * 8
|
991
|
+
num_events_in_wait_list = event_wait_list == nil ? 0 : event_wait_list.length
|
992
|
+
|
993
|
+
err = OpenCL.clEnqueueUnmapMemObject(command_queue, memobj, mapped_ptr, num_events_in_wait_list, event_wait_list == nil ? nil : event_wait_list.pack("Q"), event_buf)
|
994
|
+
error_info << err if error_info != nil
|
995
|
+
|
996
|
+
event << event_buf.unpack("Q")[0] if event != nil
|
997
|
+
return err
|
998
|
+
end
|
999
|
+
|
1000
|
+
# cl_command_queue : command_queue
|
1001
|
+
# cl_kernel : kernel
|
1002
|
+
# cl_uint : work_dim
|
1003
|
+
# const size_t * : global_work_offset
|
1004
|
+
# const size_t * : global_work_size
|
1005
|
+
# const size_t * : local_work_size
|
1006
|
+
# const cl_event * : event_wait_list
|
1007
|
+
# cl_event * : event
|
1008
|
+
def enqueueNDRangeKernel(kernel, work_dim, global_work_offset, global_work_size, local_work_size, command_queue: @command_queue, event_wait_list: nil, event: nil, error_info: nil)
|
1009
|
+
event_buf = event == nil ? nil : ' ' * 8
|
1010
|
+
num_events_in_wait_list = event_wait_list == nil ? 0 : event_wait_list.length
|
1011
|
+
|
1012
|
+
global_work_offset_buf = global_work_offset == nil ? nil : global_work_offset.pack("Q*")
|
1013
|
+
local_work_size_buf = local_work_size == nil ? nil : local_work_size.pack("Q*")
|
1014
|
+
|
1015
|
+
err = OpenCL.clEnqueueNDRangeKernel(command_queue, kernel, work_dim, global_work_offset_buf, global_work_size.pack("Q*"), local_work_size_buf, num_events_in_wait_list, event_wait_list == nil ? nil : event_wait_list.pack("Q"), event_buf)
|
1016
|
+
error_info << err if error_info != nil
|
1017
|
+
|
1018
|
+
event << event_buf.unpack("Q")[0] if event != nil
|
1019
|
+
return err
|
1020
|
+
end
|
1021
|
+
|
1022
|
+
# cl_command_queue : command_queue
|
1023
|
+
# cl_kernel : kernel
|
1024
|
+
# const cl_event * : event_wait_list
|
1025
|
+
# cl_event * : event
|
1026
|
+
def enqueueTask(kernel, command_queue: @command_queue, event_wait_list: nil, event: nil, error_info: nil)
|
1027
|
+
event_buf = event == nil ? nil : ' ' * 8
|
1028
|
+
num_events_in_wait_list = event_wait_list == nil ? 0 : event_wait_list.length
|
1029
|
+
|
1030
|
+
err = OpenCL.clEnqueueTask(command_queue, kernel, num_events_in_wait_list, event_wait_list == nil ? nil : event_wait_list.pack("Q"), event_buf)
|
1031
|
+
error_info << err if error_info != nil
|
1032
|
+
|
1033
|
+
event << event_buf.unpack("Q")[0] if event != nil
|
1034
|
+
return err
|
1035
|
+
end
|
1036
|
+
|
1037
|
+
# cl_command_queue : command_queue
|
1038
|
+
# const cl_mem * : mem_objects
|
1039
|
+
# const cl_event * : event_wait_list
|
1040
|
+
# cl_event * : event
|
1041
|
+
def enqueueAcquireGLObjects(mem_objects, command_queue: @command_queue, event_wait_list: nil, event: nil, error_info: nil)
|
1042
|
+
event_buf = event == nil ? nil : ' ' * 8
|
1043
|
+
num_events_in_wait_list = event_wait_list == nil ? 0 : event_wait_list.length
|
1044
|
+
|
1045
|
+
err = OpenCL.clEnqueueAcquireGLObjects(command_queue, mem_objects.length, mem_objects.pack("Q*"), num_events_in_wait_list, event_wait_list == nil ? nil : event_wait_list.pack("Q"), event_buf)
|
1046
|
+
error_info << err if error_info != nil
|
1047
|
+
|
1048
|
+
event << event_buf.unpack("Q")[0] if event != nil
|
1049
|
+
return err
|
1050
|
+
end
|
1051
|
+
|
1052
|
+
# cl_command_queue : command_queue
|
1053
|
+
# const cl_mem * : mem_objects
|
1054
|
+
# const cl_event * : event_wait_list
|
1055
|
+
# cl_event * : event
|
1056
|
+
def enqueueReleaseGLObjects(mem_objects, command_queue: @command_queue, event_wait_list: nil, event: nil, error_info: nil)
|
1057
|
+
event_buf = event == nil ? nil : ' ' * 8
|
1058
|
+
num_events_in_wait_list = event_wait_list == nil ? 0 : event_wait_list.length
|
1059
|
+
|
1060
|
+
err = OpenCL.clEnqueueReleaseGLObjects(command_queue, mem_objects.length, mem_objects.pack("Q*"), num_events_in_wait_list, event_wait_list == nil ? nil : event_wait_list.pack("Q"), event_buf)
|
1061
|
+
error_info << err if error_info != nil
|
1062
|
+
|
1063
|
+
event << event_buf.unpack("Q")[0] if event != nil
|
1064
|
+
return err
|
1065
|
+
end
|
1066
|
+
end
|
1067
|
+
|
1068
|
+
################################################################################
|
1069
|
+
|
1070
|
+
class CLUProgram
|
1071
|
+
attr_reader :program # cl_program
|
1072
|
+
|
1073
|
+
def initialize
|
1074
|
+
@program = nil
|
1075
|
+
end
|
1076
|
+
|
1077
|
+
# cl_context : context
|
1078
|
+
# const char ** : strings
|
1079
|
+
def createProgramWithSource(context, strings, error_info: nil)
|
1080
|
+
# cl_uint : count
|
1081
|
+
# const size_t * : lengths
|
1082
|
+
# cl_int * : errcode_ret
|
1083
|
+
errcode_ret_buf = ' ' * 4
|
1084
|
+
count = strings.length
|
1085
|
+
lengthes = strings.collect {|src| src.length}
|
1086
|
+
|
1087
|
+
program = OpenCL.clCreateProgramWithSource(context, count, strings.pack("p*"), lengthes.pack("Q*"), errcode_ret_buf)
|
1088
|
+
errcode_ret = errcode_ret_buf.unpack("l")[0]
|
1089
|
+
error_info << errcode_ret if error_info != nil
|
1090
|
+
|
1091
|
+
if errcode_ret == OpenCL::CL_SUCCESS
|
1092
|
+
@program = program
|
1093
|
+
return @program
|
1094
|
+
else
|
1095
|
+
return nil
|
1096
|
+
end
|
1097
|
+
end
|
1098
|
+
|
1099
|
+
def self.newProgramWithSource(context, strings, error_info: nil)
|
1100
|
+
obj = CLUProgram.new
|
1101
|
+
ret = obj.createProgramWithSource(context, strings, error_info: error_info)
|
1102
|
+
return ret == nil ? nil : obj
|
1103
|
+
end
|
1104
|
+
|
1105
|
+
# cl_program : program
|
1106
|
+
def retainProgram(program: @program)
|
1107
|
+
return OpenCL.clRetainProgram(program)
|
1108
|
+
end
|
1109
|
+
|
1110
|
+
# cl_program : program
|
1111
|
+
def releaseProgram(program: @program)
|
1112
|
+
return OpenCL.clReleaseProgram(program)
|
1113
|
+
end
|
1114
|
+
|
1115
|
+
# cl_program : program
|
1116
|
+
# const cl_device_id * : device_list
|
1117
|
+
# const char * : options
|
1118
|
+
# void * : pfn_notify(cl_program, void*)
|
1119
|
+
# void * : user_data
|
1120
|
+
def buildProgram(device_list, program: @program, options: nil, pfn_notify: nil, user_data: nil, error_info: nil)
|
1121
|
+
num_devices = device_list.length
|
1122
|
+
err = OpenCL.clBuildProgram(program, num_devices, device_list.pack("Q*"), options, pfn_notify, user_data)
|
1123
|
+
|
1124
|
+
if err < 0 && error_info != nil
|
1125
|
+
log_size_buf = ' ' * 4
|
1126
|
+
OpenCL.clGetProgramBuildInfo(program, device_list[0], OpenCL::CL_PROGRAM_BUILD_LOG, 0, nil, log_size_buf)
|
1127
|
+
log_size = log_size_buf.unpack("L")[0]
|
1128
|
+
program_log = ' ' * log_size
|
1129
|
+
OpenCL.clGetProgramBuildInfo(program, device_list[0], OpenCL::CL_PROGRAM_BUILD_LOG, log_size, program_log, nil)
|
1130
|
+
|
1131
|
+
error_info << program_log
|
1132
|
+
end
|
1133
|
+
|
1134
|
+
return err
|
1135
|
+
end
|
1136
|
+
end
|
1137
|
+
|
1138
|
+
################################################################################
|
1139
|
+
|
1140
|
+
class CLUKernel
|
1141
|
+
attr_reader :kernel, :name # cl_kernel and the name of '__kernel' entry point
|
1142
|
+
|
1143
|
+
def initialize
|
1144
|
+
@kernel = nil
|
1145
|
+
@name = nil
|
1146
|
+
end
|
1147
|
+
|
1148
|
+
# cl_program : program
|
1149
|
+
# const char * : kernel_name
|
1150
|
+
def createKernel(program, kernel_name, error_info: nil)
|
1151
|
+
errcode_ret_buf = ' ' * 4
|
1152
|
+
kernel = OpenCL.clCreateKernel(program, kernel_name, errcode_ret_buf)
|
1153
|
+
errcode_ret = errcode_ret_buf.unpack("l")[0]
|
1154
|
+
error_info << errcode_ret if error_info != nil
|
1155
|
+
|
1156
|
+
if errcode_ret == OpenCL::CL_SUCCESS
|
1157
|
+
@kernel = kernel
|
1158
|
+
@name = kernel_name
|
1159
|
+
return @kernel
|
1160
|
+
else
|
1161
|
+
return nil
|
1162
|
+
end
|
1163
|
+
end
|
1164
|
+
|
1165
|
+
def self.newKernel(program, kernel_name, error_info: nil)
|
1166
|
+
obj = CLUKernel.new
|
1167
|
+
ret = obj.createKernel(program, kernel_name, error_info: error_info)
|
1168
|
+
return ret == nil ? nil : obj
|
1169
|
+
end
|
1170
|
+
|
1171
|
+
# cl_kernel : kernel
|
1172
|
+
# cl_kernel_info : param_name
|
1173
|
+
def getKernelInfo(param_name, kernel: @kernel, error_info: nil)
|
1174
|
+
# size_t : param_value_size
|
1175
|
+
# void * : param_value
|
1176
|
+
# size_t * : param_value_size_ret
|
1177
|
+
param_value_buf_length = 1024
|
1178
|
+
param_value_buf = ' ' * param_value_buf_length
|
1179
|
+
param_value_size_ret_buf = ' ' * 4
|
1180
|
+
|
1181
|
+
err = OpenCL.clGetKernelInfo(kernel, param_name, param_value_buf_length, param_value_buf, param_value_size_ret_buf)
|
1182
|
+
error_info << err if error_info != nil
|
1183
|
+
|
1184
|
+
param_value_size_ret = param_value_size_ret_buf.unpack("L")[0]
|
1185
|
+
|
1186
|
+
unpack_format = @@kernel_info_param2unpack[param_name]
|
1187
|
+
case unpack_format
|
1188
|
+
when "char[]"
|
1189
|
+
return param_value_buf[0...(param_value_size_ret-1)]
|
1190
|
+
else
|
1191
|
+
return param_value_buf.unpack(unpack_format)[0]
|
1192
|
+
end
|
1193
|
+
end
|
1194
|
+
|
1195
|
+
@@kernel_info_param2unpack = {
|
1196
|
+
OpenCL::CL_KERNEL_FUNCTION_NAME => "char[]",
|
1197
|
+
OpenCL::CL_KERNEL_NUM_ARGS => "L",
|
1198
|
+
OpenCL::CL_KERNEL_REFERENCE_COUNT => "L",
|
1199
|
+
OpenCL::CL_KERNEL_CONTEXT => "Q",
|
1200
|
+
OpenCL::CL_KERNEL_PROGRAM => "Q",
|
1201
|
+
OpenCL::CL_KERNEL_ATTRIBUTES => "char[]",
|
1202
|
+
}
|
1203
|
+
|
1204
|
+
# cl_kernel : kernel
|
1205
|
+
def retainKernel(kernel: @kernel)
|
1206
|
+
return OpenCL.clRetainKernel(kernel)
|
1207
|
+
end
|
1208
|
+
|
1209
|
+
# cl_kernel : kernel
|
1210
|
+
def releaseKernel(kernel: @kernel)
|
1211
|
+
return OpenCL.clReleaseKernel(kernel)
|
1212
|
+
end
|
1213
|
+
|
1214
|
+
def sizeof_type(fiddle_type)
|
1215
|
+
size = 0
|
1216
|
+
|
1217
|
+
case fiddle_type
|
1218
|
+
when Fiddle::TYPE_VOIDP
|
1219
|
+
size = Fiddle::SIZEOF_VOIDP
|
1220
|
+
when Fiddle::TYPE_CHAR, -Fiddle::TYPE_CHAR
|
1221
|
+
size = Fiddle::SIZEOF_CHAR
|
1222
|
+
when Fiddle::TYPE_SHORT, -Fiddle::TYPE_SHORT
|
1223
|
+
size = Fiddle::SIZEOF_SHORT
|
1224
|
+
when Fiddle::TYPE_INT, -Fiddle::TYPE_INT
|
1225
|
+
size = Fiddle::SIZEOF_INT
|
1226
|
+
when Fiddle::TYPE_LONG, -Fiddle::TYPE_LONG
|
1227
|
+
size = Fiddle::SIZEOF_LONG
|
1228
|
+
when Fiddle::TYPE_FLOAT
|
1229
|
+
size = Fiddle::SIZEOF_FLOAT
|
1230
|
+
when Fiddle::TYPE_DOUBLE
|
1231
|
+
size = Fiddle::SIZEOF_DOUBLE
|
1232
|
+
when Fiddle::TYPE_SIZE_T
|
1233
|
+
size = Fiddle::SIZEOF_SIZE_T
|
1234
|
+
when Fiddle::TYPE_SSIZE_T
|
1235
|
+
size = Fiddle::SIZEOF_SSIZE_T
|
1236
|
+
when Fiddle::TYPE_PTRDIFF_T
|
1237
|
+
size = Fiddle::SIZEOF_PTRDIFF_T
|
1238
|
+
when Fiddle::TYPE_INTPTR_T
|
1239
|
+
size = Fiddle::SIZEOF_INTPTR_T
|
1240
|
+
when Fiddle::TYPE_UINTPTR_T
|
1241
|
+
size = Fiddle::SIZEOF_UINTPTR_T
|
1242
|
+
end
|
1243
|
+
|
1244
|
+
if Fiddle.const_defined?(:TYPE_LONG_LONG) && (fiddle_type == Fiddle::TYPE_LONG_LONG || fiddle_type == -Fiddle::TYPE_LONG_LONG)
|
1245
|
+
size = Fiddle::SIZEOF_LONG_LONG
|
1246
|
+
end
|
1247
|
+
|
1248
|
+
return size
|
1249
|
+
end
|
1250
|
+
private :sizeof_type
|
1251
|
+
|
1252
|
+
def pack_format(fiddle_type)
|
1253
|
+
format = ""
|
1254
|
+
|
1255
|
+
case fiddle_type
|
1256
|
+
when Fiddle::TYPE_VOIDP
|
1257
|
+
format = (Fiddle.const_defined?(:TYPE_LONG_LONG) && (Fiddle::SIZEOF_VOIDP == Fiddle::SIZEOF_LONG_LONG)) ? "Q" : "L"
|
1258
|
+
|
1259
|
+
when Fiddle::TYPE_CHAR, -Fiddle::TYPE_CHAR
|
1260
|
+
format = fiddle_type > 0 ? "c" : "C"
|
1261
|
+
|
1262
|
+
when Fiddle::TYPE_SHORT, -Fiddle::TYPE_SHORT
|
1263
|
+
format = fiddle_type > 0 ? "s" : "S"
|
1264
|
+
|
1265
|
+
when Fiddle::TYPE_INT, -Fiddle::TYPE_INT
|
1266
|
+
format = fiddle_type > 0 ? "i" : "I"
|
1267
|
+
|
1268
|
+
when Fiddle::TYPE_LONG, -Fiddle::TYPE_LONG
|
1269
|
+
format = fiddle_type > 0 ? "l" : "L"
|
1270
|
+
|
1271
|
+
when Fiddle::TYPE_FLOAT
|
1272
|
+
format = "F"
|
1273
|
+
|
1274
|
+
when Fiddle::TYPE_DOUBLE
|
1275
|
+
format = "D"
|
1276
|
+
|
1277
|
+
when Fiddle::TYPE_SIZE_T, Fiddle::TYPE_UINTPTR_T
|
1278
|
+
size = sizeof_type(fiddle_type)
|
1279
|
+
case size
|
1280
|
+
when Fiddle::SIZEOF_INT
|
1281
|
+
format = "I"
|
1282
|
+
when Fiddle::SIZEOF_LONG
|
1283
|
+
format = "L"
|
1284
|
+
else
|
1285
|
+
if Fiddle.const_defined?(:TYPE_LONG_LONG) && size == Fiddle::SIZEOF_LONG_LONG
|
1286
|
+
format = "Q"
|
1287
|
+
end
|
1288
|
+
end
|
1289
|
+
|
1290
|
+
when Fiddle::TYPE_SSIZE_T, Fiddle::TYPE_PTRDIFF_T, Fiddle::TYPE_INTPTR_T
|
1291
|
+
size = sizeof_type(fiddle_type)
|
1292
|
+
case size
|
1293
|
+
when Fiddle::SIZEOF_INT
|
1294
|
+
format = "i"
|
1295
|
+
when Fiddle::SIZEOF_LONG
|
1296
|
+
format = "l"
|
1297
|
+
else
|
1298
|
+
if Fiddle.const_defined?(:TYPE_LONG_LONG) && size == Fiddle::SIZEOF_LONG_LONG
|
1299
|
+
format = "q"
|
1300
|
+
end
|
1301
|
+
end
|
1302
|
+
end
|
1303
|
+
|
1304
|
+
if Fiddle.const_defined?(:TYPE_LONG_LONG) && (fiddle_type == Fiddle::TYPE_LONG_LONG || fiddle_type == -Fiddle::TYPE_LONG_LONG)
|
1305
|
+
format = fiddle_type > 0 ? "q" : "Q"
|
1306
|
+
end
|
1307
|
+
|
1308
|
+
return format
|
1309
|
+
end
|
1310
|
+
private :sizeof_type
|
1311
|
+
|
1312
|
+
# cl_kernel : kernel
|
1313
|
+
# cl_uint : arg_index
|
1314
|
+
# Fiddle::TYPE_VOIDP, etc. : arg_type
|
1315
|
+
# const void * : arg_value
|
1316
|
+
def setKernelArg(arg_index, arg_type, arg_value, kernel: @kernel)
|
1317
|
+
num_elements = arg_value.length
|
1318
|
+
arg_size = sizeof_type(arg_type) * num_elements
|
1319
|
+
pack_arg = pack_format(arg_type) + num_elements.to_s
|
1320
|
+
|
1321
|
+
return OpenCL.clSetKernelArg(kernel, arg_index, arg_size, arg_value.pack(pack_arg))
|
1322
|
+
end
|
1323
|
+
|
1324
|
+
# cl_kernel : kernel
|
1325
|
+
# cl_uint : arg_indx
|
1326
|
+
# cl_kernel_info : param_name
|
1327
|
+
def getKernelArgInfo(arg_index, param_name, kernel: @kernel, error_info: nil)
|
1328
|
+
# size_t : param_value_size
|
1329
|
+
# void * : param_value
|
1330
|
+
# size_t * : param_value_size_ret
|
1331
|
+
param_value_buf_length = 1024
|
1332
|
+
param_value_buf = ' ' * param_value_buf_length
|
1333
|
+
param_value_size_ret_buf = ' ' * 4
|
1334
|
+
|
1335
|
+
err = OpenCL.clGetKernelArgInfo(kernel, arg_index, param_name, param_value_buf_length, param_value_buf, param_value_size_ret_buf)
|
1336
|
+
error_info << err if error_info != nil
|
1337
|
+
param_value_size_ret = param_value_size_ret_buf.unpack("L")[0]
|
1338
|
+
|
1339
|
+
unpack_format = @@kernel_arginfo_param2unpack[param_name]
|
1340
|
+
case unpack_format
|
1341
|
+
when "char[]"
|
1342
|
+
return param_value_buf[0...(param_value_size_ret-1)]
|
1343
|
+
else
|
1344
|
+
return param_value_buf.unpack(unpack_format)[0]
|
1345
|
+
end
|
1346
|
+
end
|
1347
|
+
|
1348
|
+
@@kernel_arginfo_param2unpack = {
|
1349
|
+
OpenCL::CL_KERNEL_ARG_ADDRESS_QUALIFIER => "L",
|
1350
|
+
OpenCL::CL_KERNEL_ARG_ACCESS_QUALIFIER => "L",
|
1351
|
+
OpenCL::CL_KERNEL_ARG_TYPE_NAME => "char[]",
|
1352
|
+
OpenCL::CL_KERNEL_ARG_TYPE_QUALIFIER => "L",
|
1353
|
+
OpenCL::CL_KERNEL_ARG_NAME => "char[]",
|
1354
|
+
}
|
1355
|
+
|
1356
|
+
# cl_kernel : kernel
|
1357
|
+
# cl_device_id : device
|
1358
|
+
# cl_kernel_work_group_info : param_name
|
1359
|
+
def getKernelWorkGroupInfo(param_name, device, kernel: @kernel, error_info: nil)
|
1360
|
+
# size_t : param_value_size
|
1361
|
+
# void * : param_value
|
1362
|
+
# size_t * : param_value_size_ret
|
1363
|
+
param_value_buf_length = 1024
|
1364
|
+
param_value_buf = ' ' * param_value_buf_length
|
1365
|
+
param_value_size_ret_buf = ' ' * 4
|
1366
|
+
|
1367
|
+
err = OpenCL.clGetKernelWorkGroupInfo(kernel, device, param_name, param_value_buf_length, param_value_buf, param_value_size_ret_buf)
|
1368
|
+
error_info << err if error_info != nil
|
1369
|
+
param_value_size_ret = param_value_size_ret_buf.unpack("L")[0]
|
1370
|
+
|
1371
|
+
unpack_format = @@kernel_workgroupinfo_param2unpack[param_name]
|
1372
|
+
case unpack_format
|
1373
|
+
when "Q3"
|
1374
|
+
# Ref.: https://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/clGetKernelWorkGroupInfo.html
|
1375
|
+
# CL_INVALID_VALUE if param_name is CL_KERNEL_GLOBAL_WORK_SIZE and device
|
1376
|
+
# is not a custom device or kernel is not a built-in kernel.
|
1377
|
+
if param_name == OpenCL::CL_KERNEL_GLOBAL_WORK_SIZE && err == OpenCL::CL_INVALID_VALUE
|
1378
|
+
return [0, 0, 0]
|
1379
|
+
else
|
1380
|
+
return param_value_buf.unpack(unpack_format)
|
1381
|
+
end
|
1382
|
+
else
|
1383
|
+
return param_value_buf.unpack(unpack_format)[0]
|
1384
|
+
end
|
1385
|
+
end
|
1386
|
+
|
1387
|
+
@@kernel_workgroupinfo_param2unpack = {
|
1388
|
+
OpenCL::CL_KERNEL_GLOBAL_WORK_SIZE => "Q3",
|
1389
|
+
OpenCL::CL_KERNEL_WORK_GROUP_SIZE => "Q",
|
1390
|
+
OpenCL::CL_KERNEL_COMPILE_WORK_GROUP_SIZE => "Q3",
|
1391
|
+
OpenCL::CL_KERNEL_LOCAL_MEM_SIZE => "Q",
|
1392
|
+
OpenCL::CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE => "Q",
|
1393
|
+
OpenCL::CL_KERNEL_PRIVATE_MEM_SIZE => "Q",
|
1394
|
+
}
|
1395
|
+
end
|
1396
|
+
|
1397
|
+
################################################################################
|
1398
|
+
|
1399
|
+
class CLU
|
1400
|
+
|
1401
|
+
@@image_format = {
|
1402
|
+
# cl_channel_order
|
1403
|
+
OpenCL::CL_R => "CL_R",
|
1404
|
+
OpenCL::CL_A => "CL_A",
|
1405
|
+
OpenCL::CL_RG => "CL_RG",
|
1406
|
+
OpenCL::CL_RA => "CL_RA",
|
1407
|
+
OpenCL::CL_RGB => "CL_RGB",
|
1408
|
+
OpenCL::CL_RGBA => "CL_RGBA",
|
1409
|
+
OpenCL::CL_BGRA => "CL_BGRA",
|
1410
|
+
OpenCL::CL_ARGB => "CL_ARGB",
|
1411
|
+
OpenCL::CL_INTENSITY => "CL_INTENSITY",
|
1412
|
+
OpenCL::CL_LUMINANCE => "CL_LUMINANCE",
|
1413
|
+
OpenCL::CL_Rx => "CL_Rx",
|
1414
|
+
OpenCL::CL_RGx => "CL_RGx",
|
1415
|
+
OpenCL::CL_RGBx => "CL_RGBx",
|
1416
|
+
OpenCL::CL_DEPTH => "CL_DEPTH",
|
1417
|
+
OpenCL::CL_DEPTH_STENCIL => "CL_DEPTH_STENCIL",
|
1418
|
+
|
1419
|
+
# cl_channel_type
|
1420
|
+
OpenCL::CL_SNORM_INT8 => "CL_SNORM_INT8",
|
1421
|
+
OpenCL::CL_SNORM_INT16 => "CL_SNORM_INT16",
|
1422
|
+
OpenCL::CL_UNORM_INT8 => "CL_UNORM_INT8",
|
1423
|
+
OpenCL::CL_UNORM_INT16 => "CL_UNORM_INT16",
|
1424
|
+
OpenCL::CL_UNORM_SHORT_565 => "CL_UNORM_SHORT_565",
|
1425
|
+
OpenCL::CL_UNORM_SHORT_555 => "CL_UNORM_SHORT_555",
|
1426
|
+
OpenCL::CL_UNORM_INT_101010 => "CL_UNORM_INT_101010",
|
1427
|
+
OpenCL::CL_SIGNED_INT8 => "CL_SIGNED_INT8",
|
1428
|
+
OpenCL::CL_SIGNED_INT16 => "CL_SIGNED_INT16",
|
1429
|
+
OpenCL::CL_SIGNED_INT32 => "CL_SIGNED_INT32",
|
1430
|
+
OpenCL::CL_UNSIGNED_INT8 => "CL_UNSIGNED_INT8",
|
1431
|
+
OpenCL::CL_UNSIGNED_INT16 => "CL_UNSIGNED_INT16",
|
1432
|
+
OpenCL::CL_UNSIGNED_INT32 => "CL_UNSIGNED_INT32",
|
1433
|
+
OpenCL::CL_HALF_FLOAT => "CL_HALF_FLOAT",
|
1434
|
+
OpenCL::CL_FLOAT => "CL_FLOAT",
|
1435
|
+
OpenCL::CL_UNORM_INT24 => "CL_UNORM_INT24",
|
1436
|
+
|
1437
|
+
# 0x10000012 : ABGR and xBGR formats for CoreImage CL-GPU support (from /OpenCL.framework/Headers/cl_ext.h)
|
1438
|
+
OpenCL::CL_ABGR_APPLE => "CL_ABGR_APPLE"
|
1439
|
+
}
|
1440
|
+
|
1441
|
+
def self.getImageFormatString(image_channel)
|
1442
|
+
return @@image_format.has_key?(image_channel) ? @@image_format[image_channel] : image_channel.to_s
|
1443
|
+
end
|
1444
|
+
end
|
1445
|
+
|
1446
|
+
################################################################################
|
1447
|
+
|
1448
|
+
=begin
|
1449
|
+
Ruby-OpenCL : Yet another OpenCL wrapper for Ruby
|
1450
|
+
Copyright (c) 2015 vaiorabbit <http://twitter.com/vaiorabbit>
|
1451
|
+
|
1452
|
+
This software is provided 'as-is', without any express or implied
|
1453
|
+
warranty. In no event will the authors be held liable for any damages
|
1454
|
+
arising from the use of this software.
|
1455
|
+
|
1456
|
+
Permission is granted to anyone to use this software for any purpose,
|
1457
|
+
including commercial applications, and to alter it and redistribute it
|
1458
|
+
freely, subject to the following restrictions:
|
1459
|
+
|
1460
|
+
1. The origin of this software must not be misrepresented; you must not
|
1461
|
+
claim that you wrote the original software. If you use this software
|
1462
|
+
in a product, an acknowledgment in the product documentation would be
|
1463
|
+
appreciated but is not required.
|
1464
|
+
|
1465
|
+
2. Altered source versions must be plainly marked as such, and must not be
|
1466
|
+
misrepresented as being the original software.
|
1467
|
+
|
1468
|
+
3. This notice may not be removed or altered from any source
|
1469
|
+
distribution.
|
1470
|
+
=end
|