error* platform__get_devices(clobj_t _plat, clobj_t **_devices, uint32_t *num_devices, cl_device_type devtype) { auto plat = static_cast<platform*>(_plat); return c_handle_error([&] { *num_devices = 0; try { pyopencl_call_guarded(clGetDeviceIDs, plat, devtype, 0, nullptr, buf_arg(*num_devices)); } catch (const clerror &e) { if (e.code() != CL_DEVICE_NOT_FOUND) throw e; *num_devices = 0; } if (*num_devices == 0) { *_devices = nullptr; return; } pyopencl_buf<cl_device_id> devices(*num_devices); pyopencl_call_guarded(clGetDeviceIDs, plat, devtype, devices, buf_arg(*num_devices)); *_devices = buf_to_base<device>(devices).release(); }); }
error* enqueue_copy_buffer(clobj_t *evt, clobj_t _queue, clobj_t _src, clobj_t _dst, ptrdiff_t byte_count, size_t src_offset, size_t dst_offset, const clobj_t *_wait_for, uint32_t num_wait_for) { auto queue = static_cast<command_queue*>(_queue); auto src = static_cast<memory_object*>(_src); auto dst = static_cast<memory_object*>(_dst); return c_handle_error([&] { if (byte_count < 0) { size_t byte_count_src = 0; size_t byte_count_dst = 0; pyopencl_call_guarded( clGetMemObjectInfo, src, CL_MEM_SIZE, sizeof(byte_count), &byte_count_src, nullptr); pyopencl_call_guarded( clGetMemObjectInfo, src, CL_MEM_SIZE, sizeof(byte_count), &byte_count_dst, nullptr); byte_count = std::min(byte_count_src, byte_count_dst); } const auto wait_for = buf_from_class<event>(_wait_for, num_wait_for); retry_mem_error([&] { pyopencl_call_guarded( clEnqueueCopyBuffer, queue, src, dst, src_offset, dst_offset, byte_count, wait_for, event_out(evt)); }); }); }
error* enqueue_migrate_mem_object_ext(clobj_t *evt, clobj_t _queue, const clobj_t *_mem_obj, uint32_t num_mem_obj, cl_mem_migration_flags_ext flags, const clobj_t *_wait_for, uint32_t num_wait_for) { const auto wait_for = buf_from_class<event>(_wait_for, num_wait_for); const auto mem_obj = buf_from_class<memory_object>(_mem_obj, num_mem_obj); auto queue = static_cast<command_queue*>(_queue); return c_handle_error([&] { #if PYOPENCL_CL_VERSION >= 0x1020 // {{{ get platform cl_device_id dev; pyopencl_call_guarded(clGetCommandQueueInfo, queue, CL_QUEUE_DEVICE, size_arg(dev), nullptr); cl_platform_id plat; pyopencl_call_guarded(clGetDeviceInfo, dev, CL_DEVICE_PLATFORM, size_arg(plat), nullptr); // }}} #endif auto clEnqueueMigrateMemObjectEXT = pyopencl_get_ext_fun(plat, clEnqueueMigrateMemObjectEXT); retry_mem_error([&] { pyopencl_call_guarded(clEnqueueMigrateMemObjectsEXT, queue, mem_obj, flags, wait_for, event_out(evt)); }); }); }
pyopencl_buf<clobj_t> program::all_kernels() { cl_uint num_knls; pyopencl_call_guarded(clCreateKernelsInProgram, this, 0, nullptr, buf_arg(num_knls)); pyopencl_buf<cl_kernel> knls(num_knls); pyopencl_call_guarded(clCreateKernelsInProgram, this, knls, buf_arg(num_knls)); return buf_to_base<kernel>(knls, true); }
error* get_platforms(clobj_t **_platforms, uint32_t *num_platforms) { return c_handle_error([&] { *num_platforms = 0; pyopencl_call_guarded(clGetPlatformIDs, 0, nullptr, buf_arg(*num_platforms)); pyopencl_buf<cl_platform_id> platforms(*num_platforms); pyopencl_call_guarded(clGetPlatformIDs, platforms, buf_arg(*num_platforms)); *_platforms = buf_to_base<platform>(platforms).release(); }); }
error* enqueue_write_buffer_rect(clobj_t *evt, clobj_t _queue, clobj_t _mem, void *buf, const size_t *_buf_orig, size_t buf_orig_l, const size_t *_host_orig, size_t host_orig_l, const size_t *_reg, size_t reg_l, const size_t *_buf_pitches, size_t buf_pitches_l, const size_t *_host_pitches, size_t host_pitches_l, const clobj_t *_wait_for, uint32_t num_wait_for, int block, void *pyobj) { #if PYOPENCL_CL_VERSION >= 0x1010 const auto wait_for = buf_from_class<event>(_wait_for, num_wait_for); auto queue = static_cast<command_queue*>(_queue); auto mem = static_cast<memory_object*>(_mem); ConstBuffer<size_t, 3> buf_orig(_buf_orig, buf_orig_l); ConstBuffer<size_t, 3> host_orig(_host_orig, host_orig_l); ConstBuffer<size_t, 3> reg(_reg, reg_l, 1); ConstBuffer<size_t, 2> buf_pitches(_buf_pitches, buf_pitches_l); ConstBuffer<size_t, 2> host_pitches(_host_pitches, host_pitches_l); return c_handle_retry_mem_error([&] { pyopencl_call_guarded( clEnqueueWriteBufferRect, queue, mem, bool(block), buf_orig, host_orig, reg, buf_pitches[0], buf_pitches[1], host_pitches[0], host_pitches[1], buf, wait_for, nanny_event_out(evt, pyobj)); }); #else PYOPENCL_UNSUPPORTED(clEnqueueWriteBufferRect, "CL 1.0") #endif }
error* context__get_supported_image_formats(clobj_t _ctx, cl_mem_flags flags, cl_mem_object_type image_type, generic_info *out) { auto ctx = static_cast<context*>(_ctx); return c_handle_error([&] { cl_uint num; pyopencl_call_guarded(clGetSupportedImageFormats, ctx, flags, image_type, 0, nullptr, buf_arg(num)); pyopencl_buf<cl_image_format> formats(num); pyopencl_call_guarded(clGetSupportedImageFormats, ctx, flags, image_type, formats, buf_arg(num)); *out = pyopencl_convert_array_info(cl_image_format, formats); }); }
error* enqueue_copy_buffer_rect(clobj_t *evt, clobj_t _queue, clobj_t _src, clobj_t _dst, const size_t *_src_orig, size_t src_orig_l, const size_t *_dst_orig, size_t dst_orig_l, const size_t *_reg, size_t reg_l, const size_t *_src_pitches, size_t src_pitches_l, const size_t *_dst_pitches, size_t dst_pitches_l, const clobj_t *_wait_for, uint32_t num_wait_for) { #if PYOPENCL_CL_VERSION >= 0x1010 const auto wait_for = buf_from_class<event>(_wait_for, num_wait_for); auto queue = static_cast<command_queue*>(_queue); auto src = static_cast<memory_object*>(_src); auto dst = static_cast<memory_object*>(_dst); ConstBuffer<size_t, 3> src_orig(_src_orig, src_orig_l); ConstBuffer<size_t, 3> dst_orig(_dst_orig, dst_orig_l); ConstBuffer<size_t, 3> reg(_reg, reg_l, 1); ConstBuffer<size_t, 2> src_pitches(_src_pitches, src_pitches_l); ConstBuffer<size_t, 2> dst_pitches(_dst_pitches, dst_pitches_l); return c_handle_retry_mem_error([&] { pyopencl_call_guarded( clEnqueueCopyBufferRect, queue, src, dst, src_orig, dst_orig, reg, src_pitches[0], src_pitches[1], dst_pitches[0], dst_pitches[1], wait_for, event_out(evt)); }); #else PYOPENCL_UNSUPPORTED(clEnqueueCopyBufferRect, "CL 1.0") #endif }
error* platform__unload_compiler(clobj_t plat) { return c_handle_error([&] { pyopencl_call_guarded(clUnloadPlatformCompiler, static_cast<platform*>(plat)); }); }
error* get_gl_object_info(clobj_t mem, cl_gl_object_type *otype, GLuint *gl_name) { auto globj = static_cast<memory_object*>(mem); return c_handle_error([&] { pyopencl_call_guarded(clGetGLObjectInfo, globj, buf_arg(*otype), buf_arg(*gl_name)); }); }
error* kernel__set_arg_null(clobj_t _knl, cl_uint arg_index) { auto knl = static_cast<kernel*>(_knl); return c_handle_error([&] { const cl_mem m = 0; pyopencl_call_guarded(clSetKernelArg, knl, arg_index, size_arg(m)); }); }
// Kernel error* create_kernel(clobj_t *knl, clobj_t _prog, const char *name) { auto prog = static_cast<const program*>(_prog); return c_handle_error([&] { *knl = new kernel(pyopencl_call_guarded(clCreateKernel, prog, name), false); }); }
error* memory_object__get_host_array(clobj_t _obj, void **hostptr, size_t *size) { auto obj = static_cast<memory_object*>(_obj); return c_handle_error([&] { cl_mem_flags flags; pyopencl_call_guarded(clGetMemObjectInfo, obj, CL_MEM_FLAGS, size_arg(flags), nullptr); if (!(flags & CL_MEM_USE_HOST_PTR)) throw clerror("MemoryObject.get_host_array", CL_INVALID_VALUE, "Only MemoryObject with USE_HOST_PTR " "is supported."); pyopencl_call_guarded(clGetMemObjectInfo, obj, CL_MEM_HOST_PTR, size_arg(*hostptr), nullptr); pyopencl_call_guarded(clGetMemObjectInfo, obj, CL_MEM_SIZE, size_arg(*size), nullptr); }); }
error* kernel__set_arg_sampler(clobj_t _knl, cl_uint arg_index, clobj_t _samp) { auto knl = static_cast<kernel*>(_knl); auto samp = static_cast<sampler*>(_samp); return c_handle_error([&] { pyopencl_call_guarded(clSetKernelArg, knl, arg_index, size_arg(samp->data())); }); }
error* kernel__set_arg_buf(clobj_t _knl, cl_uint arg_index, const void *buffer, size_t size) { auto knl = static_cast<kernel*>(_knl); return c_handle_error([&] { pyopencl_call_guarded(clSetKernelArg, knl, arg_index, size_arg(buffer, size)); }); }
PYOPENCL_USE_RESULT static gl_texture* create_from_gl_texture(const context *ctx, cl_mem_flags flags, GLenum texture_target, GLint miplevel, GLuint texture, unsigned dims) { if (dims == 2) { cl_mem mem = pyopencl_call_guarded(clCreateFromGLTexture2D, ctx, flags, texture_target, miplevel, texture); return pyopencl_convert_obj(gl_texture, clReleaseMemObject, mem); } else if (dims == 3) { cl_mem mem = pyopencl_call_guarded(clCreateFromGLTexture3D, ctx, flags, texture_target, miplevel, texture); return pyopencl_convert_obj(gl_texture, clReleaseMemObject, mem); } else { throw clerror("Image", CL_INVALID_VALUE, "invalid dimension"); } }
void program::compile(const char *opts, const clobj_t *_devs, size_t num_devs, const clobj_t *_prgs, const char *const *names, size_t num_hdrs) { const auto devs = buf_from_class<device>(_devs, num_devs); const auto prgs = buf_from_class<program>(_prgs, num_hdrs); pyopencl_call_guarded(clCompileProgram, this, devs, opts, prgs, buf_arg(names, num_hdrs), nullptr, nullptr); }
error* kernel__set_arg_mem(clobj_t _knl, cl_uint arg_index, clobj_t _mem) { auto knl = static_cast<kernel*>(_knl); auto mem = static_cast<memory_object*>(_mem); return c_handle_error([&] { pyopencl_call_guarded(clSetKernelArg, knl, arg_index, size_arg(mem->data())); }); }
// Buffer error* create_buffer(clobj_t *buffer, clobj_t _ctx, cl_mem_flags flags, size_t size, void *hostbuf) { auto ctx = static_cast<context*>(_ctx); return c_handle_retry_mem_error([&] { auto mem = pyopencl_call_guarded(clCreateBuffer, ctx, flags, size, hostbuf); *buffer = new_buffer(mem); }); }
error* program__build(clobj_t _prog, const char *options, cl_uint num_devices, const clobj_t *_devices) { auto prog = static_cast<const program*>(_prog); const auto devices = buf_from_class<device>(_devices, num_devices); return c_handle_error([&] { pyopencl_call_guarded(clBuildProgram, prog, devices, options, nullptr, nullptr); }); }
error* create_from_gl_buffer(clobj_t *ptr, clobj_t _ctx, cl_mem_flags flags, GLuint bufobj) { auto ctx = static_cast<context*>(_ctx); return c_handle_error([&] { cl_mem mem = pyopencl_call_guarded(clCreateFromGLBuffer, ctx, flags, bufobj); *ptr = pyopencl_convert_obj(gl_buffer, clReleaseMemObject, mem); }); }
error* create_image_from_desc(clobj_t *img, clobj_t _ctx, cl_mem_flags flags, cl_image_format *fmt, cl_image_desc *desc, void *buf) { auto ctx = static_cast<context*>(_ctx); return c_handle_error([&] { auto mem = pyopencl_call_guarded(clCreateImage, ctx, flags, fmt, desc, buf); *img = new_image(mem, fmt); }); }
PYOPENCL_USE_RESULT buffer* buffer::get_sub_region(size_t orig, size_t size, cl_mem_flags flags) const { cl_buffer_region reg = {orig, size}; auto mem = retry_mem_error([&] { return pyopencl_call_guarded(clCreateSubBuffer, PYOPENCL_CL_CASTABLE_THIS, flags, CL_BUFFER_CREATE_TYPE_REGION, ®); }); return new_buffer(mem); }
// Image error* create_image_2d(clobj_t *img, clobj_t _ctx, cl_mem_flags flags, cl_image_format *fmt, size_t width, size_t height, size_t pitch, void *buf) { auto ctx = static_cast<context*>(_ctx); return c_handle_retry_mem_error([&] { auto mem = pyopencl_call_guarded(clCreateImage2D, ctx, flags, fmt, width, height, pitch, buf); *img = new_image(mem, fmt); }); }
// Program error* create_program_with_source(clobj_t *prog, clobj_t _ctx, const char *_src) { auto ctx = static_cast<context*>(_ctx); return c_handle_error([&] { const auto &src = _src; const size_t length = strlen(src); cl_program result = pyopencl_call_guarded( clCreateProgramWithSource, ctx, len_arg(src), buf_arg(length)); *prog = new_program(result, KND_SOURCE); }); }
error* enqueue_task(clobj_t *evt, clobj_t _queue, clobj_t _knl, const clobj_t *_wait_for, uint32_t num_wait_for) { auto queue = static_cast<command_queue*>(_queue); auto knl = static_cast<kernel*>(_knl); const auto wait_for = buf_from_class<event>(_wait_for, num_wait_for); return c_handle_retry_mem_error([&] { pyopencl_call_guarded(clEnqueueTask, queue, knl, wait_for, event_out(evt)); }); }
error* kernel__set_arg_svm_pointer(clobj_t _knl, cl_uint arg_index, void *value) { #if PYOPENCL_CL_VERSION >= 0x2000 auto knl = static_cast<kernel*>(_knl); return c_handle_error([&] { pyopencl_call_guarded(clSetKernelArgSVMPointer, knl, arg_index, value); }); #else PYOPENCL_UNSUPPORTED_BEFORE(clSetKernelArgSVMPointer, "CL 2.0") #endif }
void context::get_version(cl_context ctx, int *major, int *minor) { cl_device_id s_buff[16]; size_t size; pyopencl_buf<cl_device_id> d_buff(0); cl_device_id *devs = s_buff; pyopencl_call_guarded(clGetContextInfo, ctx, CL_CONTEXT_DEVICES, 0, nullptr, buf_arg(size)); if (PYOPENCL_UNLIKELY(!size)) { throw clerror("Context.get_version", CL_INVALID_VALUE, "Cannot get devices from context."); } if (PYOPENCL_UNLIKELY(size > sizeof(s_buff))) { d_buff.resize(size / sizeof(cl_device_id)); devs = d_buff.get(); } pyopencl_call_guarded(clGetContextInfo, ctx, CL_CONTEXT_DEVICES, size_arg(devs, size), buf_arg(size)); device::get_version(devs[0], major, minor); }
generic_info program::get_info(cl_uint param) const { switch ((cl_program_info)param) { case CL_PROGRAM_CONTEXT: return pyopencl_get_opaque_info(context, Program, this, param); case CL_PROGRAM_REFERENCE_COUNT: case CL_PROGRAM_NUM_DEVICES: return pyopencl_get_int_info(cl_uint, Program, this, param); case CL_PROGRAM_DEVICES: return pyopencl_get_opaque_array_info(device, Program, this, param); case CL_PROGRAM_SOURCE: return pyopencl_get_str_info(Program, this, param); case CL_PROGRAM_BINARY_SIZES: return pyopencl_get_array_info(size_t, Program, this, param); case CL_PROGRAM_BINARIES: { auto sizes = pyopencl_get_vec_info(size_t, Program, this, CL_PROGRAM_BINARY_SIZES); pyopencl_buf<char*> result_ptrs(sizes.len()); for (size_t i = 0;i < sizes.len();i++) { result_ptrs[i] = (char*)malloc(sizes[i]); } try { pyopencl_call_guarded(clGetProgramInfo, this, CL_PROGRAM_BINARIES, sizes.len() * sizeof(char*), result_ptrs.get(), nullptr); } catch (...) { for (size_t i = 0;i < sizes.len();i++) { free(result_ptrs[i]); } } pyopencl_buf<generic_info> gis(sizes.len()); for (size_t i = 0;i < sizes.len();i++) { gis[i].value = result_ptrs[i]; gis[i].dontfree = 0; gis[i].opaque_class = CLASS_NONE; gis[i].type = _copy_str(std::string("char[") + tostring(sizes[i]) + "]"); } return pyopencl_convert_array_info(generic_info, gis); } #if PYOPENCL_CL_VERSION >= 0x1020 case CL_PROGRAM_NUM_KERNELS: return pyopencl_get_int_info(size_t, Program, this, param); case CL_PROGRAM_KERNEL_NAMES: return pyopencl_get_str_info(Program, this, param); #endif default: throw clerror("Program.get_info", CL_INVALID_VALUE); } }
// Context error* create_context_from_type(clobj_t *_ctx, const cl_context_properties *props, cl_device_type dev_type) { // TODO debug print properties return c_handle_error([&] { *_ctx = new context( pyopencl_call_guarded( clCreateContextFromType, const_cast<cl_context_properties*>(props), dev_type, nullptr, nullptr), false); }); }