diff --git a/doc/make_constants.py b/doc/make_constants.py index e45a064acc707587e3175b5c229e09cbadd73b31..f9df2f36c2970b4861a2e28a9df99f214ca8b148 100644 --- a/doc/make_constants.py +++ b/doc/make_constants.py @@ -3,6 +3,9 @@ import pyopencl as cl def doc_class(cls): print ".. class :: %s" % cls.__name__ print + if cls.__name__.startswith("gl_"): + print " Only available when PyOpenCL is compiled with GL support. See :func:`have_gl`." + print for i in sorted(dir(cls)): if not i.startswith("_") and not i == "to_string": print " .. attribute :: %s" % i @@ -14,6 +17,11 @@ def doc_class(cls): print +if not cl.have_gl(): + print "***************************************************************" + print "WARNING: GL not supported. Incompleted docs will be generated." + print "***************************************************************" + print ".. This is an automatically generated file. DO NOT EDIT" print for cls in cl.CONSTANT_CLASSES: diff --git a/doc/source/misc.rst b/doc/source/misc.rst index a07d964eb69733f3b60c4be90e83f141b8058d93..06a16715fb9581d4bcd50f440ae8d8e27ce19f27 100644 --- a/doc/source/misc.rst +++ b/doc/source/misc.rst @@ -29,6 +29,7 @@ Version 0.91 has changed for this reason. * :meth:`pyopencl.MemoryObject.get_image_info` now actually exists. * Add :meth:`pyopencl.MemoryObject.image`. +* Fixed API tracing. Version 0.90.4 -------------- diff --git a/doc/source/reference.rst b/doc/source/reference.rst index fd0b8049133b3d3c7c3d19818725d6f0b0de9ff1..8a0b91761d4ed33e7db7f13520302921cbdb6acc 100644 --- a/doc/source/reference.rst +++ b/doc/source/reference.rst @@ -51,7 +51,9 @@ Platforms, Devices and Contexts using *"=="* and *"!="*. .. |buf-iface| replace:: must implement the Python buffer interface. (e.g. by being an :class:`numpy.ndarray`) -.. |enqueue-waitfor| replace:: Returns a new :class:`Event`. +.. |enqueue-waitfor| replace:: Returns a new :class:`Event`. *wait_for* + may either be *None* or a list of :class:`Event` instances for + whose completion this command waits before starting exeuction. .. function:: get_platforms() @@ -209,6 +211,16 @@ Memory .. method:: release() + .. method:: get_gl_object_info() + + Return a tuple *(obj_type, obj_name)*, where *obj_type* is one of the + :class:`gl_object_type` constants, and *obj_name* is the GL object + name. + Only available when PyOpenCL is compiled with GL support. See :func:`have_gl`. + + .. method:: get_gl_texture_info(param) + + See :class:`gl_texture_info` for values of *param*. Only available when PyOpenCL is compiled with GL support. See :func:`have_gl`. |comparable| Buffers @@ -409,3 +421,50 @@ Programs and Kernels .. function:: enqueue_task(queue, kernel, wait_for=None) |enqueue-waitfor| + +.. _gl-interop: + +GL Interoperability +------------------- + +Functionality in this section is only available when PyOpenCL is compiled +with GL support. See :func:`have_gl`. + +.. function:: have_gl() + + Return *True* if PyOpenCL was compiled with OpenGL interoperability, otherwise *False*. + +.. function:: create_from_gl_buffer(context, mem_flags, gl_buffer_obj) + + See :class:`mem_flags` for values of *flags*. + Returns a new :class:`MemoryObject`. + +.. function:: create_from_gl_texture_2d(context, mem_flags, texture_target, miplevel, texture) + + See :class:`mem_flags` for values of *flags*. + Returns a new :class:`MemoryObject`. + +.. function:: create_from_gl_texture_3d(context, mem_flags, texture_target, miplevel, texture) + + See :class:`mem_flags` for values of *flags*. + Returns a new :class:`MemoryObject`. + +.. function:: create_from_gl_renderbuffer(context, mem_flags, gl_renderbuffer) + + See :class:`mem_flags` for values of *flags*. + Returns a new :class:`MemoryObject`. + +.. function:: enqueue_acquire_gl_objects(queue, mem_objects, wait_for=None) + + *mem_objects* is a list of :class:`MemoryObject` instances. + |enqueue-waitfor| + +.. function:: enqueue_release_gl_objects(queue, mem_objects, wait_for=None) + + *mem_objects* is a list of :class:`MemoryObject` instances. + |enqueue-waitfor| + +.. seealso:: + + * :meth:`MemoryObject.get_gl_object_info` + * :meth:`MemoryObject.get_gl_texture_info` diff --git a/setup.py b/setup.py index c395f7d1b3488fe5355645656932f1e41760320c..5543bded8b7a076d8eede4683ce6fe0f01629f8a 100644 --- a/setup.py +++ b/setup.py @@ -13,6 +13,7 @@ def get_config_schema(): BoostLibraries("thread"), Switch("CL_TRACE", False, "Enable OpenCL API tracing"), + Switch("CL_ENABLE_GL", False, "Enable OpenCL<->OpenGL interoperability"), Switch("SHIPPED_CL_HEADERS", False, "Use shipped OpenCL headers"), IncludeDir("CL", []), @@ -70,6 +71,9 @@ def main(): ext_kwargs = dict() + if conf["CL_ENABLE_GL"]: + EXTRA_DEFINES["HAVE_GL"] = 1 + ver_dic = {} execfile("pyopencl/version.py", ver_dic) diff --git a/src/wrapper/wrap_cl.cpp b/src/wrapper/wrap_cl.cpp index 5a7d8c993ebbb7e048498a4984d290450b081b64..75ebe35039999ad6c7a380d4d7c2c776f8a4a58f 100644 --- a/src/wrapper/wrap_cl.cpp +++ b/src/wrapper/wrap_cl.cpp @@ -65,8 +65,10 @@ namespace class command_type { }; class command_execution_status { }; class profiling_info { }; -} + class gl_object_type { }; + class gl_texture_info { }; +} @@ -472,6 +474,10 @@ BOOST_PYTHON_MODULE(_cl) .DEF_SIMPLE_METHOD(release) .def(py::self == py::self) .def(py::self != py::self) +#ifdef HAVE_GL + .def("get_gl_object_info", get_gl_object_info) + .def("get_gl_texture_info", get_gl_texture_info) +#endif ; } @@ -631,4 +637,44 @@ BOOST_PYTHON_MODULE(_cl) py::return_value_policy()); // TODO: clEnqueueNativeKernel + + // GL interop --------------------------------------------------------------- + DEF_SIMPLE_FUNCTION(have_gl); + +#ifdef HAVE_GL + { + py::class_ cls("gl_object_type", py::no_init); + ADD_ATTR(GL_OBJECT_, BUFFER); + ADD_ATTR(GL_OBJECT_, TEXTURE2D); + ADD_ATTR(GL_OBJECT_, TEXTURE3D); + ADD_ATTR(GL_OBJECT_, RENDERBUFFER); + } + + { + py::class_ cls("gl_texture_info", py::no_init); + ADD_ATTR(GL_, TEXTURE_TARGET); + ADD_ATTR(GL_, MIPMAP_LEVEL); + } + + py::def("create_from_gl_buffer", create_from_gl_buffer, + py::return_value_policy()); + py::def("create_from_gl_texture_2d", create_from_gl_texture_2d, + py::return_value_policy()); + py::def("create_from_gl_texture_3d", create_from_gl_texture_3d, + py::return_value_policy()); + py::def("create_from_gl_renderbuffer", create_from_gl_renderbuffer, + py::return_value_policy()); + + py::def("enqueue_acquire_gl_objects", enqueue_acquire_gl_objects, + (py::args("queue", "mem_objects"), + py::arg("wait_for")=py::object() + ), + py::return_value_policy()); + py::def("enqueue_release_gl_objects", enqueue_release_gl_objects, + (py::args("queue", "mem_objects"), + py::arg("wait_for")=py::object() + ), + py::return_value_policy()); + +#endif } diff --git a/src/wrapper/wrap_cl.hpp b/src/wrapper/wrap_cl.hpp index 52a615936faedd45a958ea6f33183f49c1a9b2f8..8c03a9b0617d4b9114da65e6857210e8a0d3d34f 100644 --- a/src/wrapper/wrap_cl.hpp +++ b/src/wrapper/wrap_cl.hpp @@ -10,9 +10,22 @@ #ifdef __APPLE__ + +// Mac ------------------------------------------------------------------------ #include +#ifdef HAVE_GL +#include +#endif + #else + +// elsewhere ------------------------------------------------------------------ #include +#ifdef HAVE_GL +#include +#include +#endif + #endif #include @@ -202,6 +215,30 @@ +// buffer creators ------------------------------------------------------------ +#define PYOPENCL_WRAP_BUFFER_CREATOR(NAME, CL_NAME, ARGS, CL_ARGS) \ + memory_object *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 memory_object(mem, false); \ + } \ + catch (...) \ + { \ + PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem)); \ + throw; \ + } \ + } + + + namespace pyopencl @@ -994,28 +1031,9 @@ namespace pyopencl - memory_object *create_buffer( - context &ctx, - cl_mem_flags flags, - size_t size) - { - cl_int status_code; - PYOPENCL_PRINT_CALL_TRACE("clCreateBuffer"); - cl_mem mem = clCreateBuffer(ctx.data(), flags, size, 0, &status_code); - - if (status_code != CL_SUCCESS) - throw pyopencl::error("clCreateBuffer", status_code); - - try - { - return new memory_object(mem, false); - } - catch (...) - { - PYOPENCL_CALL_GUARDED(clReleaseMemObject, (mem)); - throw; - } - } + PYOPENCL_WRAP_BUFFER_CREATOR(create_buffer, clCreateBuffer, + (context &ctx, cl_mem_flags flags, size_t size), + (ctx.data(), flags, size, 0, &status_code)); @@ -1064,7 +1082,6 @@ namespace pyopencl - event *enqueue_read_buffer( command_queue &cq, memory_object &mem, @@ -2043,6 +2060,95 @@ namespace pyopencl PYOPENCL_RETURN_NEW_EVENT(evt); } + + + + + // gl interop --------------------------------------------------------------- + bool have_gl() + { +#ifdef HAVE_GL + return true; +#else + return false; +#endif + } + + + + +#ifdef HAVE_GL + PYOPENCL_WRAP_BUFFER_CREATOR(create_from_gl_buffer, clCreateFromGLBuffer, + (context &ctx, cl_mem_flags flags, GLuint bufobj), + (ctx.data(), flags, bufobj, &status_code)); + PYOPENCL_WRAP_BUFFER_CREATOR(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(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(create_from_gl_renderbuffer, clCreateFromGLRenderbuffer, + (context &ctx, cl_mem_flags flags, GLuint renderbuffer), + (ctx.data(), flags, renderbuffer, &status_code)); + + + + + py::tuple get_gl_object_info(memory_object 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); + } + + + + + py::object get_gl_texture_info(memory_object const &mem, cl_gl_texture_info param_name) + { + switch (param_name) + { + case CL_GL_TEXTURE_TARGET: + PYOPENCL_GET_INTEGRAL_INFO(GLTexture, mem.data(), param_name, GLenum); + case CL_GL_MIPMAP_LEVEL: + PYOPENCL_GET_INTEGRAL_INFO(GLTexture, mem.data(), param_name, GLint); + + default: + throw error("MemoryObject.get_gl_texture_info", CL_INVALID_VALUE); + } + } + + + + +#define WRAP_GL_ENQUEUE(what, What) \ + event *enqueue_##what##_gl_objects( \ + command_queue &cq, \ + py::object py_mem_objects, \ + py::object py_wait_for) \ + { \ + PYOPENCL_PARSE_WAIT_FOR; \ + \ + std::vector mem_objects; \ + PYTHON_FOREACH(mo, py_mem_objects) \ + mem_objects.push_back(py::extract(mo)().data()); \ + \ + cl_event evt; \ + PYOPENCL_CALL_GUARDED(clEnqueue##What##GLObjects, ( \ + cq.data(), \ + mem_objects.size(), &mem_objects.front(), \ + num_events_in_wait_list, &event_wait_list.front(), &evt \ + )); \ + \ + PYOPENCL_RETURN_NEW_EVENT(evt); \ + } + + WRAP_GL_ENQUEUE(acquire, Acquire); + WRAP_GL_ENQUEUE(release, Release); +#endif } diff --git a/src/wrapper/wrap_helpers.hpp b/src/wrapper/wrap_helpers.hpp index 39a5012b195e0eb8a585b57141d2618019bd5aa1..903cfd3f8724789c80a56bebad57eb43f3b544f5 100644 --- a/src/wrapper/wrap_helpers.hpp +++ b/src/wrapper/wrap_helpers.hpp @@ -116,8 +116,6 @@ namespace py = boost::python; return pyopencl_result; \ } - - namespace { template