PDA

View Full Version : Can I read what was written to gl_FragData[] ?



prince_polka
04-01-2017, 06:46 PM
What I wan't to do is some kind of ping-pong rendering,
If I write to gl_FragData[0] one frame, is it then stored somewhere where I can I read from it the next frame?
And if that is the case, then can I read from an arbitrary coordinate or just a fixed value like with
#extension GL_EXT_shader_framebuffer_fetch :
gl_LastFragData[] ?
Or is gl_FragData[] only good for passing on multiple values to the next step in the pipeline?

john_connor
04-02-2017, 01:44 AM
If I write to gl_FragData[0] one frame, is it then stored somewhere where I can I read from it the next frame?

if you use double-buffering, i think next frame its stored in the backbuffer
https://www.khronos.org/opengl/wiki/Default_Framebuffer#Double_buffering


And if that is the case, then can I read from an arbitrary coordinate ... ?

if you want to have access to framebuffer data of the previous frame, its better you create 2 FBOs with 2 texture attachments:
https://www.khronos.org/opengl/wiki/Framebuffer_Object
https://www.khronos.org/opengl/wiki/Framebuffer_Object#Attaching_Images

here an example:
https://sites.google.com/site/john87connor/framebuffer/tutorial-10-3-framebuffer-mrt

FBO 1:
reads from texture 1
writes into texture 2

FBO 2:
reads from texture 2
writes into texture 1

each odd frame you render into FBO 1, otherwise into FBO2, so you effectively create your own "doublebuffer" which is fully under your control

bind texture 1 to texture unit 1 (glActiveTexture(GL_TEXTURE1))
bind texture 2 to texture unit 2 (glActiveTexture(GL_TEXTURE2))

your fragmentshader should have a "uniform sampler2D mypreviousframe;" so that you can fetch from a texture
each odd frame you want have read access to texture 1, so you call:

GLint location = glGetUniformocation(myprogram, "mypreviousframe");
glUseProgram(myprogram);
if (... is odd frame ...)
glUniform1i(location, 1);
else
glUniform1i(location, 2);

Dark Photon
04-02-2017, 01:14 PM
What I wan't to do is some kind of ping-pong rendering,

If I write to gl_FragData[0] one frame, is it then stored somewhere where I can I read from it the next frame?

Yes, if you set up your destination framebuffer (and possibly source textures) properly.


And if that is the case, then can I read from an arbitrary coordinate or just a fixed value like with

#extension GL_EXT_shader_framebuffer_fetch :
gl_LastFragData[] ?

Ok, first thing's first. Are you using OpenGL or OpenGL ES? Your mention of EXT_shader_framebuffer_fetch (https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_shader_framebuffer_fetch.txt) suggests the latter.

If you are using OpenGL ES and have this extension available, definitely consider using it. Also consider using EXT_shader_pixel_local_storage (https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_shader_pixel_local_storage.txt) if it'd be useful to you and your GPU has it. These can save a ton of bandwidth and latency on most mobile GPUs (which are tilers).

With these extensions, your writes/reads of old pixel data in the shader are stored to/read in from super-fast on-chip cache and (if you play your cards right) often is never written out to or read back from slow DRAM, which is very efficient (be sure you're calling glClear() and glInvalidateFramebuffer()/glDiscardFramebuffer() in all the places you should be on all the buffers you can). This is the preferable way to do multipass on mobile (tiler) GPUs. Doing it "the OpenGL way" instead on a tiler GPU results in higher latencies and other details you have to be aware of such as extra render target GPU memory consumption, and how to pipeline daisy-chained writes/reads to multiple framebuffers efficiently on your GPU+driver.


Or is gl_FragData[] only good for passing on multiple values to the next step in the pipeline?

That's one way to do it. If you've got access to one or both of the above-mentioend extensions though, prefer them instead.

On some desktop drivers, there are more efficient ways to do what you want than ping-ponging between two textures. But I'll spare you that because it doesn't sound like you're writing for a desktop GPU.