diff --git a/pyopencl/c_wrapper/wrap_cl_core.h b/pyopencl/c_wrapper/wrap_cl_core.h index dba7fa339ff6549e292854a24714de30789e2f59..6494a460b41fdf175426d9e022368ae973e4fc89 100644 --- a/pyopencl/c_wrapper/wrap_cl_core.h +++ b/pyopencl/c_wrapper/wrap_cl_core.h @@ -114,6 +114,9 @@ error *create_image_3d(clobj_t *image, clobj_t 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 *buffer); +error *create_image_from_desc(clobj_t *img, clobj_t _ctx, cl_mem_flags flags, + cl_image_format *fmt, cl_image_desc *desc, + void *buffer); error *image__get_image_info(clobj_t img, cl_image_info param, generic_info *out); type_t image__get_fill_type(clobj_t img); diff --git a/pyopencl/cffi_cl.py b/pyopencl/cffi_cl.py index df55ec7a957a94d6e43675587865c017a2a9a06d..386e8d474d25e60c33b48317bcc7736e852eaaac 100644 --- a/pyopencl/cffi_cl.py +++ b/pyopencl/cffi_cl.py @@ -1168,6 +1168,7 @@ if _lib.have_gl(): # {{{ ImageFormat +# FIXME class ImageFormat(object): def __new__(cls, channel_order=0, channel_type=0): args = [channel_order, channel_type] @@ -1261,7 +1262,7 @@ def get_supported_image_formats(context, flags, image_type): def _write_only_property(*arg): return property().setter(*arg) -class ImageDescriptor: +class ImageDescriptor(object): def __init__(self): self.ptr = _ffi.new("cl_image_desc*") @property @@ -1290,22 +1291,24 @@ class ImageDescriptor: self.ptr.num_samples = n @_write_only_property def shape(self, shape): - if len(shape) > 3: + l = len(shape) + if l > 3: raise LogicError("shape has too many components", status_code.INVALID_VALUE, "transfer") desc = self.ptr - desc.image_width = shape[0]; - desc.image_height = shape[1]; - desc.image_depth = shape[2]; - desc.image_array_size = shape[2]; + desc.image_width = shape[0] if l > 0 else 1 + desc.image_height = shape[1] if l > 1 else 1 + desc.image_depth = shape[2] if l > 2 else 1 + desc.image_array_size = desc.image_depth; @_write_only_property def pitches(self, pitches): - if len(pitches) > 2: + l = len(pitches) + if l > 2: raise LogicError("pitches has too many components", status_code.INVALID_VALUE, "transfer") desc = self.ptr - desc.image_row_pitch = pitches[0]; - desc.image_slice_pitch = pitches[1]; + desc.image_row_pitch = pitches[0] if l > 0 else 1 + desc.image_slice_pitch = pitches[1] if l > 1 else 1 @_write_only_property def buffer(self, buff): self.ptr.buffer = buff.ptr.int_ptr if buff else _ffi.NULL @@ -1324,14 +1327,32 @@ class Image(MemoryObject): elif len(args) == 6: # <= 1.1 self.__init_legacy(*args) - else: assert False def __init_1_2(self, context, flags, fmt, desc, hostbuf): - # TODO - pass + if hostbuf is not None and not mem_flags._use_host(flags): + warnings.warn("'hostbuf' was passed, but no memory flags " + "to make use of it.") + + if hostbuf is None: + c_buf, size = _ffi.NULL, 0 + else: + need_retain = mem_flags._hold_host(flags) + c_buf, size, retained_buf = _c_buffer_from_obj( + hostbuf, writable=mem_flags._host_writable(flags), + retain=need_retain) + if need_retain: + self.__retained_buf = retained_buf + + ptr = _ffi.new('clobj_t*') + _handle_error(_lib.create_image_from_desc( + ptr, context.ptr, flags, + _ffi.new('struct _cl_image_format*', + (fmt.channel_order, fmt.channel_data_type)), + desc.ptr, c_buf)) + self.ptr = ptr[0] - def __init_legacy(self, context, flags, format, shape, pitches, hostbuf): + def __init_legacy(self, context, flags, fmt, shape, pitches, hostbuf): if shape is None: raise LogicError("Image", status_code.INVALID_VALUE, "'shape' must be given") @@ -1362,7 +1383,7 @@ class Image(MemoryObject): # check buffer size if (hostbuf is not None and - max(pitch, width * format.itemsize) * height > size): + max(pitch, width * fmt.itemsize) * height > size): raise LogicError("Image", status_code.INVALID_VALUE, "buffer too small") @@ -1370,7 +1391,7 @@ class Image(MemoryObject): _handle_error(_lib.create_image_2d( ptr, context.ptr, flags, _ffi.new('struct _cl_image_format*', - (format.channel_order, format.channel_data_type)), + (fmt.channel_order, fmt.channel_data_type)), width, height, pitch, c_buf)) self.ptr = ptr[0] elif dims == 3: @@ -1385,7 +1406,7 @@ class Image(MemoryObject): # check buffer size if (hostbuf is not None and - (max(max(pitch_x, width * format.itemsize) * + (max(max(pitch_x, width * fmt.itemsize) * height, pitch_y) * depth > size)): raise LogicError("Image", status_code.INVALID_VALUE, "buffer too small") @@ -1394,7 +1415,7 @@ class Image(MemoryObject): _handle_error(_lib.create_image_3d( ptr, context.ptr, flags, _ffi.new('struct _cl_image_format *', - (format.channel_order, format.channel_data_type)), + (fmt.channel_order, fmt.channel_data_type)), width, height, depth, pitch_x, pitch_y, c_buf)) self.ptr = ptr[0] diff --git a/src/c_wrapper/image.cpp b/src/c_wrapper/image.cpp index 49d20ec60200e76c1d3092f921323f84a1f85ce8..c6100e09cab6c799d2c30554c22cb799de47a91a 100644 --- a/src/c_wrapper/image.cpp +++ b/src/c_wrapper/image.cpp @@ -44,66 +44,6 @@ image::get_image_info(cl_image_info param) const } } -// {{{ image creation - -// #if PYOPENCL_CL_VERSION >= 0x1020 - -// PYOPENCL_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(&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 clerror("clCreateImage", status_code); - -// try -// { -// return new image(mem, false, retained_buf_obj); -// } -// catch (...) -// { -// PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem)); -// throw; -// } -// } - -// #endif - -// }}} - // {{{ image transfers // PYOPENCL_INLINE @@ -201,6 +141,23 @@ create_image_3d(clobj_t *img, clobj_t _ctx, cl_mem_flags flags, }); } +#if PYOPENCL_CL_VERSION >= 0x1020 + +error* +create_image_from_desc(clobj_t *img, clobj_t _ctx, cl_mem_flags flags, + cl_image_format *fmt, cl_image_desc *desc, void *buffer) +{ + auto ctx = static_cast(_ctx); + return c_handle_error([&] { + auto mem = pyopencl_call_guarded(clCreateImage, ctx, flags, fmt, + desc, buffer); + *img = new_image(mem, (flags & CL_MEM_USE_HOST_PTR ? + buffer : nullptr), fmt); + }); +} + +#endif + error* image__get_image_info(clobj_t _img, cl_image_info param, generic_info *out) { diff --git a/src/c_wrapper/memory_object.h b/src/c_wrapper/memory_object.h index 0a59a476334a811122887b49225ed183ef3b4139..b9eb25fb5dd58a978d544a53cc02571ffd59c51c 100644 --- a/src/c_wrapper/memory_object.h +++ b/src/c_wrapper/memory_object.h @@ -41,6 +41,7 @@ public: PYOPENCL_USE_RESULT PYOPENCL_INLINE void* hostbuf() const { + // TODO: use this? return m_hostbuf; } PYOPENCL_USE_RESULT size_t