godotengine / godot

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

Tilemaps with multiple occlusion layers tank performance when reloading the scene #84434

Open kingoftheconnors opened 1 year ago

kingoftheconnors commented 1 year ago

Godot version

4.1.3.stable.official

System information

Godot v4.1.3.stable - Windows 10.0.19043 - Vulkan (Compatibility) - Intel(R) HD Graphics 4600 (Intel Corporation; 20.19.15.5144) - Intel(R) Core(TM) i5-4590 CPU @ 3.30GHz (4 Threads)

Rendering was in COMPATIBILITY Mode

Issue description

Tilemaps with two Occlusion layers will tank performance and framerate when the scene is reloaded (such as in the case of a player dying).

For my computer, framerate goes from 177 (with V-sync disabled) to 30 after about 5 seconds of continuous reloading a scene using this code:

func _process(delta):
    if Input.is_key_pressed(KEY_R):
        get_tree().reload_current_scene()

This will reload the scene hundreds of times every second. However, this is only for a very simple scene with only a few tiles. If you draw out an entire level, you can drop your performance by 10 FPS with every reload (as in the case of a game I'm working on).

This happens whether you are using get_tree().reload_current_scene() or change_scene_to_file("res://NAME_OF_CURRENT_SCENE.tscn")

This issue also happens (but noticeably weaker) if you continually go to a second scene and then change BACK to the first scene.

The framerate shoots back up to full if the DirectionalLight2D is made invisible or shadows is turned off. On the other hand, you can change the Range Mask and Shadow Mask to have NO layers enabled, and this slowdown will still happen.

If you remove either one of the occlusion layers off the tilemap, this effect also goes away.

Steps to reproduce

  1. Make a new project using Compatibility mode rendering
  2. Create a Node2D. Give it a script with this code:
    
    extends Node

func _process(delta): if Input.is_key_pressed(KEY_R): get_tree().change_scene_to_file("res://level3.tscn")


3. Now create two nodes: A DirectionalLight2D and a TileMap
4. On the DirectionalLight2D, enable shadows
5. On the Tilemap, create a Tileset and under rendering give it two occlusion layers
6. Import the icon (or any graphic) and create a simple tile with it. Give the tile an occlusion box for BOTH occlusion layers.
7. Draw the new tile all over your scene
8. Click `Project` on the top-left and go to "Project Settings -> Display -> Window" and click the "V-Sync Mode" option and change it to disabled. Now your profiler will show you the true framerate instead of capping it at 60
9. Run the scene. Open the Debugger and click "Monitors" Now you can see the FPS.
10. Hold down the "R" button. The framerate should fall dramatically.

### Minimal reproduction project

[LightingProblem.zip](https://github.com/godotengine/godot/files/13255616/LightingProblem.zip)
AThousandShips commented 1 year ago

Can you please try this with a supported version, like 4.1.3 (only the latest patch version is supported, and it might already be fixed)

kingoftheconnors commented 1 year ago

@AThousandShips I have tested it on 4.1.3.stable.official and the problem is still there.