What is the correct way to get OpenCL to play nice with OpenGL in Qt5?

匿名 (未验证) 提交于 2019-12-03 01:36:02

问题:

I have found several unofficial sources for how to get OpenCL to play nice with OpenGL and Qt5, each with different levels of complexity:

Having these examples is nice, however they don't answer the following question: What exact steps are the minimum required to have a Qt5 widgets program display the result of a calculation made in OpenCL kernel and then transferred directly to attached OpenGL context initiated by Qt5?

Sub-questions include:

  • What is the correct way to expose the OpenGL context in Qt5 to OpenCL?
  • How do I initiate my Qt5 app in the first place to make sure that the OpenGL context is correctly set up for use with OpenCL?
  • How should OpenCL be initiated to be compatible with the OpenGL context in Qt5?
  • What quirks must I look out for to have this working across the platforms that Qt5 supports?
  • Is there such a thing as an "official" way to do this, or is Digia working on one?

Note, I am primarily interested in using OpenGL as a widget as opposed to a window/full-screen.

回答1:

I have used Qt5 and OpenCL together on mac, linux and windows with the following strategy:

  1. Create a QGLWidget and GL context (this example creates two GL context, one for Qt/visualization in the QGLwidget and one for OpenCL called mainGLContext, useful when doing multi-threading. These two context will be able to share data.)
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; }
  1. Often you want to do multi-threading, having one thread do the Qt event handling, while doing some OpenCL processing in another thread. Remember to make the GL context "current" in each thread. Use the makeCurrent and moveToThread function on the QGLContext object for this. You can find details on how I have done this here: https://github.com/smistad/FAST/blob/master/source/FAST/Visualization/Window.cpp

  2. I don't know of a Qt OpenCL wrapper to create the OpenCL context.



回答2:

After working on this some more I felt compelled to add some more info. Erik Smistad's answer is correct and will remain accepted, however it is only one of several ways to do this.

Based on this article there are at least 3 ways we can have OpenGL vs. OpenCL interop:

  1. Sharing an OpenGL texture directly with OpenCL. PROS: Fastest route since everything is zero-copy. CONS: Severely limits available supported data formats.
  2. Sharing an OpenGL PBO with OpenCL and copy from this into a Texture. Second quickest, but will force the need for a memory copy.
  3. Mapping output buffer in OpenCL to host memory and uploading texture from there. Slowest when using OpenCL on GPU. Fastest when using OpenCL on CPU. Forces data to be copied to host memory and back. Most flexible with respect to available data formats.


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!