Ответы пользователя по тегу WebAssembly
  • Как получить буфер линейной памяти wasm модуля из WebWorker без его копирования?

    @desocrew
    Действительно, вы не можете передать ArrayBuffer, который используется внутри WebAssembly, через postMessage() с опцией transfer. Это происходит потому, что в этом случае браузер пытается оторвать буфер от исходного контекста и присоединить его к новому контексту (в данном случае, от worker'а к основному потоку). Однако ArrayBuffer, связанный с памятью, используемой внутри WebAssembly, не может быть оторван и перенесен в другой контекст.

    Есть несколько вариантов, как можно передать данные между основным потоком и worker'ом без копирования.

    1. Использовать SharedArrayBuffer вместо ArrayBuffer. Однако, как вы уже заметили, у SharedArrayBuffer есть ограничения на использование в некоторых браузерах. Кроме того, не все платформы поддерживают SharedArrayBuffer (например, некоторые мобильные устройства iOS). Чтобы использовать SharedArrayBuffer в вашем случае, вы можете создать его в основном потоке и передать его в worker через postMessage(). Затем вы можете использовать этот SharedArrayBuffer внутри вашего WebAssembly модуля.

    2. Вы можете использовать Transferable Objects для передачи данных без копирования. В вашем случае, если память внутри WebAssembly модуля уже инициализирована, вы можете передать указатель на начало памяти через Transferable Objects. Например:

    Основной поток:
    const mem = instance.exports.memory.buffer;
    const ptr = instance.exports.getPixelDataPtr();
    worker.postMessage({mem, ptr}, [mem]);

    Web Worker:
    self.onmessage = (event) => {
      const {mem, ptr} = event.data;
      const pixels = new Uint8Array(mem, ptr, numPixels * 4);
      // делаем что-то с пикселями
    }

    В этом случае, вы передаете указатель на начало памяти вместе с буфером, но не копируете саму память. Вы можете использовать TypedArray для доступа к данным в памяти. Обратите внимание, что в вашем WebAssembly модуле должна быть функция, которая возвращает указатель на начало памяти, который вы можете передать в worker.

    Однако, если вы измените данные в памяти на стороне worker'а, эти изменения не будут отражены в памяти, используемой внутри WebAssembly модуля.
    Ответ написан
    1 комментарий