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

[AUDIO_WORKLET] Added support for MEMORY64 and 2GB heap (including tests) #23508

Open
wants to merge 81 commits into
base: main
Choose a base branch
from

Conversation

cwoffenden
Copy link
Contributor

@cwoffenden cwoffenden commented Jan 27, 2025

This is built on #22753 and uses the _2gb and _4gb tests (plus the parameter test) from #23659.

It adds support for MEMORY64 to audio worklets and tests that:

  • All the pointer offsets and maths now work with >2GB heap
  • Everything works building with MEMORY64 and >4GB heap

The tests already prove out various buffer combinations using the INITIAL_MEMORY and GLOBAL_BASE flags.

For the code changes, besides parameters expecting BigInt it also needed any shifts removing from the offset calculations (signed shifts fail >2GB, unsigned >4GB).

The interactive tests (from #23659) can be run with:

test/runner.py interactive_2gb.test_audio_worklet_params_mixing
test/runner.py interactive64_4gb.test_audio_worklet_params_mixing

We can remove the float-by-float JS copy and replace with this simple TypedArray set() calls.
Typed views are recreated if needed but otherwise are reused.
Lots of juggling with the various pointers, and next will be to reduce the code and move all of the output first to stop repeating some of the calculations. Some can also move to the constructor.
The code has also been brought back closer to the original for comparison.
The initial stackAlloc() is overflowing, seeming to need more space so this is accounted for.
Tested with various stack sizes, output sizes, and generators.
The assertions should now cover all cases of changes in address and size of the output views.
(Off home!)
Rough implementation to see what needs doing in JS vs Wasm.
The tests pass the audio context in a void* for convenience, which needs shortening/widening for 64-bit pointers.
@cwoffenden
Copy link
Contributor Author

What about the exsiting audio worklet tests in test_browser.py?

All the AW tests are silently failing. I'll look at fixing them next.

@cwoffenden
Copy link
Contributor Author

It looks like we already have interactive64 mode in test_interactive.py. Can you just add interactive64_4gb and interactive_2gb modes? (copy them from test_browser.py).

Done.

@cwoffenden cwoffenden marked this pull request as ready for review February 6, 2025 15:22
cwoffenden added a commit to cwoffenden/emscripten that referenced this pull request Feb 12, 2025
This mostly adds an Audio Worklet parameter test, but also tidies a little the related tests and shared code.
@cwoffenden
Copy link
Contributor Author

Note for me to look at (POINTER_TYPE and POINTER_SIZE):

pointer_size

cwoffenden added a commit to cwoffenden/emscripten that referenced this pull request Feb 20, 2025
This mostly adds an Audio Worklet parameter test, but also tidies a little the related tests and shared code.
cwoffenden added a commit to cwoffenden/emscripten that referenced this pull request Feb 20, 2025
This mostly adds an Audio Worklet parameter test, but also tidies a little the related tests and shared code.
sbc100 pushed a commit that referenced this pull request Feb 21, 2025
…tests) (#23659)

This is splits out the test changes from #23508 adding an interactive
parameter test:

```
test/runner interactive.test_audio_worklet_params_mixing
```

This test is also added to the browser tests now #23665 has merged,
offering a single test that touches all the various structs and their
offsets. When run as part of the `browser` tests it plays for 1 second,
for interactive without the `TEST_AND_EXIT` macro it will play
continuously.

It also tidies a little the shared code (and related tests) in the
process. Interactive tests had `_2gb` and `_4gb` options added (which
will fail until #23508 lands, but they're not part of the CI). All
features of these tests as interactive now work fully on Chrome, Firefox
and Safari (Safari has issues with looping, but it doesn't affect the
spirit of the test).
@@ -193,14 +273,9 @@ class BootstrapMessages extends AudioWorkletProcessor {
// 'cb' the callback function
// 'ch' the context handle
// 'ud' the passed user data
p.postMessage({'_wsc': d['cb'], 'x': [d['ch'], 1/*EM_TRUE*/, d['ud']] });
p.postMessage({'_wsc': {{{ toIndexType("d['cb']") }}}, 'x': [d['ch'], 1/*EM_TRUE*/, {{{ toIndexType("d['ud']") }}}] });
Copy link
Collaborator

Choose a reason for hiding this comment

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

Are the changes on this line necessary? I would hope that toIndexType would only be needed on lines that directly call wasm table operations. i.e. only for wasmTable.get, etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Originally the type conversions were in the calling code, here for example:

EmAudio[contextHandle].audioWorklet.bootstrapMessage.port.postMessage({

But you suggested moving them to where they're needed. Without these it results in type errors, e.g.: TypeError: Cannot convert 0 to a BigInt.

}
}
#endif

Copy link
Collaborator

Choose a reason for hiding this comment

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

This file sseems to have changed a lot more than I would expect just for the memory64 change. Am I missing something?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's built on #22753 from last October that was never merged, which contained, besides the performance improvements, the groundwork for the struct offsets which made 2GB and wasm64 support straightforward. The diff between the old PR and this isn't that large, with most of the work going into the tests (which went into their own #23659).

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'll break this down into a series of smaller PRs on the current main, e.g. move to the C_STRUCTS offsets and makeGetValue, then introduce wasm64, then the performance changes. I couldn't review in its current state what I wrote myself.

I don't know when this will be though since we're shipping it and it's done what I set out to do (we have millions of users putting in hour long sessions per day, so a few millis per second saved is a big deal on low-end school hardware when juggling 3D content with audio, and if it didn't work we'd really know about it!).

Copy link
Collaborator

Choose a reason for hiding this comment

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

We appreciate all the work you have done here.

I'm excited to see these changes lands. If you can find time to spit split the PR that would be amazing. If not, we can circle back in a few weeks.

@cwoffenden
Copy link
Contributor Author

Note for me to come back to. These test look to have broken when merged with #23108:

browser64 & browser64_4gb
test_audio_worklet_es6
test_audio_worklet_modularize
test_audio_worklet_pthreads_es6

They break here with the bigint error:

return f(...args);

Called from here:

__emscripten_wasm_worker_initialize(m['sb'], m['sz']);

Probably the switch to readEmAsmArgs().

The test_stat_chmod_nodefs failure looks unrelated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants