#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include typedef cl_platform_id OpenCL__Platform; typedef cl_device_id OpenCL__Device; typedef cl_context OpenCL__Context; typedef cl_command_queue OpenCL__Queue; typedef cl_mem OpenCL__Memory; typedef cl_sampler OpenCL__Sampler; typedef cl_program OpenCL__Program; typedef cl_kernel OpenCL__Kernel; typedef cl_event OpenCL__Event; static const struct { IV iv; const char *name; } cl_error[] = { #define def_error(name) { (IV)CL_ ## name, # name }, #include "invalid.h" }; static const char * clstrerror (cl_int res) { int i; static char numbuf [32]; for (i = sizeof (cl_error) / sizeof (cl_error [0]); i--; ) if (cl_error [i].iv == res) return cl_error [i].name; snprintf (numbuf, sizeof (numbuf), "ERROR(%d)", res); return numbuf; } #define FAIL(name,res) \ croak ("cl" # name ": %s", clstrerror (res)); #define NEED_SUCCESS(name,args) \ do { \ cl_int res = cl ## name args; \ \ if (res) \ FAIL (name, res); \ } while (0) #define NEW_MORTAL_OBJ(class,ptr) sv_setref_pv (sv_newmortal (), class, ptr) #define XPUSH_NEW_OBJ(class,ptr) XPUSHs (NEW_MORTAL_OBJ (class, ptr)) /*TODO*/ #define EVENT_LIST(items,count) cl_uint event_list_count = 0; cl_event *event_list_ptr = 0 #define INFO(class) \ { \ size_t size; \ SV *sv; \ \ NEED_SUCCESS (Get ## class ## Info, (this, name, 0, 0, &size)); \ sv = sv_2mortal (newSV (size)); \ SvUPGRADE (sv, SVt_PV); \ SvPOK_only (sv); \ SvCUR_set (sv, size); \ NEED_SUCCESS (Get ## class ## Info, (this, name, size, SvPVX (sv), 0)); \ XPUSHs (sv); \ } MODULE = OpenCL PACKAGE = OpenCL PROTOTYPES: ENABLE BOOT: { HV *stash = gv_stashpv ("OpenCL", 1); static const struct { const char *name; IV iv; } *civ, const_iv[] = { #define const_iv(name) { # name, (IV)CL_ ## name }, #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)); } void platforms () PPCODE: { cl_platform_id *list; cl_uint count; int i; NEED_SUCCESS (GetPlatformIDs, (0, 0, &count)); Newx (list, count, cl_platform_id); NEED_SUCCESS (GetPlatformIDs, (count, list, 0)); EXTEND (SP, count); for (i = 0; i < count; ++i) PUSHs (NEW_MORTAL_OBJ ("OpenCL::Platform", list [i])); Safefree (list); } void context_from_type_simple (cl_device_type type = CL_DEVICE_TYPE_DEFAULT) PPCODE: { cl_int res; cl_context ctx = clCreateContextFromType (0, type, 0, 0, &res); if (res) FAIL (CreateContextFromType, res); XPUSH_NEW_OBJ ("OpenCL::Context", ctx); } void wait_for_events (...) CODE: { EVENT_LIST (0, items); NEED_SUCCESS (WaitForEvents, (event_list_count, event_list_ptr)); } PROTOTYPES: DISABLE MODULE = OpenCL PACKAGE = OpenCL::Platform void info (OpenCL::Platform this, cl_platform_info name) PPCODE: INFO (Platform) void devices (OpenCL::Platform this, cl_device_type type = CL_DEVICE_TYPE_ALL) PPCODE: { cl_device_id *list; cl_uint count; int i; NEED_SUCCESS (GetDeviceIDs, (this, type, 0, 0, &count)); Newx (list, count, cl_device_id); NEED_SUCCESS (GetDeviceIDs, (this, type, count, list, 0)); EXTEND (SP, count); for (i = 0; i < count; ++i) PUSHs (sv_setref_pv (sv_newmortal (), "OpenCL::Device", list [i])); Safefree (list); } void context_from_type_simple (OpenCL::Platform this, cl_device_type type = CL_DEVICE_TYPE_DEFAULT) PPCODE: { cl_int res; cl_context_properties props[] = { CL_CONTEXT_PLATFORM, (cl_context_properties)this, 0 }; cl_context ctx = clCreateContextFromType (props, type, 0, 0, &res); if (res) FAIL (CreateContextFromType, res); XPUSH_NEW_OBJ ("OpenCL::Context", ctx); } void unload_compiler () CODE: NEED_SUCCESS (UnloadCompiler, ()); MODULE = OpenCL PACKAGE = OpenCL::Device void info (OpenCL::Device this, cl_device_info name) PPCODE: INFO (Device) void context_simple (OpenCL::Device this) PPCODE: { cl_int res; cl_context ctx = clCreateContext (0, 1, &this, 0, 0, &res); if (res) FAIL (CreateContext, res); XPUSH_NEW_OBJ ("OpenCL::Context", ctx); } MODULE = OpenCL PACKAGE = OpenCL::Context void DESTROY (OpenCL::Context context) CODE: clReleaseContext (context); void info (OpenCL::Context this, cl_context_info name) PPCODE: INFO (Context) void command_queue_simple (OpenCL::Context this, OpenCL::Device device) PPCODE: { cl_int res; cl_command_queue queue = clCreateCommandQueue (this, device, 0, &res); if (res) FAIL (CreateCommandQueue, res); XPUSH_NEW_OBJ ("OpenCL::Queue", queue); } void buffer (OpenCL::Context this, cl_mem_flags flags, size_t len) PPCODE: { cl_int res; cl_mem mem = clCreateBuffer (this, flags, len, 0, &res); if (res) FAIL (CreateBuffer, res); XPUSH_NEW_OBJ ("OpenCL::Memory", mem); } void buffer_sv (OpenCL::Context this, cl_mem_flags flags, SV *data) PPCODE: { STRLEN len; char *ptr = SvPVbyte (data, len); cl_int res; cl_mem mem = clCreateBuffer (this, flags, len, ptr, &res); if (res) FAIL (CreateBuffer, res); XPUSH_NEW_OBJ ("OpenCL::Memory", mem); } void sampler (OpenCL::Context this, cl_bool normalized_coords, cl_addressing_mode addressing_mode, cl_filter_mode filter_mode) PPCODE: { cl_int res; cl_sampler sampler = clCreateSampler (this, normalized_coords, addressing_mode, filter_mode, &res); if (res) FAIL (CreateSampler, res); XPUSH_NEW_OBJ ("OpenCL::Sampler", sampler); } void program_with_source (OpenCL::Context this, SV *program) PPCODE: { STRLEN len; size_t len2; const char *ptr = SvPVbyte (program, len); cl_int res; cl_program prog; len2 = len; prog = clCreateProgramWithSource (this, 1, &ptr, &len2, &res); if (res) FAIL (CreateProgramWithSource, res); XPUSH_NEW_OBJ ("OpenCL::Program", prog); } MODULE = OpenCL PACKAGE = OpenCL::Queue void DESTROY (OpenCL::Queue this) CODE: clReleaseCommandQueue (this); void info (OpenCL::Queue this, cl_command_queue_info name) PPCODE: INFO (CommandQueue) void enqueue_read_buffer (OpenCL::Queue this, OpenCL::Memory mem, cl_bool blocking, size_t offset, size_t len, SV *data, ...) PPCODE: { cl_event ev = 0; EVENT_LIST (6, items - 6); SvUPGRADE (data, SVt_PV); SvGROW (data, len); SvPOK_only (data); SvCUR_set (data, len); NEED_SUCCESS (EnqueueReadBuffer, (this, mem, blocking, offset, len, SvPVX (data), event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0)); if (ev) XPUSH_NEW_OBJ ("OpenCL::Event", ev); } void enqueue_write_buffer (OpenCL::Queue this, OpenCL::Memory mem, cl_bool blocking, size_t offset, SV *data, ...) PPCODE: { cl_event ev = 0; STRLEN len; char *ptr = SvPVbyte (data, len); EVENT_LIST (5, items - 5); NEED_SUCCESS (EnqueueReadBuffer, (this, mem, blocking, offset, len, ptr, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0)); if (ev) XPUSH_NEW_OBJ ("OpenCL::Event", ev); } void enqueue_copy_buffer (OpenCL::Queue this, OpenCL::Memory src, OpenCL::Memory dst, size_t src_offset, size_t dst_offset, size_t len, ...) PPCODE: { cl_event ev = 0; EVENT_LIST (6, items - 6); NEED_SUCCESS (EnqueueCopyBuffer, (this, src, dst, src_offset, dst_offset, len, event_list_count, event_list_ptr, GIMME_V != G_VOID ? &ev : 0)); if (ev) XPUSH_NEW_OBJ ("OpenCL::Event", ev); } void enqueue_marker (OpenCL::Queue this) PPCODE: { cl_event ev; NEED_SUCCESS (EnqueueMarker, (this, &ev)); XPUSH_NEW_OBJ ("OpenCL::Event", ev); } void enqueue_wait_for_events (OpenCL::Queue this, ...) CODE: { EVENT_LIST (1, items - 1); NEED_SUCCESS (EnqueueWaitForEvents, (this, event_list_count, event_list_ptr)); } void enqueue_barrier (OpenCL::Queue this) CODE: NEED_SUCCESS (EnqueueBarrier, (this)); MODULE = OpenCL PACKAGE = OpenCL::Memory void DESTROY (OpenCL::Memory this) CODE: clReleaseMemObject (this); void info (OpenCL::Memory this, cl_mem_info name) PPCODE: INFO (MemObject) MODULE = OpenCL PACKAGE = OpenCL::Sampler void DESTROY (OpenCL::Sampler this) CODE: clReleaseSampler (this); void info (OpenCL::Sampler this, cl_sampler_info name) PPCODE: INFO (Sampler) MODULE = OpenCL PACKAGE = OpenCL::Program void DESTROY (OpenCL::Program this) CODE: clReleaseProgram (this); void info (OpenCL::Program this, cl_program_info name) PPCODE: INFO (Program) void build (OpenCL::Program this, OpenCL::Device device, SV *options = &PL_sv_undef) CODE: NEED_SUCCESS (BuildProgram, (this, 1, &device, SvPVbyte_nolen (options), 0, 0)); void build_info (OpenCL::Program this, OpenCL::Device device, cl_program_build_info name) PPCODE: { size_t size; SV *sv; NEED_SUCCESS (GetProgramBuildInfo, (this, device, name, 0, 0, &size)); sv = sv_2mortal (newSV (size)); SvUPGRADE (sv, SVt_PV); SvPOK_only (sv); SvCUR_set (sv, size); NEED_SUCCESS (GetProgramBuildInfo, (this, device, name, size, SvPVX (sv), 0)); XPUSHs (sv); } void kernel (OpenCL::Program program, SV *function) PPCODE: { cl_int res; cl_kernel kernel = clCreateKernel (program, SvPVbyte_nolen (function), &res); if (res) FAIL (CreateKernel, res); XPUSH_NEW_OBJ ("OpenCL::Kernel", kernel); } MODULE = OpenCL PACKAGE = OpenCL::Kernel void DESTROY (OpenCL::Kernel this) CODE: clReleaseKernel (this); void info (OpenCL::Kernel this, cl_kernel_info name) PPCODE: INFO (Kernel) void set_bool (OpenCL::Kernel this, cl_uint idx, cl_bool value) CODE: clKernelSetArg (this, idx, sizeof (value), &value); MODULE = OpenCL PACKAGE = OpenCL::Event void DESTROY (OpenCL::Event this) CODE: clReleaseEvent (this); void info (OpenCL::Event this, cl_event_info name) PPCODE: INFO (Event) void wait (OpenCL::Event this) CODE: clWaitForEvents (1, &this);