guard<T> method

T guard<T>(
  1. String what,
  2. T body()
)

Runs body with a validation scope open, recording whatever the browser says into debugDrainErrors.

Without this pair nothing WebGPU rejects can ever be seen from Dart. The API validates asynchronously: createRenderPipeline hands back a pipeline object whether or not the descriptor was legal, and the complaint arrives later, on the console, where no Dart program will meet it. A backend that means to report a refusal has to bracket the call.

Synchronous in and synchronous out, so the object can be handed on while the verdict settles behind it — which is what makes this affordable at all. It is used on the calls that are rare and expensive: making a texture, a buffer, a pipeline, a bind group, and submitting a pass. Wrapping a per-draw call would add a promise per draw.

Implementation

T guard<T>(String what, T Function() body) {
  gpuDevice.pushErrorScope(GpuErrorFilter.validation);
  final T result;
  try {
    result = body();
  } catch (_) {
    // Popped either way: an unbalanced scope makes the *next* pop answer for
    // this call's errors, which reports the mistake against whatever ran
    // afterwards.
    _pending.add(gpuDevice.popErrorScope().toDart.then((GPUError? _) {}));
    rethrow;
  }
  _pending.add(
    gpuDevice.popErrorScope().toDart.then((GPUError? error) {
      if (error != null) _errors.add('$what: ${error.message}');
    }),
  );
  return result;
}