让OpenCL在Qt5中与OpenGL发挥良好的正确方法是什么?



我找到了几个非官方的资源,关于如何让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,策略如下:

  1. 创建QGLWidget和GL上下文(本例创建两个GL上下文,一个用于QGLWidget中的Qt/可视化,另一个用于OpenCL,称为mainGLContext,在执行多线程时很有用。这两个上下文将能够共享数据)
QGLWidget* widget = new QGLWidget;
QGLContext* mainGLContext = new QGLContext(QGLFormat::defaultFormat(), widget);
mainGLContext->create();
  1. 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的互操作:

    1. 直接与OpenCL共享OpenGL纹理。优点:最快的路线,因为一切都是零复制。缺点:严重限制可用的支持数据格式。
    2. 与OpenCL共享OpenGL PBO,并将其复制到纹理中。第二快,但将强制需要内存副本。
    3. 将OpenCL中的输出缓冲区映射到主机内存并从那里上传纹理。在GPU上使用OpenCL时最慢。在CPU上使用OpenCL时速度最快。强制将数据复制到主机内存并复制回来。最灵活的可用数据格式。

    相关内容

    最新更新