Combining Forward Render, HZBO and Masked materials

Hi all,

I’ve been optimizing our VR project for the last couple weeks, but today I thought I got a breakthrough when I tried running it on DX12 with HZBO, as that got us into the land of comfortably below 10 ms a frame. Now, the question isn’t DX12 relevant, DX11 has exactly the same behavior.

Unfortunately, seems like HZBO doesn’t work properly with masked materials (at least with the forward renderer, I’ll try changing to deffered just to see what happens, but we will definitely be staying in forward render).

Below is a video with the occluded elements visualized. As you can see, if when one disables HZBO, the occlusion culling works as it should, but as long as HZBO is enabled, half-transparent masked objects occlude stuff behind them. Unfortunately, hardware dynamic occlusion is a total performance killer with our draw call count.

The reason for trying to get it to work properly is that HZBO gets us roughly ~0.5ms on the GPU and ~2ms on the CPU in the heaviest cases, which is a lot when we’re hovering around ~10.5ms at GPU and ~9ms and aiming for the holy grail of stable 11.1ms.

We have a very specific scene, with the whole body composed of ~6k meshes, so we’re 100% draw-call bound. So when HZBO manages to eliminate ~20% of the draw calls at a cost of 0.3ms for building the HZB hierarchy, I’m very happy about that. But because of the weird interaction with masked materials, I’m back to using no occlusion culling at all.

I tried setting the meshes bUseAsOccluder to false, which had no effect. Also Tried setting the mesh bounds scale to 0.0f, also to no avail.

If anybody has any experience combining Forward Render, HZBO and Masked materials, any tips would be greatly appreciated!

Cheers, Tommy.

UseAsOcccluder works only when depth pre-pass is selective.
On forward rendering it is forced to full, so it will not work.

The only technical difference between HZBO on forward and deferred is potentially multisampled depth buffer and a2c on former. You should look in that way to solve your issue.

Hey, thanks for the tips. But could you tell me what a2c stands for? :smiley:

Alpha to Coverage.

Thanks, I’ve actually managed to find that yesterday but forgot to comment here.

I’ve also noticed a big difference between using masked materials in forward and deferred, as in forward render, you can fake one layer of transluscency with OpacityMask between 0 and 1 (as long as the value is above the Opacity Mask Clip value), but on deferred, it’s a hard cutoff to 0 or 1.

I guess since we’re misusing this effect for transparency, and the HZBO wasn’t designed with this in mind it only checks if the alpha is higher than the clip value, but doesn’t care if it’s lower than 1 (meaning in forward, it shows up semitransparent).

Ah well, I’ll step through the render() method and investigate the actual HZB generation code and shaders when I have some more time. Hopefully I’ll find some “if (alpha > clip)” and change it to “if (alpha == 1.0)” to get this to work the way we need.

Thanks again for the pointers.