godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
90.85k stars 21.14k forks source link

Dynamic OmniLight3D shadows are slower than godot3 #94295

Open jamie-pate opened 3 months ago

jamie-pate commented 3 months ago

Tested versions

Reproducible in 4.2.2 and 4.3-beta2

System information

Godot v4.3.beta3 - Windows 10.0.19045 - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 1070 - Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz (12 Threads)

Issue description

When porting to godot4 it can be expected that the forward+ renderer will be slower due to it's higher fidelity. I wasn't expecting such a penalty when adding lights with dynamic shadows, which also affects the compatibility renderer. Maybe we were spoiled with how fast they were in godot3?

It seems like dynamic shadows are disproportionately slower than in godot3.

Ideally optimizations can be found going forward to tighten the gap or at least we can document what quality gains we are getting for the frame time cost?

Having a baseline set of benchmarks in godot3 can help set targets for performance in godot4.

Steps to reproduce

Create a scene in godot3 and godot4 with dynamic vs baked shadows and benchmark them. (see mrp)

There is a results.ods and results.txt with much more data on other methods/drivers but this summary highlights the important parts. image

Performance for baked lighting seems comparable in the compatibility rendering method but there are large losses when dynamic shadows are enabled.

Minimal reproduction project (MRP)

shadow-perf.zip

Calinou commented 3 months ago

Lights with shadows are multipass in 4.x Compatibility, while they were single-pass in 3.x GLES3. This was done to improve compatibility with old/low-end devices and decrease the base cost of scenes with few (or no) lights with shadows enabled.

This means you should compare the performance with 3.x GLES2, not 3.x GLES3. The Mobile rendering method is closer in spirit to 3.x GLES3 in terms of how it renders lights with shadows enabled.

When targeting integrated graphics and mobile, you really want to avoid having more than one omni/spot light rendering real-time shadows. This means having e.g. a flashlight or muzzleflash casting shadows is fine, but make sure you don't have several at once. Rely on baked lightmaps as much as possible – they're fully supported in Compatibility in 4.3, provided your GPU has Vulkan support to initially bake them.

Lastly, Forward+'s clustered rendering of lights is designed with dedicated GPUs in mind. On integrated graphics (particularly old/low-end ones), the Mobile rendering method will perform significantly better.

jamie-pate commented 3 months ago

The mobile and gles2 stats from the zip for completeness:

OpenGL ES 2.0 Renderer: Intel(R) UHD Graphics 630 |   |   |   |  
  | 220.00 | 2.33 | baked | 1.64
  | 94.29 |   | dynamic | 1.27

Vulkan 1.2.162 - Forward Mobile - Using Device #0: Intel - Intel(R) UHD Graphics 630
  | 50.77 | 0.99 | baked? | 7.09
  | 51.43 |   | dynamic | 2.33

OpenGL ES 2.0 Renderer: NVIDIA GeForce GTX 1070/PCIe/SSE2 |   |   |   | 
  | 420.00 | 1.10 | baked | 1.78
  | 381.68 |   | dynamic | 2.21

Vulkan 1.3.278 - Forward Mobile - Using Device #1: NVIDIA - NVIDIA GeForce GTX 1070
  | 330.00 | 0.79 | baked? | 2.27
  | 418.75 |   | dynamic | 2.02

I left mobile out because Baked lighting didn't seem to work with the mobile method

Calinou commented 3 months ago

I left them out because Baked lighting didn't seem to work with the mobile method

This is a known issue: https://github.com/godotengine/godot/issues/85145