Reputation: 3991
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?
Upvotes: 3
Views: 1169
Reputation: 474316
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.
Upvotes: 3
Reputation: 162327
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.
Upvotes: 1
Reputation: 56397
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!
Upvotes: 0
Reputation: 5283
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.
Upvotes: 0