【问题标题】:Multiple OpenGLX rendering contexts fail on Linux with proprietary Nvidia Drivers在具有专有 Nvidia 驱动程序的 Linux 上,多个 OpenGLX 渲染上下文失败
【发布时间】:2017-07-21 10:42:39
【问题描述】:

当我尝试在单个线程上运行超过 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 上。我无法使用 Intel 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;
}

构建并运行:

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

【问题讨论】:

  • 可能是驱动程序错误,但更可能的是驱动程序只是拒绝分发这么多上下文并简单地在那里设置硬限制。 您为什么首先要创建这么多上下文? 我认为没有充分的理由需要这么多。 OpenGL 上下文的创建成本有点高,在它们之间切换也不便宜。
  • 哦,你为什么还要创建那么多线程呢?除非你的机器有超过 100 个 CPU 线程,否则这是没有意义的。
  • 你是对的。使用这么多线程/上下文绝对不是最佳的,但它只是当前实现完整渲染管道的方式。大多数线程大部分时间都在休眠。如果我们无法找到解决此限制的方法,我们将不得不探索减少线程/上下文计数的选项。
  • 感觉限制来自驱动程序。我们尝试了不同的 Nvidia Tesla/GTX GPU,结果相同。

标签: c++ linux opengl nvidia glx


【解决方案1】:

正如 cmets 中所讨论的,您似乎遇到了驱动程序限制,因为您正在做一些非常不寻常和意想不到的事情。我正在回答这个问题以将其从未回答的问题列表中删除。

【讨论】:

  • 我同意你的看法。也就是说,这个问题似乎已经收集到足够的反馈/需求。如果有人提出解决方案或可靠的解决方法,我宁愿保留这个问题。
猜你喜欢
  • 2015-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-30
  • 1970-01-01
相关资源
最近更新 更多