1 |
#include "EXTERN.h" |
2 |
#include "perl.h" |
3 |
#include "XSUB.h" |
4 |
|
5 |
#include <CL/opencl.h> |
6 |
|
7 |
typedef cl_platform_id OpenCL__Platform; |
8 |
typedef cl_device_id OpenCL__Device; |
9 |
typedef cl_context OpenCL__Context; |
10 |
typedef cl_command_queue OpenCL__Queue; |
11 |
typedef cl_mem OpenCL__Memory; |
12 |
typedef cl_sampler OpenCL__Sampler; |
13 |
typedef cl_program OpenCL__Program; |
14 |
typedef cl_kernel OpenCL__Kernel; |
15 |
typedef cl_event OpenCL__Event; |
16 |
|
17 |
static const struct { |
18 |
IV iv; |
19 |
const char *name; |
20 |
} cl_error[] = { |
21 |
#define def_error(name) { (IV)CL_ ## name, # name }, |
22 |
#include "invalid.h" |
23 |
}; |
24 |
|
25 |
static const char * |
26 |
clstrerror (cl_int res) |
27 |
{ |
28 |
int i; |
29 |
static char numbuf [32]; |
30 |
|
31 |
for (i = sizeof (cl_error) / sizeof (cl_error [0]); i--; ) |
32 |
if (cl_error [i].iv == res) |
33 |
return cl_error [i].name; |
34 |
|
35 |
snprintf (numbuf, sizeof (numbuf), "ERROR(%d)", res); |
36 |
|
37 |
return numbuf; |
38 |
} |
39 |
|
40 |
#define FAIL(name,res) \ |
41 |
croak ("cl" # name ": %s", clstrerror (res)); |
42 |
|
43 |
#define NEED_SUCCESS(name,args) \ |
44 |
do { \ |
45 |
cl_int res = cl ## name args; \ |
46 |
\ |
47 |
if (res) \ |
48 |
FAIL (name, res); \ |
49 |
} while (0) |
50 |
|
51 |
#define NEW_MORTAL_OBJ(class,ptr) sv_setref_pv (sv_newmortal (), class, ptr) |
52 |
#define XPUSH_NEW_OBJ(class,ptr) XPUSHs (NEW_MORTAL_OBJ (class, ptr)) |
53 |
|
54 |
/*TODO*/ |
55 |
#define EVENT_LIST(items,count) cl_uint event_list_count = 0; cl_event *event_list_ptr = 0 |
56 |
|
57 |
#define INFO(class) \ |
58 |
{ \ |
59 |
size_t size; \ |
60 |
SV *sv; \ |
61 |
\ |
62 |
NEED_SUCCESS (Get ## class ## Info, (this, name, 0, 0, &size)); \ |
63 |
sv = sv_2mortal (newSV (size)); \ |
64 |
SvUPGRADE (sv, SVt_PV); \ |
65 |
SvPOK_only (sv); \ |
66 |
SvCUR_set (sv, size); \ |
67 |
NEED_SUCCESS (Get ## class ## Info, (this, name, size, SvPVX (sv), 0)); \ |
68 |
XPUSHs (sv); \ |
69 |
} |
70 |
|
71 |
MODULE = OpenCL PACKAGE = OpenCL |
72 |
|
73 |
PROTOTYPES: ENABLE |
74 |
|
75 |
BOOT: |
76 |
{ |
77 |
HV *stash = gv_stashpv ("OpenCL", 1); |
78 |
static const struct { |
79 |
const char *name; |
80 |
IV iv; |
81 |
} *civ, const_iv[] = { |
82 |
#define const_iv(name) { # name, (IV)CL_ ## name }, |
83 |
#include "constiv.h" |
84 |
}; |
85 |
for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ > const_iv; civ--) |
86 |
newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv)); |
87 |
} |
88 |
|
89 |
void |
90 |
platforms () |
91 |
PPCODE: |
92 |
{ |
93 |
cl_platform_id *list; |
94 |
cl_uint count; |
95 |
int i; |
96 |
|
97 |
NEED_SUCCESS (GetPlatformIDs, (0, 0, &count)); |
98 |
Newx (list, count, cl_platform_id); |
99 |
NEED_SUCCESS (GetPlatformIDs, (count, list, 0)); |
100 |
|
101 |
EXTEND (SP, count); |
102 |
for (i = 0; i < count; ++i) |
103 |
PUSHs (NEW_MORTAL_OBJ ("OpenCL::Platform", list [i])); |
104 |
|
105 |
Safefree (list); |
106 |
} |
107 |
|
108 |
void |
109 |
context_from_type_simple (cl_device_type type = CL_DEVICE_TYPE_DEFAULT) |
110 |
PPCODE: |
111 |
{ |
112 |
cl_int res; |
113 |
cl_context ctx = clCreateContextFromType (0, type, 0, 0, &res); |
114 |
|
115 |
if (res) |
116 |
FAIL (CreateContextFromType, res); |
117 |
|
118 |
XPUSH_NEW_OBJ ("OpenCL::Context", ctx); |
119 |
} |
120 |
|
121 |
void |
122 |
wait_for_events (...) |
123 |
CODE: |
124 |
{ |
125 |
EVENT_LIST (0, items); |
126 |
NEED_SUCCESS (WaitForEvents, (event_list_count, event_list_ptr)); |
127 |
} |
128 |
|
129 |
PROTOTYPES: DISABLE |
130 |
|
131 |
MODULE = OpenCL PACKAGE = OpenCL::Platform |
132 |
|
133 |
void |
134 |
info (OpenCL::Platform this, cl_platform_info name) |
135 |
PPCODE: |
136 |
INFO (Platform) |
137 |
|
138 |
void |
139 |
devices (OpenCL::Platform this, cl_device_type type = CL_DEVICE_TYPE_ALL) |
140 |
PPCODE: |
141 |
{ |
142 |
cl_device_id *list; |
143 |
cl_uint count; |
144 |
int i; |
145 |
|
146 |
NEED_SUCCESS (GetDeviceIDs, (this, type, 0, 0, &count)); |
147 |
Newx (list, count, cl_device_id); |
148 |
NEED_SUCCESS (GetDeviceIDs, (this, type, count, list, 0)); |
149 |
|
150 |
EXTEND (SP, count); |
151 |
for (i = 0; i < count; ++i) |
152 |
PUSHs (sv_setref_pv (sv_newmortal (), "OpenCL::Device", list [i])); |
153 |
|
154 |
Safefree (list); |
155 |
} |
156 |
|
157 |
void |
158 |
context_from_type_simple (OpenCL::Platform this, cl_device_type type = CL_DEVICE_TYPE_DEFAULT) |
159 |
PPCODE: |
160 |
{ |
161 |
cl_int res; |
162 |
cl_context_properties props[] = { CL_CONTEXT_PLATFORM, (cl_context_properties)this, 0 }; |
163 |
cl_context ctx = clCreateContextFromType (props, type, 0, 0, &res); |
164 |
|
165 |
if (res) |
166 |
FAIL (CreateContextFromType, res); |
167 |
|
168 |
XPUSH_NEW_OBJ ("OpenCL::Context", ctx); |
169 |
} |
170 |
|
171 |
void |
172 |
unload_compiler () |
173 |
CODE: |
174 |
NEED_SUCCESS (UnloadCompiler, ()); |
175 |
|
176 |
MODULE = OpenCL PACKAGE = OpenCL::Device |
177 |
|
178 |
void |
179 |
info (OpenCL::Device this, cl_device_info name) |
180 |
PPCODE: |
181 |
INFO (Device) |
182 |
|
183 |
void |
184 |
context_simple (OpenCL::Device this) |
185 |
PPCODE: |
186 |
{ |
187 |
cl_int res; |
188 |
cl_context ctx = clCreateContext (0, 1, &this, 0, 0, &res); |
189 |
|
190 |
if (res) |
191 |
FAIL (CreateContext, res); |
192 |
|
193 |
XPUSH_NEW_OBJ ("OpenCL::Context", ctx); |
194 |
} |
195 |
|
196 |
MODULE = OpenCL PACKAGE = OpenCL::Context |
197 |
|
198 |
void |
199 |
DESTROY (OpenCL::Context context) |
200 |
CODE: |
201 |
clReleaseContext (context); |
202 |
|
203 |
void |
204 |
info (OpenCL::Context this, cl_context_info name) |
205 |
PPCODE: |
206 |
INFO (Context) |
207 |
|
208 |
void |
209 |
command_queue_simple (OpenCL::Context this, OpenCL::Device device) |
210 |
PPCODE: |
211 |
{ |
212 |
cl_int res; |
213 |
cl_command_queue queue = clCreateCommandQueue (this, device, 0, &res); |
214 |
|
215 |
if (res) |
216 |
FAIL (CreateCommandQueue, res); |
217 |
|
218 |
XPUSH_NEW_OBJ ("OpenCL::Queue", queue); |
219 |
} |
220 |
|
221 |
void |
222 |
buffer (OpenCL::Context this, cl_mem_flags flags, size_t len) |
223 |
PPCODE: |
224 |
{ |
225 |
cl_int res; |
226 |
cl_mem mem = clCreateBuffer (this, flags, len, 0, &res); |
227 |
|
228 |
if (res) |
229 |
FAIL (CreateBuffer, res); |
230 |
|
231 |
XPUSH_NEW_OBJ ("OpenCL::Memory", mem); |
232 |
} |
233 |
|
234 |
void |
235 |
buffer_sv (OpenCL::Context this, cl_mem_flags flags, SV *data) |
236 |
PPCODE: |
237 |
{ |
238 |
STRLEN len; |
239 |
char *ptr = SvPVbyte (data, len); |
240 |
cl_int res; |
241 |
cl_mem mem = clCreateBuffer (this, flags, len, ptr, &res); |
242 |
|
243 |
if (res) |
244 |
FAIL (CreateBuffer, res); |
245 |
|
246 |
XPUSH_NEW_OBJ ("OpenCL::Memory", mem); |
247 |
} |
248 |
|
249 |
void |
250 |
sampler (OpenCL::Context this, cl_bool normalized_coords, cl_addressing_mode addressing_mode, cl_filter_mode filter_mode) |
251 |
PPCODE: |
252 |
{ |
253 |
cl_int res; |
254 |
cl_sampler sampler = clCreateSampler (this, normalized_coords, addressing_mode, filter_mode, &res); |
255 |
|
256 |
if (res) |
257 |
FAIL (CreateSampler, res); |
258 |
|
259 |
XPUSH_NEW_OBJ ("OpenCL::Sampler", sampler); |
260 |
} |
261 |
|
262 |
void |
263 |
program_with_source (OpenCL::Context this, SV *program) |
264 |
PPCODE: |
265 |
{ |
266 |
STRLEN len; |
267 |
size_t len2; |
268 |
const char *ptr = SvPVbyte (program, len); |
269 |
cl_int res; |
270 |
cl_program prog; |
271 |
|
272 |
len2 = len; |
273 |
prog = clCreateProgramWithSource (this, 1, &ptr, &len2, &res); |
274 |
|
275 |
if (res) |
276 |
FAIL (CreateProgramWithSource, res); |
277 |
|
278 |
XPUSH_NEW_OBJ ("OpenCL::Program", prog); |
279 |
} |
280 |
|
281 |
MODULE = OpenCL PACKAGE = OpenCL::Queue |
282 |
|
283 |
void |
284 |
DESTROY (OpenCL::Queue this) |
285 |
CODE: |
286 |
clReleaseCommandQueue (this); |
287 |
|
288 |
void |
289 |
info (OpenCL::Queue this, cl_command_queue_info name) |
290 |
PPCODE: |
291 |
INFO (CommandQueue) |
292 |
|
293 |
void |
294 |
enqueue_read_buffer (OpenCL::Queue this, OpenCL::Memory mem, cl_bool blocking, size_t offset, size_t len, SV *data, ...) |
295 |
PPCODE: |
296 |
{ |
297 |
cl_event ev = 0; |
298 |
EVENT_LIST (6, items - 6); |
299 |
|
300 |
SvUPGRADE (data, SVt_PV); |
301 |
SvGROW (data, len); |
302 |
SvPOK_only (data); |
303 |
SvCUR_set (data, len); |
304 |
NEED_SUCCESS (EnqueueReadBuffer, (this, mem, blocking, offset, len, SvPVX (data), event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0)); |
305 |
|
306 |
if (ev) |
307 |
XPUSH_NEW_OBJ ("OpenCL::Event", ev); |
308 |
} |
309 |
|
310 |
void |
311 |
enqueue_write_buffer (OpenCL::Queue this, OpenCL::Memory mem, cl_bool blocking, size_t offset, SV *data, ...) |
312 |
PPCODE: |
313 |
{ |
314 |
cl_event ev = 0; |
315 |
STRLEN len; |
316 |
char *ptr = SvPVbyte (data, len); |
317 |
EVENT_LIST (5, items - 5); |
318 |
|
319 |
NEED_SUCCESS (EnqueueReadBuffer, (this, mem, blocking, offset, len, ptr, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0)); |
320 |
|
321 |
if (ev) |
322 |
XPUSH_NEW_OBJ ("OpenCL::Event", ev); |
323 |
} |
324 |
|
325 |
void |
326 |
enqueue_copy_buffer (OpenCL::Queue this, OpenCL::Memory src, OpenCL::Memory dst, size_t src_offset, size_t dst_offset, size_t len, ...) |
327 |
PPCODE: |
328 |
{ |
329 |
cl_event ev = 0; |
330 |
EVENT_LIST (6, items - 6); |
331 |
|
332 |
NEED_SUCCESS (EnqueueCopyBuffer, (this, src, dst, src_offset, dst_offset, len, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0)); |
333 |
|
334 |
if (ev) |
335 |
XPUSH_NEW_OBJ ("OpenCL::Event", ev); |
336 |
} |
337 |
|
338 |
void |
339 |
enqueue_marker (OpenCL::Queue this) |
340 |
PPCODE: |
341 |
{ |
342 |
cl_event ev; |
343 |
NEED_SUCCESS (EnqueueMarker, (this, &ev)); |
344 |
XPUSH_NEW_OBJ ("OpenCL::Event", ev); |
345 |
} |
346 |
|
347 |
void |
348 |
enqueue_wait_for_events (OpenCL::Queue this, ...) |
349 |
CODE: |
350 |
{ |
351 |
EVENT_LIST (1, items - 1); |
352 |
NEED_SUCCESS (EnqueueWaitForEvents, (this, event_list_count, event_list_ptr)); |
353 |
} |
354 |
|
355 |
void |
356 |
enqueue_barrier (OpenCL::Queue this) |
357 |
CODE: |
358 |
NEED_SUCCESS (EnqueueBarrier, (this)); |
359 |
|
360 |
MODULE = OpenCL PACKAGE = OpenCL::Memory |
361 |
|
362 |
void |
363 |
DESTROY (OpenCL::Memory this) |
364 |
CODE: |
365 |
clReleaseMemObject (this); |
366 |
|
367 |
void |
368 |
info (OpenCL::Memory this, cl_mem_info name) |
369 |
PPCODE: |
370 |
INFO (MemObject) |
371 |
|
372 |
MODULE = OpenCL PACKAGE = OpenCL::Sampler |
373 |
|
374 |
void |
375 |
DESTROY (OpenCL::Sampler this) |
376 |
CODE: |
377 |
clReleaseSampler (this); |
378 |
|
379 |
void |
380 |
info (OpenCL::Sampler this, cl_sampler_info name) |
381 |
PPCODE: |
382 |
INFO (Sampler) |
383 |
|
384 |
MODULE = OpenCL PACKAGE = OpenCL::Program |
385 |
|
386 |
void |
387 |
DESTROY (OpenCL::Program this) |
388 |
CODE: |
389 |
clReleaseProgram (this); |
390 |
|
391 |
void |
392 |
info (OpenCL::Program this, cl_program_info name) |
393 |
PPCODE: |
394 |
INFO (Program) |
395 |
|
396 |
void |
397 |
build (OpenCL::Program this, OpenCL::Device device, SV *options = &PL_sv_undef) |
398 |
CODE: |
399 |
NEED_SUCCESS (BuildProgram, (this, 1, &device, SvPVbyte_nolen (options), 0, 0)); |
400 |
|
401 |
void |
402 |
build_info (OpenCL::Program this, OpenCL::Device device, cl_program_build_info name) |
403 |
PPCODE: |
404 |
{ |
405 |
size_t size; |
406 |
SV *sv; |
407 |
|
408 |
NEED_SUCCESS (GetProgramBuildInfo, (this, device, name, 0, 0, &size)); |
409 |
sv = sv_2mortal (newSV (size)); |
410 |
SvUPGRADE (sv, SVt_PV); |
411 |
SvPOK_only (sv); |
412 |
SvCUR_set (sv, size); |
413 |
NEED_SUCCESS (GetProgramBuildInfo, (this, device, name, size, SvPVX (sv), 0)); |
414 |
XPUSHs (sv); |
415 |
} |
416 |
|
417 |
void |
418 |
kernel (OpenCL::Program program, SV *function) |
419 |
PPCODE: |
420 |
{ |
421 |
cl_int res; |
422 |
cl_kernel kernel = clCreateKernel (program, SvPVbyte_nolen (function), &res); |
423 |
|
424 |
if (res) |
425 |
FAIL (CreateKernel, res); |
426 |
|
427 |
XPUSH_NEW_OBJ ("OpenCL::Kernel", kernel); |
428 |
} |
429 |
|
430 |
MODULE = OpenCL PACKAGE = OpenCL::Kernel |
431 |
|
432 |
void |
433 |
DESTROY (OpenCL::Kernel this) |
434 |
CODE: |
435 |
clReleaseKernel (this); |
436 |
|
437 |
void |
438 |
info (OpenCL::Kernel this, cl_kernel_info name) |
439 |
PPCODE: |
440 |
INFO (Kernel) |
441 |
|
442 |
void |
443 |
set_bool (OpenCL::Kernel this, cl_uint idx, cl_bool value) |
444 |
CODE: |
445 |
clKernelSetArg (this, idx, sizeof (value), &value); |
446 |
|
447 |
MODULE = OpenCL PACKAGE = OpenCL::Event |
448 |
|
449 |
void |
450 |
DESTROY (OpenCL::Event this) |
451 |
CODE: |
452 |
clReleaseEvent (this); |
453 |
|
454 |
void |
455 |
info (OpenCL::Event this, cl_event_info name) |
456 |
PPCODE: |
457 |
INFO (Event) |
458 |
|
459 |
void |
460 |
wait (OpenCL::Event this) |
461 |
CODE: |
462 |
clWaitForEvents (1, &this); |
463 |
|