OpenCL / OpenGL互操作性纹理段错误

时间:2016-04-24 18:24:19

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

我试图将OpenCL与OpenGL互操作一起使用。在GPU上计算路径追踪算法,然后将GL纹理绘制为四边形。按照英特尔CPU的预期工作,但当我尝试在GTX 970上运行时解锁GL纹理会出现段错误。 Dunno,如果那是原因或正在运行的内核。我会让代码说明一切。我正在使用OpenCL C ++ wrapper btw。

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);

RunKernel函数

//-----------------------------------------------------------------------------
//  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

核心功能def。

__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。这修复了段错误。

1 个答案:

答案 0 :(得分:2)

我不确定这是你的问题,但无论如何我会试一试。

您没有以可移植的方式同步访问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

的文件的链接