diff --git a/pyopencl/_cffi.py b/pyopencl/_cffi.py index f21334a7f29d10af6e1b29311bf79a989e5bbb52..06c2e9121d8d2abb75c5cb4b108605d78af0d199 100644 --- a/pyopencl/_cffi.py +++ b/pyopencl/_cffi.py @@ -8,8 +8,11 @@ _ffi = FFI() _cl_header = """ /* gl.h */ +typedef unsigned int GLenum; +typedef int GLint; /* 4-byte signed */ 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 7fdf69f8259a627d417a00d8443b198217cfc595..7c7b63bdbf3f11b2f2b6773da9d5e24103f95289 100644 --- a/pyopencl/cffi_cl.py +++ b/pyopencl/cffi_cl.py @@ -433,15 +433,15 @@ def enqueue_nd_range_kernel(queue, kernel, global_work_size, local_work_size, gl )) return _create_instance(Event, ptr_event[0]) -def _c_wait_for(wait_for=None): - if wait_for is None: +def _c_obj_list(objs=None): + if objs is None: return _ffi.NULL, 0 - return _ffi.new('void *[]', [ev.ptr for ev in wait_for]), len(wait_for) + 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) ptr_event = _ffi.new('void **') - c_wait_for, num_wait_for = _c_wait_for(wait_for=wait_for) + c_wait_for, num_wait_for = _c_obj_list(wait_for) _handle_error(_lib._enqueue_read_buffer( ptr_event, queue.ptr, @@ -456,7 +456,7 @@ def _enqueue_read_buffer(queue, mem, buf, device_offset=0, wait_for=None, is_blo def _enqueue_copy_buffer(queue, src, dst, byte_count=-1, src_offset=0, dst_offset=0, wait_for=None): ptr_event = _ffi.new('void **') - c_wait_for, num_wait_for = _c_wait_for(wait_for=wait_for) + c_wait_for, num_wait_for = _c_obj_list(wait_for) _handle_error(_lib._enqueue_copy_buffer( ptr_event, queue.ptr, @@ -472,7 +472,7 @@ def _enqueue_copy_buffer(queue, src, dst, byte_count=-1, src_offset=0, dst_offse 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) ptr_event = _ffi.new('void **') - c_wait_for, num_wait_for = _c_wait_for(wait_for=wait_for) + c_wait_for, num_wait_for = _c_obj_list(wait_for) _handle_error(_lib._enqueue_write_buffer( ptr_event, queue.ptr, @@ -491,7 +491,8 @@ def _create_instance(cls, ptr): ins.ptr = ptr return ins -# gl interop +# {{{ gl interop + def have_gl(): return bool(_lib.have_gl()) @@ -499,6 +500,55 @@ 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] + ptr = _ffi.new('void **') + _handle_error(_lib._create_from_gl_buffer(ptr, context.ptr, flags, bufobj)) + self.ptr = ptr[0] + +class GLRenderBuffer(MemoryObject): + _id = 'gl_renderbuffer' + + def __init__(self, context, flags, bufobj): + ptr = _ffi.new('void **') + _handle_error(_lib._create_from_gl_renderbuffer(ptr, context.ptr, flags, bufobj)) + self.ptr = ptr[0] + + +def _create_gl_enqueue(what): + def enqueue_gl_objects(queue, mem_objects, wait_for=None): + ptr_event = _ffi.new('void **') + c_wait_for, num_wait_for = _c_obj_list(wait_for) + c_mem_objects, num_mem_objects = _c_obj_list(mem_objects) + _handle_error(what( + ptr_event, + queue.ptr, + c_mem_objects, + num_mem_objects, + c_wait_for, + num_wait_for + )) + return _create_instance(Event, ptr_event[0]) + return enqueue_gl_objects + +enqueue_acquire_gl_objects = _create_gl_enqueue(_lib._enqueue_acquire_gl_objects) +enqueue_release_gl_objects = _create_gl_enqueue(_lib._enqueue_release_gl_objects) + +class Image(MemoryObject): + _id = 'image' + + def __init__(self, context, flags, format, *args): + if len(args) == 2: + # > (1,2) + desc, hostbuf = args + elif len(args) == 3: + # <= (1,1) + shape, pitches, hostbuf = args + else: + assert False + +# class GLTexture(MemoryObject): +# _id = 'gl_texture' + +# def __init__(self, context, flags, texture_target, miplevel, texture, dims): +# ptr = _ffi.new('void **') +# _handle_error(_lib._create_from_gl_texture(ptr, context.ptr, flags, texture_target, miplevel, texture, dims)) +# self.ptr = ptr[0] diff --git a/src/c_wrapper/wrap_cl.cpp b/src/c_wrapper/wrap_cl.cpp index b374da33c8dded92f2ebf593fb89f4732472749b..a42497365adfefbbf804c68e9daad895881d7293 100644 --- a/src/c_wrapper/wrap_cl.cpp +++ b/src/c_wrapper/wrap_cl.cpp @@ -192,16 +192,19 @@ info.value = (void*)ar; \ return info; \ } - + // {{{ event helpers -------------------------------------------------------------- -#define PYOPENCL_PARSE_WAIT_FOR \ - std::vector<cl_event> event_wait_list(num_wait_for); \ - { \ - for(unsigned i = 0; i < num_wait_for; ++i) { \ - event_wait_list[i] = static_cast<pyopencl::event*>(wait_for[i])->data(); \ - } \ +#define PYOPENCL_PARSE_OBJECT_LIST(CLS, TYPE, OUT, NAME, NUM) \ + std::vector<TYPE> OUT((NUM)); \ + { \ + for(unsigned i = 0; i < (NUM); ++i) { \ + OUT[i] = static_cast<pyopencl::CLS*>(NAME[i])->data(); \ + } \ } + +#define PYOPENCL_PARSE_WAIT_FOR PYOPENCL_PARSE_OBJECT_LIST(event, cl_event, event_wait_list, wait_for, num_wait_for) + #define PYOPENCL_WAITLIST_ARGS \ num_wait_for, event_wait_list.empty( ) ? NULL : &event_wait_list.front() @@ -298,6 +301,7 @@ run_python_gc(); \ 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; \ default: throw pyopencl::error("unknown class", CL_INVALID_VALUE); \ } @@ -310,6 +314,7 @@ run_python_gc(); \ #define PYOPENCL_CL_PROGRAM cl_program #define PYOPENCL_CL_EVENT cl_event #define PYOPENCL_CL_GL_BUFFER cl_mem +#define PYOPENCL_CL_GL_RENDERBUFFER cl_mem template<class T> std::string tostring(const T& v) { @@ -1920,8 +1925,7 @@ namespace pyopencl (ctx.data(), flags, renderbuffer, &status_code)); inline - gl_texture *create_from_gl_texture( - context &ctx, cl_mem_flags flags, + gl_texture *create_from_gl_texture(context &ctx, cl_mem_flags flags, GLenum texture_target, GLint miplevel, GLuint texture, unsigned dims) { @@ -1946,34 +1950,31 @@ namespace pyopencl // 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); \ + +#define WRAP_GL_ENQUEUE(what, What) \ + inline \ + event *enqueue_##what##_gl_objects(command_queue &cq, \ + void **ptr_mem_objects, \ + uint32_t num_mem_objects, \ + void **wait_for, \ + uint32_t num_wait_for) \ + { \ + PYOPENCL_PARSE_WAIT_FOR; \ + PYOPENCL_PARSE_OBJECT_LIST(memory_object_holder, cl_mem, mem_objects, ptr_mem_objects, num_mem_objects); \ + 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 - */ + @@ -2062,7 +2063,7 @@ namespace pyopencl // } // } -#endif + // #endif // }}} @@ -3071,10 +3072,35 @@ int have_gl() { #endif } -error *_create_gl_buffer(void **ptr_buffer, void *ptr_context, cl_mem_flags flags, GLuint bufobj) { +error *_create_from_gl_buffer(void **ptr, 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; + C_HANDLE_ERROR(*ptr = create_from_gl_buffer(*ctx, flags, bufobj);); + return 0; +} + +error *_create_from_gl_renderbuffer(void **ptr, void *ptr_context, cl_mem_flags flags, GLuint bufobj) { + pyopencl::context *ctx = static_cast<pyopencl::context*>(ptr_context); + C_HANDLE_ERROR(*ptr = create_from_gl_renderbuffer(*ctx, flags, bufobj);); + return 0; +} + +::error *_enqueue_acquire_gl_objects(void **ptr_event, void *ptr_command_queue, void **ptr_mem_objects, uint32_t num_mem_objects, void **wait_for, uint32_t num_wait_for) { + C_HANDLE_ERROR( + *ptr_event = enqueue_acquire_gl_objects(*static_cast<pyopencl::command_queue*>(ptr_command_queue), + ptr_mem_objects, num_mem_objects, + wait_for, num_wait_for); + ); + return 0; +} + +::error *_enqueue_release_gl_objects(void **ptr_event, void *ptr_command_queue, void **ptr_mem_objects, uint32_t num_mem_objects, void **wait_for, uint32_t num_wait_for) { + C_HANDLE_ERROR( + *ptr_event = enqueue_release_gl_objects(*static_cast<pyopencl::command_queue*>(ptr_command_queue), + ptr_mem_objects, num_mem_objects, + wait_for, num_wait_for); + ); + return 0; } + // }}} diff --git a/src/c_wrapper/wrap_cl_core.h b/src/c_wrapper/wrap_cl_core.h index 8b24fed0a175577daf346f67043f133a60b67e35..af3f35a11fb8e9709571a5b6ca666e1b785aa97e 100644 --- a/src/c_wrapper/wrap_cl_core.h +++ b/src/c_wrapper/wrap_cl_core.h @@ -17,7 +17,8 @@ typedef enum { CLASS_PROGRAM, CLASS_EVENT, CLASS_COMMAND_QUEUE, - CLASS_GL_BUFFER + CLASS_GL_BUFFER, + CLASS_GL_RENDERBUFFER } class_t; @@ -67,4 +68,7 @@ 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); +error *_create_from_gl_buffer(void **ptr, void *ptr_context, cl_mem_flags flags, GLuint bufobj); +error *_create_from_gl_renderbuffer(void **ptr, void *ptr_context, cl_mem_flags flags, GLuint bufobj); +error *_enqueue_acquire_gl_objects(void **ptr_event, void *ptr_command_queue, void **ptr_mem_objects, uint32_t num_mem_objects, void **wait_for, uint32_t num_wait_for); +error *_enqueue_release_gl_objects(void **ptr_event, void *ptr_command_queue, void **ptr_mem_objects, uint32_t num_mem_objects, void **wait_for, uint32_t num_wait_for);