OpenGL/OpenGLES 中的帧缓冲区纹理行为

发布于 2024-11-16 21:58:37 字数 246 浏览 5 评论 0原文

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

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

In OpenGL/ES you have to be careful to not cause a feedback loop (reading pixels from the same texture you are writing to) when implementing render to texture functionality. For obvious reasons the behavior is undefined when you are reading and writing to the same pixels of a texture. However, is it also undefined behavior if you are reading and writing to different pixels of the same texture? An example would be if I was trying to make a texture atlas with a render texture inside. While I am rendering to the texture, I read the pixels from another texture stored in the texture atlas.

As I am not reading and writing the same pixels in the texture is the behavior still considered undefined, just because the data is coming from the same texture?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

枯寂 2024-11-23 21:58:37

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

是的。

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

纹理访问做同样的事情。问题是它们没有相同的缓存。因此,您可能已经写入了写入缓存中的一些数据,但纹理缓存不知道它。

现在,这里的规范有点严厉。 理论上,您可以从纹理的一个区域读取数据并写入另一个区域(但规范未定义),只要您从不从任何位置读取数据即可。已写信给,反之亦然。显然,这没有多大帮助。

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

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

However, is it also undefined behavior if you are reading and writing to different pixels of the same texture?

Yes.

Caching is the big problem here. When you write pixel data, it is not necessarily written to the image immediately. The write is stored in a cache, so that multiple pixels can be written all at once.

Texture accesses do the same thing. The problem is that they don't have the same cache. So you can have written some data that is in the write cache, but the texture cache doesn't know about it.

Now, the specification is a bit heavy-handed here. It is theoretically possible that you can read from one area of a texture and write to another (but undefined by the spec), so long as you never read from any location you've written to, and vice versa. Obviously, that's not very helpful.

The NV_texture_barrier extension allows you to get around this. Despite being an NVIDIA extension, it is supported on ATI hardware too. The way it works is that you call the glTextureBarrierNV function when you want to flush all of the caches. That way, you can be sure that when you read from a location, you have written to it.

So the idea is that you designate one area of the texture as the write area, and another as the read area. After you have rendered some stuff, and you need to do readback, you fire off a barrier and swap texture areas. It's like texture ping-ponging, but without the heavy operation of attaching a new texture or binding an FBO, or changing the drawbuffers.

相守太难 2024-11-23 21:58:37

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

The problem is not so much the possibility of feedback loops (technically this would not result in a loop, but an undefined order in which pixels are read/written causing an undefineable behaviour), but the limitations of the access modes GPUs implement: A buffer can either only be read from or written to at any given time (gather vs. scatter access). And the GPU always sees a buffer as a whole. This is the main reason for that limitation.

酒与心事 2024-11-23 21:58:37

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

要获得一些见解,您可以查看 NV_texture_barrier OpenGL 扩展,这意味着在这个领域增加一些灵活性。

Yes it still is, GPUs are massively parallel so you can't really say that you write 'one' pixel at a time, there are also cache systems that are populated when you ready a texture. If you write to the same texture, the cache would need to be synchronized, and so on.

For some insight, you can take a look at the NV_texture_barrier OpenGL extension, that is meant to add some flexibility is this area.

栩栩如生 2024-11-23 21:58:37

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

Yes, it's also undefined to read/write different areas of the texture. But why care if it's undefined or not, just write into another texture and avoid the problem altogether!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文