簡體   English   中英

OpenCL/OpenGL 互操作性紋理段錯誤

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM