如何在不同的线程上调用glReadPixels
How to call glReadPixels on different thread?
当我在另一个线程上调用glReadPixels时,它不会返回任何数据。我在某处读到建议我需要在调用线程中创建一个新的上下文并复制内存。我该怎么做呢?
这是我使用的glReadPixels代码:
pixels = new BYTE[ 3 * width * height];
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels);
image = FreeImage_ConvertFromRawBits(pixels, width, height, 3 * width, 24, 0xFF0000, 0x00FF00, 0x0000FF, false);
FreeImage_Save(FIF_PNG, image, pngpath.c_str() , 0);
或者,我从这个线程中读到他们建议使用另一段代码(见末尾),但我不明白什么是origX, origY, srcOrigX, srcOrigY?
您可以创建共享上下文,这将按照您的预期工作。参见wglShareLists
(这个名字选得很糟糕,它共享的不仅仅是列表)。或者,使用WGL_ARB_create_context
,它也直接支持共享上下文(你已经标记了问题"窗口",但类似的功能也存在于非wgl)。
然而,使用像素缓冲对象要容易得多,这将具有与多线程相同的净效果(传输将异步运行而不会阻塞渲染线程),并且它要简单得多。
你有不同的选择
你调用ReadPixel与渲染线程流水线。在这种情况下,返回的数据应该存储在一个缓冲区中,该缓冲区可以排队到一个专门用于保存图片的线程中。这可以很容易地通过一个缓冲队列,一个互斥锁和一个信号量来完成:渲染线程使用ReadPixel获取数据,锁定互斥锁,进入(系统内存)像素缓冲区,解锁互斥锁,增加信号量;工作线程(锁定在信号量上)将被渲染线程发出信号,锁定互斥锁,从像素缓冲区中取出队列,解锁互斥锁并保存图像。
否则,您可以将当前帧缓冲区复制到纹理或像素缓冲区对象上。在这种情况下,你必须有两个不同的线程,每个线程都有一个OpenGL上下文当前(通过 makeccurrent ),彼此共享它们的对象空间(如user771921所建议的)。当第一个渲染线程调用ReadPixels(或CopyPixels)时,通知第二个线程有关操作(例如使用信号量);第二个渲染线程将映射像素缓冲区对象(或获取纹理数据)。这种方法的优点是允许驱动程序将第一个线程读取操作流水线化,但它实际上通过引入额外的支持缓冲区将内存复制操作增加了一倍。此外,当第二个线程映射缓冲区时,ReadPixel操作将刷新,该操作(很可能)在第二个线程收到信号后执行。
我建议第一个选项,因为它更干净和简单。第二个过于复杂,我怀疑你能从使用它中获得好处:图像保存操作比ReadPixel慢得多。
即使ReadPixel不是流水线的,你的FPS真的变慢了吗?在你可以配置文件之前不要优化。
你链接的例子使用GDI函数,它不是OpenGL相关的。我认为代码会导致重新绘制表单事件,然后捕获窗口客户区内容。与ReadPixel相比,它似乎要慢得多,即使我没有在这个问题上执行任何分析。
嗯,在多线程程序中使用opengl是一个坏主意——特别是如果你在一个没有创建上下文的线程中使用opengl函数。
除此之外,您的代码示例中没有任何错误。
- 如何声明由多个线程调用的 C++ DLL 的内部类,而无需导出类
- 非静态成员失败的线程调用函数
- 线程调用的函数对对象删除是否安全?
- 将类成员函数作为线程调用到另一个类成员函数时发出警告消息
- 通过 Qt 中的线程调用 Rust 库
- Qt信号和插槽如果从QRunnable或其他线程调用,则不起作用
- 在销毁期间从另一个线程调用对象上调用方法是否未定义行为?
- 由并发无序映射查找线程调用的函数是否安全?
- 如何从另一个线程调用颤振引擎方法
- C++ std::线程调用方法,从对象原因到调用此类的析构函数
- 从多个线程调用 std::shuffle
- std::thread::join() 可以从非父线程调用吗?
- 如何使用 Win32 API 从 Excel VBA 中的非"Single-Threaded Apartment"线程调用 InternetGetProxyInfo
- 带参数的线程调用库函数
- 如何在本机C++中跨线程调用(在主线程上回调)
- 如果两个线程调用同一个函数,但函数中的所有变量都是局部变量,我还需要担心线程之间共享数据吗?
- 优雅断言函数不是从多个线程调用的
- 从第二个线程调用Qt信号有效 - >对连接的插槽没有影响
- 包装标准::线程调用函数
- 从 Visual C++ 2010 中的单独线程调用消息框