OpenGL glutInit():XOpenDisplay()导致分段错误

时间:2016-04-25 14:20:06

标签: c++ linux opengl cuda qemu

我正在执行CUDA API虚拟化项目。该项目基于QEMU超级遮阳板。我使用的是最新版本2.6.0rc3。我已经完成了核心模块,这个问题是关于演示它.QEMU 2.6.0rc3有OpenGL支持。

我在VM上运行了以下程序来测试OpenGL支持&它执行没有任何问题。

#include <GL/freeglut.h>
#include <GL/gl.h>

void renderFunction()
{
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0, 1.0, 1.0);
    glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
    glBegin(GL_POLYGON);
        glVertex2f(-0.5, -0.5);
        glVertex2f(-0.5, 0.5);
        glVertex2f(0.5, 0.5);
        glVertex2f(0.5, -0.5);
    glEnd();
    glFlush();
}
int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE);
    glutInitWindowSize(500,500);
    glutInitWindowPosition(100,100);
    glutCreateWindow("OpenGL - First window demo");
    glutDisplayFunc(renderFunction);
    glewInit();
    glutMainLoop();    
    return 0;
}

我还使用了名为&#34; simpleGL&#34;的NVIDIA样本图形演示。适用于https://developer.nvidia.com/cuda-toolkit-65的CUDA 6.5工具包。该演示使用OpenGL描绘波形和CUDA以进行基础计算以模拟它。当我运行此演示程序时,在glutInit()调用中发生分段错误。这是演示中的相关代码段。

bool initGL(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE);
    glutInitWindowSize(window_width, window_height);
    glutCreateWindow("Cuda GL Interop (VBO)");
    glutDisplayFunc(display);
    glutKeyboardFunc(keyboard);
    glutMotionFunc(motion);
    glutTimerFunc(REFRESH_DELAY, timerEvent,0);

    // initialize necessary OpenGL extensions
    glewInit();

    if (! glewIsSupported("GL_VERSION_2_0 "))
    {
        fprintf(stderr, "ERROR: Support for necessary OpenGL extensions missing.");
        fflush(stderr);
        return false;
    }

    // default initialization
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glDisable(GL_DEPTH_TEST);

    // viewport
    glViewport(0, 0, window_width, window_height);

    // projection
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60.0, (GLfloat)window_width / (GLfloat) window_height, 0.1, 10.0);

    SDK_CHECK_ERROR_GL();

    return true;
}

这是gdb调用堆栈。

#0  0x00007ffff57d2872 in XOpenDisplay ()
   from /usr/lib/x86_64-linux-gnu/libX11.so.6
#1  0x00007ffff76af2a3 in glutInit ()
   from /usr/lib/x86_64-linux-gnu/libglut.so.3
#2  0x000000000040394d in initGL(int, char**) ()
#3  0x0000000000403b6a in runTest(int, char**, char*) ()
#4  0x00000000004037dc in main ()

根据我的研究,当尝试打开窗口时会发生分段错误。我对OpenGL内部工作的了解非常有限,对此方面的一些帮助非常感谢。感谢。

1 个答案:

答案 0 :(得分:1)

  

我正在执行CUDA API虚拟化项目

如果没有NVidia的支持,我怀疑你可以自己做这件事。

你正在做一些以粗鲁的方式发生冲突的事情:

首先,您要在QEmu环境中运行所有内容,这意味着,如果您不通过IOMMU虚拟化将GPU传递到VM,那么CUDA运行时就没有任何内容可以合作。 CUDA旨在直接与GPU对话。

接下来,您将在VM中使用Mesa OpenGL实现。 Mesa有一个专用的后端,可以通过QEmu将OpenGL命令传递给OpenGL实现,并在#34;外部传输。它的。这或多或少是一个远程过程调用,它可以通过X11传输实现间接GLX的相同代码路径。

CUDA内部链接libGL.so,但它期望看到的libGL.是NVidia驱动程序之一,而不是一些任意的libGL.so。由于libcuda.so和libGL.so是同一个驱动程序包的一部分,即NVidia驱动程序。有一定的内部知识和#34;关于特定的libGL.so,相应的libcuda.so已经尝试使用。如果没有正确的libGL,它就会失败。

如果您想在VM中使用CUDA(完全可能),您必须将整个GPU传递到VM中。你可以通过加载pci_stub内核模块,将NVidia GPU配置为连接到存根的设备,然后通过GPU设备启动QEmu VM来实现这一点(实际上它也应该可以通过它进行热插拔,但我从来没有尝试过)。为此,nvidia内核模块必须没有获得GPU的所有权。因此,如果您有多个NVidia GPU并且只想通过它们的一部分,则必须在加载nvidia内核模块之前将这些附加到pci_stub。然后在VM内部,您可以照常使用NVidia驱动程序。