Depth Priming Advantages?

I saw the new beta includes Depth Priming in URP which sounds like an amazing feature for me. Was somebody already able to test it and the impact it makes? I have a scene with a lot of overlaying geometry (stencil based) and from what I understand Depth Priming can really cut down the render times because it will do a depth pass first and then only shade the pixels that are on top. That should do a massive boost especially for VR games I guess, or do I misunderstand something and the depth prepass is eating up all the gained render time already?

1 Like

We used to do force depth for different parts of the scene to optimize the rendering like this. We would even sort the triangles of some objects front to back (we had fixed camera angle). The win depends on a lot of things of course, but in the most dens areas of the scene we would get around 12% improvements. This should be even better, because it would apply to the whole scene and you wouldn't lose anything because of non-optimally sorted vertex buffers.

2 Likes

Hi,
Depth Priming should improve mostly GPU timing in a lot of cases.
The best results we've managed to observe were up to 16% less GPU time on Mac Metal.
We observed 3% less CPU time and 7.5% less GPU time on Windows Vulkan.

Actual gains are dependent on many factors:

  • Graphics API/Hardware/Platform: On desktop there are the variations between hardware and API's. On mobile there is variations of tile based hardware. This should in theory reduce the gains made by Depth Priming on tile based hardware when MSAA is enabled (to a point where performance could even be worse). However in practice we weren't able to observe this on the devices we tested.
  • Scene: is there lots of overlapping opaque geometry that can't be entirely handled by front to back sorting ?
    Depending on the scene we can skip a lot of redundant pixel shader invocations. With Depth Priming each opaque pixel should only be shaded once. Note that with Depth Priming enabled we try to skip the front-to-back sorting on the CPU so that should give a minor CPU frame time boost.

  • Opaque shader cost: The more expansive the shaders used in the scene, the more speedup you'll get from each pixel shader invocation that's being skipped.

  • Render setup: If your renderer setup doesn't already trigger the depth prepass, you will have to pay the cost of forcing this prepass so the Depth Priming optimization has the necessary information to optimise the opaque pass.
    This is the difference between Auto and Forced. Auto will only allow priming when there already is a prepass (like when SSAO is on) while Forced will make sure the prepass is performed to enable Depth Priming to take place.

And lastly something to be aware of: Because text and UI rendering is injected into the opaque pass you'll want to do these in an overlay camera with the cameras Clear Depth setting disabled. Since we can't perform Depth Priming in that case the UI should come through while respecting the depth from the underlying camera.

Other than the aforementioned UI/Text issue, there should be no visual differences in render results. If there are then please report them. There's one known artifacting issue on Mac with vertex displacement that we're aware of.
When measuring performance please keep in mind that priming doesn't do anything on Auto if there's no depth prepass and Forced will then also include the cost of depth prepass. Since we have to respect the MSAA of the forward pass there will some increased memory usage from the depth prepass having to allocate its rendertarget as MSAA as well.

Depth Priming has the potential to improve performance with some caveats (and hopefully the UI one can fixed in the future) but the feature has yet to be tested in the wild. I believe it was tested on VR as well so please feel free to give it a go.

8 Likes

One question to concrete usage. Is it enough to simply activate it and the shaders automatically profit from it or do I need to adjust my own shaders explicitly? And are the default URP shaders taking advantage already?

The build in URP shaders are already supported and unless you are handwriting your shaders from scratch there should be nothing special you should need to worry about. They just need a depth pass and ShaderGraph and most (if not all) the Asset store shader creation tools support or add this by default.

Something to be aware of, just like any rendering technique the advantages are situational. Turning depth pre pass on could actually worsen performance depending one the scene,shaders,hardware,platform.ect.

If you want more technical information about “Depth Priming” aka “Depth Pre-pass” you can google it, there is a lot informative and well written articles on it.

1 Like

One more question: what is the difference between Depth Priming and today's Depth Texture in URP that I can toggle already?

If you toggle on DepthTexture or if a ScriptableRendererPass request the depth texture then depth priming will automatically be used. The difference is now you have the option to force it, plus there is probably extra optimization from todays URP. I'm assuming that prior to the Depth Prime option that opaque objects might have still been sorted.

@NicoLeyman i am porting some shaders from urp 11 to 12 right now and unfortunately depth priming breaks my toon + outline shader which draws both in the same shader but in different passes.
so the outline just gets rejected because of depth testing.
i wonder if it is needed to use ZTest Equal in all cases?
needed for alpha testing to get rid of it but on a regular shader LEqual should do the job, right?
other than that: maybe we could exclude some shaders from using another ZTest than the original from the material using shader tags?

He mentions that Depth priming removes the need to sort opaque's, this might make it pretty difficult to get a toon outline shader using hull method to work properly because the depths could be written in random orders. I personally would make a custom ScriptableRenderer to render you're toon shaders, this would give you full control on how there rendered. You could removed the default universal shader tag from your shaders so they get skipped, then call your own Draw Renderers call from the scriptable context with your shader tag and specify the drawing order.

[quote=“CaffeinatedCoolaid”, post:9, topic: 846457]
He mentions that Depth priming removes the need to sort opaque’s
[/quote]
oh, i did not see this. but actually he wrote:
[quote=“NicoLeyman”, post:3, topic: 846457]
Note that with Depth Priming enabled we try to skip the front-to-back sorting on the CPU so that should give a minor CPU frame time boost.
[/quote]
so they “try” - which i guess might be a bad idea as writing out the depth or depth normals would suffer from heavy overdraw then. less expensive than overdraw in the forward or gbuffer pass but still expensive.

This is correct. On the shader side we require a depth and depth normals pass. Depth written here should be the same as the depth of the opaque pass. So don't go optimising away vertex displacement in the depth pass.

EDIT: Unlit ShaderGraph shaders should now also generate the required depth/depth normals shaders. Although I don't think you can alter the "unlit" normals from SG, they're just geometry based.

Depth pre-pass is indeed the common name for this feature. I've opted to call it Depth Priming because a depth "pre pass" already exists in URP and is performed based on your post-processing effects. Depth Priming re-uses/hijacks that pass.

Priming currently is only enabled when doing so explicitly through the Depth Priming option. Once we get the feature more battle tested we might switch to having it in Auto mode by default but before that we need to fix some issues and have to be sure that this is universally a good thing.

We force the depth comparison mode to equals for the primed opaque pass (so it deosn't really matter what the shader defines for depth comparison) since the assumption is that the depth in the depth buffer is the exact depth value that we want to shade.
What CaffeinatedCoolaid suggests is probably the best option. To make your outline shader work with priming you'd have to write out the outline depth as part of the depth prepass. You'd probably also need the depth pass to do multiple shader passes and then you'd end up with the outline depth being included in the post-pro depth which might be undesirable.

My "try" was a bit vague: we only skip the front-back sorting in the opaque pass atm.
"try" was playing it safe since since we can't actually skip the front-back sorting in the depth or depth/normals pass for the reasons you've mentioned.

[quote=“NicoLeyman”, post:11, topic: 846457]
opaque pass
[/quote]
“opaque” has been mentioned several times here and i admit i haven’t looked into alpha tested geometry so far. but i really hope that depth priming will kill the clip command in the forward and deferred passes to enable early depth testing on these. just like in HDRP.

1 Like

[quote=“NicoLeyman”, post:11, topic: 846457]
Depth pre-pass is indeed the common name for this feature. I’ve opted to call it Depth Priming because a depth “pre pass” already exists in URP and is performed based on your post-processing effects. Depth Priming re-uses/hijacks that pass.
[/quote]

Oh I feel foolish! I did not realize that it was a whole separate thing, I thought he was referring to the existing depth pass used for the Depth texture.

Hi everyone, I'm trying to add depth priming on urp 7.x. But I 'm confused how do you solve the z fighting caused by depth prepass? Is there some offset for depth prepass so that lately the draw object pass can avoid the fighting artifacts?

[quote=“yimingdz”, post:14, topic: 846457]
I’m trying to add depth priming on urp 7.x.
[/quote]
i tried it once – copying the buffer generated for the shadows? well, i do not remember exactly.
turned out that the matrices were slightly off.

[quote=“larsbertram1”, post:12, topic: 846457]
“opaque” has been mentioned several times here and i admit i haven’t looked into alpha tested geometry so far. but i really hope that depth priming will kill the clip command in the forward and deferred passes to enable early depth testing on these. just like in HDRP.
[/quote]

I’m interested in whether this feature changes anything for clipping on tile-based platforms (where alpha testing was usually discouraged). I noticed that enabling depth priming sets ZWrite to Off and ZTest to Equal on opaque draw calls. Has anyone had a chance to benchmark this yet? Can I go crazy with my alpha clipped vegetation? :eyes:

https://discussions.unity.com/t/684417
https://discussions.unity.com/t/727562
https://discussions.unity.com/t/830595

[quote=“NicoLeyman”, post:3, topic: 846457]
This should in theory reduce the gains made by Depth Priming on tile based hardware when MSAA is enabled (to a point where performance could even be worse).
[/quote]
Heya, thing is we have a game that uses A2C based shaders and MSAA for desktop but Depth Priming doesn’t run if MSAA is enabled. There’s no good technical reason for that as far as I’ve researched / asked around. Is this a legacy decision that will change?

As it means dropping our antialiased vegetation for a post effects based solution which changes the look of the game.

Further question for anyone: Is there a way to force the depth prepass version of the geometry to use a cheaper vertex shader for example we don’t want wind in the prepass, as it adds up to being a waste of performance.

Shader uses shadergraph.


i haven't looked into URPs depth priming for quite a while... but speaking about HDRP and the depth prepass: using another vertex animation or even none would break the final render. the depth prepass writes out depth, then the regular shader drops alpha testing and uses ZTest Equal which gives you the same result and preserves early depth testing - but only if the final positions match.

I see, I figured that it wouldn't be noticed after a certain distance. So could drop vertex shader cost. I think it's probably better to disguise it and drop it earlier in the main pass then. One of those game rendering problems. Thanks!


you can fade it out and drop it beyond a certain distance – but you have to do so in both passes.