问题描述
我想要一种非常快速的方法来为我的应用程序捕获openGL帧缓冲区的内容.通常,glReadPixels()用于将帧缓冲区的内容读取到缓冲区中.但这很慢.
I want a really fast way to capture the content of the openGL framebuffer for my application. Generally, glReadPixels() is used for reading the content of framebuffer into a buffer. But this is slow.
我试图通过创建4个线程使用glReadPixels()从4个不同区域读取帧缓冲区来并行化读取帧缓冲区内容的过程.但是由于分段错误,应用程序正在退出.如果我从线程中删除glReadPixels()调用,则应用程序运行正常.
I was trying to parallelise the procees of reading the framebuffer content by creating 4 threads to read framebuffer from 4 different regions using glReadPixels(). But the application is exiting due to segmentation fault. If I remove the glReadPixels() call from threads then application is running properly.
推荐答案
线程不起作用,请避免这种方法.
Threads do not work, abstain from that approach.
正如您所注意到的,创建多个线程失败,因为只有一个线程具有当前的OpenGL上下文.原则上,您可以 在调用glReadPixels
之前使每个工作线程中的上下文成为当前上下文,但这将需要您方面的额外同步(否则,可以在使上下文成为当前上下文和读回来!),而(wgl|glx)MakeCurrent
是一个非常慢的函数,它将严重停止OpenGL.最后,您将做更多的工作 来使事情变慢.
Creating several threads fails, as you have noticed, because only one thread has a current OpenGL context. In principle, you could make the context current in each worker thread before calling glReadPixels
, but this will require extra synchronization from your side (otherwise, a thread could be preempted in between making the context current and reading back!), and (wgl|glx)MakeCurrent
is a terribly slow function that will seriously stall OpenGL. In the end, you'll be doing more work to get something much slower.
没有办法使glReadPixels
更快,但是您可以解耦所花费的时间(即回读异步运行),因此它不会阻塞应用程序并有效地出现以更快"运行.
为此,您要使用像素缓冲区对象.确保正确设置缓冲区标志.
There is no way to make glReadPixels
any faster, but you can decouple the time it takes (i.e. the readback runs asynchronously), so it does not block your application and effectively appears to run "faster".
You want to use a Pixel buffer object for that. Be sure to get the buffer flags correct.
请注意,如果尚未完成完整内容的传输,则映射缓冲区以访问其内容将被 still 阻塞,因此 still 不会更快.为了解决这个问题,您要么必须阅读前一帧,要么使用可以查询以确保已完成的围栅对象.
或者,更简单但更不可靠的是,您可以在glReadPixels
和访问数据之间插入其他工作".这不能保证在您访问数据时传输已完成,因此它仍然可能会阻塞.但是,它可能就可以了,它会可能阻塞更短的时间(因此运行更快").
Note that mapping the buffer to access its contents will still block if the complete contents hasn't finished transferring, so it will still not be any faster. To account for that, you either have to read the previous frame, or use a fence object which you can query to be sure that it's done.
Or, simpler but less reliable, you can insert "some other work" in between glReadPixels
and accessing the data. This will not guarantee that the transfer has finished by the time you access the data, so it may still block. However, it may just work, and it will likely block for a shorter time (thus run "faster").
有很多方法使其变慢 ,例如如果您要求OpenGL进行一些奇怪的转换,或者您使用了错误的缓冲区标志.但是,通常无法提高速度,因为它的速度取决于传输开始之前所有先前的绘制命令是否已经完成,以及数据是否通过PCIe总线传输(具有固定的时间开销和有限的带宽). .
使回读更快"的唯一可行方法是隐藏此延迟.当然,它仍然不会更快,但是您不会感觉到它.
There are plenty of ways of making it slower, e.g. if you ask OpenGL to do some weird conversions or if you use wrong buffer flags. However, generally, there's no way to make it faster since its speed depends on all previous draw commands having finished before the transfer can even start, and the data being transferred over the PCIe bus (which has a fixed time overhead plus a finite bandwidth).
The only viable way of making readbacks "faster" is hiding this latency. It's of course still not faster, but you don't get to feel it.
这篇关于使glReadPixel()运行更快的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!