Ant*_*onK 1 c++ opengl multithreading boost glut
我希望将我的计算内容放在辅助线程中,同时将主循环保留在主线程中.
例如,我想要一个围绕OY旋转的立方体,并改变纹理.旋转摄像机的空闲功能支持立方体旋转.但我的纹理计算过于复杂,需要一些时间,所以我不能把它们放入空闲状态(每次我的立方体旋转时我都不需要改变纹理).我可以使用foo函数来执行一些计算工作,创建纹素缓冲区并在单独的线程中为多维数据集设置新纹理吗?来自main函数的这段代码不会改变旋转立方体的纹理.
glutIdleFunc(idle);
boost::thread_group tgroup;
tgroup.create_thread(boost::bind(&foo));
glutMainLoop();
tgroup.join_all();
Run Code Online (Sandbox Code Playgroud)
在不同的线程中设置新纹理也存在并发问题吗?
虽然不可能一次从多个线程调用给定上下文的OpenGL操作,但可以使用映射的PBO将纹理缓冲区操作卸载到另一个线程.
在您的(主)OpenGL线程中,为纹理的数据分配一个具有正确大小的像素缓冲对象(PBO),并将其映射到进程内存中.在这种情况下的使用模式是,PBO作为数据的短期中介,即上传到该缓冲区,然后是对该缓冲区的OpenGL访问,然后是缓冲区删除或数据更改; 这是STREAM使用模式.
GLuint pboID;
glGenBuffers(1, &pboID);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboID);
glBufferData(GL_PIXEL_UNPACk_BUFFER, size, NULL, GL_STREAM_DRAW);
void *buffermap = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
glBindBuffer(GL_PIXEL_UNPACk_BUFFER, 0); /* the memory mapping is preserved */
/* queue that pbo for the worker thread to work upon */
Run Code Online (Sandbox Code Playgroud)
您现在可以将值写入指向的内存区域buffermap; 每个线程都可以做到这一点 完成更新缓冲区后,取消映射并使用它将数据加载到纹理中.当存在像素解包缓冲区绑定时,数据参数将glTex[Sub]Image变为基于0的偏移参数,指定缓冲区对象中的偏移位置,从该位置获取数据.
if( workerthread_is_done ) {
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboID);
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
/* prepare a texture object as usual */
glTex[Sub]Image2D(…, NULL);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
Run Code Online (Sandbox Code Playgroud)
您现在可以删除PBO pboID,也可以通过向其提供新数据来重复使用它.