我试图将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。这修复了段错误。
答案 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
的文件的链接