google-chromegpugpgpumetalwebgpu

Why is webgpu on mac "max binding size" much smaller than reported "max buffer size"?


I'm developing a library based in WebGPU on a high end mac laptop using Chrome. The library is primarily designed to implement compute shader pipelines for manipulating microscopy and other 3d volume data (https://github.com/AaronWatters/webgpu_volume).

According to https://webgpureport.org/ I should be able to allocate a 4GB buffer based on the reported maxBufferSize and maxStorageBufferBindingSize.

However when I try to allocate a largish buffer I get this error message:

   Binding size (138331344) of [Buffer] is larger than the maximum binding size (134217728).

Why is the reported max buffer size 4GB and the actual limit when executing 134M?

Is there any way to request higher limits? What's up with this?

Note that the following question is similar but has no helpful responses: Binding size '...' is larger than the maximum binding size (134217728)

(edit) I tried this:

const twoGig = 2147483648;
const required_limits = {};
// https://developer.mozilla.org/en-US/docs/Web/API/GPUDevice/limits
required_limits.maxStorageBufferBindingSize = twoGig;
required_limits.maxBufferSize = twoGig;
this.device = await this.adapter.requestDevice(required_limits);

but so far it seems like the required_limits are ignored.


Solution

  • Your issue is caused by an incorrect layout of the object in your requestDevice call. The correct object format is the following:

    const twoGig = 2147483648;
    const required_limits = {};
    // https://developer.mozilla.org/en-US/docs/Web/API/GPUDevice/limits
    required_limits.maxStorageBufferBindingSize = twoGig;
    required_limits.maxBufferSize = twoGig;
    this.device = await this.adapter.requestDevice({
      "requiredLimits": required_limits
    });
    

    Notice how your required limits actually need to be a property inside of the object you pass in as a parameter. These are the relevant parts of the standard: for the requestDevice function, and its parameter object.

    On another note, in production apps, I would recommend verifying that your limits do not exceed the amount actually supported by the adapter -- if they did, then your requestDevice call would throw a TypeError, as defined by the standard. As most surveyed devices only support a maxStorageBufferBindingSize of 2147483644 (just short of 2GiB), your code would probably not work on most devices. You can easily query the adapter's limits by checking its limits property, e.g. adapter.limits.maxStorageBufferBindingSize, and use that value when calling requestDevice.