Good morning!
We were wondering if we could run through an idea we’ve had to improve performance on a very specific part of our product to see if you guys thought was viable and if it were, what would be the best way to approach it. While our target platform is relatively low-end, we’re still interested in the impact of having something like this in other platforms as well.
Currently our product has an interesting performance problem with masked and opaque particle (Niagara) emitters which we believe are caused by our depth prepass setup (set to r.EarlyZPass=3 (auto)) and the fact that we’ve also setup velocity rendering to happen as part of the prepass (r.VelocityOutputPass=0). While we generally found that outputting velocity as part of the prepass to be beneficial, the main issue we’re seeing now that we’re paying too much in terms of GPU performance to render certain particle effects twice (once for their velocity output during the RenderVelocities(opaque) pass and another one during the base pass), so we were wondering if something like what we’re about to propose would work and if it seems doable, what would be the best way of doing it code-wise.
While there are a few obvious ways where we could improve the performance of those emitters such as reducing the amount of particles and disabling motion vectors in the emitters, we don’t want to sacrifice visual quality too much so we think having a custom pass which allows rendering a (separate) base pass with both depth and velocity information while keeping our current setup might be an interesting thing to investigate. We are aware the engine already supports custom render passes and we’ve also found an example on how to create one in Engine\Plugins\Compositing\CompositeCore\Source\CompositeCore\Private\CompositeCoreSceneViewExtension.cpp as seen in the screenshot below although we’re not sure if this is the best way of doing it or not. We’ve also found the FSceneCapturePass class contains a very similar way of implementing the custom render pass.
[Image Removed]
In our case we’d probably want to execute it just before the main base pass to get the benefits from depth discards from those masked / opaque particles and we’d need a way of tagging which assets would go through this path - while it will probably need some custom work I’m sure we’d figure a way to do it.
Looking at the code in Engine\Source\Runtime\Engine\Public\Rendering\CustomRenderPass.h we’ve noticed it suggests creating a custom class that inherits from FCustomRenderPassBase to create custom behavior which we suspect will be the way to go but we thought it would be a good idea on what you think would be the best approach and if you think we’ll potentially see some improvements from the changes we’ve suggested. We are aware this might cause some issues with occlusion tests which we currently have enabled at the moment but we might require implementing this custom pass to see the full impact.
So the main idea is to have:
- A way of tagging assets, in our way specific types of particle emitters, to make sure they’re rendered as part of our custom base pass (which I believe can be done already through primitive IDs as they are received by the custom pass info.
And then rendering wise:
- Prepass (r.EarlyZPass=3)
- RenderVelocities(Opaque) (excluding opaque / masked Niagara Particles)
- [ HZB, Custom Depth, etc.. ]
- CustomBasePass (opaque / masked Niagara particles, outputs depth and velocity) -> this is what we’d need to add
- Base Pass (everything else)
- […]
Please let us know if you need more info and thanks in advance!
Adrian
[Attachment Removed]