C++ modules vs. GDExtension - who wins? #135
Replies: 3 comments 9 replies
-
I took a read and here's my thoughts:
|
Beta Was this translation helpful? Give feedback.
-
Also, I've been thinking of introducing the notion of experimental features in Goost. The idea of experimental features is that they:
This removes the obligation of maintenance, while also allowing for even faster development cycles. I've never actually seen that sort of experimental development in Godot. And this is where GDExtension can be incorporated for those kind of experimental features safely. |
Beta Was this translation helpful? Give feedback.
-
I am going for a whole different approach. Instead of beating the same old dead horse I have been looking for a new language to implement that will be faster and more multi-purpose than the currently available languages. First I looked into Wren and that had some issues. Is very limited in scope and the truthy/falsy is backwards and other issues. Then I was gonna go with a few other ones and spent a bit of time until I found what I think is the best one for Godot daScript https://dascript.org/. Compatible licensing model, is strongly typed, and looks similar to GDScript. According to their benchmarks is faster than LuaJIT, faster than C# and Java, and it reaches equal performance to unoptimized C++. Even more interesting it has pointer types like C++ and can even natively interface with external code at binary level using unsafe keyword I believe kinda how C# does it so built in abi. This language can potentially replace GDScript, Modules, GDNative and even C#. The beautiful thing is that you will be able to write all the code right in Godot Editor so you will no longer need compilers since is an interpreted language. You can build libraries of addons using .da scripts that can do anything a module, GDExtension/GDNative can. |
Beta Was this translation helpful? Give feedback.
-
Context
As you may know, Godot core developers have come up with a new system called GDExtension in Godot 4.x (still in development). It's a replacement for deprecated GDNative technology for loading dynamic libraries. But could this approach replace static C++ modules in Godot? If yes, to what extent?
For reference, I've personally added a buildsystem feature in the past called "custom modules": godotengine/godot#36922. It's a really convenient feature which allows you to compile C++ modules from anywhere by recompiling the engine with them. This is something that Goost currently uses, in fact.
According to not yet fully clear design decisions, GDExtension allegedly aims to replicate what C++ modules can do. Godot even keeps track of discrepancies when comparing to C++ modules: godotengine/godot-cpp#633.
I've opened this discussion in order to see to what extent it may be reasonable to port Goost to GDExtension at some point, especially when Goost is currently advertised as a "general-purpose Godot extension", which may lead to confusion once Godot 4.0-stable is released if we decide to keep using C++ modules for whatever reasons.
Discussion
Are C++ modules discouraged to use?
According to official responses we've got from the lead developer (see for instance godotengine/godot-proposals#565 (comment)), C++ modules are discouraged to use in the future with a generic reply of "use at your own risk". Yet according to my experience, I've rarely had issues with C++ modules in Godot.
Pros of using C++ modules
Here are some reasons why I think C++ modules are superior to use at the moment:
No need to maintain your own buildsystem. Just use whatever Godot provides to compile modules, with ability to override any compilation flags. For now, using GDNative/GDExtension requires you to write your own scripts for building libraries, for all platforms (some of them are do not support dynamic libraries and/or GDNative/GDExtension technology). This is a lot of work. Official build scripts make it possible to compile Godot for all supported platforms as well https://github.com/godotengine/build-containers and https://github.com/godotengine/godot-build-scripts, so most of the time you don't really have to worry about maintaining your own buildsystem.
No need symlink plugins to be used in several Godot projects. You can just compile the engine with modules and have all classes available built-in. Really, this is what "batteries included" means. This is not possible to achieve with GDExtension at the moment. At most, only global editor-only plugins are going to be allowed (like accessing from
editor://
, see Universal plugins [wip] godotengine/godot#35432 (comment)), but not much more than that.GDExtension will be limited to what
ClassDB
provides. If something is not exposed, you have to make changes upstream (Godot) to resolve such limitation. But then your use case may be considered as a corner case which is not worth to be exposed/maintained in Godot. Under those circumstances, it's much easier to add a feature via C++ modules because you literally have access to mostly everything in the engine. You can also patch the engine's own code slightly to resolve limitations, and features like Add callbacks toMain::setup()
/Main::start()
/Main::cleanup()
, so to allow much freedom to modules. godotengine/godot-proposals#1593 become possible to implement. This gives back control over code.Never-ending discrepancies between GDExtension and the engine. For Godot Engine contributors (like me), this will result in a delay of development. If some feature becomes available in the engine, it will always take some delay before repositories that provide GDExtension implementations like https://github.com/godotengine/godot-cpp catch up.
Godot's own source code is like a database of existing solutions. Data structures can also be reused extensively without having to use C++ standard library (which may bloat binary size and make compiler errors harder to read) If you develop a C++ module, in a lot of cases you can just copy-paste the code and it will work with little to no modifications. This really speeds up the development.
Pros of using GDExtension
Faster to recompile. Building the engine is a slow process, but frankly not that slow on my machine (10 min - full rebuild, 15-30 seconds - single file change).
Easier adoption for users. It might be easier to download and install a library rather than downloading Godot engine with Goost module precompiled.
Somewhat independent development. Those people that use Goost rely on releases of Godot + Goost. If Godot makes a new release but Goost remains at the same state, one has to make a new Godot + Goost release anyway.
I think some or most of the above limitations can be resolved, but Godot core developers must show seriousness in maintaining such a system on par with the engine itself.
Issues
There are already limitations that I see could be problematic if we port Goost to use GDExtension, so below is the list of concrete examples of issues:
AbstractPolygon2DEditor
is not exposed inClassDB
: https://github.com/goostengine/goost/blob/173af73e45395fea2c6a9ada6c78f71941f71448/scene/2d/editor/poly_node_2d_editor_plugin.h. Goost extensively reuses this class forPolyNode2D
used for boolean operations in the scene (and much more). If this class is not exposed, it would mean maintaining our own implementation, not good - duplication, too easy to go out of sync implementation-wise.Texture2D
according to [GDExtension] Missing methods, classes and API discrepancies. godotengine/godot-cpp#633 (comment), which is needed for classes likeGradientTexture2D
,LightTexture
etc.Image
API is vital in general because Goost has a dedicated image component.add_child_notify()
needed to manage children for classes likePolyCollisionShape2D
to rebuild shapes without polling or usingget_parent()
, which is in most cases discouraged.Variant
internals might be problematic. Goost hasVariantResource
, for instance. See Godot proposals like Expose Variant's internal generic pointer for GDNative godotengine/godot-proposals#3037.goost/core/register_core_types.cpp
Line 32 in 1e2074e
GoostEngine.defer_call_unique()
, which is useful for optimization that typically use "dirty" flag.Issues in other projects
Conclusion
It might be a bit early to make final conclusions, but I'd like to track issues and limitations with GDExtension here, and see if it's worth porting Goost to use GDExtension as a whole, or perhaps still provide Godot + Goost builds, or a combination of both. But according to issues outlined above, it might not be reasonable to port Goost to use GDExtension mainly due to the nature of Goost, which actually aims to reuse and extend Godot's core. This potentially signifies that more limitations like this may popup in the future.
You also have to be aware of Goost development philosophy.
This post will be updated as development goes on, with more concrete examples. Feel free to comment in the meantime!
Beta Was this translation helpful? Give feedback.
All reactions