juj/wasm_webgpu

wgpu_device_push_error_scope and wgpu_device_pop_error_scope_async

brendan-duncan opened this issue · 3 comments

Since they're still TODO in the library, I have this implementation for them. I wasn't sure how you were intending to store the GPUError for message retrieval with wgpu_error_get_message. In the meantime, I have it send the message string to the callback.

lib_webgpu.h

typedef void (*WGpuDeviceErrorCallback)(WGpuDevice device, WGpuError error, const char* message, void *userData);
void wgpu_device_pop_error_scope_async(WGpuDevice device, WGpuDeviceErrorCallback callback, void *userData);

lib_webgpu.js

wgpu_device_push_error_scope: function(device, filter) {
    wgpu[device]['pushErrorScope'](_wgpuStrings[filter]);
  },

  wgpu_device_pop_error_scope_async: function(device, callback, userdata) {
    device = wgpu[device];
    return device['popErrorScope']().then(error => {
      var buffer = 0;
      var type = 0 /*WGPU_ERROR_TYPE_NONE*/;
      if (GPUOutOfMemoryError.prototype.isPrototypeOf(error)) {
        type = 1 /* WGPU_ERROR_TYPE_OUT_OF_MEMORY_ERROR */;
      }
      if (GPUValidationError.prototype.isPrototypeOf(error)) {
        type = 2 /* WGPU_ERROR_TYPE_VALIDATION */;
        var len = lengthBytesUTF8(error.message) + 1;
        buffer = _malloc(len);
        stringToUTF8(error.message, buffer, len);
      }
      if (type != 0) {
        dynCall('viii' /*WGPUErrorCallback*/, callback, [device, type, buffer, userdata]);
      }
      if (buffer != 0) {
        _free(buffer);
      }
      return true
    },
    reason => { return false; });
  }
juj commented

That looks good. Cosmetically I'll do it a bit different (use alloca() instead of malloc(), and {{{ makeDynCaller() }}} instead of dynCall(), but functionally the same.

Started protoing an implementation, but ran into https://bugs.chromium.org/p/chromium/issues/detail?id=1224835 and a realization that createBuffer() + getMappedRange() will ot actually trigger a 'out-of-memory' error scope, but it will just plain old throw an exception. So it looks like in order to detect an OOM in GPU buffer creation for initially mapped buffers, one should look for the return value in getMappedRange().

Adjusted the code in a3c02f4 to accommodate that.

Any chance you have found a small API sequence that would work as a test for actually raising GPU validation (and/or oom) scoped errors?

juj commented

Taking another look, createBuffer() does raise a scoped error. Used that as a basis to implement support for wgpu_device_push_error_scope() and wgpu_device_pop_error_scope_async() in above commit.

juj commented

Posted gpuweb/gpuweb#1884 related to this. That would simplify the implementation.