From 96a59d5884cd12d2932ff9cf9883762c47992a98 Mon Sep 17 00:00:00 2001 From: Marko Bencun <mbencun@gmail.com> Date: Sun, 8 Sep 2013 20:40:51 +0200 Subject: [PATCH] Image, Sampler --- pyopencl/_init.py | 201 +++--- pyopencl/cffi_cl.py | 147 ++++- src/c_wrapper/wrap_cl.cpp | 1123 ++++++++++++++++++---------------- src/c_wrapper/wrap_cl_core.h | 19 +- 4 files changed, 826 insertions(+), 664 deletions(-) diff --git a/pyopencl/_init.py b/pyopencl/_init.py index d68c610c..52862916 100644 --- a/pyopencl/_init.py +++ b/pyopencl/_init.py @@ -239,14 +239,14 @@ def _add_functionality(): (Event.get_info, event_info), MemoryObjectHolder: (MemoryObjectHolder.get_info, mem_info), - # Image: - # (Image.get_image_info, image_info), + Image: + (Image.get_image_info, image_info), Program: (Program.get_info, program_info), Kernel: (Kernel.get_info, kernel_info), - # Sampler: - # (Sampler.get_info, sampler_info), + Sampler: + (Sampler.get_info, sampler_info), } def to_string(cls, value, default_format=None): @@ -510,122 +510,113 @@ def _add_functionality(): # }}} - # # {{{ Image + # {{{ Image - # image_old_init = Image.__init__ + image_old_init = Image.__init__ - # def image_init(self, context, flags, format, shape=None, pitches=None, - # hostbuf=None, is_array=False, buffer=None): + def image_init(self, context, flags, format, shape=None, pitches=None, + hostbuf=None, is_array=False, buffer=None): - # if shape is None and hostbuf is None: - # raise Error("'shape' must be passed if 'hostbuf' is not given") + if shape is None and hostbuf is None: + raise Error("'shape' must be passed if 'hostbuf' is not given") - # if shape is None and hostbuf is not None: - # shape = hostbuf.shape + if shape is None and hostbuf is not None: + shape = hostbuf.shape - # if hostbuf is not None and not \ - # (flags & (mem_flags.USE_HOST_PTR | mem_flags.COPY_HOST_PTR)): - # from warnings import warn - # warn("'hostbuf' was passed, but no memory flags to make use of it.") - - # if hostbuf is None and pitches is not None: - # raise Error("'pitches' may only be given if 'hostbuf' is given") - - # if context._get_cl_version() >= (1, 2) and get_cl_header_version() >= (1, 2): - # if buffer is not None and is_array: - # raise ValueError( - # "'buffer' and 'is_array' are mutually exclusive") + if hostbuf is not None and not \ + (flags & (mem_flags.USE_HOST_PTR | mem_flags.COPY_HOST_PTR)): + from warnings import warn + warn("'hostbuf' was passed, but no memory flags to make use of it.") + + if hostbuf is None and pitches is not None: + raise Error("'pitches' may only be given if 'hostbuf' is given") + + if context._get_cl_version() >= (1, 2) and get_cl_header_version() >= (1, 2): + if buffer is not None and is_array: + raise ValueError( + "'buffer' and 'is_array' are mutually exclusive") + + if len(shape) == 3: + if buffer is not None: + raise TypeError( + "'buffer' argument is not supported for 3D arrays") + elif is_array: + image_type = mem_object_type.IMAGE2D_ARRAY + else: + image_type = mem_object_type.IMAGE3D + + elif len(shape) == 2: + if buffer is not None: + raise TypeError( + "'buffer' argument is not supported for 2D arrays") + elif is_array: + image_type = mem_object_type.IMAGE1D_ARRAY + else: + image_type = mem_object_type.IMAGE2D - # if len(shape) == 3: - # if buffer is not None: - # raise TypeError( - # "'buffer' argument is not supported for 3D arrays") - # elif is_array: - # image_type = mem_object_type.IMAGE2D_ARRAY - # else: - # image_type = mem_object_type.IMAGE3D + elif len(shape) == 1: + if buffer is not None: + image_type = mem_object_type.IMAGE1D_BUFFER + elif is_array: + raise TypeError("array of zero-dimensional images not supported") + else: + image_type = mem_object_type.IMAGE1D - # elif len(shape) == 2: - # if buffer is not None: - # raise TypeError( - # "'buffer' argument is not supported for 2D arrays") - # elif is_array: - # image_type = mem_object_type.IMAGE1D_ARRAY - # else: - # image_type = mem_object_type.IMAGE2D + else: + raise ValueError("images cannot have more than three dimensions") - # elif len(shape) == 1: - # if buffer is not None: - # image_type = mem_object_type.IMAGE1D_BUFFER - # elif is_array: - # raise TypeError("array of zero-dimensional images not supported") - # else: - # image_type = mem_object_type.IMAGE1D + desc = ImageDescriptor() - # else: - # raise ValueError("images cannot have more than three dimensions") + desc.image_type = image_type + desc.shape = shape # also sets desc.array_size - # desc = ImageDescriptor() + if pitches is None: + desc.pitches = (0, 0) + else: + desc.pitches = pitches - # desc.image_type = image_type - # desc.shape = shape # also sets desc.array_size + desc.num_mip_levels = 0 # per CL 1.2 spec + desc.num_samples = 0 # per CL 1.2 spec + desc.buffer = buffer - # if pitches is None: - # desc.pitches = (0, 0) - # else: - # desc.pitches = pitches + image_old_init(self, context, flags, format, desc, hostbuf) + else: + # legacy init for CL 1.1 and older + if is_array: + raise TypeError("'is_array=True' is not supported for CL < 1.2") + #if num_mip_levels is not None: + #raise TypeError( + # "'num_mip_levels' argument is not supported for CL < 1.2") + #if num_samples is not None: + #raise TypeError( + # "'num_samples' argument is not supported for CL < 1.2") + if buffer is not None: + raise TypeError("'buffer' argument is not supported for CL < 1.2") + + image_old_init(self, context, flags, format, shape, + pitches, hostbuf) + + class _ImageInfoGetter: + def __init__(self, event): + from warnings import warn + warn("Image.image.attr is deprecated. " + "Use Image.attr directly, instead.") - # desc.num_mip_levels = 0 # per CL 1.2 spec - # desc.num_samples = 0 # per CL 1.2 spec - # desc.buffer = buffer + self.event = event - # image_old_init(self, context, flags, format, desc, hostbuf) - # else: - # # legacy init for CL 1.1 and older - # if is_array: - # raise TypeError("'is_array=True' is not supported for CL < 1.2") - # #if num_mip_levels is not None: - # #raise TypeError( - # # "'num_mip_levels' argument is not supported for CL < 1.2") - # #if num_samples is not None: - # #raise TypeError( - # # "'num_samples' argument is not supported for CL < 1.2") - # if buffer is not None: - # raise TypeError("'buffer' argument is not supported for CL < 1.2") - - # image_old_init(self, context, flags, format, shape, - # pitches, hostbuf) - - # class _ImageInfoGetter: - # def __init__(self, event): - # from warnings import warn - # warn("Image.image.attr is deprecated. " - # "Use Image.attr directly, instead.") - - # self.event = event - - # def __getattr__(self, name): - # try: - # inf_attr = getattr(_cl.image_info, name.upper()) - # except AttributeError: - # raise AttributeError("%s has no attribute '%s'" - # % (type(self), name)) - # else: - # return self.event.get_image_info(inf_attr) - - # def image_shape(self): - # if self.type == mem_object_type.IMAGE2D: - # return (self.width, self.height) - # elif self.type == mem_object_type.IMAGE3D: - # return (self.width, self.height, self.depth) - # else: - # raise LogicError("only images have shapes") + def __getattr__(self, name): + try: + inf_attr = getattr(_cl.image_info, name.upper()) + except AttributeError: + raise AttributeError("%s has no attribute '%s'" + % (type(self), name)) + else: + return self.event.get_image_info(inf_attr) - # Image.__init__ = image_init - # Image.image = property(_ImageInfoGetter) - # Image.shape = property(image_shape) + Image.__init__ = image_init + Image.image = property(_ImageInfoGetter) - # # }}} + # }}} # # {{{ Error @@ -825,7 +816,7 @@ def _mark_copy_deprecated(func): return new_func -# enqueue_read_image = _mark_copy_deprecated(_cl._enqueue_read_image) +enqueue_read_image = _mark_copy_deprecated(_cl._enqueue_read_image) # enqueue_write_image = _mark_copy_deprecated(_cl._enqueue_write_image) # enqueue_copy_image = _mark_copy_deprecated(_cl._enqueue_copy_image) # enqueue_copy_image_to_buffer = _mark_copy_deprecated( diff --git a/pyopencl/cffi_cl.py b/pyopencl/cffi_cl.py index 463758d6..ceb0fbb0 100644 --- a/pyopencl/cffi_cl.py +++ b/pyopencl/cffi_cl.py @@ -204,20 +204,21 @@ class MemoryObjectHolder(_Common): class MemoryObject(MemoryObjectHolder): pass + +def _c_buffer_from_obj(obj): + if obj is None: + return _ffi.NULL, 0 + # assume numpy array for now + return _ffi.cast('void *', obj.__array_interface__['data'][0]), obj.nbytes + class Buffer(MemoryObject): _id = 'buffer' - - @classmethod - def _c_buffer_from_obj(cls, obj): - # assume numpy array for now - return _ffi.cast('void *', obj.__array_interface__['data'][0]), obj.nbytes - def __init__(self, context, flags, size=0, hostbuf=None): if hostbuf is not None and not (flags & (mem_flags.USE_HOST_PTR | mem_flags.COPY_HOST_PTR)): warnings.warn("'hostbuf' was passed, but no memory flags to make use of it.") c_hostbuf = _ffi.NULL if hostbuf is not None: - c_hostbuf, hostbuf_size = self._c_buffer_from_obj(hostbuf) + c_hostbuf, hostbuf_size = _c_buffer_from_obj(hostbuf) if size > hostbuf_size: raise RuntimeError("Buffer", status_code.INVALID_VALUE, "specified size is greater than host buffer size") if size == 0: @@ -355,10 +356,15 @@ class Kernel(_Common): self.ptr = ptr_kernel[0] def set_arg(self, arg_index, arg): - if isinstance(arg, Buffer): - _handle_error(_lib.kernel__set_arg_mem_buffer(self.ptr, arg_index, arg.ptr)) + if arg is None: + _handle_error(_lib.kernel__set_arg_null(self.ptr, arg_index)) + elif isinstance(arg, MemoryObject): + _handle_error(_lib.kernel__set_arg_mem(self.ptr, arg_index, arg.ptr)) + elif isinstance(arg, Sampler): + _handle_error(_lib.kernel__set_arg_sampler(self.ptr, arg_index, arg.ptr)) else: - raise NotImplementedError() + c_buf, size = _c_buffer_from_obj(arg) + _handle_error(_lib.kernel__set_arg_buf(self.ptr, arg_index, c_buf, size)) def get_work_group_info(self, param, device): info = _ffi.new('generic_info *') @@ -440,8 +446,8 @@ def _c_obj_list(objs=None): return _ffi.NULL, 0 return _ffi.new('void *[]', [ev.ptr for ev in objs]), len(objs) -def _enqueue_read_buffer(queue, mem, buf, device_offset=0, wait_for=None, is_blocking=True): - c_buf, size = Buffer._c_buffer_from_obj(buf) +def _enqueue_read_buffer(queue, mem, hostbuf, device_offset=0, wait_for=None, is_blocking=True): + c_buf, size = _c_buffer_from_obj(hostbuf) ptr_event = _ffi.new('void **') c_wait_for, num_wait_for = _c_obj_list(wait_for) _handle_error(_lib._enqueue_read_buffer( @@ -472,7 +478,7 @@ def _enqueue_copy_buffer(queue, src, dst, byte_count=-1, src_offset=0, dst_offse return _create_instance(Event, ptr_event[0]) def _enqueue_write_buffer(queue, mem, hostbuf, device_offset=0, wait_for=None, is_blocking=True): - c_buf, size = Buffer._c_buffer_from_obj(hostbuf) + c_buf, size = _c_buffer_from_obj(hostbuf) ptr_event = _ffi.new('void **') c_wait_for, num_wait_for = _c_obj_list(wait_for) _handle_error(_lib._enqueue_write_buffer( @@ -487,6 +493,24 @@ def _enqueue_write_buffer(queue, mem, hostbuf, device_offset=0, wait_for=None, i )) return _create_instance(Event, ptr_event[0]) +def _enqueue_read_image(queue, mem, origin, region, hostbuf, row_pitch=0, slice_pitch=0, wait_for=None, is_blocking=True): + c_buf, size = _c_buffer_from_obj(hostbuf) + ptr_event = _ffi.new('void **') + c_wait_for, num_wait_for = _c_obj_list(wait_for) + _handle_error(_lib._enqueue_read_image( + ptr_event, + queue.ptr, + mem.ptr, + origin, + region, + c_buf, + size, + row_pitch, slice_pitch, + c_wait_for, num_wait_for, + bool(is_blocking) + )) + return _create_instance(Event, ptr_event[0]) + def _create_instance(cls, ptr): ins = cls.__new__(cls) @@ -613,20 +637,103 @@ def get_supported_image_formats(context, flags, image_type): _handle_error(_lib._get_supported_image_formats(context.ptr, flags, image_type, info)) return _generic_info_to_python(info) - class Image(MemoryObject): _id = 'image' - def __init__(self, context, flags, format, *args): - if len(args) == 2: + def __init__(self, *args): + if len(args) == 5: # > (1,2) - desc, hostbuf = args - elif len(args) == 3: - # <= (1,1) - shape, pitches, hostbuf = args + context, flags, format, desc, hostbuf = args + elif len(args) == 6: + # legacy init for CL 1.1 and older + self._init_legacy(*args) + else: assert False + def _init_legacy(self, context, flags, format, shape, pitches, buffer): + if shape is None: + raise LogicError("Image", status_code.INVALID_VALUE, "'shape' must be given") + + c_buf, size = _c_buffer_from_obj(buffer) + + dims = len(shape) + if dims == 2: + width, height = shape + pitch = 0 + if pitches is not None: + try: + pitch, = pitches + except ValueError: + raise LogicError("Image", status_code.INVALID_VALUE, "invalid length of pitch tuple") + + # check buffer size + if buffer is not None and max(pitch, width*format.itemsize)*height > size: + raise LogicError("Image", status_code.INVALID_VALUE, "buffer too small") + + ptr = _ffi.new('void **') + _handle_error(_lib._create_image_2d( + ptr, + context.ptr, + flags, + _ffi.new('struct _cl_image_format *', (format.channel_order, format.channel_data_type, )), + width, height, pitch, + c_buf, + size)) + self.ptr = ptr[0] + elif dims == 3: + width, height, depth = shape + pitch_x, pitch_y = 0, 0 + if pitches is not None: + try: + pitch_x, pitch_y = pitches + except ValueError: + raise LogicError("Image", status_code.INVALID_VALUE, "invalid length of pitch tuple") + + # check buffer size + if buffer is not None and max(max(pitch_x, width*format.itemsize)*height, pitch_y)*depth > size: + raise LogicError("Image", status_code.INVALID_VALUE, "buffer too small") + + ptr = _ffi.new('void **') + _handle_error(_lib._create_image_3d( + ptr, + context.ptr, + flags, + _ffi.new('struct _cl_image_format *', (format.channel_order, format.channel_data_type, )), + width, height, depth, pitch_x, pitch_y, + c_buf, + size)) + self.ptr = ptr[0] + else: + raise LogicError("Image", status_code.INVALID_VALUE, "invalid dimension"); + + def get_image_info(self, param): + info = _ffi.new('generic_info *') + _handle_error(_lib.image__get_image_info(self.ptr, param, info)) + return _generic_info_to_python(info) + + @property + def shape(self): + if self.type == mem_object_type.IMAGE2D: + return (self.width, self.height) + elif self.type == mem_object_type.IMAGE3D: + return (self.width, self.height, self.depth) + else: + raise LogicError("Image", status_code.INVALID_VALUE, "only images have shapes") + +class Sampler(_Common): + _id = 'sampler' + + def __init__(self, context, normalized_coords, addressing_mode, filter_mode): + ptr = _ffi.new('void **') + _handle_error(_lib._create_sampler( + ptr, + context.ptr, + normalized_coords, + addressing_mode, + filter_mode)) + self.ptr = ptr[0] + # class GLTexture(MemoryObject): # _id = 'gl_texture' diff --git a/src/c_wrapper/wrap_cl.cpp b/src/c_wrapper/wrap_cl.cpp index 8c3c027e..19bd9574 100644 --- a/src/c_wrapper/wrap_cl.cpp +++ b/src/c_wrapper/wrap_cl.cpp @@ -61,17 +61,17 @@ throw pyopencl::error(#NAME, status_code); \ } -#define PYOPENCL_CALL_GUARDED_CLEANUP(NAME, ARGLIST) \ - { \ - PYOPENCL_PRINT_CALL_TRACE(#NAME); \ - cl_int status_code; \ - status_code = NAME ARGLIST; \ - if (status_code != CL_SUCCESS) \ - std::cerr \ +#define PYOPENCL_CALL_GUARDED_CLEANUP(NAME, ARGLIST) \ + { \ + PYOPENCL_PRINT_CALL_TRACE(#NAME); \ + cl_int status_code; \ + status_code = NAME ARGLIST; \ + if (status_code != CL_SUCCESS) \ + std::cerr \ << "PyOpenCL WARNING: a clean-up operation failed (dead context maybe?)" \ - << std::endl \ - << #NAME " failed with code " << status_code \ - << std::endl; \ + << std::endl \ + << #NAME " failed with code " << status_code \ + << std::endl; \ } @@ -79,25 +79,25 @@ #if PYOPENCL_CL_VERSION >= 0x1020 -#define PYOPENCL_GET_EXT_FUN(PLATFORM, NAME, VAR) \ - NAME##_fn VAR \ - = (NAME##_fn) \ - clGetExtensionFunctionAddressForPlatform(PLATFORM, #NAME); \ - \ - if (!VAR) \ - throw error(#NAME, CL_INVALID_VALUE, #NAME \ - "not available"); +#define PYOPENCL_GET_EXT_FUN(PLATFORM, NAME, VAR) \ + NAME##_fn VAR \ + = (NAME##_fn) \ + clGetExtensionFunctionAddressForPlatform(PLATFORM, #NAME); \ + \ + if (!VAR) \ + throw error(#NAME, CL_INVALID_VALUE, #NAME \ + "not available"); #else -#define PYOPENCL_GET_EXT_FUN(PLATFORM, NAME, VAR) \ - NAME##_fn VAR \ - = (NAME##_fn) \ - clGetExtensionFunctionAddress(#NAME); \ - \ - if (!VAR) \ - throw error(#NAME, CL_INVALID_VALUE, #NAME \ - "not available"); +#define PYOPENCL_GET_EXT_FUN(PLATFORM, NAME, VAR) \ + NAME##_fn VAR \ + = (NAME##_fn) \ + clGetExtensionFunctionAddress(#NAME); \ + \ + if (!VAR) \ + throw error(#NAME, CL_INVALID_VALUE, #NAME \ + "not available"); #endif @@ -260,23 +260,23 @@ #define PYOPENCL_RETRY_IF_MEM_ERROR(OPERATION) \ { \ - bool failed_with_mem_error = false; \ - try \ - { \ - OPERATION \ - } \ - catch (pyopencl::error &e) \ - { \ - failed_with_mem_error = true; \ - if (!e.is_out_of_memory()) \ - throw; \ - } \ + bool failed_with_mem_error = false; \ + try \ + { \ + OPERATION \ + } \ + catch (pyopencl::error &e) \ + { \ + failed_with_mem_error = true; \ + if (!e.is_out_of_memory()) \ + throw; \ + } \ \ - if (failed_with_mem_error) \ - { \ - /* If we get here, we got an error from CL. - * We should run the Python GC to try and free up - * some memory references. */ \ + if (failed_with_mem_error) \ + { \ + /* If we get here, we got an error from CL. + * We should run the Python GC to try and free up + * some memory references. */ \ run_python_gc(); \ \ /* Now retry the allocation. If it fails again, @@ -300,8 +300,10 @@ run_python_gc(); \ case ::CLASS_BUFFER: OPERATION(BUFFER, buffer); break; \ case ::CLASS_PROGRAM: OPERATION(PROGRAM, program); break; \ case ::CLASS_EVENT: OPERATION(EVENT, event); break; \ - case ::CLASS_GL_BUFFER: OPERATION(GL_BUFFER, gl_buffer); break; \ - case ::CLASS_GL_RENDERBUFFER: OPERATION(GL_RENDERBUFFER, gl_renderbuffer); break; \ + case ::CLASS_GL_BUFFER: OPERATION(GL_BUFFER, gl_buffer); break; \ + case ::CLASS_GL_RENDERBUFFER: OPERATION(GL_RENDERBUFFER, gl_renderbuffer); break; \ + case ::CLASS_IMAGE: OPERATION(IMAGE, image); break; \ + case ::CLASS_SAMPLER: OPERATION(SAMPLER, sampler); break; \ default: throw pyopencl::error("unknown class", CL_INVALID_VALUE); \ } @@ -315,12 +317,14 @@ run_python_gc(); \ #define PYOPENCL_CL_EVENT cl_event #define PYOPENCL_CL_GL_BUFFER cl_mem #define PYOPENCL_CL_GL_RENDERBUFFER cl_mem +#define PYOPENCL_CL_IMAGE cl_mem +#define PYOPENCL_CL_SAMPLER cl_sampler template<class T> std::string tostring(const T& v) { - std::ostringstream ostr; - ostr << v; - return ostr.str(); +std::ostringstream ostr; + ostr << v; + return ostr.str(); } @@ -818,7 +822,7 @@ namespace pyopencl ~context() { PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseContext, - (m_context)); + (m_context)); } cl_context data() const @@ -959,7 +963,7 @@ namespace pyopencl ~command_queue() { PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseCommandQueue, - (m_queue)); + (m_queue)); } const cl_command_queue data() const @@ -1320,24 +1324,24 @@ namespace pyopencl #endif PYOPENCL_GET_INTEGRAL_INFO(Image, data(), param_name, size_t); -// #if PYOPENCL_CL_VERSION >= 0x1020 -// case CL_IMAGE_BUFFER: -// { -// cl_mem param_value; -// PYOPENCL_CALL_GUARDED(clGetImageInfo, (data(), param_name, sizeof(param_value), ¶m_value, 0)); -// if (param_value == 0) -// { -// // no associated memory object? no problem. -// return py::object(); -// } - -// return create_mem_object_wrapper(param_value); -// } - -// case CL_IMAGE_NUM_MIP_LEVELS: -// case CL_IMAGE_NUM_SAMPLES: -// PYOPENCL_GET_INTEGRAL_INFO(Image, data(), param_name, cl_uint); -// #endif +#if PYOPENCL_CL_VERSION >= 0x1020 + // case CL_IMAGE_BUFFER: + // { + // cl_mem param_value; + // PYOPENCL_CALL_GUARDED(clGetImageInfo, (data(), param_name, sizeof(param_value), ¶m_value, 0)); + // if (param_value == 0) + // { + // // no associated memory object? no problem. + // return py::object(); + // } + + // return create_mem_object_wrapper(param_value); + // } + + case CL_IMAGE_NUM_MIP_LEVELS: + case CL_IMAGE_NUM_SAMPLES: + PYOPENCL_GET_INTEGRAL_INFO(Image, data(), param_name, cl_uint); +#endif default: throw error("MemoryObject.get_image_info", CL_INVALID_VALUE); @@ -1366,385 +1370,332 @@ namespace pyopencl } -// // }}} - -// // {{{ image creation - -// inline -// image *create_image( -// context const &ctx, -// cl_mem_flags flags, -// cl_image_format const &fmt, -// py::object shape, -// py::object pitches, -// py::object buffer) -// { -// if (shape.ptr() == Py_None) -// throw pyopencl::error("Image", CL_INVALID_VALUE, -// "'shape' must be given"); - -// void *buf = 0; -// PYOPENCL_BUFFER_SIZE_T len; -// py::object *retained_buf_obj = 0; - -// if (buffer.ptr() != Py_None) -// { -// if (flags & CL_MEM_USE_HOST_PTR) -// { -// if (PyObject_AsWriteBuffer(buffer.ptr(), &buf, &len)) -// throw py::error_already_set(); -// } -// else -// { -// if (PyObject_AsReadBuffer( -// buffer.ptr(), const_cast<const void **>(&buf), &len)) -// throw py::error_already_set(); -// } - -// if (flags & CL_MEM_USE_HOST_PTR) -// retained_buf_obj = &buffer; -// } - -// unsigned dims = py::len(shape); -// cl_int status_code; -// cl_mem mem; -// if (dims == 2) -// { -// size_t width = py::extract<size_t>(shape[0]); -// size_t height = py::extract<size_t>(shape[1]); - -// size_t pitch = 0; -// if (pitches.ptr() != Py_None) -// { -// if (py::len(pitches) != 1) -// throw pyopencl::error("Image", CL_INVALID_VALUE, -// "invalid length of pitch tuple"); -// pitch = py::extract<size_t>(pitches[0]); -// } - -// // check buffer size -// cl_int itemsize = get_image_format_item_size(fmt); -// if (buf && std::max(pitch, width*itemsize)*height > cl_uint(len)) -// throw pyopencl::error("Image", CL_INVALID_VALUE, -// "buffer too small"); - -// PYOPENCL_PRINT_CALL_TRACE("clCreateImage2D"); -// PYOPENCL_RETRY_IF_MEM_ERROR( -// { -// mem = clCreateImage2D(ctx.data(), flags, &fmt, -// width, height, pitch, buf, &status_code); -// if (status_code != CL_SUCCESS) -// throw pyopencl::error("clCreateImage2D", status_code); -// } ); - -// } -// else if (dims == 3) -// { -// size_t width = py::extract<size_t>(shape[0]); -// size_t height = py::extract<size_t>(shape[1]); -// size_t depth = py::extract<size_t>(shape[2]); - -// size_t pitch_x = 0; -// size_t pitch_y = 0; - -// if (pitches.ptr() != Py_None) -// { -// if (py::len(pitches) != 2) -// throw pyopencl::error("Image", CL_INVALID_VALUE, -// "invalid length of pitch tuple"); - -// pitch_x = py::extract<size_t>(pitches[0]); -// pitch_y = py::extract<size_t>(pitches[1]); -// } - -// // check buffer size -// cl_int itemsize = get_image_format_item_size(fmt); -// if (buf && -// std::max(std::max(pitch_x, width*itemsize)*height, pitch_y) -// * depth > cl_uint(len)) -// throw pyopencl::error("Image", CL_INVALID_VALUE, -// "buffer too small"); - -// PYOPENCL_PRINT_CALL_TRACE("clCreateImage3D"); -// PYOPENCL_RETRY_IF_MEM_ERROR( -// { -// mem = clCreateImage3D(ctx.data(), flags, &fmt, -// width, height, depth, pitch_x, pitch_y, buf, &status_code); -// if (status_code != CL_SUCCESS) -// throw pyopencl::error("clCreateImage3D", status_code); -// } ); -// } -// else -// throw pyopencl::error("Image", CL_INVALID_VALUE, -// "invalid dimension"); - -// try -// { -// return new image(mem, false, retained_buf_obj); -// } -// catch (...) -// { -// PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem)); -// throw; -// } -// } - -// #if PYOPENCL_CL_VERSION >= 0x1020 - -// inline -// image *create_image_from_desc( -// context const &ctx, -// cl_mem_flags flags, -// cl_image_format const &fmt, -// cl_image_desc &desc, -// py::object buffer) -// { -// if (buffer.ptr() != Py_None && -// !(flags & (CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR))) -// PyErr_Warn(PyExc_UserWarning, "'hostbuf' was passed, " -// "but no memory flags to make use of it."); - -// void *buf = 0; -// PYOPENCL_BUFFER_SIZE_T len; -// py::object *retained_buf_obj = 0; - -// if (buffer.ptr() != Py_None) -// { -// if (flags & CL_MEM_USE_HOST_PTR) -// { -// if (PyObject_AsWriteBuffer(buffer.ptr(), &buf, &len)) -// throw py::error_already_set(); -// } -// else -// { -// if (PyObject_AsReadBuffer( -// buffer.ptr(), const_cast<const void **>(&buf), &len)) -// throw py::error_already_set(); -// } - -// if (flags & CL_MEM_USE_HOST_PTR) -// retained_buf_obj = &buffer; -// } - -// PYOPENCL_PRINT_CALL_TRACE("clCreateImage"); -// cl_int status_code; -// cl_mem mem = clCreateImage(ctx.data(), flags, &fmt, &desc, buf, &status_code); -// if (status_code != CL_SUCCESS) -// throw pyopencl::error("clCreateImage", status_code); - -// try -// { -// return new image(mem, false, retained_buf_obj); -// } -// catch (...) -// { -// PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem)); -// throw; -// } -// } - -// #endif - -// // }}} - -// // {{{ image transfers - -// inline -// event *enqueue_read_image( -// command_queue &cq, -// image &img, -// py::object py_origin, py::object py_region, -// py::object buffer, -// size_t row_pitch, size_t slice_pitch, -// py::object py_wait_for, -// bool is_blocking) -// { -// PYOPENCL_PARSE_WAIT_FOR; -// COPY_PY_COORD_TRIPLE(origin); -// COPY_PY_REGION_TRIPLE(region); - -// void *buf; -// PYOPENCL_BUFFER_SIZE_T len; - -// if (PyObject_AsWriteBuffer(buffer.ptr(), &buf, &len)) -// throw py::error_already_set(); - -// cl_event evt; - -// PYOPENCL_RETRY_IF_MEM_ERROR( -// PYOPENCL_CALL_GUARDED(clEnqueueReadImage, ( -// cq.data(), -// img.data(), -// PYOPENCL_CAST_BOOL(is_blocking), -// origin, region, row_pitch, slice_pitch, buf, -// PYOPENCL_WAITLIST_ARGS, &evt -// )); -// ); -// PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer); -// } - - - - -// inline -// event *enqueue_write_image( -// command_queue &cq, -// image &img, -// py::object py_origin, py::object py_region, -// py::object buffer, -// size_t row_pitch, size_t slice_pitch, -// py::object py_wait_for, -// bool is_blocking) -// { -// PYOPENCL_PARSE_WAIT_FOR; -// COPY_PY_COORD_TRIPLE(origin); -// COPY_PY_REGION_TRIPLE(region); - -// const void *buf; -// PYOPENCL_BUFFER_SIZE_T len; - -// if (PyObject_AsReadBuffer(buffer.ptr(), &buf, &len)) -// throw py::error_already_set(); - -// cl_event evt; -// PYOPENCL_RETRY_IF_MEM_ERROR( -// PYOPENCL_CALL_GUARDED(clEnqueueWriteImage, ( -// cq.data(), -// img.data(), -// PYOPENCL_CAST_BOOL(is_blocking), -// origin, region, row_pitch, slice_pitch, buf, -// PYOPENCL_WAITLIST_ARGS, &evt -// )); -// ); -// PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer); -// } - - - - -// inline -// event *enqueue_copy_image( -// command_queue &cq, -// memory_object_holder &src, -// memory_object_holder &dest, -// py::object py_src_origin, -// py::object py_dest_origin, -// py::object py_region, -// py::object py_wait_for -// ) -// { -// PYOPENCL_PARSE_WAIT_FOR; -// COPY_PY_COORD_TRIPLE(src_origin); -// COPY_PY_COORD_TRIPLE(dest_origin); -// COPY_PY_REGION_TRIPLE(region); - -// cl_event evt; -// PYOPENCL_RETRY_IF_MEM_ERROR( -// PYOPENCL_CALL_GUARDED(clEnqueueCopyImage, ( -// cq.data(), src.data(), dest.data(), -// src_origin, dest_origin, region, -// PYOPENCL_WAITLIST_ARGS, &evt -// )); -// ); -// PYOPENCL_RETURN_NEW_EVENT(evt); -// } - - - - -// inline -// event *enqueue_copy_image_to_buffer( -// command_queue &cq, -// memory_object_holder &src, -// memory_object_holder &dest, -// py::object py_origin, -// py::object py_region, -// size_t offset, -// py::object py_wait_for -// ) -// { -// PYOPENCL_PARSE_WAIT_FOR; -// COPY_PY_COORD_TRIPLE(origin); -// COPY_PY_REGION_TRIPLE(region); - -// cl_event evt; -// PYOPENCL_RETRY_IF_MEM_ERROR( -// PYOPENCL_CALL_GUARDED(clEnqueueCopyImageToBuffer, ( -// cq.data(), src.data(), dest.data(), -// origin, region, offset, -// PYOPENCL_WAITLIST_ARGS, &evt -// )); -// ); -// PYOPENCL_RETURN_NEW_EVENT(evt); -// } - - - - -// inline -// event *enqueue_copy_buffer_to_image( -// command_queue &cq, -// memory_object_holder &src, -// memory_object_holder &dest, -// size_t offset, -// py::object py_origin, -// py::object py_region, -// py::object py_wait_for -// ) -// { -// PYOPENCL_PARSE_WAIT_FOR; -// COPY_PY_COORD_TRIPLE(origin); -// COPY_PY_REGION_TRIPLE(region); - -// cl_event evt; -// PYOPENCL_RETRY_IF_MEM_ERROR( -// PYOPENCL_CALL_GUARDED(clEnqueueCopyBufferToImage, ( -// cq.data(), src.data(), dest.data(), -// offset, origin, region, -// PYOPENCL_WAITLIST_ARGS, &evt -// )); -// ); -// PYOPENCL_RETURN_NEW_EVENT(evt); -// } - -// // }}} - -// #if PYOPENCL_CL_VERSION >= 0x1020 -// inline -// event *enqueue_fill_image( -// command_queue &cq, -// memory_object_holder &mem, -// py::object color, -// py::object py_origin, py::object py_region, -// py::object py_wait_for -// ) -// { -// PYOPENCL_PARSE_WAIT_FOR; - -// COPY_PY_COORD_TRIPLE(origin); -// COPY_PY_REGION_TRIPLE(region); - -// const void *color_buf; -// PYOPENCL_BUFFER_SIZE_T color_len; - -// if (PyObject_AsReadBuffer(color.ptr(), &color_buf, &color_len)) -// throw py::error_already_set(); - -// cl_event evt; -// PYOPENCL_RETRY_IF_MEM_ERROR( -// PYOPENCL_CALL_GUARDED(clEnqueueFillImage, ( -// cq.data(), -// mem.data(), -// color_buf, origin, region, -// PYOPENCL_WAITLIST_ARGS, &evt -// )); -// ); -// PYOPENCL_RETURN_NEW_EVENT(evt); -// } -// #endif + // }}} + + // {{{ image creation + + inline + image *create_image_2d(context const &ctx, + cl_mem_flags flags, + cl_image_format const &fmt, + size_t width, size_t height, + size_t pitch, + void *buffer, size_t size) + { + cl_int status_code; + cl_mem mem; + void *retained_buf_obj = 0; + if(flags & CL_MEM_USE_HOST_PTR) + retained_buf_obj = buffer; + + PYOPENCL_PRINT_CALL_TRACE("clCreateImage2D"); + // + //PYOPENCL_RETRY_IF_MEM_ERROR( + { + mem = clCreateImage2D(ctx.data(), flags, &fmt, + width, height, pitch, buffer, &status_code); + if (status_code != CL_SUCCESS) + throw pyopencl::error("clCreateImage2D", status_code); + } + //); + + try + { + return new image(mem, false, retained_buf_obj); + } + catch (...) + { + PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem)); + throw; + } + } + + inline + image *create_image_3d(context const &ctx, + cl_mem_flags flags, + cl_image_format const &fmt, + size_t width, size_t height, size_t depth, + size_t pitch_x, size_t pitch_y, + void *buffer, size_t size) + { + cl_int status_code; + cl_mem mem; + void *retained_buf_obj = 0; + if(flags & CL_MEM_USE_HOST_PTR) + retained_buf_obj = buffer; + + PYOPENCL_PRINT_CALL_TRACE("clCreateImage3D"); + // + //PYOPENCL_RETRY_IF_MEM_ERROR( + { + mem = clCreateImage3D(ctx.data(), flags, &fmt, + width, height, depth, pitch_x, pitch_y, buffer, &status_code); + if (status_code != CL_SUCCESS) + throw pyopencl::error("clCreateImage3D", status_code); + } + //); + + try + { + return new image(mem, false, retained_buf_obj); + } + catch (...) + { + PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem)); + throw; + } + } + + + + // #if PYOPENCL_CL_VERSION >= 0x1020 + + // inline + // image *create_image_from_desc( + // context const &ctx, + // cl_mem_flags flags, + // cl_image_format const &fmt, + // cl_image_desc &desc, + // py::object buffer) + // { + // if (buffer.ptr() != Py_None && + // !(flags & (CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR))) + // PyErr_Warn(PyExc_UserWarning, "'hostbuf' was passed, " + // "but no memory flags to make use of it."); + + // void *buf = 0; + // PYOPENCL_BUFFER_SIZE_T len; + // py::object *retained_buf_obj = 0; + + // if (buffer.ptr() != Py_None) + // { + // if (flags & CL_MEM_USE_HOST_PTR) + // { + // if (PyObject_AsWriteBuffer(buffer.ptr(), &buf, &len)) + // throw py::error_already_set(); + // } + // else + // { + // if (PyObject_AsReadBuffer( + // buffer.ptr(), const_cast<const void **>(&buf), &len)) + // throw py::error_already_set(); + // } + + // if (flags & CL_MEM_USE_HOST_PTR) + // retained_buf_obj = &buffer; + // } + + // PYOPENCL_PRINT_CALL_TRACE("clCreateImage"); + // cl_int status_code; + // cl_mem mem = clCreateImage(ctx.data(), flags, &fmt, &desc, buf, &status_code); + // if (status_code != CL_SUCCESS) + // throw pyopencl::error("clCreateImage", status_code); + + // try + // { + // return new image(mem, false, retained_buf_obj); + // } + // catch (...) + // { + // PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem)); + // throw; + // } + // } + + // #endif // }}} + // {{{ image transfers + + inline + event *enqueue_read_image(command_queue &cq, + image &img, + size_t *origin, size_t *region, + void *buffer, size_t size, + size_t row_pitch, size_t slice_pitch, + void **wait_for, uint32_t num_wait_for, + bool is_blocking) + { + PYOPENCL_PARSE_WAIT_FOR; + + cl_event evt; + // TODO + //PYOPENCL_RETRY_IF_MEM_ERROR( + PYOPENCL_CALL_GUARDED(clEnqueueReadImage, + (cq.data(), + img.data(), + PYOPENCL_CAST_BOOL(is_blocking), + origin, region, row_pitch, slice_pitch, buffer, + PYOPENCL_WAITLIST_ARGS, &evt + )); + //); + PYOPENCL_RETURN_NEW_EVENT(evt); + //PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer); + } + + + + + // inline + // event *enqueue_write_image( + // command_queue &cq, + // image &img, + // py::object py_origin, py::object py_region, + // py::object buffer, + // size_t row_pitch, size_t slice_pitch, + // py::object py_wait_for, + // bool is_blocking) + // { + // PYOPENCL_PARSE_WAIT_FOR; + // COPY_PY_COORD_TRIPLE(origin); + // COPY_PY_REGION_TRIPLE(region); + + // const void *buf; + // PYOPENCL_BUFFER_SIZE_T len; + + // if (PyObject_AsReadBuffer(buffer.ptr(), &buf, &len)) + // throw py::error_already_set(); + + // cl_event evt; + // PYOPENCL_RETRY_IF_MEM_ERROR( + // PYOPENCL_CALL_GUARDED(clEnqueueWriteImage, ( + // cq.data(), + // img.data(), + // PYOPENCL_CAST_BOOL(is_blocking), + // origin, region, row_pitch, slice_pitch, buf, + // PYOPENCL_WAITLIST_ARGS, &evt + // )); + // ); + // PYOPENCL_RETURN_NEW_NANNY_EVENT(evt, buffer); + // } + + + + + // inline + // event *enqueue_copy_image( + // command_queue &cq, + // memory_object_holder &src, + // memory_object_holder &dest, + // py::object py_src_origin, + // py::object py_dest_origin, + // py::object py_region, + // py::object py_wait_for + // ) + // { + // PYOPENCL_PARSE_WAIT_FOR; + // COPY_PY_COORD_TRIPLE(src_origin); + // COPY_PY_COORD_TRIPLE(dest_origin); + // COPY_PY_REGION_TRIPLE(region); + + // cl_event evt; + // PYOPENCL_RETRY_IF_MEM_ERROR( + // PYOPENCL_CALL_GUARDED(clEnqueueCopyImage, ( + // cq.data(), src.data(), dest.data(), + // src_origin, dest_origin, region, + // PYOPENCL_WAITLIST_ARGS, &evt + // )); + // ); + // PYOPENCL_RETURN_NEW_EVENT(evt); + // } + + + + + // inline + // event *enqueue_copy_image_to_buffer( + // command_queue &cq, + // memory_object_holder &src, + // memory_object_holder &dest, + // py::object py_origin, + // py::object py_region, + // size_t offset, + // py::object py_wait_for + // ) + // { + // PYOPENCL_PARSE_WAIT_FOR; + // COPY_PY_COORD_TRIPLE(origin); + // COPY_PY_REGION_TRIPLE(region); + + // cl_event evt; + // PYOPENCL_RETRY_IF_MEM_ERROR( + // PYOPENCL_CALL_GUARDED(clEnqueueCopyImageToBuffer, ( + // cq.data(), src.data(), dest.data(), + // origin, region, offset, + // PYOPENCL_WAITLIST_ARGS, &evt + // )); + // ); + // PYOPENCL_RETURN_NEW_EVENT(evt); + // } + + + + + // inline + // event *enqueue_copy_buffer_to_image( + // command_queue &cq, + // memory_object_holder &src, + // memory_object_holder &dest, + // size_t offset, + // py::object py_origin, + // py::object py_region, + // py::object py_wait_for + // ) + // { + // PYOPENCL_PARSE_WAIT_FOR; + // COPY_PY_COORD_TRIPLE(origin); + // COPY_PY_REGION_TRIPLE(region); + + // cl_event evt; + // PYOPENCL_RETRY_IF_MEM_ERROR( + // PYOPENCL_CALL_GUARDED(clEnqueueCopyBufferToImage, ( + // cq.data(), src.data(), dest.data(), + // offset, origin, region, + // PYOPENCL_WAITLIST_ARGS, &evt + // )); + // ); + // PYOPENCL_RETURN_NEW_EVENT(evt); + // } + + // // }}} + + // #if PYOPENCL_CL_VERSION >= 0x1020 + // inline + // event *enqueue_fill_image( + // command_queue &cq, + // memory_object_holder &mem, + // py::object color, + // py::object py_origin, py::object py_region, + // py::object py_wait_for + // ) + // { + // PYOPENCL_PARSE_WAIT_FOR; + + // COPY_PY_COORD_TRIPLE(origin); + // COPY_PY_REGION_TRIPLE(region); + + // const void *color_buf; + // PYOPENCL_BUFFER_SIZE_T color_len; + + // if (PyObject_AsReadBuffer(color.ptr(), &color_buf, &color_len)) + // throw py::error_already_set(); + + // cl_event evt; + // PYOPENCL_RETRY_IF_MEM_ERROR( + // PYOPENCL_CALL_GUARDED(clEnqueueFillImage, ( + // cq.data(), + // mem.data(), + // color_buf, origin, region, + // PYOPENCL_WAITLIST_ARGS, &evt + // )); + // ); + // PYOPENCL_RETURN_NEW_EVENT(evt); + // } + // #endif + +// }}} + // {{{ gl interop @@ -1911,62 +1862,62 @@ namespace pyopencl -// #if defined(cl_khr_gl_sharing) && (cl_khr_gl_sharing >= 1) -// inline -// py::object get_gl_context_info_khr( -// py::object py_properties, -// cl_gl_context_info param_name, -// py::object py_platform -// ) -// { -// std::vector<cl_context_properties> props -// = parse_context_properties(py_properties); - -// typedef CL_API_ENTRY cl_int (CL_API_CALL -// *func_ptr_type)(const cl_context_properties * /* properties */, -// cl_gl_context_info /* param_name */, -// size_t /* param_value_size */, -// void * /* param_value */, -// size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; - -// func_ptr_type func_ptr; - -// #if PYOPENCL_CL_VERSION >= 0x1020 -// if (py_platform.ptr() != Py_None) -// { -// platform &plat = py::extract<platform &>(py_platform); - -// func_ptr = (func_ptr_type) clGetExtensionFunctionAddressForPlatform( -// plat.data(), "clGetGLContextInfoKHR"); -// } -// else -// { -// PYOPENCL_DEPRECATED("get_gl_context_info_khr with platform=None", "2013.1", ); - -// func_ptr = (func_ptr_type) clGetExtensionFunctionAddress( -// "clGetGLContextInfoKHR"); -// } -// #else -// func_ptr = (func_ptr_type) clGetExtensionFunctionAddress( -// "clGetGLContextInfoKHR"); -// #endif - - -// if (!func_ptr) -// throw error("Context.get_info", CL_INVALID_PLATFORM, -// "clGetGLContextInfoKHR extension function not present"); - -// cl_context_properties *props_ptr -// = props.empty( ) ? NULL : &props.front(); - -// switch (param_name) -// { -// case CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR: -// { -// cl_device_id param_value; -// PYOPENCL_CALL_GUARDED(func_ptr, -// (props_ptr, param_name, sizeof(param_value), ¶m_value, 0)); -// return py::object(handle_from_new_ptr( new device(param_value, /*retain*/ true))); + // #if defined(cl_khr_gl_sharing) && (cl_khr_gl_sharing >= 1) + // inline + // py::object get_gl_context_info_khr( + // py::object py_properties, + // cl_gl_context_info param_name, + // py::object py_platform + // ) + // { + // std::vector<cl_context_properties> props + // = parse_context_properties(py_properties); + + // typedef CL_API_ENTRY cl_int (CL_API_CALL + // *func_ptr_type)(const cl_context_properties * /* properties */, + // cl_gl_context_info /* param_name */, + // size_t /* param_value_size */, + // void * /* param_value */, + // size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0; + + // func_ptr_type func_ptr; + + // #if PYOPENCL_CL_VERSION >= 0x1020 + // if (py_platform.ptr() != Py_None) + // { + // platform &plat = py::extract<platform &>(py_platform); + + // func_ptr = (func_ptr_type) clGetExtensionFunctionAddressForPlatform( + // plat.data(), "clGetGLContextInfoKHR"); + // } + // else + // { + // PYOPENCL_DEPRECATED("get_gl_context_info_khr with platform=None", "2013.1", ); + + // func_ptr = (func_ptr_type) clGetExtensionFunctionAddress( + // "clGetGLContextInfoKHR"); + // } + // #else + // func_ptr = (func_ptr_type) clGetExtensionFunctionAddress( + // "clGetGLContextInfoKHR"); + // #endif + + + // if (!func_ptr) + // throw error("Context.get_info", CL_INVALID_PLATFORM, + // "clGetGLContextInfoKHR extension function not present"); + + // cl_context_properties *props_ptr + // = props.empty( ) ? NULL : &props.front(); + + // switch (param_name) + // { + // case CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR: + // { + // cl_device_id param_value; + // PYOPENCL_CALL_GUARDED(func_ptr, + // (props_ptr, param_name, sizeof(param_value), ¶m_value, 0)); + // return py::object(handle_from_new_ptr( new device(param_value, /*retain*/ true))); // } // case CL_DEVICES_FOR_GL_CONTEXT_KHR: @@ -2156,7 +2107,75 @@ namespace pyopencl // }}} // }}} - + // {{{ sampler + class sampler // : boost::noncopyable + { + private: + cl_sampler m_sampler; + + public: + sampler(context const &ctx, bool normalized_coordinates, + cl_addressing_mode am, cl_filter_mode fm) + { + cl_int status_code; + PYOPENCL_PRINT_CALL_TRACE("clCreateSampler"); + m_sampler = clCreateSampler( + ctx.data(), + normalized_coordinates, + am, fm, &status_code); + + if (status_code != CL_SUCCESS) + throw pyopencl::error("Sampler", status_code); + } + + sampler(cl_sampler samp, bool retain) + : m_sampler(samp) + { + if (retain) + PYOPENCL_CALL_GUARDED(clRetainSampler, (samp)); + } + + ~sampler() + { + PYOPENCL_CALL_GUARDED_CLEANUP(clReleaseSampler, (m_sampler)); + } + + cl_sampler data() const + { + return m_sampler; + } + + PYOPENCL_EQUALITY_TESTS(sampler); + + generic_info get_info(cl_sampler_info param_name) const + { + switch (param_name) + { + case CL_SAMPLER_REFERENCE_COUNT: + PYOPENCL_GET_INTEGRAL_INFO(Sampler, m_sampler, param_name, + cl_uint); + case CL_SAMPLER_CONTEXT: + PYOPENCL_GET_OPAQUE_INFO(Sampler, m_sampler, param_name, + cl_context, context, CONTEXT); + case CL_SAMPLER_ADDRESSING_MODE: + PYOPENCL_GET_INTEGRAL_INFO(Sampler, m_sampler, param_name, + cl_addressing_mode); + case CL_SAMPLER_FILTER_MODE: + PYOPENCL_GET_INTEGRAL_INFO(Sampler, m_sampler, param_name, + cl_filter_mode); + case CL_SAMPLER_NORMALIZED_COORDS: + PYOPENCL_GET_INTEGRAL_INFO(Sampler, m_sampler, param_name, + cl_bool); + + default: + throw error("Sampler.get_info", CL_INVALID_VALUE); + } + } + }; + + // }}} + + // {{{ program class program : public _common //: boost::noncopyable @@ -2413,28 +2432,18 @@ namespace pyopencl (m_kernel, arg_index, loc.size(), 0)); } - // void set_arg_sampler(cl_uint arg_index, sampler const &smp) - // { - // cl_sampler s = smp.data(); - // PYOPENCL_CALL_GUARDED(clSetKernelArg, - // (m_kernel, arg_index, sizeof(cl_sampler), &s)); - // } - - // void set_arg_buf(cl_uint arg_index, py::object py_buffer) - // { - // const void *buf; - // PYOPENCL_BUFFER_SIZE_T len; - - // if (PyObject_AsReadBuffer(py_buffer.ptr(), &buf, &len)) - // { - // PyErr_Clear(); - // throw error("Kernel.set_arg", CL_INVALID_VALUE, - // "invalid kernel argument"); - // } + void set_arg_sampler(cl_uint arg_index, sampler const &smp) + { + cl_sampler s = smp.data(); + PYOPENCL_CALL_GUARDED(clSetKernelArg, + (m_kernel, arg_index, sizeof(cl_sampler), &s)); + } - // PYOPENCL_CALL_GUARDED(clSetKernelArg, - // (m_kernel, arg_index, len, buf)); - // } + void set_arg_buf(cl_uint arg_index, void *buffer, size_t size) + { + PYOPENCL_CALL_GUARDED(clSetKernelArg, + (m_kernel, arg_index, size, buffer)); + } // void set_arg(cl_uint arg_index, py::object arg) // { @@ -2568,8 +2577,7 @@ namespace pyopencl event *enqueue_read_buffer( command_queue &cq, memory_object_holder &mem, - void *buffer, - size_t size, + void *buffer, size_t size, size_t device_offset, void **wait_for, uint32_t num_wait_for, bool is_blocking) @@ -2886,6 +2894,12 @@ void _free2(void **p, uint32_t size) { return 0; } +::error *_create_sampler(void **ptr_sampler, void *ptr_context, int normalized_coordinates, cl_addressing_mode am, cl_filter_mode fm) { + C_HANDLE_ERROR(*ptr_sampler = new pyopencl::sampler(*static_cast<pyopencl::context*>(ptr_context), (bool)normalized_coordinates, am, fm);); + return 0; +} + + ::error *event__get_profiling_info(void *ptr, cl_profiling_info param, generic_info *out) { C_HANDLE_ERROR(*out = static_cast<pyopencl::event*>(ptr)->get_profiling_info(param);); return 0; @@ -2904,14 +2918,29 @@ void _free2(void **p, uint32_t size) { return 0; } -::error *kernel__set_arg_mem_buffer(void *ptr_kernel, cl_uint arg_index, void *ptr_buffer) { - pyopencl::buffer *buf = static_cast<pyopencl::buffer*>(ptr_buffer); - C_HANDLE_ERROR( - static_cast<pyopencl::kernel*>(ptr_kernel)->set_arg_mem(arg_index, *buf); - ); +::error *kernel__set_arg_null(void *ptr_kernel, cl_uint arg_index) { + C_HANDLE_ERROR(static_cast<pyopencl::kernel*>(ptr_kernel)->set_arg_null(arg_index);); return 0; } +::error *kernel__set_arg_mem(void *ptr_kernel, cl_uint arg_index, void *ptr_mem) { + pyopencl::memory_object *mem = static_cast<pyopencl::memory_object*>(ptr_mem); + C_HANDLE_ERROR(static_cast<pyopencl::kernel*>(ptr_kernel)->set_arg_mem(arg_index, *mem);); + return 0; +} + +::error *kernel__set_arg_sampler(void *ptr_kernel, cl_uint arg_index, void *ptr_sampler) { + pyopencl::sampler *sampler = static_cast<pyopencl::sampler*>(ptr_sampler); + C_HANDLE_ERROR(static_cast<pyopencl::kernel*>(ptr_kernel)->set_arg_sampler(arg_index, *sampler);); + return 0; +} + +::error *kernel__set_arg_buf(void *ptr_kernel, cl_uint arg_index, void *buffer, size_t size) { + C_HANDLE_ERROR(static_cast<pyopencl::kernel*>(ptr_kernel)->set_arg_buf(arg_index, buffer, size);); + return 0; +} + + ::error *kernel__get_work_group_info(void *ptr, cl_kernel_work_group_info param, void *ptr_device, generic_info *out) { C_HANDLE_ERROR(*out = static_cast<pyopencl::kernel*>(ptr)->get_work_group_info(param, *static_cast<pyopencl::device*>(ptr_device));); return 0; @@ -2922,6 +2951,22 @@ void _free2(void **p, uint32_t size) { return 0; } +error *_create_image_2d(void **ptr_image, void *ptr_context, cl_mem_flags flags, cl_image_format *fmt, size_t width, size_t height, size_t pitch, void *ptr_buffer, size_t size) { + C_HANDLE_ERROR(*ptr_image = create_image_2d(*static_cast<pyopencl::context*>(ptr_context), flags, *fmt, width, height, pitch, ptr_buffer, size);); + return 0; +} + + +error *_create_image_3d(void **ptr_image, void *ptr_context, cl_mem_flags flags, cl_image_format *fmt, size_t width, size_t height, size_t depth, size_t pitch_x, size_t pitch_y, void *ptr_buffer, size_t size) { + C_HANDLE_ERROR(*ptr_image = create_image_3d(*static_cast<pyopencl::context*>(ptr_context), flags, *fmt, width, height, depth, pitch_x, pitch_y, ptr_buffer, size);); + return 0; +} + +::error *image__get_image_info(void *ptr, cl_image_info param, generic_info *out) { + C_HANDLE_ERROR(*out = static_cast<pyopencl::image*>(ptr)->get_image_info(param);); + return 0; +} + ::error *_enqueue_nd_range_kernel(void **ptr_event, void *ptr_command_queue, void *ptr_kernel, cl_uint work_dim, const size_t *global_work_offset, const size_t *global_work_size, const size_t *local_work_size) { C_HANDLE_ERROR( @@ -2937,32 +2982,38 @@ void _free2(void **p, uint32_t size) { ::error *_enqueue_read_buffer(void **ptr_event, void *ptr_command_queue, void *ptr_memory_object_holder, void *buffer, size_t size, size_t device_offset, void **wait_for, uint32_t num_wait_for, int is_blocking) { - C_HANDLE_ERROR( - *ptr_event = enqueue_read_buffer(*static_cast<pyopencl::command_queue*>(ptr_command_queue), + C_HANDLE_ERROR(*ptr_event = enqueue_read_buffer(*static_cast<pyopencl::command_queue*>(ptr_command_queue), *static_cast<pyopencl::memory_object_holder*>(ptr_memory_object_holder), buffer, size, device_offset, wait_for, num_wait_for, (bool)is_blocking); ); return 0; } -::error *_enqueue_write_buffer(void **ptr_event, void *ptr_command_queue, void *ptr_memory_object_holder, void *buffer, size_t size, size_t device_offset, void **wait_for, uint32_t num_wait_for, int is_blocking) { - C_HANDLE_ERROR( - *ptr_event = enqueue_write_buffer(*static_cast<pyopencl::command_queue*>(ptr_command_queue), - *static_cast<pyopencl::memory_object_holder*>(ptr_memory_object_holder), +::error *_enqueue_write_buffer(void **ptr_event, void *ptr_command_queue, void *ptr_mem, void *buffer, size_t size, size_t device_offset, void **wait_for, uint32_t num_wait_for, int is_blocking) { + C_HANDLE_ERROR(*ptr_event = enqueue_write_buffer(*static_cast<pyopencl::command_queue*>(ptr_command_queue), + *static_cast<pyopencl::memory_object_holder*>(ptr_mem), buffer, size, device_offset, wait_for, num_wait_for, (bool)is_blocking); ); return 0; } ::error *_enqueue_copy_buffer(void **ptr_event, void *ptr_command_queue, void *ptr_src, void *ptr_dst, ptrdiff_t byte_count, size_t src_offset, size_t dst_offset, void **wait_for, uint32_t num_wait_for) { - C_HANDLE_ERROR( - *ptr_event = enqueue_copy_buffer(*static_cast<pyopencl::command_queue*>(ptr_command_queue), + C_HANDLE_ERROR(*ptr_event = enqueue_copy_buffer(*static_cast<pyopencl::command_queue*>(ptr_command_queue), *static_cast<pyopencl::memory_object_holder*>(ptr_src), *static_cast<pyopencl::memory_object_holder*>(ptr_dst), byte_count, src_offset, dst_offset, wait_for, num_wait_for); ); return 0; } + +::error *_enqueue_read_image(void **ptr_event, void *ptr_command_queue, void *ptr_mem, size_t *origin, size_t *region, void *buffer, size_t size, size_t row_pitch, size_t slice_pitch, void **wait_for, uint32_t num_wait_for, int is_blocking) { + C_HANDLE_ERROR(*ptr_event = enqueue_read_image(*static_cast<pyopencl::command_queue*>(ptr_command_queue), + *static_cast<pyopencl::image*>(ptr_mem), + origin, region, buffer, size, row_pitch, slice_pitch, wait_for, num_wait_for, (bool)is_blocking); + ); + return 0; +} + intptr_t _int_ptr(void* ptr, class_t class_) { #define INT_PTR(CLSU, CLS) return (intptr_t)(static_cast<pyopencl::CLS*>(ptr)->data()); diff --git a/src/c_wrapper/wrap_cl_core.h b/src/c_wrapper/wrap_cl_core.h index 22cf2e26..c279df58 100644 --- a/src/c_wrapper/wrap_cl_core.h +++ b/src/c_wrapper/wrap_cl_core.h @@ -18,7 +18,9 @@ typedef enum { CLASS_EVENT, CLASS_COMMAND_QUEUE, CLASS_GL_BUFFER, - CLASS_GL_RENDERBUFFER + CLASS_GL_RENDERBUFFER, + CLASS_IMAGE, + CLASS_SAMPLER } class_t; @@ -42,21 +44,32 @@ error *program__build(void *ptr_program, char *options, cl_uint num_devices, voi error *program__kind(void *ptr_program, int *kind); error *program__get_build_info(void *ptr_program, void *ptr_device, cl_program_build_info param, generic_info *out); +error *_create_sampler(void **ptr_sampler, void *ptr_context, int normalized_coordinates, cl_addressing_mode am, cl_filter_mode fm); + error *event__get_profiling_info(void *ptr_event, cl_profiling_info param, generic_info *out); error *event__wait(void *ptr_event); error *_create_kernel(void **ptr_kernel, void *ptr_program, char *name); -error *kernel__set_arg_mem_buffer(void *ptr_kernel, cl_uint arg_index, void *ptr_buffer); +error *kernel__set_arg_null(void *ptr_kernel, cl_uint arg_index); +error *kernel__set_arg_mem(void *ptr_kernel, cl_uint arg_index, void *ptr_mem); +error *kernel__set_arg_sampler(void *ptr_kernel, cl_uint arg_index, void *ptr_sampler); +error *kernel__set_arg_buf(void *ptr_kernel, cl_uint arg_index, void *buffer, size_t size); + error *kernel__get_work_group_info(void *ptr_kernel, cl_kernel_work_group_info param, void *ptr_device, generic_info *out); error *_get_supported_image_formats(void *ptr_context, cl_mem_flags flags, cl_mem_object_type image_type, generic_info *out); +error *_create_image_2d(void **ptr_image, void *ptr_context, cl_mem_flags flags, cl_image_format *fmt, size_t width, size_t height, size_t pitch, void *ptr_buffer, size_t size); +error *_create_image_3d(void **ptr_image, void *ptr_context, cl_mem_flags flags, cl_image_format *fmt, size_t width, size_t height, size_t depth, size_t pitch_x, size_t pitch_y, void *ptr_buffer, size_t size); +error *image__get_image_info(void *ptr_image, cl_image_info param, generic_info *out); + long _hash(void *ptr_platform, class_t); error *_enqueue_nd_range_kernel(void **ptr_event, void *ptr_command_queue, void *ptr_kernel, cl_uint work_dim, const size_t *global_work_offset, const size_t *global_work_size, const size_t *local_work_size); -error *_enqueue_read_buffer(void **ptr_event, void *ptr_command_queue, void *ptr_memory_object_holder, void *buffer, size_t size, size_t device_offset, void **wait_for, uint32_t num_wait_for, int is_blocking); +error *_enqueue_read_buffer(void **ptr_event, void *ptr_command_queue, void *ptr_mem, void *buffer, size_t size, size_t device_offset, void **wait_for, uint32_t num_wait_for, int is_blocking); error *_enqueue_copy_buffer(void **ptr_event, void *ptr_command_queue, void *ptr_src, void *ptr_dst, ptrdiff_t byte_count, size_t src_offset, size_t dst_offset, void **wait_for, uint32_t num_wait_for); error *_enqueue_write_buffer(void **ptr_event, void *ptr_command_queue, void *ptr_memory_object_holder, void *buffer, size_t size, size_t device_offset, void **wait_for, uint32_t num_wait_for, int is_blocking); +error *_enqueue_read_image(void **ptr_event, void *ptr_command_queue, void *ptr_mem, size_t *origin, size_t *region, void *buffer, size_t size, size_t row_pitch, size_t slice_pitch, void **wait_for, uint32_t num_wait_for, int is_blocking); void populate_constants(void(*add)(const char*, const char*, long value)); intptr_t _int_ptr(void*, class_t); -- GitLab