WebGPU queue.writeBuffer() fails when WebAssembly heap size > 2GB (i.e. Wasm4GB and Wasm64 modes are not supported)
Categories
(Core :: Graphics: WebGPU, defect, P2)
Tracking
()
People
(Reporter: jujjyl, Unassigned)
References
(Blocks 1 open bug)
Details
Attachments
(2 files)
Emscripten/WebAssembly supports three memory models:
- <= 2GB memory,
- > 2GB memory (32-bit, up to 4GB)
- Wasm64 (64-bit, up to 16GB)
Currently in Firefox if one calls queue.writeBuffer() with an ArrayBufferView that flows from a WebAssembly program that is utilizing either of memory models 2. or 3. above, Firefox will fail with an exception
TypeError: GPUQueue.writeBuffer: ArrayBufferView branch of (ArrayBuffer or ArrayBufferView) can't be an ArrayBuffer or an ArrayBufferView larger than 2 GB
The WebGPU functions
queue.writeTexture()
encoder.setImmediateData()
encoder.setBindGroup()
also have the same issue, since they too take in an ArrayBufferView.
| Reporter | ||
Comment 1•4 months ago
|
||
https://github.com/juj/wasm_webgpu/ test suite workaround for this Firefox limitation: https://github.com/juj/wasm_webgpu/commit/c0f15ca39e2e6d9bc177a5881ddf5ad32146a98e
Comment 2•4 months ago
|
||
Hmm, the error being thrown here is generated by WebIDL bindings at dom/bindings/Codegen.py:6906-6918. This affects WebGPU, but is not a bug in WebGPU code, per se.
NI'ing :saschanaz, since I'm not sure if there's an existing bug to track this.
Comment 4•4 months ago
|
||
Comment 5•4 months ago
|
||
That patch I've attached just now include the WebIDL and C++ bindings changes I suspect are necessary to make this work on that side of the JS runtime. IIRC, :teoxoy mentioned that there are some other internal limits that we need to figure out before this will actually work, but I haven't run it, because I haven't set up a runnable example that hits this issue yet.
Jukka, do you have concrete steps to reproduce this issue? That would facilitate this greatly.
| Reporter | ||
Comment 6•4 months ago
•
|
||
Here's a test case
<html><body><canvas id="canvas"></canvas>
<script type="module">
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
device.pushErrorScope('validation');
const ctx = document.getElementById('canvas').getContext('webgpu');
ctx.configure({ device, format: navigator.gpu.getPreferredCanvasFormat() });
const dstBuffer = device.createBuffer({
size: 8,
usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
});
const encoder = device.createCommandEncoder();
// Allocate 16GB WebAssembly Memory.
const instance = await WebAssembly.instantiate(new Uint8Array([0,97,115,109,1,0,0,0,5,8,1,5,128,128,4,128,128,16,7,7,1,3,109,101,109,2,0]));
const memory = instance.instance.exports.mem;
memory.grow(196608n);
// Alternatively, for just 4GB: const memory = new WebAssembly.Memory({ initial: 1024*1024*1024*4/65536 });
const heap64 = new BigUint64Array(memory.buffer);
heap64[0] = 0x0123456789ABCDEFn;
const heap8 = new Uint8Array(memory.buffer);
device.queue.writeBuffer(dstBuffer, 0, heap8, 0, 8);
device.queue.submit([encoder.finish()]);
const error = await device.popErrorScope();
if (error) throw new Error(error.message);
await dstBuffer.mapAsync(GPUMapMode.READ);
const dstValue = new BigUint64Array(dstBuffer.getMappedRange(0, 8))[0];
console.log(`Got: 0x${dstValue.toString(16)}, expected: 0x${heap64[0].toString(16)}`);
if (dstValue !== heap64[0]) throw new Error('Read-back value mismatch');
dstBuffer.unmap();
console.log('Test OK');
</script></body></html>
| Reporter | ||
Comment 7•4 months ago
|
||
As for why there's that peculiar binary blob WebAssembly.instantiate(), see https://issues.chromium.org/issues/495832110
Comment 8•4 months ago
|
||
Comment 9•4 months ago
|
||
Hey Jukka, would you please try a Firefox build that tries to patch a fix? Per comment 5, I'm expecting there to be other issues, but there may not be. Here's a link to a Try push with builds: try:c73d152656ad
You can get a copy of Firefox from this link if you:
- Select one of the
Bchips (for abuildjob). You'll see a bottom section pop up with several tabs. Note that if you click away from a chip, then the bottom section disappears. - Click the
Artifacts and Debugging Toolstab of the bottom section. You'll be presented with a list of artifacts that you can use to run the build of Firefox. For instance, you can use an installer, or just extract an archive of the Firefox binary (which should run by itself).
| Reporter | ||
Comment 10•3 months ago
|
||
Downloaded Win 10 Debug build, and tried to run the HTML repro that I posted above in this message: https://bugzilla.mozilla.org/show_bug.cgi?id=2022805#c6.
Unfortunately I got the "Gah. Your tab just crashed." error. There does not seem to be anything logged to about:crashes, and the command line log does not have anything that stands out either:
[Parent 52112, sqldb:places.sqlite #2] WARNING: Suboptimal indexes for the SQL statement 0x2822e438b00 (http://mzl.la/1FuID0j).: file /builds/worker/checkouts/gecko/storage/mozStoragePrivateHelpers.cpp:112
[Parent 52112, WindowsVsyncThread] WARNING: DwmComposition dynamically disabled, falling back to software timers: file /builds/worker/checkouts/gecko/gfx/thebes/gfxWindowsPlatform.cpp:1563
[Parent 52112, IPC I/O Parent] WARNING: Call to Send() failed: file /builds/worker/checkouts/gecko/ipc/glue/NodeChannel.cpp:190
[Parent 52112, IPDL Background] WARNING: Attempt to transfer invalid or null handle to process 56876 for message INTRODUCE_MESSAGE in TransferHandles: file /builds/worker/checkouts/gecko/ipc/chromium/src/chrome/common/ipc_channel_win.cc:678
[Parent 52112, IPDL Background] WARNING: Call to Send() failed: file /builds/worker/checkouts/gecko/ipc/glue/NodeChannel.cpp:190
[Parent 52112, Main Thread] WARNING: Attempt to transfer invalid or null handle to process 56876 for message INTRODUCE_MESSAGE in TransferHandles: file /builds/worker/checkouts/gecko/ipc/chromium/src/chrome/common/ipc_channel_win.cc:678
[Parent 52112, IPDL Background] WARNING: Dropping message as channel has been closed: file /builds/worker/checkouts/gecko/ipc/glue/NodeChannel.cpp:182
[Parent 52112, Main Thread] WARNING: Call to Send() failed: file /builds/worker/checkouts/gecko/ipc/glue/NodeChannel.cpp:190
[Parent 52112, IPC I/O Parent] WARNING: [1.1]: Dropping message '<null>'; no connection to unknown peer 19ADF273526A11AE.CE4D99BC0AF91659: file /builds/worker/checkouts/gecko/ipc/glue/NodeController.cpp:366
[Parent 52112, ProcessHangMon] WARNING: IPC message 'PProcessHangMonitor::Msg_RequestContentJSInterrupt' discarded: actor cannot send: file /builds/worker/checkouts/gecko/ipc/glue/ProtocolUtils.cpp:509
[Parent 52112, Main Thread] WARNING: IPC message 'PBrowser::Msg_UpdateNativeWindowHandle' discarded: actor cannot send: file /builds/worker/checkouts/gecko/ipc/glue/ProtocolUtils.cpp:509
[Parent 52112, Main Thread] WARNING: IPC message 'PBrowser::Msg_Destroy' discarded: actor cannot send: file /builds/worker/checkouts/gecko/ipc/glue/ProtocolUtils.cpp:509
[Parent 52112, Main Thread] WARNING: No build ID mismatch: file /builds/worker/checkouts/gecko/dom/base/nsFrameLoader.cpp:3736
[Parent 52112, Main Thread] WARNING: IPC message 'PContent::Msg_GetLayoutHistoryState' discarded: actor cannot send: file /builds/worker/checkouts/gecko/ipc/glue/ProtocolUtils.cpp:509
[Parent 52112, Main Thread] WARNING: IPC message 'PContent::Msg_CommitBrowsingContextTransaction' discarded: actor cannot send: file /builds/worker/checkouts/gecko/ipc/glue/ProtocolUtils.cpp:509
[Parent 52112, Main Thread] WARNING: IPC message 'PContent::Msg_DiscardBrowsingContext' discarded: actor cannot send: file /builds/worker/checkouts/gecko/ipc/glue/ProtocolUtils.cpp:509
Not sure what to make of it.
Description
•