opencl/opengl interop using clCreateFromGLTexture 无法绘制到纹理(纹理
opencl/opengl interop using clCreateFromGLTexture fails to draw to texture (texture black)
设置有点复杂,所以我会尽力详细说明。
首先,我尝试使用 openCL/openGL 互操作。当不使用互操作 cl::ImageGL 时,代码会起作用,因此基础知识就在那里。该项目正在使用 3 个主要的 openGL 上下文(需要花费大量时间才能在其中打开 openCL 上下文)。我正在使用QGLWidgets作为上下文。首先创建一个隐藏的QGLWidget,其他2个共享隐藏的上下文。2 个 QGLWidgets 中的每一个都在自己的线程中运行。隐藏的 QGLWidget 被转移到创建 openCL 上下文的线程中。
QGLFormat qglFormat;
qglFormat.setVersion(3, 3);
qglFormat.setProfile(QGLFormat::CoreProfile);
m_hiddenGl=new GLHiddenWidget(qglFormat);
m_hiddenGl->setVisible(false);
m_view1=new GLWidget(qglFormat, m_hiddenGl);
m_view2=new GLWidget(qglFormat, m_hiddenGl);
...
QThread *processThread=m_process.qThread();
m_hiddenGl->doneCurrent();
m_hiddenGl->context()->moveToThread(processThread);
GLWidget是一个自定义类,它启动自己的线程并移动上下文,GLHiddenWidget再次自定义类,但基本上只是覆盖防止makeCurrent被主线程调用所需的所有函数。
启动时的进程线程内部如下
m_hiddenGl->makeCurrent();
hdc=wglGetCurrentDC();
glHandle=wglGetCurrentContext();
cl_context_properties clContextProps[]={
CL_CONTEXT_PLATFORM, (cl_context_properties)m_openCLPlatform(),
CL_WGL_HDC_KHR, (intptr_t) hdc,
CL_GL_CONTEXT_KHR, (intptr_t) glHandle, 0
};
m_openCLContext=cl::Context(m_openCLDevice, clContextProps, NULL, NULL, &error);
这一切都是一次尝试。从这一点开始,几个内核在传入的数据(即图像)上按顺序执行。所有内核都成功(没有错误),但是使用 openGL 纹理写出数据的一个内核无法写入任何内容。使用 openCL cl::Image2d 时,即使 openCL 上下文创建为互操作,它也能正常工作(生成正确的输出)。
openGL纹理是在创建所有 openGL 上下文和创建 openCL 上下文之后创建的(也与 openCL 上下文位于同一线程中)。在processThread开始时,纹理由隐藏的QGLWidget和glGenTextures生成。然后创建所有内核以及其他 openCL 缓冲区和图像。在内核执行之前,完成以下操作。
if(initBuffer) //runs only if buffer size is changed, allways runs first time
{
m_hiddenGl->makeCurrent();
glBindTexture(GL_TEXTURE_2D, m_texture);
//I have attempted to put data in, result is always black from kernel
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
glFinish();
//m_flags is CL_MEM_READ_WRITE
m_imageGL=cl::ImageGL(m_openCLContext, m_flags, GL_TEXTURE_2D, 0, m_texture, &error);
}
和简化的内核。
__kernel void kernel1(__read_only image2d_t src1, __read_only image2d_t src2, __write_only image2d_t dst)
{
int2 coord=(int2)(get_global_id(0), get_global_id(1));
uint4 value=255;
write_imageui(dst, coord, convert_uint4(value));
}
即使我不显示纹理,图像仍然是黑色的。当使用 cl::Image2d 或 cl::ImageGL 时,图像将从 openCL 读回并保存到硬盘。对于 cl::Image2d,对于 cl::ImageGL 来说是正确的,它是黑色的。
我遇到了同样的问题,并使用write_imagef()
(不要忘记将 RGBA 值除以 255.0
!),而不是在 OpenCL 内核中write_imageui()
解决了它,而无需更改 OpenGL 纹理的像素格式(您可能没有机会这样做,特别是如果它是现有纹理,在大型应用程序的其他地方创建)。
您必须发布更多代码才能找到错误。
无论如何,我写了一个示例程序,它做了一些非常相似的事情。它使用 OpenCL 计算曼德布洛特分形,然后在QGLWidget
内使用 OpenGL 绘制它。来源在这里:https://github.com/kylelutz/compute/blob/master/example/mandelbrot.cpp。
希望有帮助。
正如我上面评论中提到的,我发现我的问题与 openGL 纹理的定义有关。由于我在 openCL 内核中使用了 write_imageui,因此 openGL 纹理必须定义如下:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, width, height, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, NULL);
从那以后,我花了一些时间创建了一个同时使用 openGL/openCL 互操作和线程化 QGLWidgets 的示例程序。你可以在这里阅读我对它的评论 http://www.krazer.com/?p=109 和/或者你可以从 github.com 获取来源
- OpenGL ES 2.0将纹理绘制到屏幕上是行不通的
- OpenGL 2D游戏只绘制第二个精灵纹理而不是第一个
- 基本 GLSL:两个片段着色器彼此相邻,但第一个(绘制纹理)被覆盖
- 如何绘制到目标纹理大于屏幕分辨率的帧缓冲区
- 在使用PI上的OpenGL ES绘制之前,如何旋转纹理
- 在版本 440 核心中绘制具有纹理的立方体的顶点和片段着色器应该是什么
- 为什么我不能在SDL2中绘制纹理
- OpenGL 纹理无法绘制
- 在OpenGL中绘制多个2D纹理
- 使用纹理绘制多个对象不起作用
- 如何使用SKIA SKBITMAP在EGL纹理上绘制文本
- 如果我使用碎片着色器绘制纹理,如何绘制红线
- 在Cocos2dx中绘制手指运动的纹理
- OpenCL-绘制到OpenGL纹理崩溃
- 使用自定义着色器在全屏四边形上从 QGLFramebufferObject 绘制纹理
- 如何绘制一个所有面都有不同纹理的立方体
- 使用纹理,法线和索引列表从VBO绘制OpenGL对象的问题
- OpenGL没有绘制我的纹理精灵
- 在同一个VBO OpenGL上用不同的纹理绘制不同的对象
- SDL2不使用纹理绘制图像