--- OpenCL/OpenCL.xs 2012/04/16 09:42:33 1.22 +++ OpenCL/OpenCL.xs 2012/04/19 14:36:46 1.31 @@ -2,6 +2,10 @@ #include "perl.h" #include "XSUB.h" +#ifdef I_DLFCN + #include +#endif + #ifdef __APPLE__ #include #else @@ -33,15 +37,32 @@ /*****************************************************************************/ +// name must include a leading underscore +static void * +getsym (const char *name) +{ + #if defined I_DLFCN && defined RTLD_DEFAULT + #if !DLSYM_NEEDS_UNDERSCORE + ++name; // skip _ + #endif + return dlsym (RTLD_DEFAULT, name); + #else + return 0; + #endif +} + +/*****************************************************************************/ + /* up to two temporary buffers */ static void * tmpbuf (size_t size) { + enum { buffers = 3 }; static int idx; - static void *buf [2]; - static size_t len [2]; + static void *buf [buffers]; + static size_t len [buffers]; - idx ^= 1; + idx = ++idx % buffers; if (len [idx] < size) { @@ -133,6 +154,56 @@ /*****************************************************************************/ +static cl_context_properties * +SvCONTEXTPROPERTIES (const char *func, const char *svname, SV *sv, cl_context_properties *extra, int extracount) +{ + if (!sv || !SvOK (sv)) + if (extra) + sv = sv_2mortal (newRV_noinc ((SV *)newAV ())); // slow, but rarely used hopefully + else + return 0; + + if (SvROK (sv) && SvTYPE (SvRV (sv)) == SVt_PVAV) + { + AV *av = (AV *)SvRV (sv); + int i, len = av_len (av) + 1; + cl_context_properties *p = tmpbuf (sizeof (cl_context_properties) * (len + extracount + 1)); + cl_context_properties *l = p; + + if (len & 1) + croak ("%s: %s is not a property list (must be even number of elements)", func, svname); + + while (extracount--) + *l++ = *extra++; + + for (i = 0; i < len; i += 2) + { + cl_context_properties t = SvIV (*av_fetch (av, i , 0)); + SV *p_sv = *av_fetch (av, i + 1, 0); + cl_context_properties v; + + switch (t) + { + default: + /* unknown property, treat as int */ + v = SvIV (p_sv); + break; + } + + *l++ = t; + *l++ = v; + } + + *l = 0; + + return p; + } + + croak ("%s: %s is not a property list (either undef or [type => value, ...])", func, svname); +} + +/*****************************************************************************/ + static size_t img_row_pitch (cl_mem img) { @@ -161,13 +232,13 @@ #define INFO(class) \ { \ - size_t size; \ - NEED_SUCCESS (Get ## class ## Info, (self, name, 0, 0, &size)); \ + size_t size; \ + NEED_SUCCESS (Get ## class ## Info, (self, name, 0, 0, &size)); \ SV *sv = sv_2mortal (newSV (size)); \ SvUPGRADE (sv, SVt_PV); \ SvPOK_only (sv); \ SvCUR_set (sv, size); \ - NEED_SUCCESS (Get ## class ## Info, (self, name, size, SvPVX (sv), 0)); \ + NEED_SUCCESS (Get ## class ## Info, (self, name, size, SvPVX (sv), 0)); \ XPUSHs (sv); \ } @@ -177,23 +248,23 @@ BOOT: { - HV *stash = gv_stashpv ("OpenCL", 1); - static const ivstr *civ, const_iv[] = { - { sizeof (cl_char ), "SIZEOF_CHAR" }, - { sizeof (cl_uchar ), "SIZEOF_UCHAR" }, - { sizeof (cl_short ), "SIZEOF_SHORT" }, - { sizeof (cl_ushort), "SIZEOF_USHORT" }, - { sizeof (cl_int ), "SIZEOF_INT" }, - { sizeof (cl_uint ), "SIZEOF_UINT" }, - { sizeof (cl_long ), "SIZEOF_LONG" }, - { sizeof (cl_ulong ), "SIZEOF_ULONG" }, - { sizeof (cl_half ), "SIZEOF_HALF" }, - { sizeof (cl_float ), "SIZEOF_FLOAT" }, - { sizeof (cl_double), "SIZEOF_DOUBLE" }, + HV *stash = gv_stashpv ("OpenCL", 1); + static const ivstr *civ, const_iv[] = { + { sizeof (cl_char ), "SIZEOF_CHAR" }, + { sizeof (cl_uchar ), "SIZEOF_UCHAR" }, + { sizeof (cl_short ), "SIZEOF_SHORT" }, + { sizeof (cl_ushort), "SIZEOF_USHORT" }, + { sizeof (cl_int ), "SIZEOF_INT" }, + { sizeof (cl_uint ), "SIZEOF_UINT" }, + { sizeof (cl_long ), "SIZEOF_LONG" }, + { sizeof (cl_ulong ), "SIZEOF_ULONG" }, + { sizeof (cl_half ), "SIZEOF_HALF" }, + { sizeof (cl_float ), "SIZEOF_FLOAT" }, + { sizeof (cl_double), "SIZEOF_DOUBLE" }, #include "constiv.h" - }; - for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ > const_iv; civ--) - newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv)); + }; + for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ > const_iv; civ--) + newCONSTSUB (stash, (char *)civ[-1].name, newSViv (civ[-1].iv)); } cl_int @@ -223,13 +294,13 @@ PUSHs (NEW_MORTAL_OBJ ("OpenCL::Platform", list [i])); void -context_from_type (FUTURE properties = 0, cl_device_type type = CL_DEVICE_TYPE_DEFAULT, FUTURE notify = 0) +context_from_type (cl_context_properties *properties = 0, cl_device_type type = CL_DEVICE_TYPE_DEFAULT, FUTURE notify = 0) PPCODE: - NEED_SUCCESS_ARG (cl_context ctx, CreateContextFromType, (0, type, 0, 0, &res)); + NEED_SUCCESS_ARG (cl_context ctx, CreateContextFromType, (properties, type, 0, 0, &res)); XPUSH_NEW_OBJ ("OpenCL::Context", ctx); void -context (FUTURE properties, FUTURE devices, FUTURE notify = 0) +context (cl_context_properties *properties = 0, FUTURE devices, FUTURE notify = 0) PPCODE: /* der Gipfel der Kunst */ @@ -285,10 +356,10 @@ PUSHs (sv_setref_pv (sv_newmortal (), "OpenCL::Device", list [i])); void -context (OpenCL::Platform self, FUTURE properties, SV *devices, FUTURE notify = 0) +context (OpenCL::Platform self, cl_context_properties *properties = 0, SV *devices, FUTURE notify = 0) PPCODE: if (!SvROK (devices) || SvTYPE (SvRV (devices)) != SVt_PVAV) - croak ("OpenCL::Platform argument 'device' must be an arrayref with device objects, in call"); + croak ("OpenCL::Platform::context argument 'device' must be an arrayref with device objects, in call"); AV *av = (AV *)SvRV (devices); cl_uint num_devices = av_len (av) + 1; @@ -298,13 +369,14 @@ for (i = num_devices; i--; ) device_list [i] = SvPTROBJ ("clCreateContext", "devices", *av_fetch (av, i, 0), "OpenCL::Device"); - NEED_SUCCESS_ARG (cl_context ctx, CreateContext, (0, num_devices, device_list, 0, 0, &res)); + NEED_SUCCESS_ARG (cl_context ctx, CreateContext, (properties, num_devices, device_list, 0, 0, &res)); XPUSH_NEW_OBJ ("OpenCL::Context", ctx); void -context_from_type (OpenCL::Platform self, FUTURE properties = 0, cl_device_type type = CL_DEVICE_TYPE_DEFAULT, FUTURE notify = 0) +context_from_type (OpenCL::Platform self, SV *properties = 0, cl_device_type type = CL_DEVICE_TYPE_DEFAULT, FUTURE notify = 0) PPCODE: - cl_context_properties props[] = { CL_CONTEXT_PLATFORM, (cl_context_properties)self, 0 }; + cl_context_properties extra[] = { CL_CONTEXT_PLATFORM, (cl_context_properties)self }; + cl_context_properties *props = SvCONTEXTPROPERTIES ("OpenCL::Platform::context_from_type", "properties", properties, extra, 2); NEED_SUCCESS_ARG (cl_context ctx, CreateContextFromType, (props, type, 0, 0, &res)); XPUSH_NEW_OBJ ("OpenCL::Context", ctx); @@ -554,20 +626,20 @@ void queue (OpenCL::Context self, OpenCL::Device device, cl_command_queue_properties properties = 0) PPCODE: - NEED_SUCCESS_ARG (cl_command_queue queue, CreateCommandQueue, (self, device, properties, &res)); + NEED_SUCCESS_ARG (cl_command_queue queue, CreateCommandQueue, (self, device, properties, &res)); XPUSH_NEW_OBJ ("OpenCL::Queue", queue); void user_event (OpenCL::Context self) PPCODE: - NEED_SUCCESS_ARG (cl_event ev, CreateUserEvent, (self, &res)); + NEED_SUCCESS_ARG (cl_event ev, CreateUserEvent, (self, &res)); XPUSH_NEW_OBJ ("OpenCL::UserEvent", ev); void buffer (OpenCL::Context self, cl_mem_flags flags, size_t len) PPCODE: if (flags & (CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR)) - croak ("clCreateBuffer: cannot use/copy host ptr when no data is given, use $context->buffer_sv instead?"); + croak ("OpenCL::Context::buffer: cannot use/copy host ptr when no data is given, use $context->buffer_sv instead?"); NEED_SUCCESS_ARG (cl_mem mem, CreateBuffer, (self, flags, len, 0, &res)); XPUSH_NEW_OBJ ("OpenCL::BufferObj", mem); @@ -578,7 +650,7 @@ STRLEN len; char *ptr = SvOK (data) ? SvPVbyte (data, len) : 0; if (!(flags & (CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR))) - croak ("clCreateBuffer: have to specify use or copy host ptr when buffer data is given, use $context->buffer instead?"); + croak ("OpenCL::Context::buffer_sv: you have to specify use or copy host ptr when buffer data is given, use $context->buffer instead?"); NEED_SUCCESS_ARG (cl_mem mem, CreateBuffer, (self, flags, len, ptr, &res)); XPUSH_NEW_OBJ ("OpenCL::BufferObj", mem); @@ -588,7 +660,7 @@ STRLEN len; char *ptr = SvOK (data) ? SvPVbyte (data, len) : 0; const cl_image_format format = { channel_order, channel_type }; - NEED_SUCCESS_ARG (cl_mem mem, CreateImage2D, (self, flags, &format, width, height, row_pitch, ptr, &res)); + NEED_SUCCESS_ARG (cl_mem mem, CreateImage2D, (self, flags, &format, width, height, row_pitch, ptr, &res)); XPUSH_NEW_OBJ ("OpenCL::Image2D", mem); void @@ -597,9 +669,37 @@ STRLEN len; char *ptr = SvOK (data) ? SvPVbyte (data, len) : 0; const cl_image_format format = { channel_order, channel_type }; - NEED_SUCCESS_ARG (cl_mem mem, CreateImage3D, (self, flags, &format, width, height, depth, row_pitch, slice_pitch, ptr, &res)); + NEED_SUCCESS_ARG (cl_mem mem, CreateImage3D, (self, flags, &format, width, height, depth, row_pitch, slice_pitch, ptr, &res)); XPUSH_NEW_OBJ ("OpenCL::Image3D", mem); +#if cl_apple_gl_sharing || cl_khr_gl_sharing + +void +gl_buffer (OpenCL::Context self, cl_mem_flags flags, cl_GLuint bufobj) + PPCODE: + NEED_SUCCESS_ARG (cl_mem mem, CreateFromGLBuffer, (self, flags, bufobj, &res)); + XPUSH_NEW_OBJ ("OpenCL::BufferObj", mem); + +void +gl_texture2d (OpenCL::Context self, cl_mem_flags flags, cl_GLenum target, cl_GLint miplevel, cl_GLuint texture) + PPCODE: + NEED_SUCCESS_ARG (cl_mem mem, CreateFromGLTexture2D, (self, flags, target, miplevel, texture, &res)); + XPUSH_NEW_OBJ ("OpenCL::Image2D", mem); + +void +gl_texture3d (OpenCL::Context self, cl_mem_flags flags, cl_GLenum target, cl_GLint miplevel, cl_GLuint texture) + PPCODE: + NEED_SUCCESS_ARG (cl_mem mem, CreateFromGLTexture3D, (self, flags, target, miplevel, texture, &res)); + XPUSH_NEW_OBJ ("OpenCL::Image3D", mem); + +void +gl_renderbuffer (OpenCL::Context self, cl_mem_flags flags, cl_GLuint renderbuffer) + PPCODE: + NEED_SUCCESS_ARG (cl_mem mem, CreateFromGLRenderbuffer, (self, flags, renderbuffer, &res)); + XPUSH_NEW_OBJ ("OpenCL::Image2D", mem); + +#endif + void supported_image_formats (OpenCL::Context self, cl_mem_flags flags, cl_mem_object_type image_type) PPCODE: @@ -608,9 +708,9 @@ cl_image_format *list; int i; - NEED_SUCCESS (GetSupportedImageFormats, (self, flags, image_type, 0, 0, &count)); + NEED_SUCCESS (GetSupportedImageFormats, (self, flags, image_type, 0, 0, &count)); Newx (list, count, cl_image_format); - NEED_SUCCESS (GetSupportedImageFormats, (self, flags, image_type, count, list, 0)); + NEED_SUCCESS (GetSupportedImageFormats, (self, flags, image_type, count, list, 0)); EXTEND (SP, count); for (i = 0; i < count; ++i) @@ -625,7 +725,7 @@ void sampler (OpenCL::Context self, cl_bool normalized_coords, cl_addressing_mode addressing_mode, cl_filter_mode filter_mode) PPCODE: - NEED_SUCCESS_ARG (cl_sampler sampler, CreateSampler, (self, normalized_coords, addressing_mode, filter_mode, &res)); + NEED_SUCCESS_ARG (cl_sampler sampler, CreateSampler, (self, normalized_coords, addressing_mode, filter_mode, &res)); XPUSH_NEW_OBJ ("OpenCL::Sampler", sampler); void @@ -636,7 +736,7 @@ const char *ptr = SvPVbyte (program, len); len2 = len; - NEED_SUCCESS_ARG (cl_program prog, CreateProgramWithSource, (self, 1, &ptr, &len2, &res)); + NEED_SUCCESS_ARG (cl_program prog, CreateProgramWithSource, (self, 1, &ptr, &len2, &res)); XPUSH_NEW_OBJ ("OpenCL::Program", prog); #BEGIN:context @@ -960,6 +1060,36 @@ if (ev) XPUSH_NEW_OBJ ("OpenCL::Event", ev); +#if cl_apple_gl_sharing || cl_khr_gl_sharing + +void +enqueue_acquire_gl_objects (OpenCL::Queue self, SV *objects, ...) + ALIAS: + enqueue_release_gl_objects = 1 + CODE: + if (!SvROK (objects) || SvTYPE (SvRV (objects)) != SVt_PVAV) + croak ("OpenCL::Queue::enqueue_acquire/release_gl_objects argument 'objects' must be an arrayref with memory objects, in call"); + + cl_event ev = 0; + EVENT_LIST (2, items - 2); + AV *av = (AV *)SvRV (objects); + cl_uint num_objects = av_len (av) + 1; + cl_mem *object_list = tmpbuf (sizeof (cl_mem) * num_objects); + int i; + + for (i = num_objects; i--; ) + object_list [i] = SvPTROBJ ("OpenCL::Queue::enqueue_acquire/release_gl_objects", "objects", *av_fetch (av, i, 0), "OpenCL::Memory"); + + if (ix) + NEED_SUCCESS (EnqueueReleaseGLObjects, (self, num_objects, object_list, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0)); + else + NEED_SUCCESS (EnqueueAcquireGLObjects, (self, num_objects, object_list, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0)); + + if (ev) + XPUSH_NEW_OBJ ("OpenCL::Event", ev); + +#endif + void enqueue_marker (OpenCL::Queue self) PPCODE: @@ -1129,6 +1259,20 @@ #END:mem +#if cl_apple_gl_sharing || cl_khr_gl_sharing + +void +gl_object_info (OpenCL::Memory self) + PPCODE: + cl_gl_object_type type; + cl_GLuint name; + NEED_SUCCESS (GetGLObjectInfo, (self, &type, &name)); + EXTEND (SP, 2); + PUSHs (sv_2mortal (newSVuv (type))); + PUSHs (sv_2mortal (newSVuv (name))); + +#endif + MODULE = OpenCL PACKAGE = OpenCL::BufferObj void @@ -1169,6 +1313,32 @@ #END:image +#if cl_apple_gl_sharing || cl_khr_gl_sharing + +#BEGIN:gl_texture + +void +target (OpenCL::Image self) + PPCODE: + cl_GLenum value [1]; + NEED_SUCCESS (GetGLTextureInfo, (self, CL_GL_TEXTURE_TARGET, sizeof (value), value, 0)); + EXTEND (SP, 1); + const int i = 0; + PUSHs (sv_2mortal (newSVuv (value [i]))); + +void +gl_mipmap_level (OpenCL::Image self) + PPCODE: + cl_GLint value [1]; + NEED_SUCCESS (GetGLTextureInfo, (self, CL_GL_MIPMAP_LEVEL, sizeof (value), value, 0)); + EXTEND (SP, 1); + const int i = 0; + PUSHs (sv_2mortal (newSViv (value [i]))); + +#END:gl_texture + +#endif + MODULE = OpenCL PACKAGE = OpenCL::Sampler void @@ -1248,13 +1418,13 @@ void build_info (OpenCL::Program self, OpenCL::Device device, cl_program_build_info name) PPCODE: - size_t size; - NEED_SUCCESS (GetProgramBuildInfo, (self, device, name, 0, 0, &size)); + size_t size; + NEED_SUCCESS (GetProgramBuildInfo, (self, device, name, 0, 0, &size)); SV *sv = sv_2mortal (newSV (size)); SvUPGRADE (sv, SVt_PV); SvPOK_only (sv); SvCUR_set (sv, size); - NEED_SUCCESS (GetProgramBuildInfo, (self, device, name, size, SvPVX (sv), 0)); + NEED_SUCCESS (GetProgramBuildInfo, (self, device, name, size, SvPVX (sv), 0)); XPUSHs (sv); #BEGIN:program_build @@ -1287,7 +1457,7 @@ void kernel (OpenCL::Program program, SV *function) PPCODE: - NEED_SUCCESS_ARG (cl_kernel kernel, CreateKernel, (program, SvPVbyte_nolen (function), &res)); + NEED_SUCCESS_ARG (cl_kernel kernel, CreateKernel, (program, SvPVbyte_nolen (function), &res)); XPUSH_NEW_OBJ ("OpenCL::Kernel", kernel); void