OpenGL / OpenGLES中的Framebuffer纹理行为

时间:2011-06-23 19:06:46

标签: opengl opengl-es fbo render-to-texture

在OpenGL / ES中,在实现渲染到纹理功能时,必须小心不要引起反馈循环(从正在写入的相同纹理中读取像素)。出于显而易见的原因,当您正在读取和写入纹理的相同像素时,行为是未定义的。但是,如果您正在读取和写入相同纹理的不同像素,它是否也是未定义的行为?一个例子是,如果我试图制作一个内部具有渲染纹理的纹理图集。当我渲染纹理时,我从纹理图集中存储的另一个纹理中读取像素。

因为我没有在纹理中读取和写入相同的像素,所以行为仍然被认为是未定义的,只是因为数据来自相同的纹理?

4 个答案:

答案 0 :(得分:3)

  

但是,如果您正在读取和写入相同纹理的不同像素,它是否也是未定义的行为?

缓存是一个大问题。写入像素数据时,不一定要立即写入图像。写入存储在缓存中,因此可以一次写入多个像素。

纹理访问做同样的事情。问题是他们没有相同的缓存。所以你可以写一些写缓存中的数据,但纹理缓存不知道它。

现在,规范在这里有点笨拙。 理论上可能你可以从纹理的一个区域读取并写入另一个区域(但是规范未定义),只要你从不从任何位置读取你写了,反之亦然。显然,这不是很有帮助。

NV_texture_barrier扩展程序允许您解决此问题。尽管是NVIDIA扩展,但它也支持ATI硬件。它的工作方式是当你想要刷新所有缓存时调用glTextureBarrierNV函数。这样,您可以确定当您从某个位置读取时,您已写入该位置。

因此,您的想法是将纹理的一个区域指定为写入区域,将另一个区域指定为读取区域。渲染完一些内容后,需要进行回读,然后触发屏障并交换纹理区域。这就像纹理乒乓,但没有附加新纹理或绑定FBO或更改绘制缓冲区的繁重操作。

答案 1 :(得分:1)

问题不在于反馈循环的可能性(技术上这不会导致循环,而是一个未定义的顺序,其中读取/写入像素导致不可定义的行为),但访问模式GPU的限制实现:缓冲区只能在任何给定时间读取或写入(收集与分散访问)。 GPU总是会看到一个缓冲区。这是这种限制的主要原因。

答案 2 :(得分:0)

是的,GPU仍然是大规模并行的,所以你不能说你一次写'一个'像素,还有你准备好纹理时填充的缓存系统。如果您写入相同的纹理,则需要同步缓存,依此类推。

对于某些见解,您可以查看NV_texture_barrier OpenGL扩展,这是为了增加这方面的灵活性。

答案 3 :(得分:0)

是的,读取/写入纹理的不同区域也是未定义的。但是为什么要关心它是否未定义,只需写入另一个纹理并完全避免这个问题!