虽然不可能一次从多个线程调用给定上下文上的 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 */
您现在可以将值写入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);
}
您现在可以删除 PBO pboID或通过为其提供新数据来重新使用它。