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

Mak*_*gan 15 c++ opengl multithreading

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

有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();
};
Run Code Online (Sandbox Code Playgroud)

并且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;
Run Code Online (Sandbox Code Playgroud)

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

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

void Renderer::add_data(Render_Info* data)
{
    busy_queue.lock();
    render_queue.push_back(data);
    busy_queue.unlock();
}
Run Code Online (Sandbox Code Playgroud)

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

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

问题是,我只是试图创建OpenGL VAO和VBO而产生分段错误,更不用说填充数据了.

据我所知,OpenGL远离线程安全,因为长颈鹿不是海豚.

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

那么我可以做多线程程序呢?

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

Par*_*rni 5

对OpenGL的要求是为渲染创建的上下文应该由任何给定点的单个线程拥有,拥有上下文的线程应该使其成为当前,然后调用任何gl相关的函数.如果你这样做而没有拥有并使上下文变为当前,则会出现分段错误.默认情况下,上下文将是主线程的当前内容.因此,要使程序具有多线程,您有两种选择.

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

    Thread_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();
    
    Run Code Online (Sandbox Code Playgroud)

    Thread_2:

    wglMakeCurrent(dc, glrc2);
    
    DoWork();
    
    Run Code Online (Sandbox Code Playgroud)
  2. 其他选项是为每个线程创建一个上下文,并在线程启动时使其成为当前.喜欢以下

    Thread_1:

    wglMakeCurrent(NULL, NULL);
    
    WaitForThread2(); OrDoSomeCPUJob();
    
    wglMakeCurrent(dc, glrc);
    
    Run Code Online (Sandbox Code Playgroud)

    Thread_2:

    wglMakeCurrent(dc, glrc);
    
    DoSome_GL_Work();
    
    wglMakeCurrent(NULL, NULL);
    
    Run Code Online (Sandbox Code Playgroud)

希望这可以解决问题.