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



我正在尝试将OpenCL与OpenGL互操作一起使用,以在GPU上计算路径跟踪算法,然后将GL纹理绘制为四边形。在英特尔 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。这将修复段错误。

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

您尚未以可移植方式同步对 glObjects 的访问。从 OpenCL 1.1 开始:

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

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

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

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

以下是引用自以下文件的链接: https://www.khronos.org/registry/cl/specs/opencl-1.1.pdf#nameddest=section-9.8.6

正如OP在他们的编辑中已经解释的那样,问题是传递给cl::Context构造函数的CL_GLX_DISPLAY_KHR属性的值无效:

cl_context_properties cps[] = {
    CL_GL_CONTEXT_KHR, (cl_context_properties) gl_context,
    CL_GLX_DISPLAY_KHR, (cl_context_properties) glXGetCurrentDisplay(), <-- make sure that you aren't passing SDL_Window*, for example
    CL_CONTEXT_PLATFORM, (cl_context_properties) (platforms[0])(),
    0
};

在此之后,属性像往常一样与构造函数一起使用:

cl::Context context{CL_DEVICE_TYPE_GPU, cps, nullptr, nullptr, &result};

这个问题的根本原因是,虽然互联网上有大量关于如何创建OpenCL-OpenGL互操作上下文的资源,但几乎所有资源都只涵盖了如何在Windows上做到这一点。对于 X11 系统,信息非常稀缺,需要从各种来源拼凑在一起。

相关内容

  • 没有找到相关文章

最新更新