c++ - 在多线程程序中创建 OpenGL 结构?

标签 c++ multithreading opengl

我正在尝试在我正在构建的物理引擎中执行以下操作:

有 2 个线程,一个用于世界逻辑,一个用于渲染。

主线程(创建其他线程的线程)是渲染线程,然后世界线程是从它派生出来的。

在渲染线程上有一个名为渲染处理程序的全局数据结构声明为:

 class Renderer
{
    private:
        /*
          shader stuff
        */
        mutex busy_queue;
        vector<Render_Info*> render_queue;

    public:
        /*
           Bunch of methods
        */
        void add_data(Render_Info*);
        void render();
};

并且一个 Render_Info 结构被声明为:

struct Render_Info
{
    mutex info_lock;
    GLuint VAO;
    vector<GLuint> VBOs;
    vector<GLuint> types;
    uint layouts;
    uint render_instances;
    Mesh* geometry;
};

extern Renderer *Rendering_Handler;

这里的想法如下。任何希望渲染某些东西的线程都必须处理它自己的数据并将其放入 OpenGL 原语中。然后它将该信息放入 Render_Info 对象中,该对象充当线程和渲染线程之间的消息。

线程然后使用 add_data() 方法发送一个指向它的数据消息的指针,该数据消息被附加到 render_queue 为:

void Renderer::add_data(Render_Info* data)
{
    busy_queue.lock();
    render_queue.push_back(data);
    busy_queue.unlock();
}

最后,当渲染线程选择渲染某些东西时,它会锁定队列(防止任何东西被添加到队列中)渲染所有内容,然后清除队列。

现在当然需要更多的线程协调,但这就是这个想法的要点。

问题是,我只是因为尝试创建 OpenGL VAO 和 VBO 而遇到段错误,更不用说用数据填充它们了。

根据我的阅读,OpenGL 与线程安全相去甚远。 长颈鹿来自海豚。

问题的原因似乎是 OpenGL 上下文属于主线程,所以当我尝试在世界线程上创建 VAO 和 VBO 时,OpenGL 只会崩溃,因为它不知道发生了什么。

那我该怎么做多线程程序呢?

我希望尽可能接近我所描述的设计,除非有人提供了很好的理由说明为什么它不起作用。

最佳答案

OpenGL 的要求是为渲染创建的上下文应该在任何给定点由单个线程拥有,拥有上下文的线程应该使其成为当前的,然后调用任何与 gl 相关的函数。如果你在没有拥有和使上下文成为当前的情况下这样做,那么你会遇到段错误。默认情况下,主线程的上下文将是当前的。因此,要使您的程序多线程,您有两种选择。

  1. 创建两个上下文并在它们之间共享纹理对象 VAO 等资源。这种方法的优点是您可以在线程 2 中引用在线程 1 中创建的任何 VAO,并且它不会崩溃。

    线程_1:

    glrc1=wglCreateContext(dc);
    
    glrc2=wglCreateContext(dc);
    
    BOOL error=wglShareLists(glrc1, glrc2);
    
    if(error == FALSE)
    {
    
    //Unable to share contexts so delete context and safe return 
    
    }
    
    wglMakeCurrent(dc, glrc1);
    
    DoWork();
    

    线程_2:

    wglMakeCurrent(dc, glrc2);
    
    DoWork();
    
  2. 另一种选择是为每个线程创建一个上下文,并在线程启动时使其成为当前上下文。喜欢关注

    线程_1:

    wglMakeCurrent(NULL, NULL);
    
    WaitForThread2(); OrDoSomeCPUJob();
    
    wglMakeCurrent(dc, glrc);
    

    线程_2:

    wglMakeCurrent(dc, glrc);
    
    DoSome_GL_Work();
    
    wglMakeCurrent(NULL, NULL);
    

希望这能解决问题。

关于c++ - 在多线程程序中创建 OpenGL 结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47918078/

相关文章:

c++ - 带有 pthreads 和 mutexes 的 OpenCV

c++ - 在 C++ 中处理存储在 double 中的大整数时如何避免舍入/精度错误?

c++ - OpenGL 状态集

opengl - OpenGL 是否消除了没有绑定(bind)顶点缓冲区的顶点着色器?

c++ - 更改类模板成员可见性

java - 通过 JNI 将我的 Java API 扩展到 C++ : How to wrap a method returning a String?

java - java system.in可以在不使用线程的情况下同时与输入源代码一起工作吗

ASP.net 用户数据在访问对象的用户之间交叉

linux - 在进程之间传递消息

c++ - 计算与加载 OpenGL 法线