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

Register Engine, OS, ProjectSettings, and Time singletons in time for INITIZATION_LEVEL_CORE #98862

Merged

Conversation

HuntJSparra
Copy link
Contributor

@HuntJSparra HuntJSparra commented Nov 5, 2024

This PR registers the Engine, ProjectSettings, OS, and Time singletons to ClassDB earlier so that GDExtensions can access them during INITIALIZATION_LEVEL_CORE. Previously, these were only accessible in INITIALIZATION_LEVEL_SCENE and later.

Addresses GIP#9134.

This is done by:

  • Using GDREGISTER_CLASS and calling Engine::add_singleton for the 4 singletons before register_core_extensions().
  • Setting Engine and OS values earlier when possible (e.g., Engine::set_project_manager_hint.
  • Adding a null check for TextServerManager::get_singleton in OS_Windows::get_system_font_path_for_text to prevent a crash since Windows needs the TextServerManager to get the text direction, which is not created until after INITIALIZATION_LEVEL_CORE.

Caveats:
While the exposed singleton methods are all safe to call, they may not return the expected value if they depend on later setup. These exceptions include:

  • The order of GLOBAL_DEF, etc. calls for project settings unrelated to the 4 singletons is mostly untouched, meaning many defaults are not set until after INITIALIZATION_LEVEL_CORE (e.g., rendering/* settings from RenderingServer::init()).
  • OS::has_feature will still return false for any server feature until RenderingServer has been created.
  • OS_Windows::get_system_font_path_for_text depends on the TextServer and will return the empty string until it is created.

Notes on dependencies and code-paths of exposed singleton methods: [Google Sheets Link]

@clayjohn clayjohn added this to the 4.x milestone Nov 5, 2024
@HuntJSparra HuntJSparra force-pushed the early-projsettings-registration branch from 3364252 to 47764c7 Compare November 5, 2024 20:51
@HuntJSparra HuntJSparra marked this pull request as ready for review November 5, 2024 21:01
@HuntJSparra HuntJSparra requested review from a team as code owners November 5, 2024 21:01
@HuntJSparra HuntJSparra force-pushed the early-projsettings-registration branch from 47764c7 to 0ff3cc0 Compare November 5, 2024 23:18
@dsnopek dsnopek requested a review from a team November 7, 2024 18:57
@dsnopek
Copy link
Contributor

dsnopek commented Nov 7, 2024

Thanks!

I'm all for this change at a high-level: it would solve a number of long-running issues that many folks have had with GDExtension. I linked to some of the old issues where this was discussion in a comment on the proposal.

It's unfortunate that this requires so many little changes throughout main.cpp and the non-obvious one to os_windows.cpp. That makes me think there's probably going to a bunch of other little regressions that will come out of merging this, that it doesn't catch. So, if we decide to go for this in Godot 4.4, we should probably do it soon: we're still early enough in 4.4's cycle that we could cause and fix a few regressions (but not before 4.4-dev4 since there's already so much merged for that one).

Skimming through the changes, they seem fine to me.

Copy link
Contributor

@dsnopek dsnopek left a comment

Choose a reason for hiding this comment

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

I tested this with some GDExtensions on both Linux and Android, including actually using the ProjectSettings singleton in INITIALIZATION_LEVEL_CORE in the 'godot_openxr_vendors' extension (the use-case there is to not request OpenXR extensions at all if certain project settings aren't enabled -- currently, we have to always request them, but then just avoid using them).

Aside from my note below about a warning, it seemed to work fine in my testing!

Comment on lines +1913 to +1919
if (!OS::get_singleton()->_verbose_stdout) { // Not manually overridden.
OS::get_singleton()->_verbose_stdout = GLOBAL_GET("debug/settings/stdout/verbose_stdout");
}
Copy link
Contributor

Choose a reason for hiding this comment

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

When testing this locally, I'm getting this warning:

WARNING: Property not found: 'debug/settings/stdout/verbose_stdout'.
     at: get_setting_with_override (core/config/project_settings.cpp:374)

I think this line needs to also get moved up here:

GLOBAL_DEF("debug/settings/stdout/verbose_stdout", false);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have moved the "debug/settings/stdout/" settings registrations earlier, as you suggested.

@HuntJSparra
Copy link
Contributor Author

It's unfortunate that this requires so many little changes throughout main.cpp and the non-obvious one to os_windows.cpp. That makes me think there's probably going to a bunch of other little regressions that will come out of merging this, that it doesn't catch.

That is probably my biggest concern with this. I traced all the affected code-paths I could find and I have a GDExtension+project that tests the loading, but I only have a PC and an older Mac to test on. I can clean up my test project and share it here if that would help people with their review, but, even if those tests pass on all devices, I'd still be worried about edge-cases.

All that is to say: I am fine waiting until the next version in order to ensure 4.4's stability.

@HuntJSparra HuntJSparra force-pushed the early-projsettings-registration branch from 0ff3cc0 to 1ae91a2 Compare November 7, 2024 21:15
@HuntJSparra
Copy link
Contributor Author

I tested this with some GDExtensions on both Linux and Android, including actually using the ProjectSettings singleton in INITIALIZATION_LEVEL_CORE in the 'godot_openxr_vendors' extension (the use-case there is to not request OpenXR extensions at all if certain project settings aren't enabled -- currently, we have to always request them, but then just avoid using them).

The default for the XR project settings are not set until shortly before INITIALIZATION_LEVEL_SERVERS, so I suspect this would fail if the extension was somehow added before the project settings were saved for the first time. That is the case for a few hundred project settings (particularly the rendering settings) since I only moved up the settings needed for initialization and the 4 singletons.

Most of those look safe to move earlier, but I have avoided touching them because it would affect many more parts of the Engine (e.g., many rendering/ project settings defaults are set by the RenderingServer). Still, if people prefer, I can move some or as many as possible earlier.

@dsnopek
Copy link
Contributor

dsnopek commented Nov 7, 2024

The default for the XR project settings are not set until shortly before INITIALIZATION_LEVEL_SERVERS, so I suspect this would fail if the extension was somehow added before the project settings were saved for the first time. That is the case for a few hundred project settings (particularly the rendering settings) since I only moved up the settings needed for initialization and the 4 singletons.

These are project settings coming from the GDExtension, not from Godot. So, it worked fine in my testing :-)

@HuntJSparra HuntJSparra force-pushed the early-projsettings-registration branch from 1ae91a2 to 2d01822 Compare November 11, 2024 17:07
@HuntJSparra HuntJSparra requested a review from dsnopek November 11, 2024 19:06
@dsnopek
Copy link
Contributor

dsnopek commented Nov 12, 2024

Discussed at GDExtension meeting: we think this one will improve this long-standing issue with GDExtension. It could cause subtle bugs that we won't notice until later, so it probably makes sense to merge early in the 4.4 cycle, and we can partially revert or fix issues as the come up before release. ProjectSettings is a little tricky because not all settings are available right away, but there is no caching, so they can be requested later; this isn't any worse than ProjectSettings not being available at all.

@RandomShaper
Copy link
Member

  • OS::has_feature will still return false for any server feature until RenderingServer has been created.

Not sure if this would be a big deal in practice. However, we may still want to have an early has_server_feature_callback() that in debug builds, if verbose enabled, with a WARN_PRINT_ONCE or something similar stating that the query can't fall back to the servers at that point. That may help debugging some issues where a maintainer doesn't understand why they are getting false. Not sure. Just an idea.

@RandomShaper
Copy link
Member

Besides my little two comments, overall this looks good and indeed a good tradeoff between benefit and risk of regressions.

@HuntJSparra HuntJSparra force-pushed the early-projsettings-registration branch from 2d01822 to d2e87cf Compare November 21, 2024 22:41
@HuntJSparra HuntJSparra force-pushed the early-projsettings-registration branch from d2e87cf to 48fbe41 Compare November 21, 2024 23:19
@HuntJSparra
Copy link
Contributor Author

Thank you for the review!

I've implemented the verbose-debug warning for OS::has_feature and commented the TextServerManager check as you suggested.

I've also adjusted the fix from #99149 since this PR calls Engine::set_max_fps earlier but we still need RenderingDevice to propagate the max FPS after it is created.

Copy link
Member

@RandomShaper RandomShaper left a comment

Choose a reason for hiding this comment

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

Leaving my approval as there isn't anything else I can suggest to improve this and looks good enough to me for a merge now it's still early in the release cycle and seeing how it goes.

Disclaimers: I haven't tested it myself and my approval is notwithstanding there may still be outstanding suggestions or concerns from other maintainers.

Copy link
Contributor

@Repiteo Repiteo left a comment

Choose a reason for hiding this comment

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

Codestyle checks out

@Repiteo Repiteo modified the milestones: 4.x, 4.4 Nov 26, 2024
@Repiteo Repiteo merged commit 0045b1a into godotengine:master Nov 26, 2024
20 checks passed
@Repiteo
Copy link
Contributor

Repiteo commented Nov 26, 2024

Thanks! Congratulations on your first merged contribution! 🎉

@HuntJSparra HuntJSparra deleted the early-projsettings-registration branch November 30, 2024 03:51
@AThousandShips AThousandShips changed the title Register Engine, OS, ProjectSettings, and Time singletons in time for for INITIZATION_LEVEL_CORE Register Engine, OS, ProjectSettings, and Time singletons in time for INITIZATION_LEVEL_CORE Dec 4, 2024
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.

5 participants