Skip to content

[Web] Add memory64 option to setup the foundations of wasm64 #105670

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
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

adamscott
Copy link
Member

@adamscott adamscott commented Apr 23, 2025

Even if wasm64 is not the silver bullet, browsers begin to support it, so we may as well begin work to officially support builds.

The new memory64 option has 3 values (and some aliases).

  • wasm32 (default, aliases: 0, no)
  • wasm64 (aliases: 1, yes)
  • wasm32+64bitptrs (aliases: 2)

0, 1, and 2 aliases correspond to -sMEMORY64 values for Emscripten. (see that link for the wasm32+64bitptrs option explanation)

For wasm64 and wasm32+64bitptrs, the WASM_MEMORY64_ENABLED define will be set.

Currently, actually using MEMORY64 seems to break our current JS logic (as BigInt arithmetic don't like to be mixed with standard numbers). So wasm64 and wasm32+64bitptrs builds wont actually technically work out of the box.

I'm doing this PR right now because I want to setup the grounds for supporting the feature in future PRs, especially with the help of WASM_MEMORY64_ENABLED.

I currently have a feature currently baking that will need to know which type of memory we're dealing with.

Edit: I modified the PR to introduce instead bool OS_Web::is_memory64().

@adamscott adamscott added this to the 4.x milestone Apr 23, 2025
@adamscott adamscott requested a review from a team as a code owner April 23, 2025 00:35
@adamscott adamscott requested a review from a team April 23, 2025 00:35
akien-mga
akien-mga previously approved these changes Apr 23, 2025
@akien-mga akien-mga modified the milestones: 4.x, 4.5 Apr 23, 2025
@dsnopek
Copy link
Contributor

dsnopek commented Apr 23, 2025

WebXR almost certainly doesn't work with wasm64 because of the way we're passing data between JS and C++. But that's something that I'll need to work on in a future PR :-)

@adamscott
Copy link
Member Author

adamscott commented Apr 23, 2025

I modified my PR to remove WASM_MEMORY64_ENABLED and to introduce instead a runtime check instead:

// in `platform/web/os_main.h`
bool is_memory64() const { return sizeof(size_t) == sizeof(uint64_t); }

@dsnopek
Copy link
Contributor

dsnopek commented Apr 23, 2025

I modified my PR to remove WASM_MEMORY64_ENABLED and to introduce instead a runtime check instead:

If we can know at compile time, why use a runtime check?

@adamscott
Copy link
Member Author

adamscott commented Apr 23, 2025

I modified my PR to remove WASM_MEMORY64_ENABLED and to introduce instead a runtime check instead:

If we can know at compile time, why use a runtime check?

Yeah. That's a compelling argument. But I could force inlining the function and the optimizer will surely optimize the crap out of these static checks.

I'm just worried to introduce a #define that essentially does a simple sizeof() check can do.

Edit: I just did add _FORCE_INLINE_ to the function.

@@ -73,6 +73,8 @@ class OS_Web : public OS_Unix {
// Override return type to make writing static callbacks less tedious.
static OS_Web *get_singleton();

_FORCE_INLINE_ bool is_memory64() const { return sizeof(size_t) == sizeof(uint64_t); }
Copy link
Member

Choose a reason for hiding this comment

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

Is this true or false with wasm32+64bitptrs?

Copy link
Member Author

@adamscott adamscott Apr 23, 2025

Choose a reason for hiding this comment

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

Is this true or false with wasm32+64bitptrs?

This is true. The runtime is wasm32, but the pointer sizes are 64-bit wide. The previous WASM_MEMORY64_ENABLED define was applied to wasm32+64bitptrs.

Copy link
Member Author

Choose a reason for hiding this comment

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

Is this true or false with wasm32+64bitptrs?

This is true. The runtime is wasm32, but the pointer sizes are 64-bit wide. The previous WASM_MEMORY64_ENABLED define was applied to wasm32+64bitptrs.

This is why I specified the option as +64bitptrs instead of choosing a simpler, but way more cryptic wasm32+64 (which would imply wasm32+wasm64, which is not the case).

Copy link
Member Author

Choose a reason for hiding this comment

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

Mmm. Makes me reconsider the use of actual name of the function is_memory64(), as it may be misleading. Technically, wasm32+64bitptrs isn't truly MEMORY64.

@adamscott adamscott marked this pull request as draft April 23, 2025 15:20
@adamscott
Copy link
Member Author

I put the PR in draft mode for the following reason. I just realized that we append the builds with .wasm32 currently.

Capture d’écran, le 2025-04-23 à 11 20 35

As memory64=wasm64 is technically not strictly compatible/interchangeable with wasm32, I wonder if we should change the build prefix to be wasm64 instead of wasm32. It complicates everything though, buildsystem-wise.

@dsnopek
Copy link
Contributor

dsnopek commented Apr 23, 2025

But I could force inlining the function and the optimizer will surely optimize the crap out of these static checks.

My usual inclination is to not trust the compiler. :-) But this isn't my area of expertise, so I'm happy to trust more knowledgeable folks

As memory64=wasm64 is technically not strictly compatible/interchangeable with wasm32, I wonder if we should change the build prefix to be wasm64 instead of wasm32.

Personally, I think, yes, these should use the suffix wasm64 (and probably wasm32+64bitptrs too?)

I think we'll also need feature tags for these different types, because I think GDExtensions will also need to be compiled the same way as Godot in order to work together, and we'll need a way for Godot to select the right binary. Example:

web.debug.wasm32 = "res://bin/libgdexample.web.template_debug.wasm32.nothreads.wasm"
web.release.wasm32 = "res://bin/libgdexample.web.template_release.wasm32.nothreads.wasm"
web.debug.wasm64 = "res://bin/libgdexample.web.template_debug.wasm64.nothreads.wasm"
web.release.wasm64 = "res://bin/libgdexample.web.template_release.wasm64.nothreads.wasm"
web.debug.wasm32+64bitptrs = "res://bin/libgdexample.web.template_debug.wasm32+64bitptrs.nothreads.wasm"
web.release.wasm32+64bitptrs = "res://bin/libgdexample.web.template_release.wasm32+64bitptrs.nothreads.wasm"

@adamscott
Copy link
Member Author

adamscott commented Apr 23, 2025

(and probably wasm32+64bitptrs too?)

Technically, wasm32+64bitptrs should work on modern browsers, even on Safari (which don't support MEMORY64). So maybe we could stick to wasm32 for those builds.

Edit: OH. GDExtensions, right. Forgot about this. I will test the compatibility between them.

@akien-mga akien-mga dismissed their stale review April 23, 2025 19:39

Scope changed and will require another review.

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