From 66c2b9e51de13564b5810d677624b2a471a8711a Mon Sep 17 00:00:00 2001 From: Marko Bencun <mbencun@gmail.com> Date: Sat, 7 Sep 2013 23:57:05 +0200 Subject: [PATCH] started work on GL interop --- pyopencl/_cffi.py | 3 + pyopencl/cffi_cl.py | 13 +- src/c_wrapper/Makefile | 4 +- src/c_wrapper/wrap_cl.cpp | 805 ++++++++++++++++++++++++++++++++++- src/c_wrapper/wrap_cl_core.h | 7 +- 5 files changed, 825 insertions(+), 7 deletions(-) diff --git a/pyopencl/_cffi.py b/pyopencl/_cffi.py index 8fc1aa29..f21334a7 100644 --- a/pyopencl/_cffi.py +++ b/pyopencl/_cffi.py @@ -7,6 +7,9 @@ current_directory = os.path.dirname(__file__) _ffi = FFI() _cl_header = """ +/* gl.h */ +typedef unsigned int GLuint; /* 4-byte unsigned */ + /* cl.h */ /* scalar types */ typedef int8_t cl_char; diff --git a/pyopencl/cffi_cl.py b/pyopencl/cffi_cl.py index 1b8d5ef8..7fdf69f8 100644 --- a/pyopencl/cffi_cl.py +++ b/pyopencl/cffi_cl.py @@ -204,7 +204,7 @@ class MemoryObjectHolder(_Common): class MemoryObject(MemoryObjectHolder): pass -class Buffer(MemoryObjectHolder): +class Buffer(MemoryObject): _id = 'buffer' @classmethod @@ -491,3 +491,14 @@ def _create_instance(cls, ptr): ins.ptr = ptr return ins +# gl interop +def have_gl(): + return bool(_lib.have_gl()) + +class GLBuffer(MemoryObject): + _id = 'gl_buffer' + + def __init__(self, context, flags, bufobj): + ptr_buffer = _ffi.new('void **') + _handle_error(_lib._create_gl_buffer(ptr_buffer, context.ptr, flags, bufobj)) + self.ptr = ptr_buffer[0] diff --git a/src/c_wrapper/Makefile b/src/c_wrapper/Makefile index c938d8a6..7424e5de 100644 --- a/src/c_wrapper/Makefile +++ b/src/c_wrapper/Makefile @@ -1,6 +1,6 @@ all: - #g++ -c -Wall -DHAVE_GL=1 -DPYOPENCL_PRETEND_CL_VERSION=4112 -fpic wrap_cl.cpp wrap_constants.cpp bitlog.cpp - g++ -c -Wall -DPYOPENCL_PRETEND_CL_VERSION=4112 -fpic wrap_cl.cpp wrap_constants.cpp bitlog.cpp + g++ -c -Wall -DHAVE_GL=1 -DPYOPENCL_PRETEND_CL_VERSION=4112 -fpic wrap_cl.cpp wrap_constants.cpp bitlog.cpp + #g++ -c -Wall -DPYOPENCL_PRETEND_CL_VERSION=4112 -fpic wrap_cl.cpp wrap_constants.cpp bitlog.cpp g++ -shared -o libwrapcl.so wrap_cl.o wrap_constants.o bitlog.o cp libwrapcl.so ../../pyopencl/ cp wrap_cl_core.h ../../pyopencl/wrap_cl_core.h diff --git a/src/c_wrapper/wrap_cl.cpp b/src/c_wrapper/wrap_cl.cpp index 424d2e71..b374da33 100644 --- a/src/c_wrapper/wrap_cl.cpp +++ b/src/c_wrapper/wrap_cl.cpp @@ -297,6 +297,7 @@ 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; \ default: throw pyopencl::error("unknown class", CL_INVALID_VALUE); \ } @@ -308,6 +309,7 @@ run_python_gc(); \ #define PYOPENCL_CL_BUFFER cl_mem #define PYOPENCL_CL_PROGRAM cl_program #define PYOPENCL_CL_EVENT cl_event +#define PYOPENCL_CL_GL_BUFFER cl_mem template<class T> std::string tostring(const T& v) { @@ -1285,6 +1287,786 @@ namespace pyopencl // }}} + + // {{{ image + + class image : public memory_object + { + public: + image(cl_mem mem, bool retain, void *hostbuf=0) + : memory_object(mem, retain, hostbuf) + { } + + generic_info get_image_info(cl_image_info param_name) const + { + switch (param_name) + { + case CL_IMAGE_FORMAT: + PYOPENCL_GET_INTEGRAL_INFO(Image, data(), param_name, + cl_image_format); + case CL_IMAGE_ELEMENT_SIZE: + case CL_IMAGE_ROW_PITCH: + case CL_IMAGE_SLICE_PITCH: + case CL_IMAGE_WIDTH: + case CL_IMAGE_HEIGHT: + case CL_IMAGE_DEPTH: +#if PYOPENCL_CL_VERSION >= 0x1020 + case CL_IMAGE_ARRAY_SIZE: +#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 + + default: + throw error("MemoryObject.get_image_info", CL_INVALID_VALUE); + } + } + }; + + + + +// // {{{ image formats + +// inline +// cl_image_format *make_image_format(cl_channel_order ord, cl_channel_type tp) +// { +// std::auto_ptr<cl_image_format> result(new cl_image_format); +// result->image_channel_order = ord; +// result->image_channel_data_type = tp; +// return result.release(); +// } + +// inline +// py::list get_supported_image_formats( +// context const &ctx, +// cl_mem_flags flags, +// cl_mem_object_type image_type) +// { +// cl_uint num_image_formats; +// PYOPENCL_CALL_GUARDED(clGetSupportedImageFormats, ( +// ctx.data(), flags, image_type, +// 0, NULL, &num_image_formats)); + +// std::vector<cl_image_format> formats(num_image_formats); +// PYOPENCL_CALL_GUARDED(clGetSupportedImageFormats, ( +// ctx.data(), flags, image_type, +// formats.size(), formats.empty( ) ? NULL : &formats.front(), NULL)); + +// PYOPENCL_RETURN_VECTOR(cl_image_format, formats); +// } + +// inline +// cl_uint get_image_format_channel_count(cl_image_format const &fmt) +// { +// switch (fmt.image_channel_order) +// { +// case CL_R: return 1; +// case CL_A: return 1; +// case CL_RG: return 2; +// case CL_RA: return 2; +// case CL_RGB: return 3; +// case CL_RGBA: return 4; +// case CL_BGRA: return 4; +// case CL_INTENSITY: return 1; +// case CL_LUMINANCE: return 1; +// default: +// throw pyopencl::error("ImageFormat.channel_dtype_size", +// CL_INVALID_VALUE, +// "unrecognized channel order"); +// } +// } + +// inline +// cl_uint get_image_format_channel_dtype_size(cl_image_format const &fmt) +// { +// switch (fmt.image_channel_data_type) +// { +// case CL_SNORM_INT8: return 1; +// case CL_SNORM_INT16: return 2; +// case CL_UNORM_INT8: return 1; +// case CL_UNORM_INT16: return 2; +// case CL_UNORM_SHORT_565: return 2; +// case CL_UNORM_SHORT_555: return 2; +// case CL_UNORM_INT_101010: return 4; +// case CL_SIGNED_INT8: return 1; +// case CL_SIGNED_INT16: return 2; +// case CL_SIGNED_INT32: return 4; +// case CL_UNSIGNED_INT8: return 1; +// case CL_UNSIGNED_INT16: return 2; +// case CL_UNSIGNED_INT32: return 4; +// case CL_HALF_FLOAT: return 2; +// case CL_FLOAT: return 4; +// default: +// throw pyopencl::error("ImageFormat.channel_dtype_size", +// CL_INVALID_VALUE, +// "unrecognized channel data type"); +// } +// } + +// inline +// cl_uint get_image_format_item_size(cl_image_format const &fmt) +// { +// return get_image_format_channel_count(fmt) +// * get_image_format_channel_dtype_size(fmt); +// } + +// // }}} + +// // {{{ 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 + + // }}} + + + + // {{{ gl interop + + +#ifdef HAVE_GL + +#ifdef __APPLE__ + inline + cl_context_properties get_apple_cgl_share_group() + { + CGLContextObj kCGLContext = CGLGetCurrentContext(); + CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup(kCGLContext); + + return (cl_context_properties) kCGLShareGroup; + } +#endif /* __APPLE__ */ + + + + + class gl_buffer : public memory_object + { + public: + gl_buffer(cl_mem mem, bool retain, void *hostbuf=0) + : memory_object(mem, retain, hostbuf) + { } + }; + + + + + class gl_renderbuffer : public memory_object + { + public: + gl_renderbuffer(cl_mem mem, bool retain, void *hostbuf=0) + : memory_object(mem, retain, hostbuf) + { } + }; + + + + + class gl_texture : public image + { + public: + gl_texture(cl_mem mem, bool retain, void *hostbuf=0) + : image(mem, retain, hostbuf) + { } + + generic_info get_gl_texture_info(cl_gl_texture_info param_name) + { + switch (param_name) + { + case CL_GL_TEXTURE_TARGET: + PYOPENCL_GET_INTEGRAL_INFO(GLTexture, data(), param_name, GLenum); + case CL_GL_MIPMAP_LEVEL: + PYOPENCL_GET_INTEGRAL_INFO(GLTexture, data(), param_name, GLint); + + default: + throw error("MemoryObject.get_gl_texture_info", CL_INVALID_VALUE); + } + } + }; + + + + +#define PYOPENCL_WRAP_BUFFER_CREATOR(TYPE, NAME, CL_NAME, ARGS, CL_ARGS) \ + inline \ + TYPE *NAME ARGS \ + { \ + cl_int status_code; \ + PYOPENCL_PRINT_CALL_TRACE(#CL_NAME); \ + cl_mem mem = CL_NAME CL_ARGS; \ + \ + if (status_code != CL_SUCCESS) \ + throw pyopencl::error(#CL_NAME, status_code); \ + \ + try \ + { \ + return new TYPE(mem, false); \ + } \ + catch (...) \ + { \ + PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem)); \ + throw; \ + } \ + } + + + + + PYOPENCL_WRAP_BUFFER_CREATOR(gl_buffer, + create_from_gl_buffer, clCreateFromGLBuffer, + (context &ctx, cl_mem_flags flags, GLuint bufobj), + (ctx.data(), flags, bufobj, &status_code)); + PYOPENCL_WRAP_BUFFER_CREATOR(gl_texture, + create_from_gl_texture_2d, clCreateFromGLTexture2D, + (context &ctx, cl_mem_flags flags, + GLenum texture_target, GLint miplevel, GLuint texture), + (ctx.data(), flags, texture_target, miplevel, texture, &status_code)); + PYOPENCL_WRAP_BUFFER_CREATOR(gl_texture, + create_from_gl_texture_3d, clCreateFromGLTexture3D, + (context &ctx, cl_mem_flags flags, + GLenum texture_target, GLint miplevel, GLuint texture), + (ctx.data(), flags, texture_target, miplevel, texture, &status_code)); + PYOPENCL_WRAP_BUFFER_CREATOR(gl_renderbuffer, + create_from_gl_renderbuffer, clCreateFromGLRenderbuffer, + (context &ctx, cl_mem_flags flags, GLuint renderbuffer), + (ctx.data(), flags, renderbuffer, &status_code)); + + inline + gl_texture *create_from_gl_texture( + context &ctx, cl_mem_flags flags, + GLenum texture_target, GLint miplevel, + GLuint texture, unsigned dims) + { + if (dims == 2) + return create_from_gl_texture_2d(ctx, flags, texture_target, miplevel, texture); + else if (dims == 3) + return create_from_gl_texture_3d(ctx, flags, texture_target, miplevel, texture); + else + throw pyopencl::error("Image", CL_INVALID_VALUE, + "invalid dimension"); + } + + + + + + // inline + // py::tuple get_gl_object_info(memory_object_holder const &mem) + // { + // cl_gl_object_type otype; + // GLuint gl_name; + // PYOPENCL_CALL_GUARDED(clGetGLObjectInfo, (mem.data(), &otype, &gl_name)); + // return py::make_tuple(otype, gl_name); + // } + /* +#define WRAP_GL_ENQUEUE(what, What) \ + inline \ + event *enqueue_##what##_gl_objects( \ + command_queue &cq, \ + py::object py_mem_objects, \ + py::object py_wait_for) \ + { \ + PYOPENCL_PARSE_WAIT_FOR; \ + \ + std::vector<cl_mem> mem_objects; \ + PYTHON_FOREACH(mo, py_mem_objects) \ + mem_objects.push_back(py::extract<memory_object_holder &>(mo)().data()); \ + \ + cl_event evt; \ + PYOPENCL_CALL_GUARDED(clEnqueue##What##GLObjects, ( \ + cq.data(), \ + mem_objects.size(), mem_objects.empty( ) ? NULL : &mem_objects.front(), \ + PYOPENCL_WAITLIST_ARGS, &evt \ + )); \ + \ + PYOPENCL_RETURN_NEW_EVENT(evt); \ + } + + WRAP_GL_ENQUEUE(acquire, Acquire); + WRAP_GL_ENQUEUE(release, Release); +#endif + */ + + + +// #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: + // { + // size_t size; + // PYOPENCL_CALL_GUARDED(func_ptr, + // (props_ptr, param_name, 0, 0, &size)); + + // std::vector<cl_device_id> devices; + + // devices.resize(size / sizeof(devices.front())); + + // PYOPENCL_CALL_GUARDED(func_ptr, + // (props_ptr, param_name, size, + // devices.empty( ) ? NULL : &devices.front(), &size)); + + // py::list result; + // BOOST_FOREACH(cl_device_id did, devices) + // result.append(handle_from_new_ptr( + // new device(did))); + + // return result; + // } + + // default: + // throw error("get_gl_context_info_khr", CL_INVALID_VALUE); + // } + // } + +#endif + + // }}} + + // {{{ buffer @@ -1437,6 +2219,7 @@ namespace pyopencl } + // }}} // }}} @@ -1620,7 +2403,7 @@ namespace pyopencl // #endif }; - + // }}} // {{{ kernel class local_memory @@ -1843,6 +2626,7 @@ namespace pyopencl // #endif }; + // }}} // {{{ buffer transfers @@ -1976,8 +2760,6 @@ namespace pyopencl } - - // }}} inline program *create_program_with_source( context &ctx, @@ -2279,3 +3061,20 @@ int get_cl_version(void) { unsigned bitlog2(unsigned long v) { return pyopencl::bitlog2(v); } + +// {{{ gl interop +int have_gl() { +#ifdef HAVE_GL + return 1; +#else + return 0; +#endif +} + +error *_create_gl_buffer(void **ptr_buffer, void *ptr_context, cl_mem_flags flags, GLuint bufobj) { + pyopencl::context *ctx = static_cast<pyopencl::context*>(ptr_context); + C_HANDLE_ERROR(*ptr_buffer = create_from_gl_buffer(*ctx, flags, bufobj);); + return 0; +} + +// }}} diff --git a/src/c_wrapper/wrap_cl_core.h b/src/c_wrapper/wrap_cl_core.h index f828939b..8b24fed0 100644 --- a/src/c_wrapper/wrap_cl_core.h +++ b/src/c_wrapper/wrap_cl_core.h @@ -16,7 +16,8 @@ typedef enum { CLASS_BUFFER, CLASS_PROGRAM, CLASS_EVENT, - CLASS_COMMAND_QUEUE + CLASS_COMMAND_QUEUE, + CLASS_GL_BUFFER } class_t; @@ -63,3 +64,7 @@ void _free2(void**, uint32_t size); unsigned bitlog2(unsigned long v); +/* gl interop */ + +int have_gl(); +error *_create_gl_buffer(void **ptr_buffer, void *ptr_context, cl_mem_flags flags, GLuint bufobj); -- GitLab