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_queue
as:
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会崩溃,因为它不知道发生了什么.
那么我可以做多线程程序呢?
我希望保持尽可能接近我所描述的设计,除非有人提供一个很好的理由说明为什么它不起作用.
对OpenGL的要求是为渲染创建的上下文应该由任何给定点的单个线程拥有,拥有上下文的线程应该使其成为当前,然后调用任何gl相关的函数.如果你这样做而没有拥有并使上下文变为当前,则会出现分段错误.默认情况下,上下文将是主线程的当前内容.因此,要使程序具有多线程,您有两种选择.
创建两个上下文并共享资源,如纹理对象之间的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)其他选项是为每个线程创建一个上下文,并在线程启动时使其成为当前.喜欢以下
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)希望这可以解决问题.