使用专有的Nvidia驱动程序,Linux上的多个OpenGLX渲染上下文失败

当我尝试在单个线程上运行128个以上的OpenGLX渲染上下文时,调用glXMakeCurrent时会失败。

 Display *display = XOpenDisplay(":0") Window root_win = RootWindow(display, screen); Window win = XCreateWindow (display, root_win, ...) GLXContext context = glXCreateContext(display, visinfo, 0, True); glXMakeCurrent(display, win, context); <---- Fails here on 128th 

这个问题只发生在专有的Nvidia驱动程序和Nvidia GPU上。 我无法用英特尔GPU重现。

复制代码glx.cpp

 #include <GL/gl.h> #include <GL/glu.h> #include <GL/glx.h> #include <GL/glxext.h> #include <string.h> #include <unistd.h> #include <thread> #include <vector> #include <mutex> #include <condition_variable> #include <chrono> #define MAX_CONTEXTS 200; std::mutex mutex; std::condition_variable cond; bool will_stop = false; int numSuccessfulContexts = 0; #define EXIT_IF(condition, ...) if (condition) { printf(__VA_ARGS__); exit(EXIT_FAILURE);} #define RETURN_IF(condition, ...) if (condition) { printf(__VA_ARGS__); stop(); return; } void stop() { std::lock_guard<std::mutex> lk(mutex); will_stop = true; cond.notify_all(); } void createWindow() { /* Init X and GLX */ Display *display = XOpenDisplay(":0.0"); RETURN_IF(!display, "Cannot open X display\n"); int screen = DefaultScreen(display); Window root_win = RootWindow(display, screen); RETURN_IF(!glXQueryExtension(display, 0, 0),"X Server doesn't support GLX extension\n"); /* Pick an FBconfig and visual */ static const int attributeList[] = { None }; int fbcount; GLXFBConfig *fbconfig = glXChooseFBConfig(display, screen, attributeList, &fbcount); EXIT_IF(!fbconfig, "Failed to get GLXFBConfig\n"); XVisualInfo *visinfo = glXGetVisualFromFBConfig(display, *fbconfig); EXIT_IF(!visinfo, "Failed to get XVisualInfo\n"); /* Create the X window */ XSetWindowAttributes winAttr ; winAttr.colormap = XCreateColormap(display, root_win, visinfo->visual, AllocNone); unsigned int mask = CWColormap; Window win = XCreateWindow (display, root_win, 256, 64, 320, 320, 0, visinfo->depth, InputOutput, visinfo->visual, mask, &winAttr) ; /* Create an OpenGL context and attach it to our X window */ GLXContext context = glXCreateContext(display, visinfo, 0, True); EXIT_IF(!context, "Could not create GL context\n"); RETURN_IF(! glXMakeCurrent(display, win, context), "glXMakeCurrent failed 1. \n"); RETURN_IF(!glXIsDirect (display, glXGetCurrentContext()), "Indirect GLX rendering context obtained\n"); RETURN_IF(!glXMakeCurrent(display, win, context), "glXMakeCurrent failed 2.\n"); numSuccessfulContexts++; std::unique_lock<std::mutex> lk(mutex); cond.wait(lk, [] {return will_stop;}); } int main(int argc, char *argv[]) { std::vector<std::thread> ts; printf("Starting, your computer might become unresponsive...\n"); int maxContexts = MAX_CONTEXTS; while (maxContexts--) { ts.push_back(std::thread(&createWindow)); } { std::unique_lock<std::mutex> lk(mutex); cond.wait_for(lk, std::chrono::seconds(10), []{return will_stop;}); } if (!will_stop) { stop(); } for (auto& v: ts) { v.join(); } printf("Done. Max concurrent contexts: %d\n", numSuccessfulContexts); return EXIT_SUCCESS; } 

构build和运行:

 g++ -std=c++11 glx.cpp -L/usr/lib/nvidia-375 -lGL -lX11 -lGLU -lGLX -lpthread -o glx && ./glx 

它完全是驱动程序,一些具体的操作系统具体有多少独立和可共享的上下文允许你创建。 你可以做的是,而不是创建单独的上下文创建有限的上下文,并调用wglShareList(),使他们在线程共享。 由此,在一个线程中创建的所有资源都可以在任何其他线程中访问。 我希望这有帮助。