-
Notifications
You must be signed in to change notification settings - Fork 30
Description
Safari WebGPU crashes: GPUComputePassEncoder.setBindGroup called with wrong dynamic offsets overload/type (Uint32Array required)
Environment
-
App: C++/Wasm (Emscripten) + WebGPU
-
Browser:
- ✅ Chrome: works
- ❌ Safari: fails at first compute pass bind
-
Safari: WebGPU enabled via feature flag
-
Repro: any compute dispatch that calls
wgpu_encoder_set_bind_group(..., dynamicOffsets=nullptr, numDynamicOffsets=0)through this library’s JS glue
What happens
On Safari, the app fails with:
Unhandled Promise Rejection: TypeError:
Argument 3 ('dynamicOffsetsData') to GPUComputePassEncoder.setBindGroup
must be an instance of Uint32Array
Stack points into the generated WebGPU shim and the call to setBindGroup.
Root cause (suspected)
The library’s glue code always calls the “dynamic offsets” overload of WebGPU setBindGroup, even when no dynamic offsets are used.
Current glue implementation (excerpt):
wgpu_encoder_set_bind_group: function(encoder, index, bindGroup, dynamicOffsets, numDynamicOffsets) {
// ...
wgpu[encoder]['setBindGroup'](index, wgpu[bindGroup], HEAPU32, dynamicOffsets >> 2, numDynamicOffsets);
},When numDynamicOffsets == 0 (the common case), Safari appears to treat argument 3 as dynamicOffsetsData and enforces that it’s a Uint32Array, rejecting the call path. Chrome accepts this.
Expected behavior
If numDynamicOffsets == 0, the glue should call the 2-argument overload:
encoder.setBindGroup(index, bindGroupOrNull);If numDynamicOffsets > 0, the glue should pass a real Uint32Array (e.g. via subarray) to satisfy Safari’s type checks.
Proposed fix
Branch on numDynamicOffsets and use Safari-friendly typed array handling:
wgpu_encoder_set_bind_group: function(encoder, index, bindGroup, dynamicOffsets, numDynamicOffsets) {
const bg = (bindGroup === 0) ? null : wgpu[bindGroup];
if (numDynamicOffsets === 0) {
wgpu[encoder]['setBindGroup'](index, bg);
return;
}
const start = (dynamicOffsets >>> 2);
const offsetsView = HEAPU32.subarray(start, start + numDynamicOffsets);
wgpu[encoder]['setBindGroup'](index, bg, offsetsView);
},