SerenityOS / serenity

The Serenity Operating System 🐞
https://serenityos.org
BSD 2-Clause "Simplified" License
30.39k stars 3.18k forks source link

LibWeb+LibJS+LibWasm: Features desired/required for the Ruffle Flash Player emulator #17993

Open Lubrsi opened 1 year ago

Lubrsi commented 1 year ago

Features desired/required by the Ruffle Flash Player emulator:

This list is not exhaustive, I only tested Ruffle with Robot Unicorn Attack and Flight of the Hamsters.

There are many more issues with how we render flash files with Ruffle, but they have not been looked into to find what the specific issues are, for example:

https://user-images.githubusercontent.com/25595356/227027812-91fbd834-b5a8-4cf5-9fe3-398580b578d7.mp4

To see how the game is supposed to look, here's a game website that uses Ruffle: https://www.crazygames.com/game/robot-unicorn-attack

alimpfard commented 1 year ago

WebAssembly.Memory.buffer must return the same ArrayBuffer every time and must grow in place as Wasm's memory buffer is expanded (required, as Ruffle keeps a cached reference to this ArrayBuffer in a global variable and fully expects it to grow in place, as after a while memory indices will suddenly point outside of the buffer if not grown in place)

WebAssembly.Memory.buffer only returns a new wrapper ArrayBuffer object, the underlying buffer always points to the actual underlying bytebuffer and grows accordingly. Also, I don't think that attribute is supposed to be cacheable, see https://webassembly.github.io/spec/js-api/#dom-memory-grow:

  1. Let store be the surrounding agent's associated store.
  2. Let memaddr be this.[[Memory]].
  3. Let ret be the mem_size(store, memaddr).
  4. Let store be mem_grow(store, memaddr, delta).
  5. If store is error, throw a RangeError exception.
  6. Set the surrounding agent's associated store to store.
  7. Reset the memory buffer of memaddr.
  8. Return ret.

The "reset the memory buffer" step is supposed to replace the value of Memory.buffer.

Lubrsi commented 1 year ago

Ohh, you just reminded me that the actual issue is that typed arrays don't respond to it's underlying ArrayBuffer getting resized (it still has old size values, for example). Changed the comment.

Lubrsi commented 1 year ago

The actual actual issue is: Wasm memory growth doesn't detach any ArrayBuffers returned by WebAssembly.Memory.buffer. (required, as it keeps a Uint8Array cache of the buffer, and it only knows to update the cache when TypedArray#byteLength becomes 0, which it does when the underlying ArrayBuffer is detached)

alimpfard commented 1 year ago

Implemented that behaviour in #18079.

torokati44 commented 1 year ago

Hi, Ruffle contributor here!

Awesome to see this being worked on, and even more amazing that it already runs "somewhat"! And thank you for the comprehensive list of stuff to do!

One minor correction: There are actually 5 WASM extensions needed/used by the "fancier" build, not just SIMD. See: https://github.com/ruffle-rs/ruffle/blob/b01e797e99e37b42ebe552d7958e2ba51d3125b7/web/packages/core/src/load-ruffle.ts#L45-L49

alimpfard commented 1 year ago
            bulkMemory(),
            simd(),
            saturatedFloatToInt(),
            signExtensions(),
            referenceTypes(),

Of the listed extensions, the only currently unimplemented one in LibWasm is SIMD;

I have an old WIP branch starting on SIMD (https://github.com/alimpfard/serenity/tree/wasm-simd), but that's probably drowning in conflicts by now :sweat_smile:

torokati44 commented 1 year ago

Of the listed extensions, the only currently unimplemented one in LibWasm is SIMD;

Oh, wow, that's incredible! Wouldn't have thought that this much is done already (sorry), but should have checked!

msub2 commented 1 year ago

After poking around with Audion on some Ruffle games it seems like the minimum needed from WebAudio would be:

Along with BaseAudioContext/AudioContext, which I am currently working on.