ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/OpenCL/OpenCL.xs
Revision: 1.83
Committed: Mon Apr 7 22:36:54 2014 UTC (10 years, 1 month ago) by root
Branch: MAIN
CVS Tags: HEAD
Changes since 1.82: +5 -3 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.80 #include <stddef.h>
2    
3 root 1.1 #include "EXTERN.h"
4     #include "perl.h"
5     #include "XSUB.h"
6    
7 root 1.83 #define ECB_NO_THREADS 1
8     #define ECB_NO_LIBM 1
9     #include "ecb.h"
10 root 1.64
11 root 1.51 #define X_STACKSIZE sizeof (void *) * 512 * 1024 // 2-4mb should be enough, really
12     #include "xthread.h"
13     #include "schmorp.h"
14    
15 root 1.30 #ifdef I_DLFCN
16     #include <dlfcn.h>
17     #endif
18    
19 root 1.37 // how stupid is that, the 1.2 header files define CL_VERSION_1_1,
20     // but then fail to define the api functions unless you ALSO define
21     // this. This breaks 100% of the opencl 1.1 apps, for what reason?
22     // after all, the functions are deprecated, not removed.
23     // in addition, you cannot test for this in any future-proof way.
24     // each time a new opencl version comes out, you need to make a new
25     // release.
26     #define CL_USE_DEPRECATED_OPENCL_1_2_APIS /* just guessing, you stupid idiots */
27    
28 root 1.45 #ifndef PREFER_1_1
29 root 1.44 #define PREFER_1_1 1
30     #endif
31    
32     #if PREFER_1_1
33     #define CL_USE_DEPRECATED_OPENCL_1_1_APIS
34     #endif
35    
36 root 1.19 #ifdef __APPLE__
37 root 1.74 #define CLHDR(name) <OpenCL/name>
38 root 1.19 #else
39 root 1.74 #define CLHDR(name) <CL/name>
40     #endif
41    
42     #include CLHDR(opencl.h)
43    
44 root 1.81 #if 0
45 root 1.74 #ifndef CL_VERSION_1_2
46     #include CLHDR(cl_d3d9.h)
47     #endif
48 root 1.81 #endif
49 root 1.74
50     #if _WIN32
51     #include CLHDR(cl_d3d10.h)
52     #if CL_VERSION_1_2
53 root 1.83 #include CLHDR(cl_d3d11.h)
54 root 1.74 #endif
55 root 1.83 #include CLHDR(cl_dx9_media_sharing.h)
56 root 1.19 #endif
57 root 1.1
58 root 1.44 #ifndef CL_VERSION_1_2
59     #undef PREFER_1_1
60     #define PREFER_1_1 1
61 root 1.38 #endif
62    
63 root 1.74 // make sure all constants we might use are actually defined
64     #include "default.h"
65    
66 root 1.16 typedef cl_platform_id OpenCL__Platform;
67     typedef cl_device_id OpenCL__Device;
68 root 1.65 typedef cl_device_id OpenCL__SubDevice;
69 root 1.16 typedef cl_context OpenCL__Context;
70     typedef cl_command_queue OpenCL__Queue;
71     typedef cl_mem OpenCL__Memory;
72     typedef cl_mem OpenCL__Buffer;
73 root 1.18 typedef cl_mem OpenCL__BufferObj;
74 root 1.16 typedef cl_mem OpenCL__Image;
75     typedef cl_mem OpenCL__Memory_ornull;
76     typedef cl_mem OpenCL__Buffer_ornull;
77     typedef cl_mem OpenCL__Image_ornull;
78     typedef cl_sampler OpenCL__Sampler;
79     typedef cl_program OpenCL__Program;
80     typedef cl_kernel OpenCL__Kernel;
81     typedef cl_event OpenCL__Event;
82     typedef cl_event OpenCL__UserEvent;
83 root 1.5
84 root 1.61 typedef struct mapped * OpenCL__Mapped;
85    
86     static HV
87     *stash_platform,
88     *stash_device,
89 root 1.65 *stash_subdevice,
90 root 1.61 *stash_context,
91     *stash_queue,
92     *stash_program,
93     *stash_kernel,
94     *stash_sampler,
95     *stash_event,
96     *stash_userevent,
97     *stash_memory,
98     *stash_buffer,
99     *stash_bufferobj,
100     *stash_image,
101     *stash_image1d,
102     *stash_image1darray,
103     *stash_image1dbuffer,
104     *stash_image2d,
105     *stash_image2darray,
106     *stash_image3d,
107     *stash_mapped,
108     *stash_mappedbuffer,
109     *stash_mappedimage;
110    
111 root 1.5 /*****************************************************************************/
112    
113 root 1.30 // name must include a leading underscore
114 root 1.32 // all of this horrors would be unneceesary if somebody wrote a proper OpenGL module
115     // for perl. doh.
116 root 1.30 static void *
117 root 1.32 glsym (const char *name)
118 root 1.30 {
119 root 1.32 void *fun = 0;
120    
121 root 1.30 #if defined I_DLFCN && defined RTLD_DEFAULT
122 root 1.32 fun = dlsym (RTLD_DEFAULT, name + 1);
123     if (!fun) fun = dlsym (RTLD_DEFAULT, name);
124    
125     if (!fun)
126     {
127     static void *libgl;
128     static const char *glso[] = {
129     "libGL.so.1",
130     "libGL.so.3",
131     "libGL.so.4.0",
132     "libGL.so",
133     "/usr/lib/libGL.so",
134     "/usr/X11R6/lib/libGL.1.dylib"
135     };
136     int i;
137    
138     for (i = 0; !libgl && i < sizeof (glso) / sizeof (glso [0]); ++i)
139     {
140     libgl = dlopen (glso [i], RTLD_LAZY);
141     if (libgl)
142     break;
143     }
144    
145     if (libgl)
146     {
147     fun = dlsym (libgl, name + 1);
148     if (!fun) fun = dlsym (libgl, name);
149     }
150     }
151 root 1.30 #endif
152 root 1.32
153     return fun;
154 root 1.30 }
155    
156     /*****************************************************************************/
157    
158 root 1.5 /* up to two temporary buffers */
159 root 1.64 static void * ecb_noinline
160 root 1.5 tmpbuf (size_t size)
161     {
162 root 1.64 enum { buffers = 4 };
163 root 1.5 static int idx;
164 root 1.24 static void *buf [buffers];
165     static size_t len [buffers];
166 root 1.5
167 root 1.37 idx = (idx + 1) % buffers;
168 root 1.5
169     if (len [idx] < size)
170     {
171     free (buf [idx]);
172     len [idx] = ((size + 31) & ~4095) + 4096 - 32;
173     buf [idx] = malloc (len [idx]);
174     }
175    
176     return buf [idx];
177     }
178    
179 root 1.69 static const char * ecb_noinline
180     cv_get_name (CV *cv)
181     {
182     static char fullname [256];
183    
184     GV *gv = CvGV (cv); // gv better be nonzero
185    
186     HV *stash = GvSTASH (gv);
187     const char *hvname = HvNAME_get (stash); // stash also better be nonzero
188     const char *gvname = GvNAME (gv);
189    
190     snprintf (fullname, sizeof (fullname), "%s::%s", hvname, gvname);
191     return fullname;
192     }
193    
194 root 1.5 /*****************************************************************************/
195 root 1.1
196 root 1.3 typedef struct
197     {
198 root 1.1 IV iv;
199     const char *name;
200 root 1.3 #define const_iv(name) { (IV)CL_ ## name, # name },
201     } ivstr;
202 root 1.1
203 root 1.76 typedef struct
204     {
205     NV nv;
206     const char *name;
207     #define const_nv(name) { (NV)CL_ ## name, # name },
208     } nvstr;
209    
210 root 1.1 static const char *
211 root 1.3 iv2str (IV value, const ivstr *base, int count, const char *fallback)
212 root 1.1 {
213     int i;
214 root 1.3 static char strbuf [32];
215    
216     for (i = count; i--; )
217     if (base [i].iv == value)
218     return base [i].name;
219    
220     snprintf (strbuf, sizeof (strbuf), fallback, (int)value);
221    
222     return strbuf;
223     }
224    
225     static const char *
226     enum2str (cl_uint value)
227     {
228     static const ivstr enumstr[] = {
229     #include "enumstr.h"
230     };
231 root 1.1
232 root 1.3 return iv2str (value, enumstr, sizeof (enumstr) / sizeof (enumstr [0]), "ENUM(0x%04x)");
233     }
234 root 1.1
235 root 1.3 static const char *
236     err2str (cl_int err)
237     {
238     static const ivstr errstr[] = {
239     #include "errstr.h"
240     };
241 root 1.1
242 root 1.3 return iv2str (err, errstr, sizeof (errstr) / sizeof (errstr [0]), "ERROR(%d)");
243 root 1.1 }
244    
245 root 1.5 /*****************************************************************************/
246    
247 root 1.8 static cl_int res;
248 root 1.5
249 root 1.8 #define FAIL(name) \
250     croak ("cl" # name ": %s", err2str (res));
251 root 1.1
252     #define NEED_SUCCESS(name,args) \
253     do { \
254 root 1.8 res = cl ## name args; \
255 root 1.1 \
256     if (res) \
257 root 1.8 FAIL (name); \
258 root 1.1 } while (0)
259    
260 root 1.8 #define NEED_SUCCESS_ARG(retdecl, name, args) \
261     retdecl = cl ## name args; \
262     if (res) \
263     FAIL (name);
264    
265 root 1.5 /*****************************************************************************/
266    
267 root 1.65 static SV *
268     new_clobj (HV *stash, IV id)
269     {
270     return sv_2mortal (sv_bless (newRV_noinc (newSViv (id)), stash));
271     }
272    
273     #define PUSH_CLOBJ(stash,id) PUSHs (new_clobj ((stash), (IV)(id)))
274     #define XPUSH_CLOBJ(stash,id) XPUSHs (new_clobj ((stash), (IV)(id)))
275    
276     /* cl objects are either \$iv, or [$iv, ...] */
277     /* they can be upgraded at runtime to the array form */
278     static void * ecb_noinline
279 root 1.71 SvCLOBJ (CV *cv, const char *svname, SV *sv, const char *pkg)
280 root 1.65 {
281     // sv_derived_from is quite slow :(
282     if (SvROK (sv) && sv_derived_from (sv, pkg))
283     return (void *)SvIV (SvRV (sv));
284    
285 root 1.71 croak ("%s: %s is not of type %s", cv_get_name (cv), svname, pkg);
286 root 1.65 }
287    
288     // the "no-inherit" version of the above
289     static void * ecb_noinline
290 root 1.71 SvCLOBJ_ni (CV *cv, const char *svname, SV *sv, HV *stash)
291 root 1.65 {
292     if (SvROK (sv) && SvSTASH (SvRV (sv)) == stash)
293     return (void *)SvIV (SvRV (sv));
294    
295 root 1.71 croak ("%s: %s is not of type %s", cv_get_name (cv), svname, HvNAME (stash));
296 root 1.65 }
297    
298     /*****************************************************************************/
299    
300 root 1.64 static cl_context_properties * ecb_noinline
301 root 1.71 SvCONTEXTPROPERTIES (CV *cv, const char *svname, SV *sv, cl_context_properties *extra, int extracount)
302 root 1.24 {
303     if (!sv || !SvOK (sv))
304     if (extra)
305     sv = sv_2mortal (newRV_noinc ((SV *)newAV ())); // slow, but rarely used hopefully
306     else
307     return 0;
308    
309     if (SvROK (sv) && SvTYPE (SvRV (sv)) == SVt_PVAV)
310     {
311     AV *av = (AV *)SvRV (sv);
312 root 1.28 int i, len = av_len (av) + 1;
313 root 1.24 cl_context_properties *p = tmpbuf (sizeof (cl_context_properties) * (len + extracount + 1));
314     cl_context_properties *l = p;
315    
316     if (len & 1)
317 root 1.71 croak ("%s: %s is not a property list (must contain an even number of elements)", cv_get_name (cv), svname);
318 root 1.24
319     while (extracount--)
320     *l++ = *extra++;
321    
322 root 1.29 for (i = 0; i < len; i += 2)
323 root 1.24 {
324 root 1.29 cl_context_properties t = SvIV (*av_fetch (av, i , 0));
325     SV *p_sv = *av_fetch (av, i + 1, 0);
326 root 1.32 cl_context_properties v = SvIV (p_sv); // code below can override
327 root 1.24
328     switch (t)
329     {
330 root 1.65 case CL_CONTEXT_PLATFORM:
331     if (SvROK (p_sv))
332 root 1.71 v = (cl_context_properties)SvCLOBJ (cv, svname, p_sv, "OpenCL::Platform");
333 root 1.65 break;
334    
335 root 1.32 case CL_GLX_DISPLAY_KHR:
336     if (!SvOK (p_sv))
337     {
338     void *func = glsym ("_glXGetCurrentDisplay");
339     if (func)
340     v = (cl_context_properties)((void *(*)(void))func)();
341     }
342     break;
343    
344     case CL_GL_CONTEXT_KHR:
345     if (!SvOK (p_sv))
346     {
347     void *func = glsym ("_glXGetCurrentContext");
348     if (func)
349     v = (cl_context_properties)((void *(*)(void))func)();
350     }
351     break;
352    
353 root 1.24 default:
354     /* unknown property, treat as int */
355     break;
356     }
357    
358     *l++ = t;
359     *l++ = v;
360     }
361    
362     *l = 0;
363    
364     return p;
365     }
366    
367 root 1.71 croak ("%s: %s is not a property list (either undef or [type => value, ...])", cv_get_name (cv), svname);
368 root 1.24 }
369    
370 root 1.71 // parse an array of CLOBJ into a void ** array in C - works only for CLOBJs whose representation
371     // is a pointer (and only on well-behaved systems).
372 root 1.69 static void * ecb_noinline
373     object_list (CV *cv, int or_undef, const char *argname, SV *arg, const char *klass, cl_uint *rcount)
374     {
375     if (!SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
376     croak ("%s: '%s' parameter must be %sa reference to an array of %s objects",
377 root 1.71 cv_get_name (cv), argname, or_undef ? "undef or " : "", klass);
378 root 1.69
379     AV *av = (AV *)SvRV (arg);
380     void **list = 0;
381     cl_uint count = av_len (av) + 1;
382    
383     if (count)
384     {
385     list = tmpbuf (sizeof (*list) * count);
386     int i;
387     for (i = 0; i < count; ++i)
388 root 1.71 list [i] = SvCLOBJ (cv, argname, *av_fetch (av, i, 1), klass);
389 root 1.69 }
390    
391     if (!count && !or_undef)
392     croak ("%s: '%s' must contain at least one %s object",
393 root 1.71 cv_get_name (cv), argname, klass);
394 root 1.69
395     *rcount = count;
396     return (void *)list;
397     }
398    
399 root 1.24 /*****************************************************************************/
400 root 1.51 /* callback stuff */
401    
402     /* default context callback, log to stderr */
403     static void CL_CALLBACK
404     context_default_notify (const char *msg, const void *info, size_t cb, void *data)
405     {
406     fprintf (stderr, "OpenCL Context Notify: %s\n", msg);
407     }
408    
409     typedef struct
410     {
411     int free_cb;
412     void (*push)(void *data1, void *data2, void *data3);
413     } eq_vtbl;
414    
415     typedef struct eq_item
416     {
417     struct eq_item *next;
418     eq_vtbl *vtbl;
419     SV *cb;
420     void *data1, *data2, *data3;
421     } eq_item;
422    
423     static void (*eq_signal_func)(void *signal_arg, int value);
424     static void *eq_signal_arg;
425     static xmutex_t eq_lock = X_MUTEX_INIT;
426     static eq_item *eq_head, *eq_tail;
427    
428 root 1.64 static void ecb_noinline
429 root 1.51 eq_enq (eq_vtbl *vtbl, SV *cb, void *data1, void *data2, void *data3)
430     {
431     eq_item *item = malloc (sizeof (eq_item));
432    
433     item->next = 0;
434     item->vtbl = vtbl;
435     item->cb = cb;
436     item->data1 = data1;
437     item->data2 = data2;
438     item->data3 = data3;
439    
440     X_LOCK (eq_lock);
441    
442     *(eq_head ? &eq_tail->next : &eq_head) = item;
443     eq_tail = item;
444    
445     X_UNLOCK (eq_lock);
446    
447     eq_signal_func (eq_signal_arg, 0);
448     }
449    
450     static eq_item *
451     eq_dec (void)
452     {
453     eq_item *res;
454    
455     X_LOCK (eq_lock);
456    
457     res = eq_head;
458     if (res)
459     eq_head = res->next;
460    
461     X_UNLOCK (eq_lock);
462    
463     return res;
464     }
465    
466     static void
467     eq_poll (void)
468     {
469     eq_item *item;
470    
471     while ((item = eq_dec ()))
472     {
473     ENTER;
474     SAVETMPS;
475    
476     dSP;
477     PUSHMARK (SP);
478     EXTEND (SP, 2);
479    
480     if (item->vtbl->free_cb)
481     sv_2mortal (item->cb);
482    
483     PUTBACK;
484     item->vtbl->push (item->data1, item->data2, item->data3);
485    
486     SV *cb = item->cb;
487     free (item);
488    
489     call_sv (cb, G_DISCARD | G_VOID);
490    
491     FREETMPS;
492     LEAVE;
493     }
494     }
495    
496     static void
497     eq_poll_interrupt (pTHX_ void *c_arg, int value)
498     {
499     eq_poll ();
500     }
501    
502 root 1.52 /*****************************************************************************/
503 root 1.51 /* context notify */
504    
505 root 1.64 static void ecb_noinline
506 root 1.51 eq_context_push (void *data1, void *data2, void *data3)
507     {
508     dSP;
509     PUSHs (sv_2mortal (newSVpv (data1, 0)));
510     PUSHs (sv_2mortal (newSVpvn (data2, (STRLEN)data3)));
511     PUTBACK;
512 root 1.52
513     free (data1);
514     free (data2);
515 root 1.51 }
516    
517     static eq_vtbl eq_context_vtbl = { 0, eq_context_push };
518    
519 root 1.52 static void CL_CALLBACK
520     eq_context_notify (const char *msg, const void *pvt, size_t cb, void *user_data)
521     {
522     void *pvt_copy = malloc (cb);
523     memcpy (pvt_copy, pvt, cb);
524     eq_enq (&eq_context_vtbl, user_data, strdup (msg), pvt_copy, (void *)cb);
525     }
526    
527     #define CONTEXT_NOTIFY_CALLBACK \
528     void (CL_CALLBACK *pfn_notify)(const char *, const void *, size_t, void *) = context_default_notify; \
529     void *user_data = 0; \
530     \
531     if (SvOK (notify)) \
532     { \
533     pfn_notify = eq_context_notify; \
534     user_data = s_get_cv (notify); \
535     }
536    
537 root 1.64 static SV * ecb_noinline
538 root 1.52 new_clobj_context (cl_context ctx, void *user_data)
539     {
540 root 1.61 SV *sv = new_clobj (stash_context, (IV)ctx);
541 root 1.52
542     if (user_data)
543     sv_magicext (SvRV (sv), user_data, PERL_MAGIC_ext, 0, 0, 0);
544    
545     return sv;
546     }
547    
548     #define XPUSH_CLOBJ_CONTEXT XPUSHs (new_clobj_context (ctx, user_data));
549    
550     /*****************************************************************************/
551 root 1.51 /* build/compile/link notify */
552    
553     static void
554     eq_program_push (void *data1, void *data2, void *data3)
555     {
556     dSP;
557 root 1.61 PUSH_CLOBJ (stash_program, data1);
558 root 1.51 PUTBACK;
559     }
560    
561     static eq_vtbl eq_program_vtbl = { 1, eq_program_push };
562    
563     static void CL_CALLBACK
564     eq_program_notify (cl_program program, void *user_data)
565     {
566 root 1.69 clRetainProgram (program);
567    
568 root 1.51 eq_enq (&eq_program_vtbl, user_data, (void *)program, 0, 0);
569     }
570    
571 root 1.69 typedef void (CL_CALLBACK *program_callback)(cl_program program, void *user_data);
572    
573     static program_callback ecb_noinline
574     make_program_callback (SV *notify, void **ruser_data)
575     {
576     if (SvOK (notify))
577     {
578     *ruser_data = SvREFCNT_inc (s_get_cv (notify));
579     return eq_program_notify;
580     }
581     else
582     {
583     *ruser_data = 0;
584     return 0;
585     }
586     }
587    
588 root 1.51 struct build_args
589     {
590     cl_program program;
591     char *options;
592     void *user_data;
593     cl_uint num_devices;
594     };
595    
596     X_THREAD_PROC (build_program_thread)
597     {
598     struct build_args *arg = thr_arg;
599    
600     clBuildProgram (arg->program, arg->num_devices, arg->num_devices ? (void *)(arg + 1) : 0, arg->options, 0, 0);
601    
602     if (arg->user_data)
603     eq_program_notify (arg->program, arg->user_data);
604     else
605     clReleaseProgram (arg->program);
606    
607     free (arg->options);
608     free (arg);
609 root 1.64
610     return 0;
611 root 1.51 }
612    
613     static void
614     build_program_async (cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, void *user_data)
615     {
616     struct build_args *arg = malloc (sizeof (struct build_args) + sizeof (*device_list) * num_devices);
617    
618     arg->program = program;
619     arg->options = strdup (options);
620     arg->user_data = user_data;
621     arg->num_devices = num_devices;
622     memcpy (arg + 1, device_list, sizeof (*device_list) * num_devices);
623    
624     xthread_t id;
625 root 1.82 xthread_create (&id, build_program_thread, arg);
626 root 1.51 }
627    
628 root 1.52 /*****************************************************************************/
629 root 1.78 /* mem object destructor notify */
630    
631     static void ecb_noinline
632     eq_destructor_push (void *data1, void *data2, void *data3)
633     {
634     }
635    
636     static eq_vtbl eq_destructor_vtbl = { 0, eq_destructor_push };
637    
638     static void CL_CALLBACK
639     eq_destructor_notify (cl_mem memobj, void *user_data)
640     {
641     eq_enq (&eq_destructor_vtbl, (SV *)user_data, (void *)memobj, 0, 0);
642     }
643    
644     /*****************************************************************************/
645 root 1.51 /* event objects */
646    
647     static void
648     eq_event_push (void *data1, void *data2, void *data3)
649     {
650     dSP;
651 root 1.61 PUSH_CLOBJ (stash_event, data1);
652 root 1.51 PUSHs (sv_2mortal (newSViv ((IV)data2)));
653     PUTBACK;
654     }
655    
656     static eq_vtbl eq_event_vtbl = { 1, eq_event_push };
657    
658     static void CL_CALLBACK
659     eq_event_notify (cl_event event, cl_int event_command_exec_status, void *user_data)
660     {
661     clRetainEvent (event);
662 root 1.52 eq_enq (&eq_event_vtbl, user_data, (void *)event, (void *)(IV)event_command_exec_status, 0);
663 root 1.51 }
664    
665     /*****************************************************************************/
666 root 1.62 /* utilities for XS code */
667    
668     static size_t
669     img_row_pitch (cl_mem img)
670     {
671     size_t res;
672     clGetImageInfo (img, CL_IMAGE_ROW_PITCH, sizeof (res), &res, 0);
673     return res;
674     }
675    
676 root 1.64 static cl_event * ecb_noinline
677 root 1.71 event_list (CV *cv, SV **items, cl_uint *rcount, cl_event extra)
678 root 1.62 {
679     cl_uint count = *rcount;
680    
681 root 1.64 if (count > 0x7fffffffU) // yeah, it's a hack - the caller might have underflowed
682     *rcount = count = 0;
683 root 1.62
684     if (!count && !extra)
685     return 0;
686    
687     cl_event *list = tmpbuf (sizeof (cl_event) * (count + 1));
688     int i = 0;
689    
690     while (count--)
691     if (SvOK (items [count]))
692 root 1.71 list [i++] = SvCLOBJ (cv, "wait_events", items [count], "OpenCL::Event");
693 root 1.62
694     if (extra)
695     list [i++] = extra;
696    
697     *rcount = i;
698    
699     return i ? list : 0;
700     }
701    
702     #define EVENT_LIST(skip) \
703     cl_uint event_list_count = items - (skip); \
704 root 1.71 cl_event *event_list_ptr = event_list (cv, &ST (skip), &event_list_count, 0)
705 root 1.62
706     #define INFO(class) \
707     { \
708     size_t size; \
709     NEED_SUCCESS (Get ## class ## Info, (self, name, 0, 0, &size)); \
710     SV *sv = sv_2mortal (newSV (size)); \
711     SvUPGRADE (sv, SVt_PV); \
712     SvPOK_only (sv); \
713     SvCUR_set (sv, size); \
714     NEED_SUCCESS (Get ## class ## Info, (self, name, size, SvPVX (sv), 0)); \
715     XPUSHs (sv); \
716     }
717    
718     /*****************************************************************************/
719 root 1.61 /* mapped_xxx */
720    
721     static OpenCL__Mapped
722     SvMAPPED (SV *sv)
723     {
724     // no typechecking atm., keep your fingers crossed
725     return (OpenCL__Mapped)SvMAGIC (SvRV (sv))->mg_ptr;
726     }
727    
728     struct mapped
729     {
730     cl_command_queue queue;
731     cl_mem memobj;
732     void *ptr;
733     size_t cb;
734     cl_event event;
735     size_t row_pitch;
736     size_t slice_pitch;
737 root 1.80
738     size_t element_size;
739     size_t width, height, depth;
740 root 1.61 };
741    
742     static SV *
743 root 1.80 mapped_new (
744     HV *stash, cl_command_queue queue, cl_mem memobj, cl_map_flags flags,
745     void *ptr, size_t cb, cl_event ev,
746     size_t row_pitch, size_t slice_pitch, size_t element_size,
747     size_t width, size_t height, size_t depth
748     )
749 root 1.61 {
750     SV *data = newSV (0);
751     SvUPGRADE (data, SVt_PVMG);
752    
753     OpenCL__Mapped mapped;
754     New (0, mapped, 1, struct mapped);
755    
756     clRetainCommandQueue (queue);
757    
758 root 1.80 mapped->queue = queue;
759     mapped->memobj = memobj;
760     mapped->ptr = ptr;
761     mapped->cb = cb;
762     mapped->event = ev;
763     mapped->row_pitch = row_pitch;
764     mapped->slice_pitch = slice_pitch;
765    
766     mapped->element_size = element_size;
767     mapped->width = width;
768     mapped->height = height;
769     mapped->depth = depth;
770 root 1.61
771     sv_magicext (data, 0, PERL_MAGIC_ext, 0, (char *)mapped, 0);
772    
773     if (SvLEN (data))
774     Safefree (data);
775    
776     SvPVX (data) = (char *)ptr;
777     SvCUR_set (data, cb);
778     SvLEN_set (data, 0);
779     SvPOK_only (data);
780    
781 root 1.62 SV *obj = sv_2mortal (sv_bless (newRV_noinc (data), stash));
782    
783     if (!(flags & CL_MAP_WRITE))
784     SvREADONLY_on (data);
785    
786     return obj;
787 root 1.61 }
788    
789     static void
790     mapped_detach (SV *sv, OpenCL__Mapped mapped)
791     {
792     SV *data = SvRV (sv);
793    
794 root 1.62 // the next check checks both before AND after detach, where SvPVX should STILL be 0
795 root 1.61 if (SvPVX (data) != (char *)mapped->ptr)
796     warn ("FATAL: OpenCL memory mapped scalar changed location, detected");
797     else
798     {
799     SvREADONLY_off (data);
800     SvCUR_set (data, 0);
801     SvPVX (data) = 0;
802     SvOK_off (data);
803     }
804    
805     mapped->ptr = 0;
806     }
807    
808 root 1.62 static void
809 root 1.71 mapped_unmap (CV *cv, SV *self, OpenCL__Mapped mapped, cl_command_queue queue, SV **wait_list, cl_uint event_list_count)
810 root 1.11 {
811 root 1.71 cl_event *event_list_ptr = event_list (cv, wait_list, &event_list_count, mapped->event);
812 root 1.62 cl_event ev;
813 root 1.11
814 root 1.62 NEED_SUCCESS (EnqueueUnmapMemObject, (queue, mapped->memobj, mapped->ptr, event_list_count, event_list_ptr, &ev));
815 root 1.35
816 root 1.62 clReleaseEvent (mapped->event);
817     mapped->event = ev;
818 root 1.61
819 root 1.62 mapped_detach (self, mapped);
820 root 1.5 }
821    
822 root 1.80 static size_t
823     mapped_element_size (OpenCL__Mapped self)
824     {
825     if (!self->element_size)
826     clGetImageInfo (self->memobj, CL_IMAGE_ELEMENT_SIZE, sizeof (self->element_size), &self->element_size, 0);
827    
828     return self->element_size;
829     }
830    
831 root 1.62 /*****************************************************************************/
832 root 1.2
833 root 1.1 MODULE = OpenCL PACKAGE = OpenCL
834    
835 root 1.2 PROTOTYPES: ENABLE
836    
837 root 1.51 void
838     poll ()
839     CODE:
840     eq_poll ();
841    
842     void
843     _eq_initialise (IV func, IV arg)
844     CODE:
845     eq_signal_func = (void (*)(void *, int))func;
846     eq_signal_arg = (void*)arg;
847    
848 root 1.1 BOOT:
849     {
850 root 1.24 HV *stash = gv_stashpv ("OpenCL", 1);
851 root 1.76
852 root 1.24 static const ivstr *civ, const_iv[] = {
853     { sizeof (cl_char ), "SIZEOF_CHAR" },
854     { sizeof (cl_uchar ), "SIZEOF_UCHAR" },
855     { sizeof (cl_short ), "SIZEOF_SHORT" },
856     { sizeof (cl_ushort), "SIZEOF_USHORT" },
857     { sizeof (cl_int ), "SIZEOF_INT" },
858     { sizeof (cl_uint ), "SIZEOF_UINT" },
859     { sizeof (cl_long ), "SIZEOF_LONG" },
860     { sizeof (cl_ulong ), "SIZEOF_ULONG" },
861     { sizeof (cl_half ), "SIZEOF_HALF" },
862     { sizeof (cl_float ), "SIZEOF_FLOAT" },
863     { sizeof (cl_double), "SIZEOF_DOUBLE" },
864 root 1.72 { PREFER_1_1 , "PREFER_1_1" },
865 root 1.1 #include "constiv.h"
866 root 1.24 };
867 root 1.51
868 root 1.24 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ > const_iv; civ--)
869     newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv));
870 root 1.51
871 root 1.76 static const nvstr *cnv, const_nv[] = {
872     #include "constnv.h"
873     };
874    
875     for (cnv = const_nv + sizeof (const_nv) / sizeof (const_nv [0]); cnv > const_nv; cnv--)
876     newCONSTSUB (stash, (char *)cnv[-1].name, newSVnv (cnv[-1].nv));
877    
878     newCONSTSUB (stash, "NAN", newSVnv (CL_NAN)); // CL_NAN might be a function call
879    
880 root 1.61 stash_platform = gv_stashpv ("OpenCL::Platform", GV_ADD);
881     stash_device = gv_stashpv ("OpenCL::Device", GV_ADD);
882 root 1.65 stash_subdevice = gv_stashpv ("OpenCL::SubDevice", GV_ADD);
883 root 1.61 stash_context = gv_stashpv ("OpenCL::Context", GV_ADD);
884     stash_queue = gv_stashpv ("OpenCL::Queue", GV_ADD);
885     stash_program = gv_stashpv ("OpenCL::Program", GV_ADD);
886     stash_kernel = gv_stashpv ("OpenCL::Kernel", GV_ADD);
887     stash_sampler = gv_stashpv ("OpenCL::Sampler", GV_ADD);
888     stash_event = gv_stashpv ("OpenCL::Event", GV_ADD);
889     stash_userevent = gv_stashpv ("OpenCL::UserEvent", GV_ADD);
890     stash_memory = gv_stashpv ("OpenCL::Memory", GV_ADD);
891     stash_buffer = gv_stashpv ("OpenCL::Buffer", GV_ADD);
892     stash_bufferobj = gv_stashpv ("OpenCL::BufferObj", GV_ADD);
893     stash_image = gv_stashpv ("OpenCL::Image", GV_ADD);
894     stash_image1d = gv_stashpv ("OpenCL::Image1D", GV_ADD);
895     stash_image1darray = gv_stashpv ("OpenCL::Image1DArray", GV_ADD);
896     stash_image1dbuffer = gv_stashpv ("OpenCL::Image1DBuffer", GV_ADD);
897     stash_image2d = gv_stashpv ("OpenCL::Image2D", GV_ADD);
898     stash_image2darray = gv_stashpv ("OpenCL::Image2DArray", GV_ADD);
899     stash_image3d = gv_stashpv ("OpenCL::Image3D", GV_ADD);
900     stash_mapped = gv_stashpv ("OpenCL::Mapped", GV_ADD);
901     stash_mappedbuffer = gv_stashpv ("OpenCL::MappedBuffer", GV_ADD);
902     stash_mappedimage = gv_stashpv ("OpenCL::MappedImage", GV_ADD);
903    
904 root 1.51 sv_setiv (perl_get_sv ("OpenCL::POLL_FUNC", TRUE), (IV)eq_poll_interrupt);
905 root 1.1 }
906    
907 root 1.5 cl_int
908     errno ()
909     CODE:
910 root 1.37 RETVAL = res;
911     OUTPUT:
912     RETVAL
913 root 1.5
914 root 1.3 const char *
915 root 1.57 err2str (cl_int err = res)
916 root 1.3
917     const char *
918     enum2str (cl_uint value)
919    
920 root 1.1 void
921     platforms ()
922     PPCODE:
923     cl_platform_id *list;
924     cl_uint count;
925     int i;
926    
927 root 1.2 NEED_SUCCESS (GetPlatformIDs, (0, 0, &count));
928 root 1.4 list = tmpbuf (sizeof (*list) * count);
929 root 1.2 NEED_SUCCESS (GetPlatformIDs, (count, list, 0));
930 root 1.1
931     EXTEND (SP, count);
932     for (i = 0; i < count; ++i)
933 root 1.65 PUSH_CLOBJ (stash_platform, list [i]);
934 root 1.1
935     void
936 root 1.52 context_from_type (cl_context_properties *properties = 0, cl_device_type type = CL_DEVICE_TYPE_DEFAULT, SV *notify = &PL_sv_undef)
937 root 1.1 PPCODE:
938 root 1.52 CONTEXT_NOTIFY_CALLBACK;
939 root 1.64 NEED_SUCCESS_ARG (cl_context ctx, CreateContextFromType, (properties, type, pfn_notify, user_data, &res));
940 root 1.52 XPUSH_CLOBJ_CONTEXT;
941 root 1.37
942 root 1.8 void
943 root 1.71 context (cl_context_properties *properties, SV *devices, SV *notify = &PL_sv_undef)
944 root 1.8 PPCODE:
945 root 1.71 cl_uint device_count;
946     cl_device_id *device_list = object_list (cv, 0, "devices", devices, "OpenCL::Device", &device_count);
947    
948     CONTEXT_NOTIFY_CALLBACK;
949     NEED_SUCCESS_ARG (cl_context ctx, CreateContext, (properties, device_count, device_list, pfn_notify, user_data, &res));
950     XPUSH_CLOBJ_CONTEXT;
951 root 1.1
952 root 1.2 void
953     wait_for_events (...)
954     CODE:
955 root 1.61 EVENT_LIST (0);
956 root 1.2 NEED_SUCCESS (WaitForEvents, (event_list_count, event_list_ptr));
957    
958     PROTOTYPES: DISABLE
959    
960 root 1.1 MODULE = OpenCL PACKAGE = OpenCL::Platform
961    
962     void
963 root 1.22 info (OpenCL::Platform self, cl_platform_info name)
964 root 1.1 PPCODE:
965 root 1.2 INFO (Platform)
966 root 1.1
967 root 1.47 void
968     unload_compiler (OpenCL::Platform self)
969     CODE:
970     #if CL_VERSION_1_2
971     clUnloadPlatformCompiler (self);
972     #endif
973    
974 root 1.13 #BEGIN:platform
975    
976     void
977 root 1.22 profile (OpenCL::Platform self)
978 root 1.16 ALIAS:
979     profile = CL_PLATFORM_PROFILE
980     version = CL_PLATFORM_VERSION
981     name = CL_PLATFORM_NAME
982     vendor = CL_PLATFORM_VENDOR
983     extensions = CL_PLATFORM_EXTENSIONS
984 root 1.14 PPCODE:
985     size_t size;
986 root 1.22 NEED_SUCCESS (GetPlatformInfo, (self, ix, 0, 0, &size));
987 root 1.14 char *value = tmpbuf (size);
988 root 1.22 NEED_SUCCESS (GetPlatformInfo, (self, ix, size, value, 0));
989 root 1.16 EXTEND (SP, 1);
990     const int i = 0;
991 root 1.14 PUSHs (sv_2mortal (newSVpv (value, 0)));
992 root 1.13
993     #END:platform
994    
995 root 1.1 void
996 root 1.22 devices (OpenCL::Platform self, cl_device_type type = CL_DEVICE_TYPE_ALL)
997 root 1.1 PPCODE:
998     cl_device_id *list;
999     cl_uint count;
1000     int i;
1001    
1002 root 1.22 NEED_SUCCESS (GetDeviceIDs, (self, type, 0, 0, &count));
1003 root 1.4 list = tmpbuf (sizeof (*list) * count);
1004 root 1.22 NEED_SUCCESS (GetDeviceIDs, (self, type, count, list, 0));
1005 root 1.1
1006     EXTEND (SP, count);
1007     for (i = 0; i < count; ++i)
1008 root 1.61 PUSH_CLOBJ (stash_device, list [i]);
1009 root 1.1
1010     void
1011 root 1.71 context (OpenCL::Platform self, SV *properties, SV *devices, SV *notify = &PL_sv_undef)
1012 root 1.8 PPCODE:
1013 root 1.64 cl_context_properties extra[] = { CL_CONTEXT_PLATFORM, (cl_context_properties)self };
1014 root 1.71 cl_context_properties *props = SvCONTEXTPROPERTIES (cv, "properties", properties, extra, 2);
1015 root 1.64
1016 root 1.71 cl_uint device_count;
1017     cl_device_id *device_list = object_list (cv, 0, "devices", devices, "OpenCL::Device", &device_count);
1018 root 1.8
1019 root 1.52 CONTEXT_NOTIFY_CALLBACK;
1020 root 1.69 NEED_SUCCESS_ARG (cl_context ctx, CreateContext, (props, device_count, device_list, pfn_notify, user_data, &res));
1021 root 1.52 XPUSH_CLOBJ_CONTEXT;
1022 root 1.8
1023     void
1024 root 1.52 context_from_type (OpenCL::Platform self, SV *properties = 0, cl_device_type type = CL_DEVICE_TYPE_DEFAULT, SV *notify = &PL_sv_undef)
1025 root 1.1 PPCODE:
1026 root 1.24 cl_context_properties extra[] = { CL_CONTEXT_PLATFORM, (cl_context_properties)self };
1027 root 1.71 cl_context_properties *props = SvCONTEXTPROPERTIES (cv, "properties", properties, extra, 2);
1028 root 1.52
1029     CONTEXT_NOTIFY_CALLBACK;
1030 root 1.64 NEED_SUCCESS_ARG (cl_context ctx, CreateContextFromType, (props, type, pfn_notify, user_data, &res));
1031 root 1.52 XPUSH_CLOBJ_CONTEXT;
1032 root 1.1
1033 root 1.16 MODULE = OpenCL PACKAGE = OpenCL::Device
1034 root 1.14
1035     void
1036 root 1.22 info (OpenCL::Device self, cl_device_info name)
1037 root 1.16 PPCODE:
1038     INFO (Device)
1039 root 1.14
1040 root 1.65 #if CL_VERSION_1_2
1041    
1042     void
1043     sub_devices (OpenCL::Device self, SV *properties)
1044     PPCODE:
1045     if (!SvROK (properties) || SvTYPE (SvRV (properties)) != SVt_PVAV)
1046     croak ("OpenCL::Device::sub_devices: properties must be specified as reference to an array of property-value pairs");
1047    
1048     properties = SvRV (properties);
1049    
1050     cl_uint count = av_len ((AV *)properties) + 1;
1051     cl_device_partition_property *props = tmpbuf (sizeof (*props) * count + 1);
1052    
1053     int i;
1054     for (i = 0; i < count; ++i)
1055     props [i] = (cl_device_partition_property)SvIV (*av_fetch ((AV *)properties, i, 0));
1056    
1057     props [count] = 0;
1058    
1059     cl_uint num_devices;
1060     NEED_SUCCESS (CreateSubDevices, (self, props, 0, 0, &num_devices));
1061     cl_device_id *list = tmpbuf (sizeof (*list) * num_devices);
1062     NEED_SUCCESS (CreateSubDevices, (self, props, num_devices, list, 0));
1063    
1064     EXTEND (SP, num_devices);
1065     for (i = 0; i < count; ++i)
1066     PUSH_CLOBJ (stash_subdevice, list [i]);
1067    
1068     #endif
1069    
1070 root 1.16 #BEGIN:device
1071 root 1.14
1072     void
1073 root 1.22 type (OpenCL::Device self)
1074 root 1.79 ALIAS:
1075     type = CL_DEVICE_TYPE
1076     address_bits = CL_DEVICE_ADDRESS_BITS
1077     max_mem_alloc_size = CL_DEVICE_MAX_MEM_ALLOC_SIZE
1078     single_fp_config = CL_DEVICE_SINGLE_FP_CONFIG
1079     global_mem_cache_size = CL_DEVICE_GLOBAL_MEM_CACHE_SIZE
1080     global_mem_size = CL_DEVICE_GLOBAL_MEM_SIZE
1081     max_constant_buffer_size = CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE
1082     local_mem_size = CL_DEVICE_LOCAL_MEM_SIZE
1083     execution_capabilities = CL_DEVICE_EXECUTION_CAPABILITIES
1084     properties = CL_DEVICE_QUEUE_PROPERTIES
1085     double_fp_config = CL_DEVICE_DOUBLE_FP_CONFIG
1086     half_fp_config = CL_DEVICE_HALF_FP_CONFIG
1087 root 1.14 PPCODE:
1088 root 1.79 cl_ulong value [1];
1089     NEED_SUCCESS (GetDeviceInfo, (self, ix, sizeof (value), value, 0));
1090 root 1.16 EXTEND (SP, 1);
1091     const int i = 0;
1092 root 1.61 PUSHs (sv_2mortal (newSVuv (value [i])));
1093 root 1.14
1094     void
1095 root 1.22 vendor_id (OpenCL::Device self)
1096 root 1.16 ALIAS:
1097     vendor_id = CL_DEVICE_VENDOR_ID
1098     max_compute_units = CL_DEVICE_MAX_COMPUTE_UNITS
1099     max_work_item_dimensions = CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS
1100     preferred_vector_width_char = CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR
1101     preferred_vector_width_short = CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT
1102     preferred_vector_width_int = CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT
1103     preferred_vector_width_long = CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG
1104     preferred_vector_width_float = CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT
1105     preferred_vector_width_double = CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE
1106     max_clock_frequency = CL_DEVICE_MAX_CLOCK_FREQUENCY
1107     max_read_image_args = CL_DEVICE_MAX_READ_IMAGE_ARGS
1108     max_write_image_args = CL_DEVICE_MAX_WRITE_IMAGE_ARGS
1109     image_support = CL_DEVICE_IMAGE_SUPPORT
1110     max_samplers = CL_DEVICE_MAX_SAMPLERS
1111     mem_base_addr_align = CL_DEVICE_MEM_BASE_ADDR_ALIGN
1112     min_data_type_align_size = CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE
1113 root 1.79 global_mem_cache_type = CL_DEVICE_GLOBAL_MEM_CACHE_TYPE
1114 root 1.16 global_mem_cacheline_size = CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE
1115     max_constant_args = CL_DEVICE_MAX_CONSTANT_ARGS
1116 root 1.79 local_mem_type = CL_DEVICE_LOCAL_MEM_TYPE
1117 root 1.16 preferred_vector_width_half = CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF
1118     native_vector_width_char = CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR
1119     native_vector_width_short = CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT
1120     native_vector_width_int = CL_DEVICE_NATIVE_VECTOR_WIDTH_INT
1121     native_vector_width_long = CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG
1122     native_vector_width_float = CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT
1123     native_vector_width_double = CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE
1124     native_vector_width_half = CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF
1125 root 1.41 reference_count_ext = CL_DEVICE_REFERENCE_COUNT_EXT
1126 root 1.14 PPCODE:
1127     cl_uint value [1];
1128 root 1.22 NEED_SUCCESS (GetDeviceInfo, (self, ix, sizeof (value), value, 0));
1129 root 1.14 EXTEND (SP, 1);
1130     const int i = 0;
1131     PUSHs (sv_2mortal (newSVuv (value [i])));
1132    
1133     void
1134 root 1.22 max_work_group_size (OpenCL::Device self)
1135 root 1.16 ALIAS:
1136     max_work_group_size = CL_DEVICE_MAX_WORK_GROUP_SIZE
1137     image2d_max_width = CL_DEVICE_IMAGE2D_MAX_WIDTH
1138     image2d_max_height = CL_DEVICE_IMAGE2D_MAX_HEIGHT
1139     image3d_max_width = CL_DEVICE_IMAGE3D_MAX_WIDTH
1140     image3d_max_height = CL_DEVICE_IMAGE3D_MAX_HEIGHT
1141     image3d_max_depth = CL_DEVICE_IMAGE3D_MAX_DEPTH
1142     max_parameter_size = CL_DEVICE_MAX_PARAMETER_SIZE
1143     profiling_timer_resolution = CL_DEVICE_PROFILING_TIMER_RESOLUTION
1144 root 1.14 PPCODE:
1145 root 1.16 size_t value [1];
1146 root 1.22 NEED_SUCCESS (GetDeviceInfo, (self, ix, sizeof (value), value, 0));
1147 root 1.14 EXTEND (SP, 1);
1148     const int i = 0;
1149     PUSHs (sv_2mortal (newSVuv (value [i])));
1150    
1151     void
1152 root 1.22 max_work_item_sizes (OpenCL::Device self)
1153 root 1.14 PPCODE:
1154 root 1.16 size_t size;
1155 root 1.22 NEED_SUCCESS (GetDeviceInfo, (self, CL_DEVICE_MAX_WORK_ITEM_SIZES, 0, 0, &size));
1156 root 1.16 size_t *value = tmpbuf (size);
1157 root 1.22 NEED_SUCCESS (GetDeviceInfo, (self, CL_DEVICE_MAX_WORK_ITEM_SIZES, size, value, 0));
1158 root 1.16 int i, n = size / sizeof (*value);
1159     EXTEND (SP, n);
1160     for (i = 0; i < n; ++i)
1161 root 1.14 PUSHs (sv_2mortal (newSVuv (value [i])));
1162    
1163     void
1164 root 1.22 error_correction_support (OpenCL::Device self)
1165 root 1.16 ALIAS:
1166     error_correction_support = CL_DEVICE_ERROR_CORRECTION_SUPPORT
1167     endian_little = CL_DEVICE_ENDIAN_LITTLE
1168     available = CL_DEVICE_AVAILABLE
1169     compiler_available = CL_DEVICE_COMPILER_AVAILABLE
1170     host_unified_memory = CL_DEVICE_HOST_UNIFIED_MEMORY
1171 root 1.14 PPCODE:
1172 root 1.79 cl_uint value [1];
1173 root 1.22 NEED_SUCCESS (GetDeviceInfo, (self, ix, sizeof (value), value, 0));
1174 root 1.14 EXTEND (SP, 1);
1175     const int i = 0;
1176 root 1.16 PUSHs (sv_2mortal (value [i] ? &PL_sv_yes : &PL_sv_no));
1177 root 1.14
1178     void
1179 root 1.22 platform (OpenCL::Device self)
1180 root 1.14 PPCODE:
1181 root 1.16 cl_platform_id value [1];
1182 root 1.22 NEED_SUCCESS (GetDeviceInfo, (self, CL_DEVICE_PLATFORM, sizeof (value), value, 0));
1183 root 1.14 EXTEND (SP, 1);
1184     const int i = 0;
1185 root 1.79 PUSH_CLOBJ (stash_platform, value [i]);
1186 root 1.14
1187     void
1188 root 1.22 name (OpenCL::Device self)
1189 root 1.16 ALIAS:
1190     name = CL_DEVICE_NAME
1191     vendor = CL_DEVICE_VENDOR
1192     driver_version = CL_DRIVER_VERSION
1193     profile = CL_DEVICE_PROFILE
1194     version = CL_DEVICE_VERSION
1195     extensions = CL_DEVICE_EXTENSIONS
1196 root 1.14 PPCODE:
1197     size_t size;
1198 root 1.22 NEED_SUCCESS (GetDeviceInfo, (self, ix, 0, 0, &size));
1199 root 1.16 char *value = tmpbuf (size);
1200 root 1.22 NEED_SUCCESS (GetDeviceInfo, (self, ix, size, value, 0));
1201 root 1.16 EXTEND (SP, 1);
1202     const int i = 0;
1203     PUSHs (sv_2mortal (newSVpv (value, 0)));
1204 root 1.14
1205     void
1206 root 1.22 parent_device_ext (OpenCL::Device self)
1207 root 1.14 PPCODE:
1208 root 1.16 cl_device_id value [1];
1209 root 1.22 NEED_SUCCESS (GetDeviceInfo, (self, CL_DEVICE_PARENT_DEVICE_EXT, sizeof (value), value, 0));
1210 root 1.14 EXTEND (SP, 1);
1211     const int i = 0;
1212 root 1.79 PUSH_CLOBJ (stash_device, value [i]);
1213 root 1.14
1214     void
1215 root 1.22 partition_types_ext (OpenCL::Device self)
1216 root 1.16 ALIAS:
1217     partition_types_ext = CL_DEVICE_PARTITION_TYPES_EXT
1218     affinity_domains_ext = CL_DEVICE_AFFINITY_DOMAINS_EXT
1219     partition_style_ext = CL_DEVICE_PARTITION_STYLE_EXT
1220 root 1.14 PPCODE:
1221     size_t size;
1222 root 1.22 NEED_SUCCESS (GetDeviceInfo, (self, ix, 0, 0, &size));
1223 root 1.14 cl_device_partition_property_ext *value = tmpbuf (size);
1224 root 1.22 NEED_SUCCESS (GetDeviceInfo, (self, ix, size, value, 0));
1225 root 1.15 int i, n = size / sizeof (*value);
1226 root 1.14 EXTEND (SP, n);
1227     for (i = 0; i < n; ++i)
1228     PUSHs (sv_2mortal (newSVuv (value [i])));
1229    
1230     #END:device
1231    
1232 root 1.65 MODULE = OpenCL PACKAGE = OpenCL::SubDevice
1233    
1234     #if CL_VERSION_1_2
1235    
1236     void
1237     DESTROY (OpenCL::SubDevice self)
1238     CODE:
1239     clReleaseDevice (self);
1240    
1241     #endif
1242    
1243 root 1.1 MODULE = OpenCL PACKAGE = OpenCL::Context
1244    
1245     void
1246 root 1.65 DESTROY (OpenCL::Context self)
1247 root 1.1 CODE:
1248 root 1.65 clReleaseContext (self);
1249 root 1.1
1250     void
1251 root 1.22 info (OpenCL::Context self, cl_context_info name)
1252 root 1.1 PPCODE:
1253 root 1.2 INFO (Context)
1254    
1255     void
1256 root 1.22 queue (OpenCL::Context self, OpenCL::Device device, cl_command_queue_properties properties = 0)
1257 root 1.2 PPCODE:
1258 root 1.23 NEED_SUCCESS_ARG (cl_command_queue queue, CreateCommandQueue, (self, device, properties, &res));
1259 root 1.61 XPUSH_CLOBJ (stash_queue, queue);
1260 root 1.2
1261     void
1262 root 1.22 user_event (OpenCL::Context self)
1263 root 1.5 PPCODE:
1264 root 1.23 NEED_SUCCESS_ARG (cl_event ev, CreateUserEvent, (self, &res));
1265 root 1.61 XPUSH_CLOBJ (stash_userevent, ev);
1266 root 1.5
1267     void
1268 root 1.22 buffer (OpenCL::Context self, cl_mem_flags flags, size_t len)
1269 root 1.2 PPCODE:
1270 root 1.3 if (flags & (CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR))
1271 root 1.27 croak ("OpenCL::Context::buffer: cannot use/copy host ptr when no data is given, use $context->buffer_sv instead?");
1272 root 1.3
1273 root 1.22 NEED_SUCCESS_ARG (cl_mem mem, CreateBuffer, (self, flags, len, 0, &res));
1274 root 1.61 XPUSH_CLOBJ (stash_bufferobj, mem);
1275 root 1.2
1276     void
1277 root 1.22 buffer_sv (OpenCL::Context self, cl_mem_flags flags, SV *data)
1278 root 1.2 PPCODE:
1279     STRLEN len;
1280 root 1.21 char *ptr = SvOK (data) ? SvPVbyte (data, len) : 0;
1281 root 1.3 if (!(flags & (CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR)))
1282 root 1.27 croak ("OpenCL::Context::buffer_sv: you have to specify use or copy host ptr when buffer data is given, use $context->buffer instead?");
1283 root 1.22 NEED_SUCCESS_ARG (cl_mem mem, CreateBuffer, (self, flags, len, ptr, &res));
1284 root 1.61 XPUSH_CLOBJ (stash_bufferobj, mem);
1285 root 1.3
1286 root 1.42 #if CL_VERSION_1_2
1287    
1288     void
1289 root 1.55 image (OpenCL::Context self, cl_mem_flags flags, cl_channel_order channel_order, cl_channel_type channel_type, cl_mem_object_type type, size_t width, size_t height, size_t depth = 0, size_t array_size = 0, size_t row_pitch = 0, size_t slice_pitch = 0, cl_uint num_mip_level = 0, cl_uint num_samples = 0, SV *data = &PL_sv_undef)
1290 root 1.42 PPCODE:
1291     STRLEN len;
1292     char *ptr = SvOK (data) ? SvPVbyte (data, len) : 0;
1293     const cl_image_format format = { channel_order, channel_type };
1294     const cl_image_desc desc = {
1295     type,
1296     width, height, depth,
1297     array_size, row_pitch, slice_pitch,
1298     num_mip_level, num_samples,
1299 root 1.71 type == CL_MEM_OBJECT_IMAGE1D_BUFFER ? (cl_mem)SvCLOBJ (cv, "data", data, "OpenCL::Buffer") : 0
1300 root 1.42 };
1301     NEED_SUCCESS_ARG (cl_mem mem, CreateImage, (self, flags, &format, &desc, ptr, &res));
1302 root 1.61 HV *stash = stash_image;
1303 root 1.42 switch (type)
1304     {
1305 root 1.61 case CL_MEM_OBJECT_IMAGE1D_BUFFER: stash = stash_image1dbuffer; break;
1306     case CL_MEM_OBJECT_IMAGE1D: stash = stash_image1d; break;
1307     case CL_MEM_OBJECT_IMAGE1D_ARRAY: stash = stash_image2darray; break;
1308     case CL_MEM_OBJECT_IMAGE2D: stash = stash_image2d; break;
1309     case CL_MEM_OBJECT_IMAGE2D_ARRAY: stash = stash_image2darray; break;
1310     case CL_MEM_OBJECT_IMAGE3D: stash = stash_image3d; break;
1311 root 1.42 }
1312 root 1.61 XPUSH_CLOBJ (stash, mem);
1313 root 1.42
1314     #endif
1315    
1316 root 1.3 void
1317 root 1.22 image2d (OpenCL::Context self, cl_mem_flags flags, cl_channel_order channel_order, cl_channel_type channel_type, size_t width, size_t height, size_t row_pitch = 0, SV *data = &PL_sv_undef)
1318 root 1.3 PPCODE:
1319     STRLEN len;
1320 root 1.21 char *ptr = SvOK (data) ? SvPVbyte (data, len) : 0;
1321 root 1.3 const cl_image_format format = { channel_order, channel_type };
1322 root 1.44 #if PREFER_1_1
1323     NEED_SUCCESS_ARG (cl_mem mem, CreateImage2D, (self, flags, &format, width, height, row_pitch, ptr, &res));
1324     #else
1325 root 1.42 const cl_image_desc desc = { CL_MEM_OBJECT_IMAGE2D, width, height, 0, 0, row_pitch, 0, 0, 0, 0 };
1326     NEED_SUCCESS_ARG (cl_mem mem, CreateImage, (self, flags, &format, &desc, ptr, &res));
1327     #endif
1328 root 1.61 XPUSH_CLOBJ (stash_image2d, mem);
1329 root 1.3
1330     void
1331 root 1.22 image3d (OpenCL::Context self, cl_mem_flags flags, cl_channel_order channel_order, cl_channel_type channel_type, size_t width, size_t height, size_t depth, size_t row_pitch = 0, size_t slice_pitch = 0, SV *data = &PL_sv_undef)
1332 root 1.3 PPCODE:
1333     STRLEN len;
1334 root 1.21 char *ptr = SvOK (data) ? SvPVbyte (data, len) : 0;
1335 root 1.3 const cl_image_format format = { channel_order, channel_type };
1336 root 1.44 #if PREFER_1_1
1337     NEED_SUCCESS_ARG (cl_mem mem, CreateImage3D, (self, flags, &format, width, height, depth, row_pitch, slice_pitch, ptr, &res));
1338     #else
1339 root 1.42 const cl_image_desc desc = { CL_MEM_OBJECT_IMAGE3D, width, height, depth, 0, row_pitch, slice_pitch, 0, 0, 0 };
1340     NEED_SUCCESS_ARG (cl_mem mem, CreateImage, (self, flags, &format, &desc, ptr, &res));
1341     #endif
1342 root 1.61 XPUSH_CLOBJ (stash_image3d, mem);
1343 root 1.3
1344 root 1.25 #if cl_apple_gl_sharing || cl_khr_gl_sharing
1345    
1346     void
1347     gl_buffer (OpenCL::Context self, cl_mem_flags flags, cl_GLuint bufobj)
1348     PPCODE:
1349     NEED_SUCCESS_ARG (cl_mem mem, CreateFromGLBuffer, (self, flags, bufobj, &res));
1350 root 1.61 XPUSH_CLOBJ (stash_bufferobj, mem);
1351 root 1.25
1352     void
1353 root 1.40 gl_renderbuffer (OpenCL::Context self, cl_mem_flags flags, cl_GLuint renderbuffer)
1354 root 1.25 PPCODE:
1355 root 1.40 NEED_SUCCESS_ARG (cl_mem mem, CreateFromGLRenderbuffer, (self, flags, renderbuffer, &res));
1356 root 1.61 XPUSH_CLOBJ (stash_image2d, mem);
1357 root 1.25
1358 root 1.39 #if CL_VERSION_1_2
1359    
1360     void
1361     gl_texture (OpenCL::Context self, cl_mem_flags flags, cl_GLenum target, cl_GLint miplevel, cl_GLuint texture)
1362 root 1.43 ALIAS:
1363 root 1.39 PPCODE:
1364 root 1.43 NEED_SUCCESS_ARG (cl_mem mem, CreateFromGLTexture, (self, flags, target, miplevel, texture, &res));
1365     cl_gl_object_type type;
1366     NEED_SUCCESS (GetGLObjectInfo, (mem, &type, 0)); // TODO: use target instead?
1367 root 1.61 HV *stash = stash_memory;
1368 root 1.42 switch (type)
1369 root 1.39 {
1370 root 1.61 case CL_GL_OBJECT_TEXTURE_BUFFER: stash = stash_image1dbuffer; break;
1371     case CL_GL_OBJECT_TEXTURE1D: stash = stash_image1d; break;
1372     case CL_GL_OBJECT_TEXTURE1D_ARRAY: stash = stash_image2darray; break;
1373     case CL_GL_OBJECT_TEXTURE2D: stash = stash_image2d; break;
1374     case CL_GL_OBJECT_TEXTURE2D_ARRAY: stash = stash_image2darray; break;
1375     case CL_GL_OBJECT_TEXTURE3D: stash = stash_image3d; break;
1376 root 1.39 }
1377 root 1.61 XPUSH_CLOBJ (stash, mem);
1378 root 1.39
1379 root 1.44 #endif
1380 root 1.40
1381 root 1.25 void
1382 root 1.40 gl_texture2d (OpenCL::Context self, cl_mem_flags flags, cl_GLenum target, cl_GLint miplevel, cl_GLuint texture)
1383 root 1.25 PPCODE:
1384 root 1.44 #if PREFER_1_1
1385 root 1.40 NEED_SUCCESS_ARG (cl_mem mem, CreateFromGLTexture2D, (self, flags, target, miplevel, texture, &res));
1386 root 1.44 #else
1387     NEED_SUCCESS_ARG (cl_mem mem, CreateFromGLTexture , (self, flags, target, miplevel, texture, &res));
1388     #endif
1389 root 1.61 XPUSH_CLOBJ (stash_image2d, mem);
1390 root 1.25
1391 root 1.40 void
1392     gl_texture3d (OpenCL::Context self, cl_mem_flags flags, cl_GLenum target, cl_GLint miplevel, cl_GLuint texture)
1393     PPCODE:
1394 root 1.44 #if PREFER_1_1
1395 root 1.40 NEED_SUCCESS_ARG (cl_mem mem, CreateFromGLTexture3D, (self, flags, target, miplevel, texture, &res));
1396 root 1.44 #else
1397     NEED_SUCCESS_ARG (cl_mem mem, CreateFromGLTexture , (self, flags, target, miplevel, texture, &res));
1398     #endif
1399 root 1.61 XPUSH_CLOBJ (stash_image3d, mem);
1400 root 1.40
1401     #endif
1402    
1403 root 1.3 void
1404 root 1.22 supported_image_formats (OpenCL::Context self, cl_mem_flags flags, cl_mem_object_type image_type)
1405 root 1.3 PPCODE:
1406     {
1407     cl_uint count;
1408     cl_image_format *list;
1409     int i;
1410    
1411 root 1.23 NEED_SUCCESS (GetSupportedImageFormats, (self, flags, image_type, 0, 0, &count));
1412 root 1.3 Newx (list, count, cl_image_format);
1413 root 1.23 NEED_SUCCESS (GetSupportedImageFormats, (self, flags, image_type, count, list, 0));
1414 root 1.3
1415     EXTEND (SP, count);
1416     for (i = 0; i < count; ++i)
1417     {
1418     AV *av = newAV ();
1419     av_store (av, 1, newSVuv (list [i].image_channel_data_type));
1420     av_store (av, 0, newSVuv (list [i].image_channel_order));
1421     PUSHs (sv_2mortal (newRV_noinc ((SV *)av)));
1422     }
1423 root 1.2 }
1424    
1425     void
1426 root 1.22 sampler (OpenCL::Context self, cl_bool normalized_coords, cl_addressing_mode addressing_mode, cl_filter_mode filter_mode)
1427 root 1.2 PPCODE:
1428 root 1.23 NEED_SUCCESS_ARG (cl_sampler sampler, CreateSampler, (self, normalized_coords, addressing_mode, filter_mode, &res));
1429 root 1.61 XPUSH_CLOBJ (stash_sampler, sampler);
1430 root 1.1
1431     void
1432 root 1.22 program_with_source (OpenCL::Context self, SV *program)
1433 root 1.1 PPCODE:
1434 root 1.2 STRLEN len;
1435     size_t len2;
1436     const char *ptr = SvPVbyte (program, len);
1437    
1438     len2 = len;
1439 root 1.23 NEED_SUCCESS_ARG (cl_program prog, CreateProgramWithSource, (self, 1, &ptr, &len2, &res));
1440 root 1.61 XPUSH_CLOBJ (stash_program, prog);
1441 root 1.1
1442 root 1.64 void
1443     program_with_binary (OpenCL::Context self, SV *devices, SV *binaries)
1444     PPCODE:
1445 root 1.70 cl_uint device_count;
1446     cl_device_id *device_list = object_list (cv, 0, "devices", devices, "OpenCL::Device", &device_count);
1447 root 1.64
1448     if (!SvROK (binaries) || SvTYPE (SvRV (binaries)) != SVt_PVAV)
1449     croak ("OpenCL::Context::program_with_binary: binaries must be specified as reference to an array of strings");
1450    
1451     binaries = SvRV (binaries);
1452    
1453 root 1.70 if (device_count != av_len ((AV *)binaries) + 1)
1454 root 1.64 croak ("OpenCL::Context::program_with_binary: differing numbers of devices and binaries are not allowed");
1455    
1456 root 1.70 size_t *length_list = tmpbuf (sizeof (*length_list) * device_count);
1457     const unsigned char **binary_list = tmpbuf (sizeof (*binary_list) * device_count);
1458     cl_int *status_list = tmpbuf (sizeof (*status_list) * device_count);
1459 root 1.64
1460     int i;
1461 root 1.70 for (i = 0; i < device_count; ++i)
1462 root 1.64 {
1463     STRLEN len;
1464     binary_list [i] = (const unsigned char *)SvPVbyte (*av_fetch ((AV *)binaries, i, 0), len);
1465     length_list [i] = len;
1466     }
1467    
1468 root 1.70 NEED_SUCCESS_ARG (cl_program prog, CreateProgramWithBinary, (self, device_count, device_list,
1469     length_list, binary_list,
1470     GIMME_V == G_ARRAY ? status_list : 0, &res));
1471 root 1.64
1472     EXTEND (SP, 2);
1473     PUSH_CLOBJ (stash_program, prog);
1474    
1475     if (GIMME_V == G_ARRAY)
1476     {
1477     AV *av = newAV ();
1478     PUSHs (sv_2mortal (newRV_noinc ((SV *)av)));
1479    
1480 root 1.70 for (i = device_count; i--; )
1481 root 1.64 av_store (av, i, newSViv (status_list [i]));
1482     }
1483    
1484 root 1.65 #if CL_VERSION_1_2
1485    
1486     void
1487     program_with_built_in_kernels (OpenCL::Context self, SV *devices, SV *kernel_names)
1488     PPCODE:
1489 root 1.71 cl_uint device_count;
1490     cl_device_id *device_list = object_list (cv, 0, "devices", devices, "OpenCL::Device", &device_count);
1491 root 1.69
1492     NEED_SUCCESS_ARG (cl_program prog, CreateProgramWithBuiltInKernels, (self, device_count, device_list, SvPVbyte_nolen (kernel_names), &res));
1493    
1494     XPUSH_CLOBJ (stash_program, prog);
1495    
1496     void
1497     link_program (OpenCL::Context self, SV *devices, SV *options, SV *programs, SV *notify = &PL_sv_undef)
1498     CODE:
1499     cl_uint device_count = 0;
1500     cl_device_id *device_list = 0;
1501 root 1.65
1502 root 1.69 if (SvOK (devices))
1503     device_list = object_list (cv, 1, "devices", devices, "OpenCL::Device", &device_count);
1504 root 1.65
1505 root 1.69 cl_uint program_count;
1506     cl_program *program_list = object_list (cv, 0, "programs", programs, "OpenCL::Program", &program_count);
1507 root 1.65
1508 root 1.69 void *user_data;
1509     program_callback pfn_notify = make_program_callback (notify, &user_data);
1510 root 1.65
1511 root 1.69 NEED_SUCCESS_ARG (cl_program prog, LinkProgram, (self, device_count, device_list, SvPVbyte_nolen (options),
1512     program_count, program_list, pfn_notify, user_data, &res));
1513 root 1.65
1514     XPUSH_CLOBJ (stash_program, prog);
1515    
1516     #endif
1517    
1518 root 1.13 #BEGIN:context
1519    
1520 root 1.14 void
1521 root 1.22 reference_count (OpenCL::Context self)
1522 root 1.16 ALIAS:
1523     reference_count = CL_CONTEXT_REFERENCE_COUNT
1524     num_devices = CL_CONTEXT_NUM_DEVICES
1525 root 1.14 PPCODE:
1526     cl_uint value [1];
1527 root 1.22 NEED_SUCCESS (GetContextInfo, (self, ix, sizeof (value), value, 0));
1528 root 1.14 EXTEND (SP, 1);
1529     const int i = 0;
1530     PUSHs (sv_2mortal (newSVuv (value [i])));
1531    
1532     void
1533 root 1.22 devices (OpenCL::Context self)
1534 root 1.14 PPCODE:
1535     size_t size;
1536 root 1.22 NEED_SUCCESS (GetContextInfo, (self, CL_CONTEXT_DEVICES, 0, 0, &size));
1537 root 1.14 cl_device_id *value = tmpbuf (size);
1538 root 1.22 NEED_SUCCESS (GetContextInfo, (self, CL_CONTEXT_DEVICES, size, value, 0));
1539 root 1.15 int i, n = size / sizeof (*value);
1540 root 1.14 EXTEND (SP, n);
1541     for (i = 0; i < n; ++i)
1542 root 1.79 PUSH_CLOBJ (stash_device, value [i]);
1543 root 1.14
1544     void
1545 root 1.22 properties (OpenCL::Context self)
1546 root 1.14 PPCODE:
1547     size_t size;
1548 root 1.22 NEED_SUCCESS (GetContextInfo, (self, CL_CONTEXT_PROPERTIES, 0, 0, &size));
1549 root 1.14 cl_context_properties *value = tmpbuf (size);
1550 root 1.22 NEED_SUCCESS (GetContextInfo, (self, CL_CONTEXT_PROPERTIES, size, value, 0));
1551 root 1.15 int i, n = size / sizeof (*value);
1552 root 1.14 EXTEND (SP, n);
1553     for (i = 0; i < n; ++i)
1554     PUSHs (sv_2mortal (newSVuv ((UV)value [i])));
1555    
1556 root 1.13 #END:context
1557    
1558 root 1.1 MODULE = OpenCL PACKAGE = OpenCL::Queue
1559    
1560     void
1561 root 1.22 DESTROY (OpenCL::Queue self)
1562 root 1.1 CODE:
1563 root 1.22 clReleaseCommandQueue (self);
1564 root 1.1
1565     void
1566 root 1.55 read_buffer (OpenCL::Queue self, OpenCL::Buffer mem, cl_bool blocking, size_t offset, size_t len, SV *data, ...)
1567     ALIAS:
1568     enqueue_read_buffer = 0
1569 root 1.2 PPCODE:
1570 root 1.61 EVENT_LIST (6);
1571 root 1.2
1572     SvUPGRADE (data, SVt_PV);
1573     SvGROW (data, len);
1574     SvPOK_only (data);
1575     SvCUR_set (data, len);
1576 root 1.69
1577     cl_event ev = 0;
1578 root 1.22 NEED_SUCCESS (EnqueueReadBuffer, (self, mem, blocking, offset, len, SvPVX (data), event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0));
1579 root 1.2
1580     if (ev)
1581 root 1.61 XPUSH_CLOBJ (stash_event, ev);
1582 root 1.2
1583     void
1584 root 1.55 write_buffer (OpenCL::Queue self, OpenCL::Buffer mem, cl_bool blocking, size_t offset, SV *data, ...)
1585     ALIAS:
1586     enqueue_write_buffer = 0
1587 root 1.2 PPCODE:
1588 root 1.69 EVENT_LIST (5);
1589    
1590 root 1.2 STRLEN len;
1591     char *ptr = SvPVbyte (data, len);
1592    
1593 root 1.69 cl_event ev = 0;
1594 root 1.34 NEED_SUCCESS (EnqueueWriteBuffer, (self, mem, blocking, offset, len, ptr, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0));
1595 root 1.2
1596     if (ev)
1597 root 1.61 XPUSH_CLOBJ (stash_event, ev);
1598 root 1.2
1599 root 1.48 #if CL_VERSION_1_2
1600    
1601     void
1602 root 1.55 fill_buffer (OpenCL::Queue self, OpenCL::Buffer mem, SV *data, size_t offset, size_t size, ...)
1603     ALIAS:
1604     enqueue_fill_buffer = 0
1605 root 1.48 PPCODE:
1606 root 1.69 EVENT_LIST (5);
1607    
1608 root 1.48 STRLEN len;
1609     char *ptr = SvPVbyte (data, len);
1610    
1611 root 1.69 cl_event ev = 0;
1612 root 1.48 NEED_SUCCESS (EnqueueFillBuffer, (self, mem, ptr, len, offset, size, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0));
1613    
1614     if (ev)
1615 root 1.61 XPUSH_CLOBJ (stash_event, ev);
1616 root 1.48
1617     void
1618 root 1.55 fill_image (OpenCL::Queue self, OpenCL::Image img, NV r, NV g, NV b, NV a, size_t x, size_t y, size_t z, size_t width, size_t height, size_t depth, ...)
1619     ALIAS:
1620     enqueue_fill_image = 0
1621 root 1.48 PPCODE:
1622 root 1.69 EVENT_LIST (12);
1623    
1624 root 1.48 const size_t origin [3] = { x, y, z };
1625     const size_t region [3] = { width, height, depth };
1626    
1627     const cl_float c_f [4] = { r, g, b, a };
1628     const cl_uint c_u [4] = { r, g, b, a };
1629     const cl_int c_s [4] = { r, g, b, a };
1630     const void *c_fus [3] = { &c_f, &c_u, &c_s };
1631     static const char fus [] = { 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 1, 1, 1, 0, 0 };
1632     cl_image_format format;
1633 root 1.50 NEED_SUCCESS (GetImageInfo, (img, CL_IMAGE_FORMAT, sizeof (format), &format, 0));
1634 root 1.48 assert (sizeof (fus) == CL_FLOAT + 1 - CL_SNORM_INT8);
1635     if (format.image_channel_data_type < CL_SNORM_INT8 || CL_FLOAT < format.image_channel_data_type)
1636     croak ("enqueue_fill_image: image has unsupported channel type, only opencl 1.2 channel types supported.");
1637    
1638 root 1.69 cl_event ev = 0;
1639 root 1.55 NEED_SUCCESS (EnqueueFillImage, (self, img, c_fus [fus [format.image_channel_data_type - CL_SNORM_INT8]],
1640 root 1.48 origin, region, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0));
1641    
1642     if (ev)
1643 root 1.61 XPUSH_CLOBJ (stash_event, ev);
1644 root 1.48
1645     #endif
1646    
1647 root 1.2 void
1648 root 1.55 copy_buffer (OpenCL::Queue self, OpenCL::Buffer src, OpenCL::Buffer dst, size_t src_offset, size_t dst_offset, size_t len, ...)
1649     ALIAS:
1650     enqueue_copy_buffer = 0
1651 root 1.2 PPCODE:
1652 root 1.61 EVENT_LIST (6);
1653 root 1.2
1654 root 1.69 cl_event ev = 0;
1655 root 1.22 NEED_SUCCESS (EnqueueCopyBuffer, (self, src, dst, src_offset, dst_offset, len, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0));
1656 root 1.2
1657     if (ev)
1658 root 1.61 XPUSH_CLOBJ (stash_event, ev);
1659 root 1.2
1660 root 1.3 void
1661 root 1.55 read_buffer_rect (OpenCL::Queue self, OpenCL::Memory buf, cl_bool blocking, size_t buf_x, size_t buf_y, size_t buf_z, size_t host_x, size_t host_y, size_t host_z, size_t width, size_t height, size_t depth, size_t buf_row_pitch, size_t buf_slice_pitch, size_t host_row_pitch, size_t host_slice_pitch, SV *data, ...)
1662     ALIAS:
1663     enqueue_read_buffer_rect = 0
1664 root 1.17 PPCODE:
1665 root 1.69 EVENT_LIST (17);
1666    
1667 root 1.17 const size_t buf_origin [3] = { buf_x , buf_y , buf_z };
1668     const size_t host_origin[3] = { host_x, host_y, host_z };
1669     const size_t region[3] = { width, height, depth };
1670    
1671     if (!buf_row_pitch)
1672     buf_row_pitch = region [0];
1673    
1674     if (!buf_slice_pitch)
1675     buf_slice_pitch = region [1] * buf_row_pitch;
1676    
1677     if (!host_row_pitch)
1678     host_row_pitch = region [0];
1679    
1680     if (!host_slice_pitch)
1681     host_slice_pitch = region [1] * host_row_pitch;
1682    
1683     size_t len = host_row_pitch * host_slice_pitch * region [2];
1684    
1685     SvUPGRADE (data, SVt_PV);
1686     SvGROW (data, len);
1687     SvPOK_only (data);
1688     SvCUR_set (data, len);
1689 root 1.69
1690     cl_event ev = 0;
1691 root 1.22 NEED_SUCCESS (EnqueueReadBufferRect, (self, buf, blocking, buf_origin, host_origin, region, buf_row_pitch, buf_slice_pitch, host_row_pitch, host_slice_pitch, SvPVX (data), event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0));
1692 root 1.17
1693     if (ev)
1694 root 1.61 XPUSH_CLOBJ (stash_event, ev);
1695 root 1.17
1696     void
1697 root 1.55 write_buffer_rect (OpenCL::Queue self, OpenCL::Memory buf, cl_bool blocking, size_t buf_x, size_t buf_y, size_t buf_z, size_t host_x, size_t host_y, size_t host_z, size_t width, size_t height, size_t depth, size_t buf_row_pitch, size_t buf_slice_pitch, size_t host_row_pitch, size_t host_slice_pitch, SV *data, ...)
1698     ALIAS:
1699     enqueue_write_buffer_rect = 0
1700 root 1.17 PPCODE:
1701 root 1.69 EVENT_LIST (17);
1702    
1703 root 1.17 const size_t buf_origin [3] = { buf_x , buf_y , buf_z };
1704     const size_t host_origin[3] = { host_x, host_y, host_z };
1705     const size_t region[3] = { width, height, depth };
1706     STRLEN len;
1707     char *ptr = SvPVbyte (data, len);
1708    
1709     if (!buf_row_pitch)
1710     buf_row_pitch = region [0];
1711    
1712     if (!buf_slice_pitch)
1713     buf_slice_pitch = region [1] * buf_row_pitch;
1714    
1715     if (!host_row_pitch)
1716     host_row_pitch = region [0];
1717    
1718     if (!host_slice_pitch)
1719     host_slice_pitch = region [1] * host_row_pitch;
1720    
1721     size_t min_len = host_row_pitch * host_slice_pitch * region [2];
1722    
1723     if (len < min_len)
1724     croak ("clEnqueueWriteImage: data string is shorter than what would be transferred");
1725    
1726 root 1.69 cl_event ev = 0;
1727 root 1.37 NEED_SUCCESS (EnqueueWriteBufferRect, (self, buf, blocking, buf_origin, host_origin, region, buf_row_pitch, buf_slice_pitch, host_row_pitch, host_slice_pitch, ptr, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0));
1728 root 1.17
1729     if (ev)
1730 root 1.61 XPUSH_CLOBJ (stash_event, ev);
1731 root 1.17
1732     void
1733 root 1.55 copy_buffer_rect (OpenCL::Queue self, OpenCL::Buffer src, OpenCL::Buffer dst, size_t src_x, size_t src_y, size_t src_z, size_t dst_x, size_t dst_y, size_t dst_z, size_t width, size_t height, size_t depth, size_t src_row_pitch, size_t src_slice_pitch, size_t dst_row_pitch, size_t dst_slice_pitch, ...)
1734     ALIAS:
1735     enqueue_copy_buffer_rect = 0
1736 root 1.18 PPCODE:
1737 root 1.69 EVENT_LIST (16);
1738    
1739 root 1.18 const size_t src_origin[3] = { src_x, src_y, src_z };
1740     const size_t dst_origin[3] = { dst_x, dst_y, dst_z };
1741     const size_t region[3] = { width, height, depth };
1742    
1743 root 1.69 cl_event ev = 0;
1744 root 1.22 NEED_SUCCESS (EnqueueCopyBufferRect, (self, src, dst, src_origin, dst_origin, region, src_row_pitch, src_slice_pitch, dst_row_pitch, dst_slice_pitch, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0));
1745 root 1.18
1746     if (ev)
1747 root 1.61 XPUSH_CLOBJ (stash_event, ev);
1748 root 1.18
1749     void
1750 root 1.55 read_image (OpenCL::Queue self, OpenCL::Image src, cl_bool blocking, size_t src_x, size_t src_y, size_t src_z, size_t width, size_t height, size_t depth, size_t row_pitch, size_t slice_pitch, SV *data, ...)
1751     ALIAS:
1752     enqueue_read_image = 0
1753 root 1.3 PPCODE:
1754 root 1.69 EVENT_LIST (12);
1755    
1756 root 1.3 const size_t src_origin[3] = { src_x, src_y, src_z };
1757     const size_t region[3] = { width, height, depth };
1758 root 1.10
1759 root 1.11 if (!row_pitch)
1760     row_pitch = img_row_pitch (src);
1761    
1762     if (depth > 1 && !slice_pitch)
1763     slice_pitch = row_pitch * height;
1764    
1765     size_t len = slice_pitch ? slice_pitch * depth : row_pitch * height;
1766 root 1.3
1767     SvUPGRADE (data, SVt_PV);
1768     SvGROW (data, len);
1769     SvPOK_only (data);
1770     SvCUR_set (data, len);
1771 root 1.69
1772     cl_event ev = 0;
1773 root 1.22 NEED_SUCCESS (EnqueueReadImage, (self, src, blocking, src_origin, region, row_pitch, slice_pitch, SvPVX (data), event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0));
1774 root 1.3
1775     if (ev)
1776 root 1.61 XPUSH_CLOBJ (stash_event, ev);
1777 root 1.3
1778     void
1779 root 1.55 write_image (OpenCL::Queue self, OpenCL::Image dst, cl_bool blocking, size_t dst_x, size_t dst_y, size_t dst_z, size_t width, size_t height, size_t depth, size_t row_pitch, size_t slice_pitch, SV *data, ...)
1780     ALIAS:
1781     enqueue_write_image = 0
1782 root 1.3 PPCODE:
1783 root 1.69 EVENT_LIST (12);
1784    
1785 root 1.3 const size_t dst_origin[3] = { dst_x, dst_y, dst_z };
1786     const size_t region[3] = { width, height, depth };
1787     STRLEN len;
1788     char *ptr = SvPVbyte (data, len);
1789    
1790 root 1.11 if (!row_pitch)
1791     row_pitch = img_row_pitch (dst);
1792    
1793     if (depth > 1 && !slice_pitch)
1794     slice_pitch = row_pitch * height;
1795    
1796     size_t min_len = slice_pitch ? slice_pitch * depth : row_pitch * height;
1797    
1798     if (len < min_len)
1799     croak ("clEnqueueWriteImage: data string is shorter than what would be transferred");
1800    
1801 root 1.69 cl_event ev = 0;
1802 root 1.37 NEED_SUCCESS (EnqueueWriteImage, (self, dst, blocking, dst_origin, region, row_pitch, slice_pitch, ptr, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0));
1803 root 1.3
1804     if (ev)
1805 root 1.61 XPUSH_CLOBJ (stash_event, ev);
1806 root 1.3
1807     void
1808 root 1.55 copy_image (OpenCL::Queue self, OpenCL::Image src, OpenCL::Image dst, size_t src_x, size_t src_y, size_t src_z, size_t dst_x, size_t dst_y, size_t dst_z, size_t width, size_t height, size_t depth, ...)
1809     ALIAS:
1810     enqueue_copy_image = 0
1811 root 1.3 PPCODE:
1812 root 1.69 EVENT_LIST (12);
1813    
1814 root 1.3 const size_t src_origin[3] = { src_x, src_y, src_z };
1815     const size_t dst_origin[3] = { dst_x, dst_y, dst_z };
1816     const size_t region[3] = { width, height, depth };
1817    
1818 root 1.69 cl_event ev = 0;
1819 root 1.22 NEED_SUCCESS (EnqueueCopyImage, (self, src, dst, src_origin, dst_origin, region, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0));
1820 root 1.3
1821     if (ev)
1822 root 1.61 XPUSH_CLOBJ (stash_event, ev);
1823 root 1.3
1824     void
1825 root 1.55 copy_image_to_buffer (OpenCL::Queue self, OpenCL::Image src, OpenCL::Buffer dst, size_t src_x, size_t src_y, size_t src_z, size_t width, size_t height, size_t depth, size_t dst_offset, ...)
1826     ALIAS:
1827     enqueue_copy_image_to_buffer = 0
1828 root 1.3 PPCODE:
1829 root 1.69 EVENT_LIST (10);
1830    
1831 root 1.61 const size_t src_origin[3] = { src_x, src_y, src_z };
1832     const size_t region [3] = { width, height, depth };
1833 root 1.3
1834 root 1.69 cl_event ev = 0;
1835 root 1.22 NEED_SUCCESS (EnqueueCopyImageToBuffer, (self, src, dst, src_origin, region, dst_offset, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0));
1836 root 1.3
1837     if (ev)
1838 root 1.61 XPUSH_CLOBJ (stash_event, ev);
1839 root 1.3
1840     void
1841 root 1.55 copy_buffer_to_image (OpenCL::Queue self, OpenCL::Buffer src, OpenCL::Image dst, size_t src_offset, size_t dst_x, size_t dst_y, size_t dst_z, size_t width, size_t height, size_t depth, ...)
1842     ALIAS:
1843     enqueue_copy_buffer_to_image = 0
1844 root 1.3 PPCODE:
1845 root 1.69 EVENT_LIST (10);
1846    
1847 root 1.61 const size_t dst_origin[3] = { dst_x, dst_y, dst_z };
1848     const size_t region [3] = { width, height, depth };
1849 root 1.3
1850 root 1.69 cl_event ev = 0;
1851 root 1.22 NEED_SUCCESS (EnqueueCopyBufferToImage, (self, src, dst, src_offset, dst_origin, region, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0));
1852 root 1.3
1853     if (ev)
1854 root 1.61 XPUSH_CLOBJ (stash_event, ev);
1855    
1856     void
1857 root 1.64 map_buffer (OpenCL::Queue self, OpenCL::Buffer buf, cl_bool blocking = 1, cl_map_flags map_flags = CL_MAP_READ | CL_MAP_WRITE, size_t offset = 0, SV *cb_ = &PL_sv_undef, ...)
1858 root 1.61 ALIAS:
1859     enqueue_map_buffer = 0
1860     PPCODE:
1861 root 1.62 EVENT_LIST (6);
1862 root 1.69
1863 root 1.64 size_t cb = SvIV (cb_);
1864    
1865     if (!SvOK (cb_))
1866     {
1867     NEED_SUCCESS (GetMemObjectInfo, (buf, CL_MEM_SIZE, sizeof (cb), &cb, 0));
1868     cb -= offset;
1869     }
1870 root 1.61
1871 root 1.69 cl_event ev;
1872 root 1.61 NEED_SUCCESS_ARG (void *ptr, EnqueueMapBuffer, (self, buf, blocking, map_flags, offset, cb, event_list_count, event_list_ptr, &ev, &res));
1873 root 1.80 XPUSHs (mapped_new (stash_mappedbuffer, self, buf, map_flags, ptr, cb, ev, 0, 0, 1, cb, 1, 1));
1874 root 1.61
1875     void
1876 root 1.64 map_image (OpenCL::Queue self, OpenCL::Image img, cl_bool blocking = 1, cl_map_flags map_flags = CL_MAP_READ | CL_MAP_WRITE, size_t x = 0, size_t y = 0, size_t z = 0, SV *width_ = &PL_sv_undef, SV *height_ = &PL_sv_undef, SV *depth_ = &PL_sv_undef, ...)
1877 root 1.61 ALIAS:
1878     enqueue_map_image = 0
1879     PPCODE:
1880 root 1.64 size_t width = SvIV (width_);
1881     if (!SvOK (width_))
1882     {
1883     NEED_SUCCESS (GetImageInfo, (img, CL_IMAGE_WIDTH, sizeof (width), &width, 0));
1884     width -= x;
1885     }
1886    
1887     size_t height = SvIV (width_);
1888     if (!SvOK (height_))
1889     {
1890     NEED_SUCCESS (GetImageInfo, (img, CL_IMAGE_HEIGHT, sizeof (height), &height, 0));
1891     height -= y;
1892 root 1.80
1893     // stupid opencl returns 0 for depth, but requires 1 for 2d images
1894     if (!height)
1895     height = 1;
1896 root 1.64 }
1897    
1898     size_t depth = SvIV (width_);
1899     if (!SvOK (depth_))
1900     {
1901     NEED_SUCCESS (GetImageInfo, (img, CL_IMAGE_DEPTH, sizeof (depth), &depth, 0));
1902     depth -= z;
1903    
1904     // stupid opencl returns 0 for depth, but requires 1 for 2d images
1905     if (!depth)
1906     depth = 1;
1907     }
1908    
1909 root 1.61 const size_t origin[3] = { x, y, z };
1910     const size_t region[3] = { width, height, depth };
1911     size_t row_pitch, slice_pitch;
1912 root 1.62 EVENT_LIST (10);
1913 root 1.61
1914 root 1.64 cl_event ev;
1915 root 1.61 NEED_SUCCESS_ARG (void *ptr, EnqueueMapImage, (self, img, blocking, map_flags, origin, region, &row_pitch, &slice_pitch, event_list_count, event_list_ptr, &ev, &res));
1916    
1917     size_t cb = slice_pitch ? slice_pitch * region [2]
1918     : row_pitch ? row_pitch * region [1]
1919     : region [0];
1920    
1921 root 1.80 XPUSHs (mapped_new (stash_mappedimage, self, img, map_flags, ptr, cb, ev, row_pitch, slice_pitch, 0, width, height, depth));
1922 root 1.61
1923     void
1924     unmap (OpenCL::Queue self, OpenCL::Mapped mapped, ...)
1925     PPCODE:
1926 root 1.71 mapped_unmap (cv, ST (1), mapped, self, &ST (2), items - 2);
1927 root 1.61 if (GIMME_V != G_VOID)
1928 root 1.62 {
1929     clRetainEvent (mapped->event);
1930     XPUSH_CLOBJ (stash_event, mapped->event);
1931     }
1932 root 1.3
1933     void
1934 root 1.55 task (OpenCL::Queue self, OpenCL::Kernel kernel, ...)
1935     ALIAS:
1936     enqueue_task = 0
1937 root 1.3 PPCODE:
1938 root 1.61 EVENT_LIST (2);
1939 root 1.3
1940 root 1.69 cl_event ev = 0;
1941 root 1.22 NEED_SUCCESS (EnqueueTask, (self, kernel, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0));
1942 root 1.3
1943     if (ev)
1944 root 1.61 XPUSH_CLOBJ (stash_event, ev);
1945 root 1.3
1946 root 1.4 void
1947 root 1.55 nd_range_kernel (OpenCL::Queue self, OpenCL::Kernel kernel, SV *global_work_offset, SV *global_work_size, SV *local_work_size = &PL_sv_undef, ...)
1948     ALIAS:
1949     enqueue_nd_range_kernel = 0
1950 root 1.4 PPCODE:
1951 root 1.69 EVENT_LIST (5);
1952    
1953 root 1.4 size_t *gwo = 0, *gws, *lws = 0;
1954     int gws_len;
1955     size_t *lists;
1956     int i;
1957    
1958     if (!SvROK (global_work_size) || SvTYPE (SvRV (global_work_size)) != SVt_PVAV)
1959     croak ("clEnqueueNDRangeKernel: global_work_size must be an array reference");
1960    
1961     gws_len = AvFILLp (SvRV (global_work_size)) + 1;
1962    
1963     lists = tmpbuf (sizeof (size_t) * 3 * gws_len);
1964    
1965     gws = lists + gws_len * 0;
1966     for (i = 0; i < gws_len; ++i)
1967 root 1.58 {
1968     gws [i] = SvIV (AvARRAY (SvRV (global_work_size))[i]);
1969     // at least nvidia crashes for 0-sized work group sizes, work around
1970     if (!gws [i])
1971     croak ("clEnqueueNDRangeKernel: global_work_size[%d] is zero, must be non-zero", i);
1972     }
1973 root 1.4
1974     if (SvOK (global_work_offset))
1975     {
1976     if (!SvROK (global_work_offset) || SvTYPE (SvRV (global_work_offset)) != SVt_PVAV)
1977     croak ("clEnqueueNDRangeKernel: global_work_offset must be undef or an array reference");
1978    
1979     if (AvFILLp (SvRV (global_work_size)) + 1 != gws_len)
1980     croak ("clEnqueueNDRangeKernel: global_work_offset must be undef or an array of same size as global_work_size");
1981    
1982     gwo = lists + gws_len * 1;
1983     for (i = 0; i < gws_len; ++i)
1984     gwo [i] = SvIV (AvARRAY (SvRV (global_work_offset))[i]);
1985     }
1986    
1987     if (SvOK (local_work_size))
1988     {
1989 root 1.37 if ((SvOK (local_work_size) && !SvROK (local_work_size)) || SvTYPE (SvRV (local_work_size)) != SVt_PVAV)
1990 root 1.58 croak ("clEnqueueNDRangeKernel: local_work_size must be undef or an array reference");
1991 root 1.4
1992     if (AvFILLp (SvRV (local_work_size)) + 1 != gws_len)
1993     croak ("clEnqueueNDRangeKernel: local_work_local must be undef or an array of same size as global_work_size");
1994    
1995     lws = lists + gws_len * 2;
1996     for (i = 0; i < gws_len; ++i)
1997 root 1.58 {
1998     lws [i] = SvIV (AvARRAY (SvRV (local_work_size))[i]);
1999     // at least nvidia crashes for 0-sized work group sizes, work around
2000     if (!lws [i])
2001     croak ("clEnqueueNDRangeKernel: local_work_size[%d] is zero, must be non-zero", i);
2002     }
2003 root 1.4 }
2004    
2005 root 1.69 cl_event ev = 0;
2006 root 1.22 NEED_SUCCESS (EnqueueNDRangeKernel, (self, kernel, gws_len, gwo, gws, lws, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0));
2007 root 1.4
2008     if (ev)
2009 root 1.61 XPUSH_CLOBJ (stash_event, ev);
2010 root 1.3
2011 root 1.65 #if CL_VERSION_1_2
2012    
2013     void
2014     migrate_mem_objects (OpenCL::Queue self, SV *objects, cl_mem_migration_flags flags, ...)
2015     ALIAS:
2016     enqueue_migrate_mem_objects = 0
2017     PPCODE:
2018     EVENT_LIST (3);
2019    
2020 root 1.69 cl_uint obj_count;
2021     cl_mem *obj_list = object_list (cv, 0, "objects", objects, "OpenCL::Memory", &obj_count);
2022 root 1.65
2023     cl_event ev = 0;
2024 root 1.69 NEED_SUCCESS (EnqueueMigrateMemObjects, (self, obj_count, obj_list, flags, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0));
2025 root 1.65
2026     if (ev)
2027     XPUSH_CLOBJ (stash_event, ev);
2028    
2029     #endif
2030    
2031 root 1.25 #if cl_apple_gl_sharing || cl_khr_gl_sharing
2032    
2033     void
2034 root 1.55 acquire_gl_objects (OpenCL::Queue self, SV *objects, ...)
2035     ALIAS:
2036 root 1.60 release_gl_objects = 1
2037 root 1.55 enqueue_acquire_gl_objects = 0
2038 root 1.27 enqueue_release_gl_objects = 1
2039 root 1.36 PPCODE:
2040 root 1.69 EVENT_LIST (2);
2041    
2042     cl_uint obj_count;
2043     cl_mem *obj_list = object_list (cv, 0, "objects", objects, "OpenCL::Memory", &obj_count);
2044 root 1.27
2045 root 1.25 cl_event ev = 0;
2046    
2047 root 1.27 if (ix)
2048 root 1.69 NEED_SUCCESS (EnqueueReleaseGLObjects, (self, obj_count, obj_list, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0));
2049 root 1.27 else
2050 root 1.69 NEED_SUCCESS (EnqueueAcquireGLObjects, (self, obj_count, obj_list, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0));
2051 root 1.25
2052     if (ev)
2053 root 1.61 XPUSH_CLOBJ (stash_event, ev);
2054 root 1.25
2055     #endif
2056    
2057 root 1.2 void
2058 root 1.55 wait_for_events (OpenCL::Queue self, ...)
2059     ALIAS:
2060     enqueue_wait_for_events = 0
2061 root 1.2 CODE:
2062 root 1.61 EVENT_LIST (1);
2063 root 1.47 #if PREFER_1_1
2064 root 1.22 NEED_SUCCESS (EnqueueWaitForEvents, (self, event_list_count, event_list_ptr));
2065 root 1.47 #else
2066     NEED_SUCCESS (EnqueueBarrierWithWaitList, (self, event_list_count, event_list_ptr, 0));
2067 root 1.38 #endif
2068    
2069     void
2070 root 1.55 marker (OpenCL::Queue self, ...)
2071     ALIAS:
2072     enqueue_marker = 0
2073 root 1.38 PPCODE:
2074 root 1.69 EVENT_LIST (1);
2075 root 1.38 cl_event ev = 0;
2076 root 1.45 #if PREFER_1_1
2077 root 1.47 if (!event_list_count)
2078     NEED_SUCCESS (EnqueueMarker, (self, GIMME_V != G_VOID ? &ev : 0));
2079     else
2080 root 1.46 #if CL_VERSION_1_2
2081     NEED_SUCCESS (EnqueueMarkerWithWaitList, (self, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0));
2082     #else
2083 root 1.50 {
2084     NEED_SUCCESS (EnqueueWaitForEvents, (self, event_list_count, event_list_ptr)); // also a barrier
2085     NEED_SUCCESS (EnqueueMarker, (self, GIMME_V != G_VOID ? &ev : 0));
2086     }
2087 root 1.46 #endif
2088 root 1.45 #else
2089     NEED_SUCCESS (EnqueueMarkerWithWaitList, (self, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0));
2090 root 1.38 #endif
2091     if (ev)
2092 root 1.61 XPUSH_CLOBJ (stash_event, ev);
2093 root 1.38
2094 root 1.2 void
2095 root 1.55 barrier (OpenCL::Queue self, ...)
2096     ALIAS:
2097     enqueue_barrier = 0
2098 root 1.38 PPCODE:
2099 root 1.69 EVENT_LIST (1);
2100 root 1.38 cl_event ev = 0;
2101 root 1.45 #if PREFER_1_1
2102 root 1.47 if (!event_list_count && GIMME_V == G_VOID)
2103     NEED_SUCCESS (EnqueueBarrier, (self));
2104     else
2105 root 1.46 #if CL_VERSION_1_2
2106     NEED_SUCCESS (EnqueueBarrierWithWaitList, (self, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0));
2107     #else
2108 root 1.47 {
2109     if (event_list_count)
2110 root 1.50 NEED_SUCCESS (EnqueueWaitForEvents, (self, event_list_count, event_list_ptr));
2111 root 1.47
2112     if (GIMME_V != G_VOID)
2113     NEED_SUCCESS (EnqueueMarker, (self, &ev));
2114     }
2115 root 1.46 #endif
2116 root 1.45 #else
2117 root 1.46 NEED_SUCCESS (EnqueueBarrierWithWaitList, (self, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0));
2118 root 1.37 #endif
2119 root 1.38 if (ev)
2120 root 1.61 XPUSH_CLOBJ (stash_event, ev);
2121 root 1.37
2122 root 1.3 void
2123 root 1.22 flush (OpenCL::Queue self)
2124 root 1.3 CODE:
2125 root 1.22 NEED_SUCCESS (Flush, (self));
2126 root 1.3
2127     void
2128 root 1.22 finish (OpenCL::Queue self)
2129 root 1.3 CODE:
2130 root 1.22 NEED_SUCCESS (Finish, (self));
2131 root 1.3
2132 root 1.14 void
2133 root 1.22 info (OpenCL::Queue self, cl_command_queue_info name)
2134 root 1.14 PPCODE:
2135     INFO (CommandQueue)
2136    
2137     #BEGIN:command_queue
2138    
2139     void
2140 root 1.22 context (OpenCL::Queue self)
2141 root 1.14 PPCODE:
2142     cl_context value [1];
2143 root 1.22 NEED_SUCCESS (GetCommandQueueInfo, (self, CL_QUEUE_CONTEXT, sizeof (value), value, 0));
2144 root 1.14 EXTEND (SP, 1);
2145     const int i = 0;
2146 root 1.79 NEED_SUCCESS (RetainContext, (value [i]));
2147     PUSH_CLOBJ (stash_context, value [i]);
2148 root 1.14
2149     void
2150 root 1.22 device (OpenCL::Queue self)
2151 root 1.14 PPCODE:
2152     cl_device_id value [1];
2153 root 1.22 NEED_SUCCESS (GetCommandQueueInfo, (self, CL_QUEUE_DEVICE, sizeof (value), value, 0));
2154 root 1.14 EXTEND (SP, 1);
2155     const int i = 0;
2156 root 1.79 PUSH_CLOBJ (stash_device, value [i]);
2157 root 1.14
2158     void
2159 root 1.22 reference_count (OpenCL::Queue self)
2160 root 1.14 PPCODE:
2161     cl_uint value [1];
2162 root 1.22 NEED_SUCCESS (GetCommandQueueInfo, (self, CL_QUEUE_REFERENCE_COUNT, sizeof (value), value, 0));
2163 root 1.14 EXTEND (SP, 1);
2164     const int i = 0;
2165     PUSHs (sv_2mortal (newSVuv (value [i])));
2166    
2167     void
2168 root 1.22 properties (OpenCL::Queue self)
2169 root 1.14 PPCODE:
2170 root 1.79 cl_ulong value [1];
2171 root 1.22 NEED_SUCCESS (GetCommandQueueInfo, (self, CL_QUEUE_PROPERTIES, sizeof (value), value, 0));
2172 root 1.14 EXTEND (SP, 1);
2173     const int i = 0;
2174 root 1.61 PUSHs (sv_2mortal (newSVuv (value [i])));
2175 root 1.14
2176     #END:command_queue
2177    
2178 root 1.2 MODULE = OpenCL PACKAGE = OpenCL::Memory
2179    
2180     void
2181 root 1.22 DESTROY (OpenCL::Memory self)
2182 root 1.2 CODE:
2183 root 1.22 clReleaseMemObject (self);
2184 root 1.2
2185     void
2186 root 1.22 info (OpenCL::Memory self, cl_mem_info name)
2187 root 1.2 PPCODE:
2188     INFO (MemObject)
2189    
2190 root 1.77 void
2191     destructor_callback (OpenCL::Memory self, SV *notify)
2192     PPCODE:
2193 root 1.78 clSetMemObjectDestructorCallback (self, eq_destructor_notify, SvREFCNT_inc (s_get_cv (notify)));
2194 root 1.77
2195 root 1.14 #BEGIN:mem
2196    
2197     void
2198 root 1.22 type (OpenCL::Memory self)
2199 root 1.79 ALIAS:
2200     type = CL_MEM_TYPE
2201     map_count = CL_MEM_MAP_COUNT
2202     reference_count = CL_MEM_REFERENCE_COUNT
2203 root 1.14 PPCODE:
2204 root 1.79 cl_uint value [1];
2205     NEED_SUCCESS (GetMemObjectInfo, (self, ix, sizeof (value), value, 0));
2206 root 1.14 EXTEND (SP, 1);
2207     const int i = 0;
2208 root 1.61 PUSHs (sv_2mortal (newSVuv (value [i])));
2209 root 1.14
2210     void
2211 root 1.22 flags (OpenCL::Memory self)
2212 root 1.14 PPCODE:
2213 root 1.79 cl_ulong value [1];
2214 root 1.22 NEED_SUCCESS (GetMemObjectInfo, (self, CL_MEM_FLAGS, sizeof (value), value, 0));
2215 root 1.14 EXTEND (SP, 1);
2216     const int i = 0;
2217 root 1.61 PUSHs (sv_2mortal (newSVuv (value [i])));
2218 root 1.14
2219     void
2220 root 1.22 size (OpenCL::Memory self)
2221 root 1.16 ALIAS:
2222     size = CL_MEM_SIZE
2223     offset = CL_MEM_OFFSET
2224 root 1.14 PPCODE:
2225     size_t value [1];
2226 root 1.22 NEED_SUCCESS (GetMemObjectInfo, (self, ix, sizeof (value), value, 0));
2227 root 1.14 EXTEND (SP, 1);
2228     const int i = 0;
2229     PUSHs (sv_2mortal (newSVuv (value [i])));
2230    
2231     void
2232 root 1.22 host_ptr (OpenCL::Memory self)
2233 root 1.14 PPCODE:
2234     void * value [1];
2235 root 1.22 NEED_SUCCESS (GetMemObjectInfo, (self, CL_MEM_HOST_PTR, sizeof (value), value, 0));
2236 root 1.14 EXTEND (SP, 1);
2237     const int i = 0;
2238     PUSHs (sv_2mortal (newSVuv ((IV)(intptr_t)value [i])));
2239    
2240     void
2241 root 1.22 context (OpenCL::Memory self)
2242 root 1.14 PPCODE:
2243     cl_context value [1];
2244 root 1.22 NEED_SUCCESS (GetMemObjectInfo, (self, CL_MEM_CONTEXT, sizeof (value), value, 0));
2245 root 1.14 EXTEND (SP, 1);
2246     const int i = 0;
2247 root 1.79 NEED_SUCCESS (RetainContext, (value [i]));
2248     PUSH_CLOBJ (stash_context, value [i]);
2249 root 1.14
2250     void
2251 root 1.22 associated_memobject (OpenCL::Memory self)
2252 root 1.14 PPCODE:
2253     cl_mem value [1];
2254 root 1.22 NEED_SUCCESS (GetMemObjectInfo, (self, CL_MEM_ASSOCIATED_MEMOBJECT, sizeof (value), value, 0));
2255 root 1.14 EXTEND (SP, 1);
2256     const int i = 0;
2257 root 1.79 NEED_SUCCESS (RetainMemObject, (value [i]));
2258     PUSH_CLOBJ (stash_memory, value [i]);
2259 root 1.14
2260     #END:mem
2261    
2262 root 1.26 #if cl_apple_gl_sharing || cl_khr_gl_sharing
2263    
2264     void
2265     gl_object_info (OpenCL::Memory self)
2266     PPCODE:
2267     cl_gl_object_type type;
2268     cl_GLuint name;
2269 root 1.31 NEED_SUCCESS (GetGLObjectInfo, (self, &type, &name));
2270 root 1.26 EXTEND (SP, 2);
2271     PUSHs (sv_2mortal (newSVuv (type)));
2272     PUSHs (sv_2mortal (newSVuv (name)));
2273    
2274     #endif
2275    
2276 root 1.18 MODULE = OpenCL PACKAGE = OpenCL::BufferObj
2277    
2278     void
2279 root 1.22 sub_buffer_region (OpenCL::BufferObj self, cl_mem_flags flags, size_t origin, size_t size)
2280 root 1.18 PPCODE:
2281     if (flags & (CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR | CL_MEM_ALLOC_HOST_PTR))
2282     croak ("clCreateSubBuffer: cannot use/copy/alloc host ptr, doesn't make sense, check your flags!");
2283    
2284     cl_buffer_region crdata = { origin, size };
2285    
2286 root 1.22 NEED_SUCCESS_ARG (cl_mem mem, CreateSubBuffer, (self, flags, CL_BUFFER_CREATE_TYPE_REGION, &crdata, &res));
2287 root 1.61 XPUSH_CLOBJ (stash_buffer, mem);
2288 root 1.18
2289 root 1.13 MODULE = OpenCL PACKAGE = OpenCL::Image
2290    
2291     void
2292 root 1.22 image_info (OpenCL::Image self, cl_image_info name)
2293 root 1.13 PPCODE:
2294     INFO (Image)
2295    
2296 root 1.49 void
2297     format (OpenCL::Image self)
2298     PPCODE:
2299     cl_image_format format;
2300     NEED_SUCCESS (GetImageInfo, (self, CL_IMAGE_FORMAT, sizeof (format), &format, 0));
2301     EXTEND (SP, 2);
2302     PUSHs (sv_2mortal (newSVuv (format.image_channel_order)));
2303     PUSHs (sv_2mortal (newSVuv (format.image_channel_data_type)));
2304    
2305 root 1.14 #BEGIN:image
2306    
2307     void
2308 root 1.22 element_size (OpenCL::Image self)
2309 root 1.16 ALIAS:
2310     element_size = CL_IMAGE_ELEMENT_SIZE
2311     row_pitch = CL_IMAGE_ROW_PITCH
2312     slice_pitch = CL_IMAGE_SLICE_PITCH
2313     width = CL_IMAGE_WIDTH
2314     height = CL_IMAGE_HEIGHT
2315     depth = CL_IMAGE_DEPTH
2316 root 1.14 PPCODE:
2317     size_t value [1];
2318 root 1.22 NEED_SUCCESS (GetImageInfo, (self, ix, sizeof (value), value, 0));
2319 root 1.14 EXTEND (SP, 1);
2320     const int i = 0;
2321     PUSHs (sv_2mortal (newSVuv (value [i])));
2322    
2323     #END:image
2324    
2325 root 1.26 #if cl_apple_gl_sharing || cl_khr_gl_sharing
2326    
2327     #BEGIN:gl_texture
2328    
2329     void
2330     target (OpenCL::Image self)
2331     PPCODE:
2332     cl_GLenum value [1];
2333 root 1.31 NEED_SUCCESS (GetGLTextureInfo, (self, CL_GL_TEXTURE_TARGET, sizeof (value), value, 0));
2334 root 1.26 EXTEND (SP, 1);
2335     const int i = 0;
2336     PUSHs (sv_2mortal (newSVuv (value [i])));
2337    
2338     void
2339     gl_mipmap_level (OpenCL::Image self)
2340     PPCODE:
2341     cl_GLint value [1];
2342 root 1.31 NEED_SUCCESS (GetGLTextureInfo, (self, CL_GL_MIPMAP_LEVEL, sizeof (value), value, 0));
2343 root 1.26 EXTEND (SP, 1);
2344     const int i = 0;
2345     PUSHs (sv_2mortal (newSViv (value [i])));
2346    
2347     #END:gl_texture
2348    
2349     #endif
2350    
2351 root 1.2 MODULE = OpenCL PACKAGE = OpenCL::Sampler
2352    
2353     void
2354 root 1.22 DESTROY (OpenCL::Sampler self)
2355 root 1.2 CODE:
2356 root 1.22 clReleaseSampler (self);
2357 root 1.2
2358     void
2359 root 1.22 info (OpenCL::Sampler self, cl_sampler_info name)
2360 root 1.2 PPCODE:
2361     INFO (Sampler)
2362    
2363 root 1.14 #BEGIN:sampler
2364    
2365     void
2366 root 1.22 reference_count (OpenCL::Sampler self)
2367 root 1.79 ALIAS:
2368     reference_count = CL_SAMPLER_REFERENCE_COUNT
2369     normalized_coords = CL_SAMPLER_NORMALIZED_COORDS
2370     addressing_mode = CL_SAMPLER_ADDRESSING_MODE
2371 root 1.14 PPCODE:
2372     cl_uint value [1];
2373 root 1.79 NEED_SUCCESS (GetSamplerInfo, (self, ix, sizeof (value), value, 0));
2374 root 1.14 EXTEND (SP, 1);
2375     const int i = 0;
2376     PUSHs (sv_2mortal (newSVuv (value [i])));
2377    
2378     void
2379 root 1.22 context (OpenCL::Sampler self)
2380 root 1.14 PPCODE:
2381     cl_context value [1];
2382 root 1.22 NEED_SUCCESS (GetSamplerInfo, (self, CL_SAMPLER_CONTEXT, sizeof (value), value, 0));
2383 root 1.14 EXTEND (SP, 1);
2384     const int i = 0;
2385 root 1.79 NEED_SUCCESS (RetainContext, (value [i]));
2386     PUSH_CLOBJ (stash_context, value [i]);
2387 root 1.14
2388     void
2389 root 1.22 filter_mode (OpenCL::Sampler self)
2390 root 1.14 PPCODE:
2391 root 1.79 cl_uint value [1];
2392 root 1.22 NEED_SUCCESS (GetSamplerInfo, (self, CL_SAMPLER_FILTER_MODE, sizeof (value), value, 0));
2393 root 1.14 EXTEND (SP, 1);
2394     const int i = 0;
2395     PUSHs (sv_2mortal (value [i] ? &PL_sv_yes : &PL_sv_no));
2396    
2397     #END:sampler
2398    
2399 root 1.2 MODULE = OpenCL PACKAGE = OpenCL::Program
2400    
2401     void
2402 root 1.22 DESTROY (OpenCL::Program self)
2403 root 1.2 CODE:
2404 root 1.22 clReleaseProgram (self);
2405 root 1.2
2406     void
2407 root 1.51 build (OpenCL::Program self, SV *devices = &PL_sv_undef, SV *options = &PL_sv_undef, SV *notify = &PL_sv_undef)
2408     ALIAS:
2409     build_async = 1
2410 root 1.2 CODE:
2411 root 1.69 cl_uint device_count = 0;
2412     cl_device_id *device_list = 0;
2413 root 1.51
2414     if (SvOK (devices))
2415 root 1.69 device_list = object_list (cv, 1, "devices", devices, "OpenCL::Device", &device_count);
2416    
2417     void *user_data;
2418     program_callback pfn_notify = make_program_callback (notify, &user_data);
2419    
2420     if (ix)
2421     build_program_async (self, device_count, device_list, SvPVbyte_nolen (options), user_data);
2422     else
2423     NEED_SUCCESS (BuildProgram, (self, device_count, device_list, SvPVbyte_nolen (options), pfn_notify, user_data));
2424    
2425     #if CL_VERSION_1_2
2426    
2427     void
2428     compile (OpenCL::Program self, SV *devices, SV *options = &PL_sv_undef, SV *headers = &PL_sv_undef, SV *notify = &PL_sv_undef)
2429     CODE:
2430     cl_uint device_count = 0;
2431     cl_device_id *device_list = 0;
2432    
2433     if (SvOK (devices))
2434     device_list = object_list (cv, 1, "devices", devices, "OpenCL::Device", &device_count);
2435    
2436     cl_uint header_count = 0;
2437     cl_program *header_list = 0;
2438     const char **header_name = 0;
2439    
2440     if (SvOK (headers))
2441     {
2442     if (!SvROK (devices) || SvTYPE (SvRV (devices)) != SVt_PVHV)
2443     croak ("clCompileProgram: headers must be undef or a hashref of name => OpenCL::Program pairs");
2444 root 1.51
2445 root 1.69 HV *hv = (HV *)SvRV (devices);
2446 root 1.51
2447 root 1.69 header_count = hv_iterinit (hv);
2448     header_list = tmpbuf (sizeof (*header_list) * header_count);
2449     header_name = tmpbuf (sizeof (*header_name) * header_count);
2450    
2451     HE *he;
2452     int i = 0;
2453     while (he = hv_iternext (hv))
2454 root 1.51 {
2455 root 1.69 header_name [i] = SvPVbyte_nolen (HeSVKEY_force (he));
2456 root 1.71 header_list [i] = SvCLOBJ (cv, "headers", HeVAL (he), "OpenCL::Program");
2457 root 1.69 ++i;
2458 root 1.51 }
2459     }
2460    
2461 root 1.69 void *user_data;
2462     program_callback pfn_notify = make_program_callback (notify, &user_data);
2463    
2464     NEED_SUCCESS (CompileProgram, (self, device_count, device_list, SvPVbyte_nolen (options),
2465     header_count, header_list, header_name, pfn_notify, user_data));
2466 root 1.51
2467 root 1.69 #endif
2468 root 1.2
2469     void
2470 root 1.22 build_info (OpenCL::Program self, OpenCL::Device device, cl_program_build_info name)
2471 root 1.2 PPCODE:
2472 root 1.23 size_t size;
2473     NEED_SUCCESS (GetProgramBuildInfo, (self, device, name, 0, 0, &size));
2474 root 1.10 SV *sv = sv_2mortal (newSV (size));
2475 root 1.1 SvUPGRADE (sv, SVt_PV);
2476     SvPOK_only (sv);
2477     SvCUR_set (sv, size);
2478 root 1.23 NEED_SUCCESS (GetProgramBuildInfo, (self, device, name, size, SvPVX (sv), 0));
2479 root 1.1 XPUSHs (sv);
2480    
2481 root 1.14 #BEGIN:program_build
2482    
2483     void
2484 root 1.22 build_status (OpenCL::Program self, OpenCL::Device device)
2485 root 1.14 PPCODE:
2486 root 1.79 cl_int value [1];
2487 root 1.22 NEED_SUCCESS (GetProgramBuildInfo, (self, device, CL_PROGRAM_BUILD_STATUS, sizeof (value), value, 0));
2488 root 1.14 EXTEND (SP, 1);
2489     const int i = 0;
2490     PUSHs (sv_2mortal (newSViv (value [i])));
2491    
2492     void
2493 root 1.22 build_options (OpenCL::Program self, OpenCL::Device device)
2494 root 1.16 ALIAS:
2495     build_options = CL_PROGRAM_BUILD_OPTIONS
2496     build_log = CL_PROGRAM_BUILD_LOG
2497 root 1.14 PPCODE:
2498     size_t size;
2499 root 1.22 NEED_SUCCESS (GetProgramBuildInfo, (self, device, ix, 0, 0, &size));
2500 root 1.14 char *value = tmpbuf (size);
2501 root 1.22 NEED_SUCCESS (GetProgramBuildInfo, (self, device, ix, size, value, 0));
2502 root 1.16 EXTEND (SP, 1);
2503     const int i = 0;
2504 root 1.14 PUSHs (sv_2mortal (newSVpv (value, 0)));
2505    
2506 root 1.73 void
2507     binary_type (OpenCL::Program self, OpenCL::Device device)
2508     PPCODE:
2509 root 1.79 cl_uint value [1];
2510 root 1.73 NEED_SUCCESS (GetProgramBuildInfo, (self, device, CL_PROGRAM_BINARY_TYPE, sizeof (value), value, 0));
2511     EXTEND (SP, 1);
2512     const int i = 0;
2513 root 1.74 PUSHs (sv_2mortal (newSVuv ((UV)value [i])));
2514 root 1.73
2515 root 1.14 #END:program_build
2516    
2517 root 1.2 void
2518     kernel (OpenCL::Program program, SV *function)
2519     PPCODE:
2520 root 1.23 NEED_SUCCESS_ARG (cl_kernel kernel, CreateKernel, (program, SvPVbyte_nolen (function), &res));
2521 root 1.61 XPUSH_CLOBJ (stash_kernel, kernel);
2522 root 1.2
2523 root 1.14 void
2524 root 1.47 kernels_in_program (OpenCL::Program program)
2525     PPCODE:
2526     cl_uint num_kernels;
2527     NEED_SUCCESS (CreateKernelsInProgram, (program, 0, 0, &num_kernels));
2528     cl_kernel *kernels = tmpbuf (sizeof (cl_kernel) * num_kernels);
2529     NEED_SUCCESS (CreateKernelsInProgram, (program, num_kernels, kernels, 0));
2530    
2531     int i;
2532     EXTEND (SP, num_kernels);
2533     for (i = 0; i < num_kernels; ++i)
2534 root 1.61 PUSH_CLOBJ (stash_kernel, kernels [i]);
2535 root 1.47
2536     void
2537 root 1.22 info (OpenCL::Program self, cl_program_info name)
2538 root 1.14 PPCODE:
2539     INFO (Program)
2540    
2541 root 1.15 void
2542 root 1.22 binaries (OpenCL::Program self)
2543 root 1.15 PPCODE:
2544     cl_uint n, i;
2545     size_t size;
2546    
2547 root 1.22 NEED_SUCCESS (GetProgramInfo, (self, CL_PROGRAM_NUM_DEVICES , sizeof (n) , &n , 0));
2548 root 1.15 if (!n) XSRETURN_EMPTY;
2549    
2550     size_t *sizes = tmpbuf (sizeof (*sizes) * n);
2551 root 1.22 NEED_SUCCESS (GetProgramInfo, (self, CL_PROGRAM_BINARY_SIZES, sizeof (*sizes) * n, sizes, &size));
2552 root 1.15 if (size != sizeof (*sizes) * n) XSRETURN_EMPTY;
2553     unsigned char **ptrs = tmpbuf (sizeof (*ptrs) * n);
2554    
2555     EXTEND (SP, n);
2556     for (i = 0; i < n; ++i)
2557     {
2558     SV *sv = sv_2mortal (newSV (sizes [i]));
2559     SvUPGRADE (sv, SVt_PV);
2560     SvPOK_only (sv);
2561     SvCUR_set (sv, sizes [i]);
2562 root 1.37 ptrs [i] = (void *)SvPVX (sv);
2563 root 1.15 PUSHs (sv);
2564     }
2565    
2566 root 1.22 NEED_SUCCESS (GetProgramInfo, (self, CL_PROGRAM_BINARIES , sizeof (*ptrs ) * n, ptrs , &size));
2567 root 1.15 if (size != sizeof (*ptrs) * n) XSRETURN_EMPTY;
2568    
2569 root 1.14 #BEGIN:program
2570    
2571     void
2572 root 1.22 reference_count (OpenCL::Program self)
2573 root 1.16 ALIAS:
2574     reference_count = CL_PROGRAM_REFERENCE_COUNT
2575     num_devices = CL_PROGRAM_NUM_DEVICES
2576 root 1.14 PPCODE:
2577     cl_uint value [1];
2578 root 1.22 NEED_SUCCESS (GetProgramInfo, (self, ix, sizeof (value), value, 0));
2579 root 1.14 EXTEND (SP, 1);
2580     const int i = 0;
2581     PUSHs (sv_2mortal (newSVuv (value [i])));
2582    
2583     void
2584 root 1.22 context (OpenCL::Program self)
2585 root 1.14 PPCODE:
2586     cl_context value [1];
2587 root 1.22 NEED_SUCCESS (GetProgramInfo, (self, CL_PROGRAM_CONTEXT, sizeof (value), value, 0));
2588 root 1.14 EXTEND (SP, 1);
2589     const int i = 0;
2590 root 1.79 NEED_SUCCESS (RetainContext, (value [i]));
2591     PUSH_CLOBJ (stash_context, value [i]);
2592 root 1.14
2593     void
2594 root 1.22 devices (OpenCL::Program self)
2595 root 1.14 PPCODE:
2596     size_t size;
2597 root 1.22 NEED_SUCCESS (GetProgramInfo, (self, CL_PROGRAM_DEVICES, 0, 0, &size));
2598 root 1.14 cl_device_id *value = tmpbuf (size);
2599 root 1.22 NEED_SUCCESS (GetProgramInfo, (self, CL_PROGRAM_DEVICES, size, value, 0));
2600 root 1.15 int i, n = size / sizeof (*value);
2601 root 1.14 EXTEND (SP, n);
2602     for (i = 0; i < n; ++i)
2603 root 1.79 PUSH_CLOBJ (stash_device, value [i]);
2604 root 1.14
2605     void
2606 root 1.22 source (OpenCL::Program self)
2607 root 1.14 PPCODE:
2608     size_t size;
2609 root 1.22 NEED_SUCCESS (GetProgramInfo, (self, CL_PROGRAM_SOURCE, 0, 0, &size));
2610 root 1.14 char *value = tmpbuf (size);
2611 root 1.22 NEED_SUCCESS (GetProgramInfo, (self, CL_PROGRAM_SOURCE, size, value, 0));
2612 root 1.16 EXTEND (SP, 1);
2613     const int i = 0;
2614 root 1.14 PUSHs (sv_2mortal (newSVpv (value, 0)));
2615    
2616     void
2617 root 1.22 binary_sizes (OpenCL::Program self)
2618 root 1.14 PPCODE:
2619     size_t size;
2620 root 1.22 NEED_SUCCESS (GetProgramInfo, (self, CL_PROGRAM_BINARY_SIZES, 0, 0, &size));
2621 root 1.14 size_t *value = tmpbuf (size);
2622 root 1.22 NEED_SUCCESS (GetProgramInfo, (self, CL_PROGRAM_BINARY_SIZES, size, value, 0));
2623 root 1.15 int i, n = size / sizeof (*value);
2624 root 1.14 EXTEND (SP, n);
2625     for (i = 0; i < n; ++i)
2626     PUSHs (sv_2mortal (newSVuv (value [i])));
2627    
2628     #END:program
2629    
2630 root 1.2 MODULE = OpenCL PACKAGE = OpenCL::Kernel
2631    
2632     void
2633 root 1.22 DESTROY (OpenCL::Kernel self)
2634 root 1.2 CODE:
2635 root 1.22 clReleaseKernel (self);
2636 root 1.2
2637     void
2638 root 1.56 setf (OpenCL::Kernel self, const char *format, ...)
2639     CODE:
2640     int i;
2641     for (i = 2; ; ++i)
2642     {
2643     while (*format == ' ')
2644     ++format;
2645    
2646     char type = *format++;
2647    
2648     if (!type)
2649     break;
2650    
2651     if (i >= items)
2652     croak ("OpenCL::Kernel::setf format string too long (not enough arguments)");
2653    
2654     SV *sv = ST (i);
2655    
2656     union
2657     {
2658     cl_char cc; cl_uchar cC; cl_short cs; cl_ushort cS;
2659     cl_int ci; cl_uint cI; cl_long cl; cl_ulong cL;
2660     cl_half ch; cl_float cf; cl_double cd;
2661     cl_mem cm;
2662     cl_sampler ca;
2663     size_t cz;
2664     cl_event ce;
2665     } arg;
2666     size_t size;
2667 root 1.59 int nullarg = 0;
2668 root 1.56
2669     switch (type)
2670     {
2671     case 'c': arg.cc = SvIV (sv); size = sizeof (arg.cc); break;
2672     case 'C': arg.cC = SvUV (sv); size = sizeof (arg.cC); break;
2673     case 's': arg.cs = SvIV (sv); size = sizeof (arg.cs); break;
2674     case 'S': arg.cS = SvUV (sv); size = sizeof (arg.cS); break;
2675     case 'i': arg.ci = SvIV (sv); size = sizeof (arg.ci); break;
2676     case 'I': arg.cI = SvUV (sv); size = sizeof (arg.cI); break;
2677     case 'l': arg.cl = SvIV (sv); size = sizeof (arg.cl); break;
2678     case 'L': arg.cL = SvUV (sv); size = sizeof (arg.cL); break;
2679    
2680     case 'h': arg.ch = SvUV (sv); size = sizeof (arg.ch); break;
2681     case 'f': arg.cf = SvNV (sv); size = sizeof (arg.cf); break;
2682     case 'd': arg.cd = SvNV (sv); size = sizeof (arg.cd); break;
2683    
2684 root 1.59 case 'z': nullarg = 1; size = SvIV (sv); break;
2685    
2686 root 1.71 case 'm': nullarg = !SvOK (sv); arg.cm = SvCLOBJ (cv, "m", sv, "OpenCL::Memory" ); size = sizeof (arg.cm); break;
2687     case 'a': nullarg = !SvOK (sv); arg.ca = SvCLOBJ (cv, "a", sv, "OpenCL::Sampler"); size = sizeof (arg.ca); break;
2688     case 'e': nullarg = !SvOK (sv); arg.ca = SvCLOBJ (cv, "e", sv, "OpenCL::Event" ); size = sizeof (arg.ce); break;
2689 root 1.56
2690     default:
2691     croak ("OpenCL::Kernel::setf format character '%c' not supported", type);
2692     }
2693    
2694 root 1.59 res = clSetKernelArg (self, i - 2, size, nullarg ? 0 : &arg);
2695     if (res)
2696     croak ("OpenCL::Kernel::setf kernel parameter '%c' (#%d): %s", type, i - 2, err2str (res));
2697 root 1.56 }
2698    
2699     if (i != items)
2700     croak ("OpenCL::Kernel::setf format string too short (too many arguments)");
2701    
2702     void
2703 root 1.22 set_char (OpenCL::Kernel self, cl_uint idx, cl_char value)
2704 root 1.3 CODE:
2705 root 1.22 clSetKernelArg (self, idx, sizeof (value), &value);
2706 root 1.3
2707     void
2708 root 1.22 set_uchar (OpenCL::Kernel self, cl_uint idx, cl_uchar value)
2709 root 1.3 CODE:
2710 root 1.22 clSetKernelArg (self, idx, sizeof (value), &value);
2711 root 1.3
2712     void
2713 root 1.22 set_short (OpenCL::Kernel self, cl_uint idx, cl_short value)
2714 root 1.3 CODE:
2715 root 1.22 clSetKernelArg (self, idx, sizeof (value), &value);
2716 root 1.3
2717     void
2718 root 1.22 set_ushort (OpenCL::Kernel self, cl_uint idx, cl_ushort value)
2719 root 1.3 CODE:
2720 root 1.22 clSetKernelArg (self, idx, sizeof (value), &value);
2721 root 1.3
2722     void
2723 root 1.22 set_int (OpenCL::Kernel self, cl_uint idx, cl_int value)
2724 root 1.3 CODE:
2725 root 1.22 clSetKernelArg (self, idx, sizeof (value), &value);
2726 root 1.3
2727     void
2728 root 1.22 set_uint (OpenCL::Kernel self, cl_uint idx, cl_uint value)
2729 root 1.3 CODE:
2730 root 1.22 clSetKernelArg (self, idx, sizeof (value), &value);
2731 root 1.3
2732     void
2733 root 1.22 set_long (OpenCL::Kernel self, cl_uint idx, cl_long value)
2734 root 1.3 CODE:
2735 root 1.22 clSetKernelArg (self, idx, sizeof (value), &value);
2736 root 1.3
2737     void
2738 root 1.22 set_ulong (OpenCL::Kernel self, cl_uint idx, cl_ulong value)
2739 root 1.3 CODE:
2740 root 1.22 clSetKernelArg (self, idx, sizeof (value), &value);
2741 root 1.3
2742     void
2743 root 1.22 set_half (OpenCL::Kernel self, cl_uint idx, cl_half value)
2744 root 1.3 CODE:
2745 root 1.22 clSetKernelArg (self, idx, sizeof (value), &value);
2746 root 1.3
2747     void
2748 root 1.22 set_float (OpenCL::Kernel self, cl_uint idx, cl_float value)
2749 root 1.3 CODE:
2750 root 1.22 clSetKernelArg (self, idx, sizeof (value), &value);
2751 root 1.3
2752     void
2753 root 1.22 set_double (OpenCL::Kernel self, cl_uint idx, cl_double value)
2754 root 1.5 CODE:
2755 root 1.22 clSetKernelArg (self, idx, sizeof (value), &value);
2756 root 1.5
2757     void
2758 root 1.22 set_memory (OpenCL::Kernel self, cl_uint idx, OpenCL::Memory_ornull value)
2759 root 1.3 CODE:
2760 root 1.59 clSetKernelArg (self, idx, sizeof (value), value ? &value : 0);
2761 root 1.3
2762     void
2763 root 1.22 set_buffer (OpenCL::Kernel self, cl_uint idx, OpenCL::Buffer_ornull value)
2764 root 1.3 CODE:
2765 root 1.59 clSetKernelArg (self, idx, sizeof (value), value ? &value : 0);
2766 root 1.3
2767     void
2768 root 1.54 set_image (OpenCL::Kernel self, cl_uint idx, OpenCL::Image_ornull value)
2769 root 1.3 CODE:
2770 root 1.59 clSetKernelArg (self, idx, sizeof (value), value ? &value : 0);
2771 root 1.3
2772     void
2773 root 1.22 set_sampler (OpenCL::Kernel self, cl_uint idx, OpenCL::Sampler value)
2774 root 1.3 CODE:
2775 root 1.22 clSetKernelArg (self, idx, sizeof (value), &value);
2776 root 1.3
2777     void
2778 root 1.33 set_local (OpenCL::Kernel self, cl_uint idx, size_t size)
2779     CODE:
2780     clSetKernelArg (self, idx, size, 0);
2781    
2782     void
2783 root 1.22 set_event (OpenCL::Kernel self, cl_uint idx, OpenCL::Event value)
2784 root 1.2 CODE:
2785 root 1.22 clSetKernelArg (self, idx, sizeof (value), &value);
2786 root 1.2
2787 root 1.14 void
2788 root 1.22 info (OpenCL::Kernel self, cl_kernel_info name)
2789 root 1.14 PPCODE:
2790     INFO (Kernel)
2791    
2792     #BEGIN:kernel
2793    
2794     void
2795 root 1.22 function_name (OpenCL::Kernel self)
2796 root 1.14 PPCODE:
2797     size_t size;
2798 root 1.22 NEED_SUCCESS (GetKernelInfo, (self, CL_KERNEL_FUNCTION_NAME, 0, 0, &size));
2799 root 1.14 char *value = tmpbuf (size);
2800 root 1.22 NEED_SUCCESS (GetKernelInfo, (self, CL_KERNEL_FUNCTION_NAME, size, value, 0));
2801 root 1.16 EXTEND (SP, 1);
2802     const int i = 0;
2803 root 1.14 PUSHs (sv_2mortal (newSVpv (value, 0)));
2804    
2805     void
2806 root 1.22 num_args (OpenCL::Kernel self)
2807 root 1.16 ALIAS:
2808     num_args = CL_KERNEL_NUM_ARGS
2809     reference_count = CL_KERNEL_REFERENCE_COUNT
2810 root 1.14 PPCODE:
2811     cl_uint value [1];
2812 root 1.22 NEED_SUCCESS (GetKernelInfo, (self, ix, sizeof (value), value, 0));
2813 root 1.14 EXTEND (SP, 1);
2814     const int i = 0;
2815     PUSHs (sv_2mortal (newSVuv (value [i])));
2816    
2817     void
2818 root 1.22 context (OpenCL::Kernel self)
2819 root 1.14 PPCODE:
2820     cl_context value [1];
2821 root 1.22 NEED_SUCCESS (GetKernelInfo, (self, CL_KERNEL_CONTEXT, sizeof (value), value, 0));
2822 root 1.14 EXTEND (SP, 1);
2823     const int i = 0;
2824 root 1.79 NEED_SUCCESS (RetainContext, (value [i]));
2825     PUSH_CLOBJ (stash_context, value [i]);
2826 root 1.14
2827     void
2828 root 1.22 program (OpenCL::Kernel self)
2829 root 1.14 PPCODE:
2830     cl_program value [1];
2831 root 1.22 NEED_SUCCESS (GetKernelInfo, (self, CL_KERNEL_PROGRAM, sizeof (value), value, 0));
2832 root 1.14 EXTEND (SP, 1);
2833     const int i = 0;
2834 root 1.79 NEED_SUCCESS (RetainProgram, (value [i]));
2835     PUSH_CLOBJ (stash_program, value [i]);
2836 root 1.14
2837     #END:kernel
2838    
2839     void
2840 root 1.22 work_group_info (OpenCL::Kernel self, OpenCL::Device device, cl_kernel_work_group_info name)
2841 root 1.14 PPCODE:
2842 root 1.22 size_t size;
2843     NEED_SUCCESS (GetKernelWorkGroupInfo, (self, device, name, 0, 0, &size));
2844 root 1.14 SV *sv = sv_2mortal (newSV (size));
2845     SvUPGRADE (sv, SVt_PV);
2846     SvPOK_only (sv);
2847     SvCUR_set (sv, size);
2848 root 1.22 NEED_SUCCESS (GetKernelWorkGroupInfo, (self, device, name, size, SvPVX (sv), 0));
2849 root 1.14 XPUSHs (sv);
2850    
2851     #BEGIN:kernel_work_group
2852    
2853     void
2854 root 1.22 work_group_size (OpenCL::Kernel self, OpenCL::Device device)
2855 root 1.16 ALIAS:
2856     work_group_size = CL_KERNEL_WORK_GROUP_SIZE
2857     preferred_work_group_size_multiple = CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE
2858 root 1.14 PPCODE:
2859     size_t value [1];
2860 root 1.22 NEED_SUCCESS (GetKernelWorkGroupInfo, (self, device, ix, sizeof (value), value, 0));
2861 root 1.14 EXTEND (SP, 1);
2862     const int i = 0;
2863     PUSHs (sv_2mortal (newSVuv (value [i])));
2864    
2865     void
2866 root 1.22 compile_work_group_size (OpenCL::Kernel self, OpenCL::Device device)
2867 root 1.14 PPCODE:
2868     size_t size;
2869 root 1.22 NEED_SUCCESS (GetKernelWorkGroupInfo, (self, device, CL_KERNEL_COMPILE_WORK_GROUP_SIZE, 0, 0, &size));
2870 root 1.14 size_t *value = tmpbuf (size);
2871 root 1.22 NEED_SUCCESS (GetKernelWorkGroupInfo, (self, device, CL_KERNEL_COMPILE_WORK_GROUP_SIZE, size, value, 0));
2872 root 1.15 int i, n = size / sizeof (*value);
2873 root 1.14 EXTEND (SP, n);
2874     for (i = 0; i < n; ++i)
2875     PUSHs (sv_2mortal (newSVuv (value [i])));
2876    
2877     void
2878 root 1.22 local_mem_size (OpenCL::Kernel self, OpenCL::Device device)
2879 root 1.16 ALIAS:
2880     local_mem_size = CL_KERNEL_LOCAL_MEM_SIZE
2881     private_mem_size = CL_KERNEL_PRIVATE_MEM_SIZE
2882 root 1.14 PPCODE:
2883     cl_ulong value [1];
2884 root 1.22 NEED_SUCCESS (GetKernelWorkGroupInfo, (self, device, ix, sizeof (value), value, 0));
2885 root 1.14 EXTEND (SP, 1);
2886     const int i = 0;
2887     PUSHs (sv_2mortal (newSVuv (value [i])));
2888    
2889     #END:kernel_work_group
2890    
2891 root 1.66 #if CL_VERSION_1_2
2892    
2893     void
2894     arg_info (OpenCL::Kernel self, cl_uint idx, cl_kernel_arg_info name)
2895     PPCODE:
2896     size_t size;
2897 root 1.67 NEED_SUCCESS (GetKernelArgInfo, (self, idx, name, 0, 0, &size));
2898 root 1.66 SV *sv = sv_2mortal (newSV (size));
2899     SvUPGRADE (sv, SVt_PV);
2900     SvPOK_only (sv);
2901     SvCUR_set (sv, size);
2902 root 1.67 NEED_SUCCESS (GetKernelArgInfo, (self, idx, name, size, SvPVX (sv), 0));
2903 root 1.66 XPUSHs (sv);
2904    
2905     #BEGIN:kernel_arg
2906    
2907 root 1.68 void
2908     arg_address_qualifier (OpenCL::Kernel self, cl_uint idx)
2909 root 1.79 ALIAS:
2910     arg_address_qualifier = CL_KERNEL_ARG_ADDRESS_QUALIFIER
2911     arg_access_qualifier = CL_KERNEL_ARG_ACCESS_QUALIFIER
2912 root 1.68 PPCODE:
2913 root 1.79 cl_uint value [1];
2914     NEED_SUCCESS (GetKernelArgInfo, (self, idx, ix, sizeof (value), value, 0));
2915 root 1.68 EXTEND (SP, 1);
2916     const int i = 0;
2917     PUSHs (sv_2mortal (newSVuv (value [i])));
2918    
2919     void
2920     arg_type_name (OpenCL::Kernel self, cl_uint idx)
2921     ALIAS:
2922     arg_type_name = CL_KERNEL_ARG_TYPE_NAME
2923     arg_name = CL_KERNEL_ARG_NAME
2924     PPCODE:
2925     size_t size;
2926     NEED_SUCCESS (GetKernelArgInfo, (self, idx, ix, 0, 0, &size));
2927     char *value = tmpbuf (size);
2928     NEED_SUCCESS (GetKernelArgInfo, (self, idx, ix, size, value, 0));
2929     EXTEND (SP, 1);
2930     const int i = 0;
2931     PUSHs (sv_2mortal (newSVpv (value, 0)));
2932    
2933     void
2934     arg_type_qualifier (OpenCL::Kernel self, cl_uint idx)
2935     PPCODE:
2936 root 1.79 cl_ulong value [1];
2937 root 1.68 NEED_SUCCESS (GetKernelArgInfo, (self, idx, CL_KERNEL_ARG_TYPE_QUALIFIER, sizeof (value), value, 0));
2938     EXTEND (SP, 1);
2939     const int i = 0;
2940     PUSHs (sv_2mortal (newSVuv (value [i])));
2941    
2942 root 1.66 #END:kernel_arg
2943    
2944     #endif
2945    
2946 root 1.2 MODULE = OpenCL PACKAGE = OpenCL::Event
2947    
2948     void
2949 root 1.22 DESTROY (OpenCL::Event self)
2950 root 1.2 CODE:
2951 root 1.22 clReleaseEvent (self);
2952 root 1.2
2953     void
2954 root 1.22 wait (OpenCL::Event self)
2955 root 1.14 CODE:
2956 root 1.22 clWaitForEvents (1, &self);
2957 root 1.14
2958     void
2959 root 1.51 cb (OpenCL::Event self, cl_int command_exec_callback_type, SV *cb)
2960     CODE:
2961     clSetEventCallback (self, command_exec_callback_type, eq_event_notify, SvREFCNT_inc (s_get_cv (cb)));
2962    
2963     void
2964 root 1.22 info (OpenCL::Event self, cl_event_info name)
2965 root 1.2 PPCODE:
2966     INFO (Event)
2967    
2968 root 1.14 #BEGIN:event
2969    
2970     void
2971 root 1.22 command_queue (OpenCL::Event self)
2972 root 1.14 PPCODE:
2973     cl_command_queue value [1];
2974 root 1.22 NEED_SUCCESS (GetEventInfo, (self, CL_EVENT_COMMAND_QUEUE, sizeof (value), value, 0));
2975 root 1.14 EXTEND (SP, 1);
2976     const int i = 0;
2977 root 1.79 NEED_SUCCESS (RetainCommandQueue, (value [i]));
2978     PUSH_CLOBJ (stash_queue, value [i]);
2979 root 1.14
2980     void
2981 root 1.22 command_type (OpenCL::Event self)
2982 root 1.16 ALIAS:
2983 root 1.79 command_type = CL_EVENT_COMMAND_TYPE
2984 root 1.16 reference_count = CL_EVENT_REFERENCE_COUNT
2985     command_execution_status = CL_EVENT_COMMAND_EXECUTION_STATUS
2986 root 1.14 PPCODE:
2987     cl_uint value [1];
2988 root 1.22 NEED_SUCCESS (GetEventInfo, (self, ix, sizeof (value), value, 0));
2989 root 1.14 EXTEND (SP, 1);
2990     const int i = 0;
2991     PUSHs (sv_2mortal (newSVuv (value [i])));
2992    
2993     void
2994 root 1.22 context (OpenCL::Event self)
2995 root 1.14 PPCODE:
2996     cl_context value [1];
2997 root 1.22 NEED_SUCCESS (GetEventInfo, (self, CL_EVENT_CONTEXT, sizeof (value), value, 0));
2998 root 1.14 EXTEND (SP, 1);
2999     const int i = 0;
3000 root 1.79 NEED_SUCCESS (RetainContext, (value [i]));
3001     PUSH_CLOBJ (stash_context, value [i]);
3002 root 1.14
3003     #END:event
3004    
3005 root 1.2 void
3006 root 1.22 profiling_info (OpenCL::Event self, cl_profiling_info name)
3007 root 1.13 PPCODE:
3008     INFO (EventProfiling)
3009    
3010 root 1.14 #BEGIN:profiling
3011    
3012 root 1.13 void
3013 root 1.22 profiling_command_queued (OpenCL::Event self)
3014 root 1.16 ALIAS:
3015     profiling_command_queued = CL_PROFILING_COMMAND_QUEUED
3016     profiling_command_submit = CL_PROFILING_COMMAND_SUBMIT
3017     profiling_command_start = CL_PROFILING_COMMAND_START
3018     profiling_command_end = CL_PROFILING_COMMAND_END
3019 root 1.14 PPCODE:
3020     cl_ulong value [1];
3021 root 1.22 NEED_SUCCESS (GetEventProfilingInfo, (self, ix, sizeof (value), value, 0));
3022 root 1.14 EXTEND (SP, 1);
3023     const int i = 0;
3024     PUSHs (sv_2mortal (newSVuv (value [i])));
3025    
3026     #END:profiling
3027 root 1.2
3028 root 1.5 MODULE = OpenCL PACKAGE = OpenCL::UserEvent
3029    
3030     void
3031 root 1.22 set_status (OpenCL::UserEvent self, cl_int execution_status)
3032 root 1.5 CODE:
3033 root 1.22 clSetUserEventStatus (self, execution_status);
3034 root 1.5
3035 root 1.61 MODULE = OpenCL PACKAGE = OpenCL::Mapped
3036    
3037     void
3038     DESTROY (SV *self)
3039     CODE:
3040     OpenCL__Mapped mapped = SvMAPPED (self);
3041    
3042     clEnqueueUnmapMemObject (mapped->queue, mapped->memobj, mapped->ptr, 1, &mapped->event, 0);
3043     mapped_detach (self, mapped);
3044    
3045     clReleaseCommandQueue (mapped->queue);
3046 root 1.62 clReleaseEvent (mapped->event);
3047 root 1.61 Safefree (mapped);
3048    
3049 root 1.62 void
3050     unmap (OpenCL::Mapped self, ...)
3051     CODE:
3052 root 1.71 mapped_unmap (cv, ST (0), self, self->queue, &ST (1), items - 1);
3053 root 1.62
3054 root 1.61 bool
3055     mapped (OpenCL::Mapped self)
3056     CODE:
3057     RETVAL = !!self->ptr;
3058     OUTPUT:
3059     RETVAL
3060    
3061     void
3062     wait (OpenCL::Mapped self)
3063     PPCODE:
3064     if (self->event)
3065     NEED_SUCCESS (WaitForEvents, (1, &self->event));
3066    
3067     void
3068     event (OpenCL::Mapped self)
3069     PPCODE:
3070     if (!self->event)
3071     XSRETURN_UNDEF;
3072    
3073     clRetainEvent (self->event);
3074     XPUSH_CLOBJ (stash_event, self->event);
3075    
3076 root 1.80 #define MAPPED_OFFSET_CB offsetof (struct mapped, cb)
3077     #define MAPPED_OFFSET_ROW_PITCH offsetof (struct mapped, row_pitch)
3078     #define MAPPED_OFFSET_SLICE_PITCH offsetof (struct mapped, slice_pitch)
3079     #define MAPPED_OFFSET_WIDTH offsetof (struct mapped, width)
3080     #define MAPPED_OFFSET_HEIGHT offsetof (struct mapped, height)
3081     #define MAPPED_OFFSET_DEPTH offsetof (struct mapped, depth)
3082    
3083     IV
3084 root 1.61 size (OpenCL::Mapped self)
3085 root 1.80 ALIAS:
3086     size = MAPPED_OFFSET_CB
3087     row_pitch = MAPPED_OFFSET_ROW_PITCH
3088     slice_pitch = MAPPED_OFFSET_SLICE_PITCH
3089     width = MAPPED_OFFSET_WIDTH
3090     height = MAPPED_OFFSET_HEIGHT
3091     depth = MAPPED_OFFSET_DEPTH
3092 root 1.61 CODE:
3093 root 1.80 RETVAL = *(size_t *)((char *)self + ix);
3094 root 1.61 OUTPUT:
3095     RETVAL
3096    
3097     IV
3098     ptr (OpenCL::Mapped self)
3099     CODE:
3100     RETVAL = PTR2IV (self->ptr);
3101     OUTPUT:
3102     RETVAL
3103    
3104 root 1.63 void
3105     set (OpenCL::Mapped self, size_t offset, SV *data)
3106     CODE:
3107     STRLEN len;
3108     const char *ptr = SvPVbyte (data, len);
3109    
3110 root 1.64 if (offset + len > self->cb)
3111 root 1.63 croak ("OpenCL::Mapped::set out of bound condition detected");
3112    
3113     memcpy (offset + (char *)self->ptr, ptr, len);
3114    
3115 root 1.80 void
3116     get_row (OpenCL::Mapped self, size_t count, size_t x = 0, size_t y = 0, size_t z = 0)
3117     PPCODE:
3118     if (!SvOK (ST (1)))
3119     count = self->width - x;
3120    
3121     if (x + count > self->width)
3122     croak ("OpenCL::Mapped::get: x + count crosses a row boundary");
3123    
3124     if (y >= self->height)
3125     croak ("OpenCL::Mapped::get: y coordinate out of bounds");
3126    
3127     if (z >= self->depth)
3128     croak ("OpenCL::Mapped::get: z coordinate out of bounds");
3129    
3130     size_t element = mapped_element_size (self);
3131    
3132     count *= element;
3133     x *= element;
3134    
3135     char *ptr = (char *)self->ptr + x + y * self->row_pitch + z * self->slice_pitch;
3136     XPUSHs (sv_2mortal (newSVpvn (ptr, count)));
3137    
3138     void
3139     set_row (OpenCL::Mapped self, SV *data, size_t x = 0, size_t y = 0, size_t z = 0)
3140     PPCODE:
3141     STRLEN count;
3142     char *dataptr = SvPVbyte (data, count);
3143     size_t element = mapped_element_size (self);
3144    
3145     x *= element;
3146    
3147     if (x + count > self->width * element)
3148     croak ("OpenCL::Mapped::set: x + data size crosses a row boundary");
3149    
3150     if (y >= self->height)
3151     croak ("OpenCL::Mapped::set: y coordinate out of bounds");
3152    
3153     if (z >= self->depth)
3154     croak ("OpenCL::Mapped::set: z coordinate out of bounds");
3155    
3156     char *ptr = (char *)self->ptr + x + y * self->row_pitch + z * self->slice_pitch;
3157     memcpy (ptr, dataptr, count);
3158    
3159 root 1.61 MODULE = OpenCL PACKAGE = OpenCL::MappedBuffer
3160    
3161     MODULE = OpenCL PACKAGE = OpenCL::MappedImage
3162    
3163     IV
3164 root 1.80 element_size (OpenCL::Mapped self)
3165 root 1.61 CODE:
3166 root 1.80 RETVAL = mapped_element_size (self);
3167 root 1.61 OUTPUT:
3168     RETVAL
3169