[英]OpenCL/OpenGL interoperability texture segfault
我正在嘗試將 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。 這修復了段錯誤。
我不確定這是你的問題,但無論如何我都會試一試。
您沒有以可移植的方式同步對 glObjects 的訪問。 從 OpenCL 1.1 開始:
在調用 clEnqueueAcquireGLObjects 之前,應用程序必須確保訪問 mem_objects 中指定的對象的任何掛起的 GL 操作都已完成。 這可以通過在所有具有對這些對象的未決引用的 GL 上下文上發出並等待 glFinish 命令完成來可移植地完成。 實現可以提供更有效的同步方法; 例如,在某些平台上,調用 glFlush 可能就足夠了,或者同步可能隱含在一個線程中,或者可能存在特定於供應商的擴展,可以在 GL 命令流中放置一個柵欄並等待該柵欄在 CL 命令隊列中完成. 請注意,此時除了 glFinish 之外,沒有其他同步方法可在 OpenGL 實現之間移植。
基本上,可移植行為需要 glFinish。
在下面已經引用的段落中,有更多可能感興趣的信息:
類似地,在調用 clEnqueueReleaseGLObjects 之后,應用程序負責確保訪問 mem_objects 中指定的對象的任何掛起的 OpenCL 操作在執行引用這些對象的后續 GL 命令之前已經完成。 這可以通過使用 clEnqueueRelease GL 對象返回的事件對象調用 clWaitForEvents 或通過調用 clFinish 可移植地完成。 如上所述,一些實現可能提供更有效的方法。
這是引用自以下文件的鏈接: https : //www.khronos.org/registry/cl/specs/opencl-1.1.pdf#nameddest=section-9.8.6
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.