godotengine / godot

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

Physics process delayed when adding camera to viewport #72510

Open rcorre opened 1 year ago

rcorre commented 1 year ago

Godot version

3.5.1.stable.arch_linux

System information

Linux 6.1.8-arch1-1, Nvidia 3080 525.85.05-2, GLES3

Issue description

I have a scene that already has a camera in it. That 3D scene is a child of a Viewport which is displayed to a TextureRect. That camera is current. When I add a second camera to that scene (non-current), the whole game hangs for ~500ms, meaning my next _physics_process call is ~500ms from the last one. Adding more cameras after that does not have any impact. If I remove the Viewport and rely on the builtin Viewport instead, the issue goes away. As far as I'm aware though, displaying a child viewport to a TextureRect is the suggested way to implement resolution scaling in Godot3.

My main script looks like this:

extends Control

onready var last_physics_frame := Time.get_ticks_msec()

func _unhandled_key_input(event: InputEventKey) -> void:
    if event.scancode == KEY_SPACE and event.is_pressed():
        var dup = Camera.new()
        get_tree().current_scene.add_child(dup)

func _physics_process(_delta: float) -> void:
    var time := Time.get_ticks_msec()
    var delay := time - last_physics_frame
    if delay > 200:
        print("Long physics delay ", delay, "ms")
    last_physics_frame = time

After pressing SPACE the first time, I see Long physics delay 436ms.

Steps to reproduce

  1. Open example project
  2. Run Main scene
  3. Press SPACE to spawn a new camera

Minimal reproduction project

example.zip

TheDuriel commented 1 year ago

displaying a child viewport to a TextureRect is the suggested way to implement resolution scaling in Godot3.

Not quite. If you want fine control over the scaling, other than what the project settings give you. You want to use a ViewportContainer.

Though this likely won't affect the camera initialization lag the issue itself is about.

rcorre commented 1 year ago

Huh, I didn't know there was much difference between a ViewportContainer and a TextureRect with a ViewportTexture. I can't remember why I picked one over the other.

I took some perf recordings:

When adding the camera, Main::iteration is spending a lot more time in these calls:

--8.59%--Main::iteration
|          
--7.75%--VisualServerWrapMT::draw
|          
--7.72%--VisualServerRaster::draw
        |          
        |--5.66%--VisualServerViewport::draw_viewports
        |          VisualServerViewport::_draw_viewport
        |          |          
        |           --5.07%--VisualServerViewport::_draw_3d
        |                     VisualServerScene::render_camera
        |                     |          
        |                     |--3.69%--VisualServerScene::_render_scene
        |                     |          |          
        |                     |           --3.65%--RasterizerSceneGLES3::render_scene
        |                     |                     |          
        |                     |                     |--2.29%--RasterizerSceneGLES3::_render_list
        |                     |                     |          |          
        |                     |                     |           --1.33%--RasterizerSceneGLES3::_setup_light
        |                     |                     |          
        |                     |                      --0.77%--RasterizerSceneGLES3::_fill_render_list
        |                     |                                |          
        |                     |                                 --0.56%--RasterizerSceneGLES3::_add_geometry

It does not happen in GLES2.

rcorre commented 1 year ago

Huh. This is really tricky to repro. It was happening consistently when I reported it. After a reboot, it never reproes. I haven't updated anything.