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);
},
Safari WebGPU crashes:
GPUComputePassEncoder.setBindGroupcalled with wrong dynamic offsets overload/type (Uint32Arrayrequired)Environment
App: C++/Wasm (Emscripten) + WebGPU
Browser:
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 glueWhat happens
On Safari, the app fails with:
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):
When
numDynamicOffsets == 0(the common case), Safari appears to treat argument 3 asdynamicOffsetsDataand enforces that it’s aUint32Array, rejecting the call path. Chrome accepts this.Expected behavior
If
numDynamicOffsets == 0, the glue should call the 2-argument overload:If
numDynamicOffsets > 0, the glue should pass a realUint32Array(e.g. viasubarray) to satisfy Safari’s type checks.Proposed fix
Branch on
numDynamicOffsetsand use Safari-friendly typed array handling: