3

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

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

4

4 回答 4

3

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

是的。

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

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

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

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

所以想法是您将纹理的一个区域指定为写入区域,将另一个区域指定为读取区域。在你渲染了一些东西之后,你需要做回读,你发射一个屏障并交换纹理区域。这就像纹理乒乓球,但没有附加新纹理或绑定 FBO 或更改绘制缓冲区的繁重操作。

于 2011-06-24T02:07:34.107 回答
1

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

于 2011-06-23T19:50:16.593 回答
0

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

对于一些见解,您可以查看NV_texture_barrier OpenGL 扩展,这意味着在该区域添加一些灵活性。

于 2011-06-23T19:18:33.817 回答
0

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

于 2011-06-23T19:19:39.813 回答