PDA

View Full Version : Depth / Stencil as both a FBO attachment and sampler?



Michael Anderson
03-02-2015, 02:59 PM
I am attempting to implement a deffered renderer using OGLES 2.0. I have everything working satisfactorily in 3 passes (no MRT in OGLES 2.0). One of the optimizations I am trying to employ requires me to use the stencil buffer of the GBuffer pass during the subsequent lighting pass, the problem is that depth & stencil are packed together and I need to use both the depth as a sampler and the stencil as a FBO attachment at the same time. I first tried using a renderbuffer for stencil and a depth only texture as separate FBO attachments, to no avail. Next I tried just using the GBuffer depth/stencil as both the depth/stencil FBO attachment and a sampler in the lighting pass, this seems to work but it seems exotic/dangerous to me. Is it safe to use a texture as both an active FBO attachment and a sampler at the same time?

Alfonse Reinheart
03-02-2015, 03:36 PM
I have everything working satisfactorily in 3 passes (no MRT in OGLES 2.0).

Isn't the point of deferred rendering to not have so many passes? Since deferred rendering is a complicated optimization, if you're having to do that many passes just to fill out your G-buffers, you might be better off with just a depth pre-pass rather than a full-scale deferred renderer.

One more thing. The class of ES hardware that is limited to ES 2.0 (unless you're using WebGL) is almost always tile-based deferred to some degree (especially hardware that can't support MRT). In that hardware, deferred rendering is very likely to hurt your performance. Especially if you're having to make 3 passes just to render all of your G-buffers.


the problem is that depth & stencil are packed together and I need to use both the depth as a sampler and the stencil as a FBO attachment at the same time.

On plain OpenGL ES 2.0? The only thing you could really do is blit your depth/stencil image to a second depth/stencil image. That way, you can read from one and do your stencil updates to another.


Is it safe to use a texture as both an active FBO attachment and a sampler at the same time?

As far as the specification is concerned, absolutely not (https://www.opengl.org/wiki/Memory_Model#Framebuffer_objects). The spec is quite strict about this.

However, if your stencil operation does not involve actually changing the stencil value in the framebuffer (uses GL_KEEP), and you aren't writing to the depth (via glDepthMask), then it is theoretically OK. That doesn't mean it's actually OK. Especially for tile-based renderers; they can be kinda squirrelly about things like that.

Michael Anderson
03-02-2015, 05:02 PM
Isn't the point of deferred rendering to not have so many passes? Since deferred rendering is a complicated optimization, if you're having to do that many passes just to fill out your G-buffers, you might be better off with just a depth pre-pass rather than a full-scale deferred renderer.

I am using the light pre-pass approach (https://software.intel.com/en-us/articles/deferred-rendering-for-opengl-es30-on-android). I am writing normals, spec pow, depth, and stencil for lit geo during the GBuffer pass (No MRT). I then do the light accumulation pass (this is where I need both the depth as a sampler and the stencil test to mask light fragments). Finally I render the whole scene using the light accumulation texture on lit geo. So I actually only do two passes on lit geo.


One more thing. The class of ES hardware that is limited to ES 2.0 (unless you're using WebGL) is almost always tile-based deferred to some degree (especially hardware that can't support MRT). In that hardware, deferred rendering is very likely to hurt your performance. Especially if you're having to make 3 passes just to render all of your G-buffers.



On plain OpenGL ES 2.0? The only thing you could really do is blit your depth/stencil image to a second depth/stencil image. That way, you can read from one and do your stencil updates to another.



As far as the specification is concerned, absolutely not (https://www.opengl.org/wiki/Memory_Model#Framebuffer_objects). The spec is quite strict about this.

However, if your stencil operation does not involve actually changing the stencil value in the framebuffer (uses GL_KEEP), and you aren't writing to the depth (via glDepthMask), then it is theoretically OK. That doesn't mean it's actually OK. Especially for tile-based renderers; they can be kinda squirrelly about things like that.

Ya, I am doing exactly as you described, the depth/stencil attachment is read only during this pass. I suspect I will just have to bail on this optimization, to do it safely and blit the depth stencil into another texture will likely be slower than just eating the extra fragment shading. Out of curiosity though do you have any examples on how to copy a depth/stencil texture?

Michael Anderson
03-03-2015, 10:53 AM
So it occurred to me that if I do my second pass before the lighting pass I can generate a second depth buffer with the stencil mask I need. This is more like a traditional deffered renderer except I have to do 2 passes on the lit geo before doing the lighting pass.