OpenGL中更新纹理的有效方法 [英] Efficient way of updating texture in OpenGL

查看:414
本文介绍了OpenGL中更新纹理的有效方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用OpenGL渲染多个视频流.目前,我正在使用JOGL提供的glTexImage2D并在Swing窗口上进行渲染.为了更新每个视频帧的纹理内容,我正在调用glTexImage2D.我想知道是否有任何更快的方法来更新纹理而无需为每个帧调用glTexImage2D.

I wanted to render multiple video streams using OpenGL. Currently I am performing using glTexImage2D provided by JOGL and rendering on Swing window. For updating texture content for each video frame I am calling glTexImage2D. I want to know is there any faster method to update texture without calling glTexImage2D for each frame.

推荐答案

您将始终使用 glTexImage2D ,但是区别在于数据来自缓冲区对象(

You will always be using glTexImage2D, but with the difference that data comes from a buffer object (what is this?) rather than from a pointer.

更新纹理的慢点不是更新纹理,而是与当前绘制操作和PCIe传输进行同步(阻塞).当您调用 glTexImage 时,OpenGL必须等待直到绘制完最后一帧仍在从纹理中读取的最后一帧为止.在此期间,您的应用程序被阻止并且不执行任何操作(这是必需的,因为否则您可以在OpenGL复制它之前修改或释放所指向的内存!).然后,它必须复制数据并将其传输到图形卡,然后您的应用程序才能继续运行.
虽然不能使该过程更快,但是可以使它异步运行,因此这种等待时间几乎消失了.

What's slow in updating a texture is not updating the texture, but synchronizing (blocking) with the current draw operation, and the PCIe transfer. When you call glTexImage, OpenGL must wait until it is done drawing the last frame during which it is still reading from the texture. During that time, your application is blocked and does nothing (this is necessary because otherwise you could modify or free the memory pointed to before OpenGL can copy it!). Then it must copy the data and transfer it to the graphics card, and only then your application continues to run.
While one can't make that process much faster, one can make it run asynchronously, so this latency pretty much disappears.

对于视频帧,最简单的方法是创建缓冲区名称,将其绑定,然后保留初始化一次.
然后,在随后的每个帧上,通过使用空数据指针调用 glBufferData 来丢弃它初始化,并在其中填充

The easiest way of doing this is to for video frames is to create a buffer name, bind it, and reserve-initialize it once.
Then, on each subsequent frame, discard-initialize it by calling glBufferData with a null data pointer, and fill it either with a non-reserving call, or by mapping the buffer's complete range.

为什么要执行此奇怪的舞蹈而不是简单地覆盖缓冲区,是因为它不会阻塞.OpenGL将同步对缓冲区对象的访问,因此当数据仍在从中读取时,您不会覆盖它们.带有空数据指针的 glBufferData 是一种告诉OpenGL的方式,您实际上并不在乎缓冲区,也不需要使用相同缓冲区.因此,它将分配另一个,然后再给您一个,继续从旧版本中读取内容,并在完成时秘密地交换它们.

The reason why you want to do this strange dance instead of simply overwriting the buffer is that this will not block. OpenGL will synchronize access to buffer objects so you do not overwrite data while it is still reading from it. glBufferData with a null data pointer is a way of telling OpenGL that you don't really care about the buffer and that you don't necessary want the same buffer. So it will just allocate another one and give you that one, keep reading from the old one, and secretly swap them when it's done.

由于已经使用了同步"一词,因此在上面的链接中,我将解释我对 glMapBufferRange 的选择,而实际上您想映射整个缓冲区,而不是某个范围.为什么要这样?
即使OpenGL在使用上述丢弃技术时大部分可以避免同步,有时还是必须这样做.
同样,它仍然必须运行某种内存分配算法来管理缓冲区,这会花费驱动程序时间. glMapBufferRange 可让您指定其他标志,尤其是(在更高版本的OpenGL中)标有不同步"的标志.这允许使用更复杂但仍然更快的方法,即创建一个两倍于所需大小的缓冲区,然后继续映射/写入下半部或上半部,告诉OpenGL根本不同步.然后,您有责任知道何时安全(大概是通过使用fence对象),但是您要尽可能避免所有开销.

Since the word "synchronization" was used already, I shall explain my choice of glMapBufferRange in the link above, when in fact you want to map the whole buffer, not some range. Why would one want that?
Even if OpenGL can mostly avoid synchronizing when using the discard technique above, it may still have to, sometimes.
Also, it still has to run some kind of memory allocation algorithm to manage the buffers, which takes driver time. glMapBufferRange lets you specify additional flags, in particular (in later OpenGL versions) a flag that says "don't synchronize". This allows for a more complicated but still faster approach in which you create a single buffer twice the size you need once, and then keep mapping/writing either the lower or upper half, telling OpenGL not to synchronize at all. It is then your responsibility to know when it's safe (presumably by using a fence object), but you avoid all overhead as much as possible.

这篇关于OpenGL中更新纹理的有效方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆