   z prepass myth, culling and overdraw
  I tried everything, but it seems there is now way (on my GeForce 6800 Ultra) to tell the pipeline to avoid shading a pixelm by mean of the zbuffer test, BEFORE it is actually shaded... which is the most time consuming step, and which is the goal of Z PrePass.With Z prepass I except more or less the same FPS regardless of where the camera is pointing, assuming that the Z PrePass is ultra fast (which is). But this does not happen, I tried everything.So, since this technique is not so robust, I figured out that the only thing to do is doing a z prepass, then manually remove objects before the GBuffer rendering step, which it seems to be what they do with Unreal Engine:<<Z pre-passa.k.a. depth set-up passUses fast hardware path - no shadingComplete Z-buffer generated for all opaque objectsPer-object hardware occlusion queries to cull the later (expensive) shader rendering>>What do you think ?I can't thing anything else to avoid having a huge overdraw in an FPS engine.What do you do ?   
Quote:Original post by NiGoeaWith Z prepass I except more or less the same FPS regardless of where the camera is pointing, assuming that the Z PrePass is ultra fast (which is). This is just a wrong assumption. Z Prepass will avoid pixelshading operation of not visible pixels. But your FPS depends on much more like vertex shader performance, different pixel shader for visible pixel etc. ;Quote:Original post by NiGoeaWith Z prepass I except more or less the same FPS regardless of where the camera is pointing, assuming that the Z PrePass is ultra fast (which is). But this does not happen, I tried everything.Does the number of draw-calls vary depending on where the camera is pointing?Quote:So, since this technique is not so robust, I figured out that the only thing to do is doing a z prepass, then manually remove objects before the GBuffer rendering step, which it seems to be what they do with Unreal EngineZ-pre-pass  only reduces the pixel shading cost. If your GBuffer-generation pixel shader isn't very expensive, then there's not much point peforming z-pre-pass to optimise the GBuffer pass... The number of draw-calls is probably your biggest problem, and adding a dedicated z-pass before the GBuffer pass is doubling your draw calls!Z-pre-pass was originally used in non-deferred renderers (i.e. without a GBuffer), because the pixel shaders were ridiculously expensive. In a deferred renderer, most of the pixel-shader cost comes AFTER GBuffer generation in the lighting passes - so to reduce pixel-shader costs you should be targeting these passes with optimisation techniques like scissoring and stencil tests.Most Unreal Engine do not use a GBuffer or deferred lighting.   ;  First of all early Z culling is exactly what it is, reject pixel before they get shaded (theoretically). Doing your depth pass then setting your depth comparison to equal should gain you a slight increase in performance. Its obvious that your frame rate (which is not a real indication of performance anyways) will vary slightly based on where the camera is pointing seeing their will be more or less objects in the frustum at a given time. As for not visible pixels that has nothing to do with early Z culling, those will be discarded by viewport clipping, the only cost you pay is processing those vertices (vertex and fragment). Don't depend on FPS to measure performance. Place timing calls around your draw function and see what times you are getting with and without Z Prepass and that will give you a better idea of where you bottle neck may be.   ;Quote:Original post by HodgmanZ-pre-pass was originally used in non-deferred renderers (i.e. without a GBuffer), because the pixel shaders were ridiculously expensive. In a deferred renderer, most of the pixel-shader cost comes AFTER GBuffer generation in the lighting passes - so to reduce pixel-shader costs you should be targeting these passes with optimisation techniques like scissoring and stencil tests.Most Unreal Engine do not use a GBuffer or deferred lighting.I'm in agreement here - with a deferred rendering process, are you not already limiting the costly pixel shader operations to once-per-pixel? The generation of the GBuffer data should be pretty lightweight in comparison to the deferred step. If it is not, isn't one of the benefits of a deferred renderer lost?In any rendering environment, you'll want to make sure you have a system that keeps as much complexity off of the visible area as possible. That means culling it somehow. Occluders and z-prepass can help you with what's in the visible frustum, but you'll need to give the gpu a hand trimming down the amount of data you are sending, since you'll most likely be vertex bound during gbuffer generation.   ;  I would recommend profiling with perfHUD to identify what is really going on.  There are many sources of possible frame to frame performance changes - overdraw is probably the least likely for the reasons you have already mentioned...   ;  I would recommend profiling with perfHUD to identify what is really going on.  There are many sources of possible frame to frame performance changes - overdraw is probably the least likely for the reasons you have already mentioned...   ;  I would recommend profiling with perfHUD to identify what is really going on.  There are many sources of possible frame to frame performance changes - overdraw is probably the least likely for the reasons you have already mentioned...   ;  Early-z units in hardware are pretty complicated. You can't assume that early-z will cull the pixel just because it fails the depth test. Most units use a significantly simplified (reduced in size and precision) version of of the depth/stencil buffer in z-cull RAM, and a pixel will only get culled if the unit can conservatively determine that all pixels in some block size will fail the depth test. It varies across different hardware, but in general your best bets for good z-cull performance are:-don't swap out depth buffers too much-don't change the depth test direction-use scenes with lower depth/geometry complexity-don't output depth from your pixel shader!I do agree with others that you should make sure that you're actually fragment bound for whichever pass you're concerned with, otherwise even a perfect z-cull implementation won't do anything for you.   ;  I see that practically all of you disagree with me. But I'm not changing my point of view, please let me try to explain better what I think.First, some assumptions:1)I'm talking about an FPS => high overdraw.If camera is watching a wall, there can be tens of other walls behind it.2) Deferred renderer GBuffer shader can be not so light: I have two normalize(), a couple of dot products, lots of multiplications and divides. Plus I'm outputing in three RenderTargets and sampling from 3 textures.It's not huge, but not as light as a peanut neither.3) Z prepass IS FAST. It takes HALF millisecond (checked with PerfHUD) to render the whole scene (only static geometry, which is what I care of) and filling the depth render target that I will use in the GBuffer pass.Wouldn't it worth wasting HALF MILLISECOND to fill a zbuffer ? Yes to me.===> My personal idea:- Z prepass to fill zbuffer (VERY FAST)- GBuffer ONLY on visible pixels (almost CONSTANT TIME, because invisible pixels SHOULD be avoided BEFORE entering the shading stage, which is FAST)===> My results:it seems that z prepass doesn't serve so well. If I watch a wall that behind has tens of other walls, I experience a tremendous FPS drop :°)Like ALL the pixel were getting shaded.-----On a paper from EPIC about Unreal Engine 3D, they say they DO USE Z Prepass. What I didn't understand is if they are using it to perform culling on a per-pixel level or a per-object level (or triangle level).I mean........ what do you do if in front of you there are tons of objects one behind another ???NOW YOU CAN SWEAR AT ME :-)Thanks !   