[Andreas Kloeckner] Re: OpenGL Interoperability
by Andreas Kloeckner
Hi Paolo,
On Tue, 15 Jun 2010 12:02:07 +0200, Paolo Simone Gasparello <djgaspa(a)gmail.=
com> wrote:
> Hi guys, anyone got OpenGL interoperability work?
> With the following patch I'm able to create a context sharing OpenGL
> buffers.
Applied, thanks. (And I'm kind of embarrassed that you had to fix these
two...) :)
> Where fun_double is a kernel included in the file program.cl that simply
> does each coord *=3D 2.
>=20
> There are better ways to do this? I tryed to perform the cast to
> c_void_p in C++ code using boost::python, but I was not able to make the
> code work.
I took a look, and it doesn't seem like ctypes has much in the way of
C-accessible interface. One can of course emulate the Python code in
C++, but I'm not sure that's necessary. If you'd like guidance on how to
do that, let me know.
Lastly, would you mind posting a fully functional example so that I can
add it to the examples/ directory shipped with PyOpenCL? I think that
could be rather helpful for people trying to follow in your footsteps.
Thanks for your work!
Andreas
9 years, 5 months
OpenGL Interoperability
by Paolo Simone Gasparello
Hi guys, anyone got OpenGL interoperability work?
With the following patch I'm able to create a context sharing OpenGL
buffers.
=== begin patch ===
diff --git a/src/wrapper/wrap_cl.cpp b/src/wrapper/wrap_cl.cpp
index 161bc16..f19d3b6 100644
--- a/src/wrapper/wrap_cl.cpp
+++ b/src/wrapper/wrap_cl.cpp
@@ -756,7 +756,7 @@ BOOST_PYTHON_MODULE(_cl)
"GLBuffer", py::no_init)
.def("__init__", make_constructor(create_from_gl_buffer,
py::default_call_policies(),
- (py::args("context", "flags" "bufobj"))))
+ (py::args("context", "flags", "bufobj"))))
.def("get_gl_object_info", get_gl_object_info)
;
}
@@ -767,7 +767,7 @@ BOOST_PYTHON_MODULE(_cl)
"GLRenderBuffer", py::no_init)
.def("__init__", make_constructor(create_from_gl_renderbuffer,
py::default_call_policies(),
- (py::args("context", "flags" "bufobj"))))
+ (py::args("context", "flags", "bufobj"))))
.def("get_gl_object_info", get_gl_object_info)
;
}
diff --git a/src/wrapper/wrap_cl.hpp b/src/wrapper/wrap_cl.hpp
index c9fb1eb..5f12d70 100644
--- a/src/wrapper/wrap_cl.hpp
+++ b/src/wrapper/wrap_cl.hpp
@@ -637,20 +637,24 @@ namespace pyopencl
py::extract<cl_context_properties>(prop_tuple[0]);
props.push_back(prop);
- if (prop == CL_CONTEXT_PLATFORM
+ if (prop == CL_CONTEXT_PLATFORM)
+ {
+ py::extract<const platform &> value(prop_tuple[1]);
+ props.push_back(
+ reinterpret_cast<cl_context_properties>(value().data()));
+ }
#if defined(cl_khr_gl_sharing) && (cl_khr_gl_sharing >= 1)
- || prop == CL_GL_CONTEXT_KHR
+ else if (prop == CL_GL_CONTEXT_KHR
|| prop == CL_EGL_DISPLAY_KHR
|| prop == CL_GLX_DISPLAY_KHR
|| prop == CL_WGL_HDC_KHR
|| prop == CL_CGL_SHAREGROUP_KHR
+ )
+ {
+ py::extract<cl_context_properties> value(prop_tuple[1]);
+ props.push_back(value);
+ }
#endif
- )
- {
- py::extract<const platform &> value(prop_tuple[1]);
- props.push_back(
- reinterpret_cast<cl_context_properties>(value().data()));
- }
else
throw error("Context", CL_INVALID_VALUE, "invalid context
property");
}
=== end patch ===
The python code I used in my example is this:
from PyQt4.QtOpenGL import QGLWidget
from OpenGL.GL import *
import OpenGL.platform
try:
from OpenGL.WGL import wglGetCurrentDisplay as GetCurrentDisplay,
wglGetCurrentContext as GetCurrentContext
except:
pass
try:
from OpenGL.GLX import glXGetCurrentDisplay as GetCurrentDisplay,
glXGetCurrentContext as GetCurrentContext
except:
pass
import pyopencl as cl
import numpy
class Viewer(QGLWidget):
def __init__(self, parent=None):
QGLWidget.__init__(self, parent)
def initializeGL(self):
with open('program.cl', 'r') as f:
src = f.read()
gl_ctx = ctypes.cast(GetCurrentContext(), ctypes.c_void_p).value
display = ctypes.cast(GetCurrentDisplay(),
ctypes.c_void_p).value
p = cl.get_platforms()
ctx_props = cl.context_properties
props = [(ctx_props.PLATFORM, p[0]), (ctx_props.GL_CONTEXT_KHR,
gl_ctx), (ctx_props.GLX_DISPLAY_KHR, display)]
ctx = cl.Context(properties=props)
glClearColor(1, 1, 1, 1)
glColor(0, 1, 0)
self.vbo = glGenBuffers(2)
coords = numpy.array([[0, 0, 0], [1, 0, 0], [0.5, 1, 0]],
dtype='float32')
glBindBuffer(GL_ARRAY_BUFFER, self.vbo[0])
glBufferData(GL_ARRAY_BUFFER, coords, GL_STATIC_DRAW)
glEnableClientState(GL_VERTEX_ARRAY)
glVertexPointer(3, GL_FLOAT, 0, None)
flags = cl.mem_flags.READ_WRITE
vbo_id = self.vbo[0]
coords_dev = cl.GLBuffer(ctx, flags, int(vbo_id))
prog = cl.Program(ctx, src).build()
queue = cl.CommandQueue(ctx)
cl.enqueue_acquire_gl_objects(queue, [coords_dev])
prog.fun_double(queue, (9,), coords_dev)
cl.enqueue_release_gl_objects(queue, [coords_dev])
queue.finish()
glFlush()
Where fun_double is a kernel included in the file program.cl that simply
does each coord *= 2.
There are better ways to do this? I tryed to perform the cast to
c_void_p in C++ code using boost::python, but I was not able to make the
code work.
--
Paolo Simone Gasparello <djgaspa(a)gmail.com>
9 years, 5 months