Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a built-in debug menu that displays current performance #100829

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Calinou
Copy link
Member

@Calinou Calinou commented Dec 26, 2024

This can be used to diagnose performance issues, both for developers and players (since this is also available in exported projects). Compared to the editor's Monitors tab, this has a few advantages:

  • Performance information is overlaid on the running game, so you can still view it while in fullscreen on a single-monitor setup.
  • The editor doesn't need to be running in the background, so it works in exported projects where performance is the most indicative of what players will experience.

Press F3 to cycle between 3 modes: hidden, compact (FPS/frametime display only), detailed. This key can be changed in the project settings' input map by modifying ui_cycle_debug_menu (remember to enable Show Built-in Actions). The debug menu can also be programmatically shown by changing SceneTree.debug_menu_mode from a script.

The debug menu's scale automatically adapts to the window size if using the canvas_items or viewport stretch mode. The default scale is controlled using the gui/theme/default_theme_scale project setting.

This PR is a C++ port of the godot-debug-menu add-on I wrote with a few tweaks. Happy holidays 🙂

Preview

Forward+

Example integration in the game editor (notice how the viewport sizes match):

Forward+

Mobile

Mobile

Compatibility

Featuring a shader compilation stutter, so you can see what it looks like on the graph.

Compatibility

TODO

  • Rename to something else than DebugMenu, e.g. PerformanceOverlay. This "menu" doesn't provide any options you can interact with and it's not really related to debugging per se, so a different name would be more suited.
  • Add a project setting to set the debug menu mode to use on startup.
  • Add a project setting to change the location the debug menu appears in? This could be needed for some games where it'd overlap with HUD elements.
    • This could be an enum with 8 positions (top-left, top center, top-right, and so on).
  • Update the graphics settings description whenever any of the graphics settings is changed in RenderingServer. This can likely be done by emitting a signal in RenderingServer and connecting to it in DebugMenu.
  • Make the graphics settings description more compact somehow? While I've made the C++ port more compact than the add-on by reducing line spacing, it still takes up quite a bit of screen real estate right now.
    • One way to make it more compact is to write abbreviations next to each other, similar to what DuckStation and PCSX2 do with their debug overlays:

image

  • Prevent DebugMenu nodes from being selectable in the game editor (as they can get in the way). @YeldhamDev Is there some kind of node metadata available for this?

Debug menu in game editor

  • Figure out the occasional frametime spikes that occur with the detailed view. This is most likely due to graph drawing as commenting it out fixes the issue. Perhaps switching to Image-based drawing like the editor (visual) profiler might work better.
    • This is not a recent engine regression nor an issue specific to the C++ port as the add-on has the same issue, even on 4.2.stable.

This can be used to diagnose performance issues, both for developers
and players (since this is also available in exported projects).

Press F3 to cycle between 3 modes: hidden, compact (FPS/frametime display only),
detailed.
@drcucaracha
Copy link

Hi, could you add something like a label to know how much video memory and RAM is consumed by the application/game?

@tetrapod00
Copy link
Contributor

tetrapod00 commented Dec 26, 2024

I'm not sure it makes sense to color-code the entire bottom section of text based on the currently used rendering method. That same range of color hues (blue, green at least, arguably the vaguely red color for Mobile) is already used to indicate performance elsewhere in the UI. I think colorcoding just the renderer name or the line it is on might make more sense.

@RedMser
Copy link
Contributor

RedMser commented Dec 26, 2024

While this feature will be largely useful to many people, I don't really agree with the way it is implemented here. It feels very inflexible and too tightly coupled to SceneTree.

Wouldn't it be enough to expose the DebugMenu class (or however it'll be named) as a node you can add to your game?
This way you have full control over when it is visible, you can export properties on it which can be modified (e.g. styling, turning display mode into multiple booleans, position, etc.) and you could even insert it into multiple different viewports at once for split-screen or multi-window games (currently just the main window can have the overlay visible it seems).
For simple cases, the user may just add it as an Autoload so it hooks to the main window like in the current implementation.

This means the SceneTree API, the input map changes and the ProjectSettings changes could all be reverted. The class is exposed to ClassDB. Some logic that currently assumes that the node never moves would also need updating (e.g. detecting reparenting for viewport_node size_changed signal).

And in turn it would then require the user to add the node to an appropriate location by hand, and to use scripting to show/hide the overlay instead of a magic built-in action.

@Calinou
Copy link
Member Author

Calinou commented Dec 26, 2024

Wouldn't it be enough to expose the DebugMenu class (or however it'll be named) as a node you can add to your game?

I've thought about it, but then it's no longer automatically available in every project out of the box. This is an issue when testing MRPs or working on prototypes, as having to configure it manually in every of these projects would get tedious quickly. I understand the concerns about tight coupling, but having good integration/UX for this is paramount if you want people to be able to use it early on in their projects. Without having this in place, having this in core is only slightly easier than using the existing add-on.

There might be an argument for splitscreen or multi-window but from what I've seen, all these debug overlays are common across all viewports in other engines/games. The information they report doesn't change from viewport to viewport after all, with the exception of resolution (but in splitscreen games, it's often the same across all viewports anyway - just a divisor of the fullscreen size). For non-game applications (the main user of multiple window support), they aren't as likely to use a debug overlay like this in the first place.

Note that the node is dynamically added by SceneTree, so there is no performance or memory cost when the debug menu isn't visible (it's freed once you hide it and recreated when needed).

I'm not sure it makes sense to color-code the entire bottom section of text based on the currently used rendering method. That same range of color hues (blue, green at least, arguably the vaguely red color for Mobile) is already used to indicate performance elsewhere in the UI. I think colorcoding just the renderer name or the line it is on might make more sense.

That can be done, it'll just need splitting the rendering method line to its own node.

Hi, could you add something like a label to know how much video memory and RAM is consumed by the application/game?

This needs godotengine/godot-proposals#4871 to be implemented first, along with another API to query the amount of VRAM used by the game. Only RenderingDevice-based rendering methods will be able to implement this, as OpenGL has no standard API for this.

Regarding RAM utilization, Godot has some debug counters available for this, but in my experience, it doesn't accurately reflect the RAM used by the whole Godot process (I'm not sure why). If you compare what you see in the Windows task manager for instance, what Godot reports will often be a fair bit lower than what's reported in the task manager. I would need to make sure what it's reporting is 100% accurate before we expose this information in the debug menu, as displaying misleading information is worse than not displaying any information.

@arkology
Copy link
Contributor

The only thing I know for sure - this one will be great addition for Game Editor/Workspace. Other questions (should it be separate node accessable by users (including in exported release builds), which data it should provide and so on) are still opened.

@YeldhamDev
Copy link
Member

Prevent DebugMenu nodes from being selectable in the game editor (as they can get in the way). @YeldhamDev Is there some kind of node metadata available for this?

Not currently, no. If such system would be implemented, it would also need to prevent it appearing in the remote tree as well.

@timoschwarzer
Copy link
Contributor

It would be nice if this would be somehow expandable by user code.
(DebugMenuPlugin?). I'm thinking of stuff like network latency for other games or general debug information that is specific to the game (scene management, 3rd party integrations like FMOD etc.pp.).
In split screen games (i.e. subviewports) the time it took to render that specific viewport would be interesting.

@ckaiser
Copy link
Contributor

ckaiser commented Dec 26, 2024

Tested on Windows, works as intended. I've been using your extension on most of my projects so having this built in would be great! 🥳

Something I noticed but that is purely personal preference is that I like the old colors a bit better, it looks more contrasty and the green seems to over-highlight text that really isn't that important and doesn't change much.

extension_v_inbuilt

@Alexofp
Copy link

Alexofp commented Dec 27, 2024

pic

Great plugin, would be incredibly useful to have in the engine, I would love if there was a way to show how many drawcalls, gpu memory and triangles are being pushed to the renderer. Very important info when you're trying to optimize your game
I modified the gdscript plugin to show that info and it's been perfect for me. Would be nice to have these options (maybe optionally) somewhere here if it's gonna be added..

Copy link
Contributor

@Mickeon Mickeon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docs are ffffffffine

@@ -1679,6 +1680,37 @@ bool SceneTree::is_multiplayer_poll_enabled() const {
return multiplayer_poll;
}

void SceneTree::set_debug_menu_display_mode(DebugMenuDisplayMode p_mode) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both setter and getter should probably be completely hollow in release (non-debug) builds. Same goes for other aspects of this menu.

Copy link
Member Author

@Calinou Calinou Dec 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's allowed in release builds on purpose (see OP for rationale) 🙂

If you want to disable it in release builds in your project, you could unbind the built-in input event from the project settings. I believe you can use feature tags on input action names so that you can still have something assigned to ui_cycle_debug_menu.debug, similar to the various .macos overrides already present there. If this doesn't suffice, we could always have a dedicated allow_debug_menu project setting that you could override to false for the release feature tag.

@Calinou
Copy link
Member Author

Calinou commented Dec 27, 2024

I would love if there was a way to show how many drawcalls, gpu memory and triangles are being pushed to the renderer. Very important info when you're trying to optimize your game

This information is only reported for 3D currently (it doesn't take anything 2D into account), so it would be irrelevant for 2D projects. If it was to be added to the debug menu, it'd have to be a project setting you manually enable, or we could hide it if the reported draw call/primitive count is 0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add toggleable on-screen debugging information/statistics while the project is running
10 participants