we’ve been messing around with rendering paths to see what were the advantages of deferred rendering over forward but it seems I didn’t quite get what it was about and what you could expect or not.
I know deferred rendering offers a lot more concerning shadows but that part doesn’t really interest us for the time being since we deal with 2D projects mainly.
I expected, maybe wrongly, to get less drawcalls for objects lighted with multiple lights with deferred lighting. Every tests we’ve made ended with always more draw calls for the deferred path, even if all lights were marked as ‘important’ for forward path (forcing them to be per pixel lights).
With deferred lighting the statistics window of the editor shows an equivalent or slightly larger number of drawcalls but a number of tris largely inferior. Even with this decrease of tris, performances are always significantly better with forward rendering.
You will only see a significant improvement from forward to deferred when you are using a lot of lights. Deferred rendering doesn’t affect shadows but it does affect the number of dynamic (non lightmapped) lights in the scene. It allows for dozens and dozens of visible pixel lights at the same time which is not even remotely possible with forward lighting. And whereas forward lighting is based on geometry complexity, Deferred lighting is based on the size of the light on the screen. So reducing polys, but having that light illuminate the entire visible scene will shift the benefit towards forward rendering. However if you had a scene with 500 little streetlights all over on a complex scene, then deferred would be significantly better, as it is a lot of lights that are very small.
Edit: As an added you can only generally have 8 or so visible lights(vertex lights, pixel is less) in forward rendering before going into multiple draw calls. There are deferred rendering samples (not unity) of hundreds of visible dynamic lights. Something that would be completely inconceivable with forward rendering. It’s really good for high end AAA visuals, but for more cartoony and non realistic visuals forward can be a lot better.
Forward is more processing time per light but no base overhead.
Deferred is a lot of overhead but very little processing time per light.
There is a hard limit of 8 vertex lights per-object. You can have unlimited vertex lights total. There’s no limit on pixel lights, but every one (including the first one) in forward rendering adds an extra draw call.
Aside from lights, deferred rendering uses G-buffers, so as long as they have to be made anyway, you can use them for image effects (like soft particles) without any more performance hit.
What is the expected behaviour of draw calls when adding lights in deferred rendering ? Is it normal to have one additional draw call per light for this mode ? Do these draw calls ‘cost as much’ as an addtional draw call in forward mode ?
No, in deferred rendering the lights are processed afterward in a full screen effect. It’s done only on the visible pixels as well, so you could have 1000 meshes on screen, or 1 it’s still the same amount of processing for lighting.
Deferred: each object is drawn twice; each light is drawn once (or twice, if it’s lightmapped). So it’s 2objects + 2lights draw calls, so to speak. On some platforms (Mac+Radeon GPUs) we have to do one more pass over the scene (so it’s 3*objects) due to driver bugs.
Forward: each object is drawn once for each per-pixel light that touches it. So in the worst case it’s objects*lights draw calls.
That said, draw calls only matter if you’re CPU bound. They can (and often are) a CPU bottleneck, but you could very well be GPU fillrate bound (for example). Optimizing to lower the draw calls won’t help in that case - the bottleneck is not the CPU!
Thanks Aras, that’s exactly what I wanted to know !
I’m aware draw calls are not necessarily the first bottleneck you bump, I just like to understand how things work internally to avoid doing stupid things ^^
I would say deferred in Unity is Useless as it doesnt use MRT. If you take a look at the scene composition with Pix it renders the scene TWICE which basically double the draw calls.
Also, I never seen a commercial engine resetting render states/textures and shaders before each draw call. That’s a minimum, I am not a expert but I know that we usually avoid such calls, even a simple per material organisation before rendering the scene would drastically improve performances.
actually, dynamic batching should avoid exactly that kind of resetting.
if you decide to disable batching then it will do exactly that: not batch anything and stop giving a damn about the order in what stuff happens