-
-
Notifications
You must be signed in to change notification settings - Fork 21.4k
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
Promote CowData to 64 bits #86730
Promote CowData to 64 bits #86730
Conversation
Note that this requires Also needs a godot-cpp companion |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good overall.
I'm wondering if this is neglecting 32-bit builds (they don't need or won't support 64-bit stuff such as > 3 GiB allocations and maybe not even 64-bit atomics) and so size_t
should be used intead.
UPDATE: Per @AThousandShips, size_t
won't necessarilly be 64-bit on 64-bit targets, so maybe something else that matches sizeof(void *)
, but you get the idea.
I changed to use a typedef for the size, depending on compiler, so it remains 32 bits on 32 bit platforms. |
@AThousandShips regarding GodotCPP, I am not certain if something has to change on that side. |
It does, it redeclares the type, unless we're okay with lack of parity over there |
core/templates/vector.h
Outdated
@@ -157,40 +158,40 @@ class Vector { | |||
return ret; | |||
} | |||
|
|||
Vector<T> slice(int p_begin, int p_end = INT_MAX) const { | |||
Vector<T> slice(Size p_begin, Size p_end = INT64_MAX) const { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need a macro for the max as well, I'd suggest a SIZE_MAX/MIN
and USIZE_MAX/MIN
though might clash with definitions existing already
@AThousandShips ah I completely forgot we strive to use the same syntax in GodotCPP than in Godot modules.. Will have to ask @bruvzg to lend a hand changing the code there once this one is merged. So I guess this PR is "kind of" compat breaking.. though it likely only affects GodotCPP, not the rest of the extensions. |
Thank God. I haven't tested yet, but will link up related issues. Lack of 64-bit resources is a problem for Terrain3D users with big terrains. So hopefully this will help fix our issue, crashing when saving large terrains in a >1gb resource file. And Godot issue #62585 |
While changing the size values of Also iteration over the packed vectors assume a 32 bit iteration value, might be worth looking into, and a number of other potential places, as well as any iteration over any of these types, avoiding errors |
@AThousandShips A lot other structures have to be fixed, not just those. Image also assumes 32 bits and this is giving troubles, but I don't want to do a huge PR that will take a long time to get merged and that I have to keep up to date, so I prefer we merge this one first, then work on individual PRs for the other structures. |
As long as the iteration cases aren't broken it should be safe enough |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code looks good to me, the sizing checks should work correctly with the new po2 method and my previous fix for the resize should still handle that just with a new range
Needs to ensure that any iteration being done isn't broken, might need a fix of any for (int...)
loops using Vector
so we don't get broken data etc., as part of the fixes involved in this are for cases where data does run out
Otherwise looks good, if everything else works right
490cee5
to
e9a7bf8
Compare
There's a MSVC warning to fix:
And the "Test project converter" in the C# build fails with a C# stacktrace: But I don't know if it's actually due to a C# issue, or just a Godot error that would happen on a non-dotnet build with just a different error (that project converter test is only run on the "Editor w/ Mono" Linux build). The test is just this, so this can be attempted locally to see if the error is reproducible:
|
cc. @Bromeon @dsnopek (GDExtension related) |
fixed the shift issue. |
Would suggest compiling with |
I haven't used MSVC to compile in an eternity, will check during the week. |
I don't think this is exactly true. It will only break godot-cpp, if godot-cpp is interacting with a I think with bruvzg's godot-cpp PR godotengine/godot-cpp#1357, we should be good going forward. And I think we can cherrypick it for the 4.2 and 4.1 versions of godot-cpp. But if a GDExtension compiled with an older godot-cpp is used with a newer Godot, AND it's passed a |
To the extent that this changes the memory layout of Variant types, it has an impact on C# interop structs. In C# we define interop structs that must match the memory layout of the C++ types so they can be reinterpreted and consumed from C#. For example, we get the size of a Godot String like this: godot/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs Line 477 in 107f296
This is basically copied from the C++ code ( godot/core/templates/cowdata.h Line 85 in 107f296
But this has changed in this PR since now the size is 64-bit, so it needs to be updated in C# too. As long as the changes are kept internally, it should not break compatibility but changing the user-facing API would be a problem. And if any of these types actually has a size that doesn't fit in a 32-bit Here's a somewhat naive diff that should fix the stackoverflow you are getting on CI:diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs
index d5d9404ed1b..c806263edb5 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropStructs.cs
@@ -474,7 +474,7 @@ namespace Godot.NativeInterop
public readonly unsafe int Size
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => _ptr != IntPtr.Zero ? *((int*)_ptr - 1) : 0;
+ get => _ptr != IntPtr.Zero ? (int)(*((ulong*)_ptr - 1)) : 0;
}
}
@@ -725,7 +725,7 @@ namespace Godot.NativeInterop
public readonly unsafe int Size
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => _ptr != null ? *((int*)_ptr - 1) : 0;
+ get => _ptr != null ? (int)(*((ulong*)_ptr - 1)) : 0;
}
}
@@ -875,7 +875,7 @@ namespace Godot.NativeInterop
public readonly unsafe int Size
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => _ptr != null ? *((int*)_ptr - 1) : 0;
+ get => _ptr != null ? (int)(*((ulong*)_ptr - 1)) : 0;
}
}
@@ -939,7 +939,7 @@ namespace Godot.NativeInterop
public readonly unsafe int Size
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => _ptr != null ? *((int*)_ptr - 1) : 0;
+ get => _ptr != null ? (int)(*((ulong*)_ptr - 1)) : 0;
}
}
@@ -971,7 +971,7 @@ namespace Godot.NativeInterop
public readonly unsafe int Size
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => _ptr != null ? *((int*)_ptr - 1) : 0;
+ get => _ptr != null ? (int)(*((ulong*)_ptr - 1)) : 0;
}
}
@@ -1003,7 +1003,7 @@ namespace Godot.NativeInterop
public readonly unsafe int Size
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => _ptr != null ? *((int*)_ptr - 1) : 0;
+ get => _ptr != null ? (int)(*((ulong*)_ptr - 1)) : 0;
}
}
@@ -1035,7 +1035,7 @@ namespace Godot.NativeInterop
public readonly unsafe int Size
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => _ptr != null ? *((int*)_ptr - 1) : 0;
+ get => _ptr != null ? (int)(*((ulong*)_ptr - 1)) : 0;
}
}
@@ -1067,7 +1067,7 @@ namespace Godot.NativeInterop
public readonly unsafe int Size
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => _ptr != null ? *((int*)_ptr - 1) : 0;
+ get => _ptr != null ? (int)(*((ulong*)_ptr - 1)) : 0;
}
}
@@ -1099,7 +1099,7 @@ namespace Godot.NativeInterop
public readonly unsafe int Size
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => _ptr != null ? *((int*)_ptr - 1) : 0;
+ get => _ptr != null ? (int)(*((ulong*)_ptr - 1)) : 0;
}
}
@@ -1131,7 +1131,7 @@ namespace Godot.NativeInterop
public readonly unsafe int Size
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => _ptr != null ? *((int*)_ptr - 1) : 0;
+ get => _ptr != null ? (int)(*((ulong*)_ptr - 1)) : 0;
}
}
Footnotes
|
@raulsntos Yeah I guess the Mono bindings should not really be accessing these internals. We have explicit functions exposed in the extension API now to avoid these situations, so I suppose it would be just a matter to move to that eventually (when Mono is moved to extension) |
I don't want to get too off-topic, but I don't agree that the move to GDExtensions would help here. The API exposed to retrieve this data would have a bigger cost than accessing the internals directly as we are doing today so we wouldn't change that in the new system. And to be honest that's not the problem, we just need to update the C# internals to match the C++ internals (similar to how godot-cpp is doing). I shared a diff that does just that and doesn't break compatibility since it doesn't change publicly exposed API. The main issue is that C# types like To put it in simple terms, if we have a Footnotes |
Just to be clear (although, it probably isn't necessary :-)) this isn't what the godot-cpp change is doing. godot-cpp doesn't directly access Godot's internals, it always goes through the GDExtension interface. The change to godot-cpp is doing two things:
|
Trying to review some of the ones mentioned in this PR, linked issues, or some I could find searching for references to CowData and 32/64 bits.
Reproducible in Not fixed by this PR. The stacktrace changes from Seems related indeed, but I tested and this PR does not solve the issue. It still crashes in the same place.
Tested with the MRP from #62585 (comment), this fixes it. Fixed by this PR. Fixed by this PR. |
Diff that should make the PR pass CI (two more MSVC warning fixes, and @raulsntos' C# changes): |
@akien-mga thanks lots for taking the time for this! |
Fixes a lot of bugs, please help me fill the list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested locally, seems to work well!
As I pointed out, further work will be needed at least for Image and BitMap to make their size handling 64-bit too. Possibly other classes based on CowData internally.
Thanks! |
Fixes a lot of bugs, please help me fill the list.
After this is merged, other areas of the engine can be fixed, such as Image, which also uses 32 bits offsets and causes crashes in some reasonable scenarios (such as baking lightmaps), but it depends on this one. Serialization also may need to be fixed.
Bugsquad edit: