【问题标题】:OpenCL/OpenGL interoperability texture segfaultOpenCL/OpenGL 互操作性纹理段错误
【发布时间】:2016-08-18 01:14:07
【问题描述】:

我正在尝试将 OpenCL 与 OpenGL 互操作一起使用。在 GPU 上计算路径跟踪算法,然后将 GL 纹理绘制到四边形。在 Intel CPU 上按预期工作,但是当我尝试在 GTX 970 上运行时,解锁 GL 纹理时出现段错误。不知道这是原因还是正在运行的内核。我会让代码自己说话。顺便说一句,我正在使用 OpenCL C++ 包装器。

GL 纹理创建

glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
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_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer);
glBindTexture(GL_TEXTURE_2D, 0); //Unbind texture

CL 纹理分配

m_textureCL = cl::ImageGL(m_context,
        CL_MEM_READ_WRITE, 
        GL_TEXTURE_2D,
        0,
        texture,
        &errCode);

运行内核函数

//-----------------------------------------------------------------------------
//  Lock texture
//-----------------------------------------------------------------------------
std::vector<cl::Memory> glObjects; //Create vector of GL objects to lock
glObjects.push_back(m_textureCL); //Add created CL texture buffer
glFlush(); //Flush GL queue

errCode = m_cmdQueue.enqueueAcquireGLObjects(&glObjects, NULL, NULL);
if(errCode != CL_SUCCESS) {
    std::cerr << "Error locking texture" << errCode << std::endl;
    return errCode;
}
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
//  Run queue
//-----------------------------------------------------------------------------
errCode = m_cmdQueue.enqueueNDRangeKernel(
        m_kernel,
        cl::NullRange,
        cl::NDRange(height*width),
        cl::NullRange,
        NULL,
        NULL);
if(errCode != CL_SUCCESS) {
    std::cerr << "Error running queue: " << errCode << std::endl;
    return errCode;
}
//---------------------------------------


//-----------------------------------------------------------------------------
//  Unlock
//-----------------------------------------------------------------------------
errCode = m_cmdQueue.enqueueReleaseGLObjects(&glObjects, NULL, NULL);
if(errCode != CL_SUCCESS) {
    std::cerr << "Error unlocking texture: " << errCode << std::endl;
    return errCode;
} <<------ Here's where segfault occurs, can't get past this point

内核函数定义

__kernel void RadianceGPU (
    __write_only image2d_t texture,
    other_stuff...)

在内核中写入纹理

write_imagef(
        texture,
        (int2)(x, height-y-1),
        (float4)(
            clamp(framebuffer[id].x, 0.0f, 1.0f),
            clamp(framebuffer[id].y, 0.0f, 1.0f),
            clamp(framebuffer[id].z, 0.0f, 1.0f),
            1.0f) * 1.0f);

有趣的是尽管纹理是 UNSIGNED_BYTE,但 write_imagef() 仍然有效。

编辑: 所以我终于弄清楚是什么导致了这个问题。创建 CL 属性时设置错误的显示。我刚刚从 GLFW 粘贴了那里的窗口,这导致 Nvidia 驱动程序出现问题。您需要使用 glxGetCurrentDisplay 或 glfwGetX11Display。这修复了段错误。

【问题讨论】:

  • 您使用的是哪个版本的 OpenCL?

标签: c++ linux opengl segmentation-fault opencl


【解决方案1】:

我不确定这是你的问题,但我还是会试一试。

您没有以可移植的方式同步访问 glObjects。从 OpenCL 1.1:

在调用 clEnqueueAcquireGLObjects 之前,应用程序必须 确保访问对象的任何挂起的 GL 操作 mem_objects 中指定的已完成。这可以实现 通过发出并等待 glFinish 命令完成可移植 在所有对这些对象有未决引用的 GL 上下文中。 实现可以提供更有效的同步方法;为了 在某些平台上调用 glFlush 的示例可能就足够了,或者 同步可能隐含在线程中,也可能存在 小贩 - 允许在 GL 命令流中放置栅栏并在 CL 命令中等待栅栏完成的特定扩展 队列。请注意,除了 glFinish 之外没有其他同步方法 目前可在 OpenGL 实现之间移植。

基本上 glFinish 是可移植行为所必需的。

在下面已经引用的段落中,有更多可能感兴趣的信息:

同样,在调用 clEnqueueReleaseGLObjects 之后,应用程序 负责确保任何未决的 OpenCL 操作 对 mem_objects 中指定的对象的访问已完成 在执行引用这些的后续 GL 命令之前 对象。这可以通过调用可移植地完成 带有 clEnqueueRelease GL 返回的事件对象的 clWaitForEvents 对象,或者通过调用 clFinish。如上,一些实现 可能会提供更有效的方法。

这里是引用的文档链接:https://www.khronos.org/registry/cl/specs/opencl-1.1.pdf#nameddest=section-9.8.6

【讨论】:

  • 感谢您的回答,有机会我会试一试。困扰我的另一件事是当我分配 CL 纹理时,我无法访问 GL 纹理。当我使用 Nvidia opencl 1.2 和 OpenGL 4.5 时会发生这种情况,但是在 Intel CPU/GPU 和 OpenGL 3.3 上使用 AMD 的 opencl 1.2 时没有任何问题
  • @Nixx 将其作为另一个问题代码发布。
猜你喜欢
  • 1970-01-01
  • 2016-10-31
  • 1970-01-01
  • 2013-07-27
  • 2012-11-22
  • 1970-01-01
  • 2012-04-12
  • 1970-01-01
  • 2019-11-05
相关资源
最近更新 更多