Open Bug 2022805 Opened 4 months ago Updated 1 month ago

WebGPU queue.writeBuffer() fails when WebAssembly heap size > 2GB (i.e. Wasm4GB and Wasm64 modes are not supported)

Categories

(Core :: Graphics: WebGPU, defect, P2)

defect

Tracking

()

People

(Reporter: jujjyl, Unassigned)

References

(Blocks 1 open bug)

Details

Attachments

(2 files)

Emscripten/WebAssembly supports three memory models:

  1. <= 2GB memory,
  2. > 2GB memory (32-bit, up to 4GB)
  3. 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.

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.

Severity: -- → S3
Flags: needinfo?(krosylight)
Depends on: 2022010
Flags: needinfo?(krosylight)

P2: Incorrect existing

Priority: -- → P2

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.

Flags: needinfo?(jujjyl)

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>
Flags: needinfo?(jujjyl)

As for why there's that peculiar binary blob WebAssembly.instantiate(), see https://issues.chromium.org/issues/495832110

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:

  1. Select one of the B chips (for a build job). 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.
  2. Click the Artifacts and Debugging Tools tab 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).
Flags: needinfo?(jujjyl)

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.

Flags: needinfo?(jujjyl)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: