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

[DRAFT] GDExtension: Add compatibility system for virtual methods #100674

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

dsnopek
Copy link
Contributor

@dsnopek dsnopek commented Dec 20, 2024

This is the start of a compatibility system that will allow us to change the signature of virtual methods, and not crash existing GDExtensions that implemented the old version of the virtual methods.

It allows registering compatibility virtual methods, like:

#ifndef DISABLE_DEPRECATED
	// The "_save_compat_100447" is an alias that allows us to refer to this older version of the virtual method.
	GDVIRTUAL3R_COMPAT(_save_compat_100447, Error, _save, Ref<Resource>, String, uint32_t)
#endif

	// This is the current version that has the new signature with the new argument.
	GDVIRTUAL4R(Error, _save, Ref<Resource>, String, uint32_t, FileAccess::SaveIntegrityLevel)

Then when we're calling the virtual method, we can do something like this:

	Error err = ERR_METHOD_NOT_FOUND;

	if (GDVIRTUAL_CALL(_save, p_resource, p_path, p_flags, p_integrity_level, err)) {
		// We return here if the GDExtension implements the current version of the virtual method.
		return err;
	}

#ifndef DISABLE_DEPRECATED
	// If not, we fall back on the old one. Notice the "_save_compat_100447" alias we're using here instead of "_save".
	GDVIRTUAL_CALL(_save_compat_100447, p_resource, p_path, p_flags, err);
#endif // DISABLE_DEPRECATED

	return err;
}

This also changes the extension_api.json file to include a hash for the signature of each virtual method, and updates the GDExtension interface to include a hash argument when Godot is asking the GDExtension for a particular virtual method.

The idea is: the bindings will hang on to the hashes for all the virtual methods they support, and when Godot asks for a particular virtual method, if the hash doesn't match what the GDExtension has, then return nullptr as if the GDExtension didn't implement the virtual method at all. So, if a GDExtension was compiled with an older hash, then the first GDVIRTUAL_CALL() will return false (indicating that the virtual method isn't implemented), but then the second one will succeed because the hash will match what the GDExtension has.

PR godotengine/godot-cpp#1676 are the companion changes for godot-cpp

Marking as DRAFT because there's still a couple things to do:

  • Make a godot-cpp PR that implements this
  • Do lots and lots more testing :-)
  • Store the hashes for the compatibility methods, so we can include them in the JSON
  • Compare the hashes for virtual methods when comparing JSON files, so that we can detected missing compatibility methods via CI

NOTE: This presently includes the changes from PR #100447 so that I'd have a change to test, since there is a virtual method signature that we want to change there.

darksylinc and others added 2 commits December 19, 2024 19:10
This PR adds an argument to most save functions to specify what level of
integrity should Godot attempt to guarantee when writing a file.

This in preparation for PR godotengine#98361; which will introduce a full sync
barrier when performing save operations to avoid data loss.

This PR puts such expensive sync() behind the enum
SAVE_INTEGRITY_SAVE_SWAP_PLUS_SYNC; which should be used sparingly for
important information.

This PR also sets most cache files to be saved as either
SAVE_INTEGRITY_SAVE_SWAP (old default behavior) or SAVE_INTEGRITY_NONE;
because Godot can easily generate thousands of these file saving
operations. Performing thousands of full syncs() would be too expensive,
specially when these files can be regenerated if they're corrupted or
lost.

The PR is incomplete as it does not yet expose integrity levels to the
user, which is relevant for certain file saving operations, such as when
game save files that store the player's progress (those should be done
with SAVE_INTEGRITY_SAVE_SWAP_PLUS_SYNC).
@Zylann
Copy link
Contributor

Zylann commented Dec 21, 2024

GDVIRTUAL also includes calls to scripts, so is this going to benefit scripts as well?
Also, will extensions be able to define compatibility virtual methods too?

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.

3 participants