我找到了几个非官方的资源,关于如何让OpenCL与OpenGL和Qt5一起玩得很好,每个都有不同的复杂程度:
- https://github.com/smistad/Qt-OpenGL-OpenCL-Interoperability
- https://github.com/petoknm/QtOpenCLGLInterop
- http://www.krazer.com/?p=109
有这些例子很好,但是他们没有回答以下问题:有一个Qt5小部件程序显示在OpenCL内核中进行的计算结果,然后直接转移到由Qt5发起的附加的OpenGL上下文所需的最小的确切步骤是什么?
潜在包括:
- 在Qt5中暴露OpenGL上下文的正确方法是什么?
- 我如何在第一时间启动我的Qt5应用程序,以确保OpenGL上下文正确设置为OpenCL使用?
- 如何在Qt5中启动OpenGL以与OpenGL上下文兼容?
- 要在Qt5支持的平台上工作,我必须注意哪些怪癖? 是否有这样一个"官方"的方式来做这件事,或者是Digia正在研究一个?
注意,我主要感兴趣的是使用OpenGL作为一个小部件,而不是一个窗口/全屏。
我在mac, linux和windows上使用Qt5和OpenCL,策略如下:
- 创建QGLWidget和GL上下文(本例创建两个GL上下文,一个用于QGLWidget中的Qt/可视化,另一个用于OpenCL,称为mainGLContext,在执行多线程时很有用。这两个上下文将能够共享数据)
QGLWidget* widget = new QGLWidget;
QGLContext* mainGLContext = new QGLContext(QGLFormat::defaultFormat(), widget);
mainGLContext->create();
- Create an OpenCL context using the OpenGL context. This is platform specific. For linux you use glx, for windows wgl, and mac cgl sharegroups. Below is the function I use to create the context properties for interoperability. The display variable is used on linux and windows and you can get it with glXGetCurrentDisplay() and wglGetCurrentDC().
cl_context_properties* createInteropContextProperties(
const cl::Platform &platform,
cl_context_properties OpenGLContext,
cl_context_properties display) {
#if defined(__APPLE__) || defined(__MACOSX)
CGLSetCurrentContext((CGLContextObj)OpenGLContext);
CGLShareGroupObj shareGroup = CGLGetShareGroup((CGLContextObj)OpenGLContext);
if(shareGroup == NULL)
throw Exception("Not able to get sharegroup");
cl_context_properties * cps = new cl_context_properties[3];
cps[0] = CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE;
cps[1] = (cl_context_properties)shareGroup;
cps[2] = 0;
#else
#ifdef _WIN32
// Windows
cl_context_properties * cps = new cl_context_properties[7];
cps[0] = CL_GL_CONTEXT_KHR;
cps[1] = OpenGLContext;
cps[2] = CL_WGL_HDC_KHR;
cps[3] = display;
cps[4] = CL_CONTEXT_PLATFORM;
cps[5] = (cl_context_properties) (platform)();
cps[6] = 0;
#else
cl_context_properties * cps = new cl_context_properties[7];
cps[0] = CL_GL_CONTEXT_KHR;
cps[1] = OpenGLContext;
cps[2] = CL_GLX_DISPLAY_KHR;
cps[3] = display;
cps[4] = CL_CONTEXT_PLATFORM;
cps[5] = (cl_context_properties) (platform)();
cps[6] = 0;
#endif
#endif
return cps;
}
通常你想做多线程,让一个线程做Qt事件处理,而在另一个线程做一些OpenCL处理。记住在每个线程中使GL上下文是"当前的"。为此,使用QGLContext对象上的makeccurrent和moveToThread函数。你可以在这里找到我是如何做到这一点的详细信息:https://github.com/smistad/FAST/blob/master/source/FAST/Visualization/Window.cpp
我不知道Qt OpenCL包装器来创建OpenCL上下文。
在做了更多的工作之后,我觉得有必要添加一些更多的信息。Erik Smistad的答案是正确的,将继续被接受,但这只是实现这一目标的几种方法之一。
基于这篇文章,我们至少有三种方法可以实现OpenGL和OpenCL的互操作:
- 直接与OpenCL共享OpenGL纹理。优点:最快的路线,因为一切都是零复制。缺点:严重限制可用的支持数据格式。 与OpenCL共享OpenGL PBO,并将其复制到纹理中。第二快,但将强制需要内存副本。
- 将OpenCL中的输出缓冲区映射到主机内存并从那里上传纹理。在GPU上使用OpenCL时最慢。在CPU上使用OpenCL时速度最快。强制将数据复制到主机内存并复制回来。最灵活的可用数据格式。