When I try to run over 128 current OpenGLX rendering contexts on individual threads, the call to glXMakeCurrent
starts failing.
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
This issue only occurs with proprietary Nvidia drivers and Nvidia GPUs. I was not able to reproduce with Intel GPUs.
Reproduction code 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 & Run:
g++ -std=c++11 glx.cpp -L/usr/lib/nvidia-375 -lGL -lX11 -lGLU -lGLX -lpthread -o glx && ./glx
As discussed in the comments, it seems you're hitting a driver limitation because you're doing something highly unusual and unexpected. I'm answering this to remove it from the list of unanswered questions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With